Shopping List v2.0
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ListItem.svelte 2.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. <script>
  2. import { createEventDispatcher } from 'svelte';
  3. export let item;
  4. let dispatch = createEventDispatcher();
  5. let emitRemove = () => dispatch("remove", item);
  6. function transIn(node) {
  7. if (!item.pending) return { delay: 0, duration: 0 };
  8. let comp = getComputedStyle(node);
  9. let height = parseInt(comp.height);
  10. let paddingTop = parseInt(comp["padding-top"]);
  11. return {
  12. delay: 0,
  13. duration: 200,
  14. css: t => `
  15. overflow: hidden;
  16. height: ${t * height}px;
  17. padding-top: ${t * paddingTop}px;`
  18. };
  19. }
  20. function transOut(node) {
  21. let comp = getComputedStyle(node);
  22. let opacity = parseFloat(comp.opacity);
  23. let height = parseInt(comp.height);
  24. let paddingTop = parseInt(comp["padding-top"]);
  25. function part(t, from, to) {
  26. return Math.max((t - from), 0) / (to - from);
  27. }
  28. return {
  29. delay: 0,
  30. duration: 200,
  31. css: t => `
  32. overflow: hidden;
  33. height: ${part(t, 0.3, 1) * height}px;
  34. padding-top: ${part(t, 0.3, 1) * paddingTop}px;
  35. transform: translateX(-${(1 - t) * 150}px);
  36. opacity: ${part(t, 0, 0.7) * opacity}`
  37. };
  38. }
  39. function capitalize(str) {
  40. var first = str[0].toUpperCase();
  41. return first + str.substring(1);
  42. }
  43. </script>
  44. <style>
  45. .item {
  46. transition: background-color 0.3s;
  47. padding-left: 12px;
  48. padding-top: 42px;
  49. position: relative;
  50. margin: auto;
  51. text-align: left;
  52. width: 100%;
  53. height: 70px;
  54. overflow: hidden;
  55. border-bottom: 1px solid #ccc;
  56. }
  57. .item.pending {
  58. background-color: #eee;
  59. }
  60. .item .name {
  61. position: relative;
  62. display: inline-block;
  63. max-width: calc(100% - 60px);
  64. overflow: hidden;
  65. text-overflow: ellipsis;
  66. }
  67. .item .ok {
  68. position: relative;
  69. display: inline-block;
  70. float: right;
  71. margin-right: 6px;
  72. height: 50px;
  73. width: 50px;
  74. bottom: 33px;
  75. background-image: url(/icon-check.svg);
  76. background-size: 24px 24px;
  77. background-repeat: no-repeat;
  78. background-position: center;
  79. cursor: pointer;
  80. border-radius: 100px;
  81. background-color: #eee;
  82. }
  83. .item .ok:hover {
  84. background-color: #ddd;
  85. }
  86. </style>
  87. <div in:transIn out:transOut class={`item ${item.pending ? 'pending' : ''}`}>
  88. <div class="name">{capitalize(item.content)}</div>
  89. {#if !item.pending}
  90. <span class="ok" on:click={emitRemove}></span>
  91. {/if}
  92. </div>