From b16e429fe01f4be919f708984f262a29108fccab Mon Sep 17 00:00:00 2001 From: "phongit.kha" <153442976+phongit-kha@users.noreply.github.com> Date: Thu, 23 Jan 2025 22:36:08 +0700 Subject: [PATCH] feat(v2)/multi select - DEV-28 (#736) * chore: update bits-ui * feat: add separator component * chore: update vite * feat(v2): add select component * feat(v2): add select component storybook * docs: add comment for select * feat: add multiple select with chip storybook --------- Co-authored-by: Nutthapat Pongtanyavichai --- packages/ui/package.json | 5 +- .../ui/src/components/atom/separator/index.ts | 7 + .../atom/separator/separator.svelte | 23 ++ .../src/components/molecule/select/index.ts | 34 +++ .../molecule/select/select-content.svelte | 36 ++++ .../select/select-group-heading.svelte | 17 ++ .../molecule/select/select-item.svelte | 41 ++++ .../select/select-scroll-down-button.svelte | 23 ++ .../select/select-scroll-up-button.svelte | 23 ++ .../molecule/select/select-separator.svelte | 19 ++ .../molecule/select/select-trigger.svelte | 33 +++ .../molecule/select/select.stories.svelte | 199 ++++++++++++++++++ pnpm-lock.yaml | 115 +++++----- 13 files changed, 519 insertions(+), 56 deletions(-) create mode 100644 packages/ui/src/components/atom/separator/index.ts create mode 100644 packages/ui/src/components/atom/separator/separator.svelte create mode 100644 packages/ui/src/components/molecule/select/index.ts create mode 100644 packages/ui/src/components/molecule/select/select-content.svelte create mode 100644 packages/ui/src/components/molecule/select/select-group-heading.svelte create mode 100644 packages/ui/src/components/molecule/select/select-item.svelte create mode 100644 packages/ui/src/components/molecule/select/select-scroll-down-button.svelte create mode 100644 packages/ui/src/components/molecule/select/select-scroll-up-button.svelte create mode 100644 packages/ui/src/components/molecule/select/select-separator.svelte create mode 100644 packages/ui/src/components/molecule/select/select-trigger.svelte create mode 100644 packages/ui/src/components/molecule/select/select.stories.svelte diff --git a/packages/ui/package.json b/packages/ui/package.json index 38b71b5e3..a2c3f41bd 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -28,11 +28,12 @@ }, "dependencies": { "@repo/utils": "workspace:^", - "bits-ui": "^0.22.0", + "bits-ui": "1.0.0-next.74", "clsx": "^2.1.1", "lucide-svelte": "^0.473.0", "tailwind-merge": "^2.6.0", "tailwind-variants": "^0.3.1", - "tailwindcss": "^3.4.17" + "tailwindcss": "^3.4.17", + "vite": "^6.0.11" } } diff --git a/packages/ui/src/components/atom/separator/index.ts b/packages/ui/src/components/atom/separator/index.ts new file mode 100644 index 000000000..42c117068 --- /dev/null +++ b/packages/ui/src/components/atom/separator/index.ts @@ -0,0 +1,7 @@ +import Root from './separator.svelte' + +export { + Root, + // + Root as Separator, +} diff --git a/packages/ui/src/components/atom/separator/separator.svelte b/packages/ui/src/components/atom/separator/separator.svelte new file mode 100644 index 000000000..b64c63c81 --- /dev/null +++ b/packages/ui/src/components/atom/separator/separator.svelte @@ -0,0 +1,23 @@ + + + diff --git a/packages/ui/src/components/molecule/select/index.ts b/packages/ui/src/components/molecule/select/index.ts new file mode 100644 index 000000000..3096669f8 --- /dev/null +++ b/packages/ui/src/components/molecule/select/index.ts @@ -0,0 +1,34 @@ +import { Select as SelectPrimitive } from 'bits-ui' + +import Content from './select-content.svelte' +import GroupHeading from './select-group-heading.svelte' +import Item from './select-item.svelte' +import ScrollDownButton from './select-scroll-down-button.svelte' +import ScrollUpButton from './select-scroll-up-button.svelte' +import Separator from './select-separator.svelte' +import Trigger from './select-trigger.svelte' + +const Root = SelectPrimitive.Root +const Group = SelectPrimitive.Group + +export { + Content, + Group, + GroupHeading, + Item, + Root, + ScrollDownButton, + ScrollUpButton, + // + Root as Select, + Content as SelectContent, + Group as SelectGroup, + GroupHeading as SelectGroupHeading, + Item as SelectItem, + ScrollDownButton as SelectScrollDownButton, + ScrollUpButton as SelectScrollUpButton, + Separator as SelectSeparator, + Trigger as SelectTrigger, + Separator, + Trigger, +} diff --git a/packages/ui/src/components/molecule/select/select-content.svelte b/packages/ui/src/components/molecule/select/select-content.svelte new file mode 100644 index 000000000..593f029c9 --- /dev/null +++ b/packages/ui/src/components/molecule/select/select-content.svelte @@ -0,0 +1,36 @@ + + + + + + {@render children?.()} + + + diff --git a/packages/ui/src/components/molecule/select/select-group-heading.svelte b/packages/ui/src/components/molecule/select/select-group-heading.svelte new file mode 100644 index 000000000..39db2b7cd --- /dev/null +++ b/packages/ui/src/components/molecule/select/select-group-heading.svelte @@ -0,0 +1,17 @@ + + + diff --git a/packages/ui/src/components/molecule/select/select-item.svelte b/packages/ui/src/components/molecule/select/select-item.svelte new file mode 100644 index 000000000..d58fdcd09 --- /dev/null +++ b/packages/ui/src/components/molecule/select/select-item.svelte @@ -0,0 +1,41 @@ + + + + {#snippet children({ selected, highlighted })} + {#if childrenProp} + {@render childrenProp({ selected, highlighted })} + {:else} + {label || value} + {/if} + {#if check} + + {#if selected} + + {/if} + + {/if} + {/snippet} + diff --git a/packages/ui/src/components/molecule/select/select-scroll-down-button.svelte b/packages/ui/src/components/molecule/select/select-scroll-down-button.svelte new file mode 100644 index 000000000..efcac55e8 --- /dev/null +++ b/packages/ui/src/components/molecule/select/select-scroll-down-button.svelte @@ -0,0 +1,23 @@ + + + + + diff --git a/packages/ui/src/components/molecule/select/select-scroll-up-button.svelte b/packages/ui/src/components/molecule/select/select-scroll-up-button.svelte new file mode 100644 index 000000000..8faca6cc9 --- /dev/null +++ b/packages/ui/src/components/molecule/select/select-scroll-up-button.svelte @@ -0,0 +1,23 @@ + + + + + diff --git a/packages/ui/src/components/molecule/select/select-separator.svelte b/packages/ui/src/components/molecule/select/select-separator.svelte new file mode 100644 index 000000000..153450022 --- /dev/null +++ b/packages/ui/src/components/molecule/select/select-separator.svelte @@ -0,0 +1,19 @@ + + + diff --git a/packages/ui/src/components/molecule/select/select-trigger.svelte b/packages/ui/src/components/molecule/select/select-trigger.svelte new file mode 100644 index 000000000..ce0e7855b --- /dev/null +++ b/packages/ui/src/components/molecule/select/select-trigger.svelte @@ -0,0 +1,33 @@ + + +span]:line-clamp-1', + className, + )} + {...restProps} +> +
+ {@render children?.()} +
+ {#if arrow} + + {/if} + +
diff --git a/packages/ui/src/components/molecule/select/select.stories.svelte b/packages/ui/src/components/molecule/select/select.stories.svelte new file mode 100644 index 000000000..523385051 --- /dev/null +++ b/packages/ui/src/components/molecule/select/select.stories.svelte @@ -0,0 +1,199 @@ + + + + + + + + {triggerContent} + + + + Fruits + {#each fruits as fruit} + + {fruit.label} + + {/each} + + + + + + + + + {triggerContent} + + + + Fruits + {#each fruits as fruit} + + {fruit.label} + + {/each} + + + + + + + + + {#if !value2.length} + เลือก + {:else} + {#each value2 as temp} + {themes.find((item) => item.value === temp)?.label + ', ' || + temp + ', '} + {/each} + {/if} + + + + {#each themes as fruit} + + {fruit.label} + + {/each} + + + + + + + +
+ {#if value2.length} +
+ {#each value2 as temp} + { + event.stopPropagation() + value2 = value2.filter((item) => item != temp) + }} + aria-label={`Remove ${themes.find((item) => item.value === temp)?.label || temp}`} + > + {themes.find((item) => item.value === temp)?.label || temp} + + {/each} +
+ {/if} + + {#if !value2.length} + เลือก + {/if} + +
+ + + {#each themes as fruit} + + {fruit.label} + + {/each} + + +
+
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7b1718198..d8f7e88be 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -133,7 +133,7 @@ importers: devDependencies: '@playwright/test': specifier: ^1.49.1 - version: 1.49.1 + version: 1.50.0 '@repo/config': specifier: workspace:^ version: link:../../packages/config @@ -284,8 +284,8 @@ importers: specifier: workspace:^ version: link:../utils bits-ui: - specifier: ^0.22.0 - version: 0.22.0(svelte@5.19.2) + specifier: 1.0.0-next.74 + version: 1.0.0-next.74(svelte@5.19.2) clsx: specifier: ^2.1.1 version: 2.1.1 @@ -301,6 +301,9 @@ importers: tailwindcss: specifier: ^3.4.17 version: 3.4.17 + vite: + specifier: ^6.0.11 + version: 6.0.11(@types/node@22.10.9)(jiti@1.21.7)(sass-embedded@1.83.4)(tsx@4.19.2)(yaml@2.7.0) devDependencies: '@repo/config': specifier: workspace:^ @@ -1150,11 +1153,6 @@ packages: '@types/react': '>=16' react: '>=16' - '@melt-ui/svelte@0.76.2': - resolution: {integrity: sha512-7SbOa11tXUS95T3fReL+dwDs5FyJtCEqrqG3inRziDws346SYLsxOQ6HmX+4BkIsQh1R8U3XNa+EMmdMt38lMA==} - peerDependencies: - svelte: '>=3 <5' - '@noble/hashes@1.7.1': resolution: {integrity: sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==} engines: {node: ^14.21.3 || >=16} @@ -1182,8 +1180,8 @@ packages: resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - '@playwright/test@1.49.1': - resolution: {integrity: sha512-Ky+BVzPz8pL6PQxHqNRW1k3mIyv933LML7HktS8uik0bUXNCdPhoS/kLihiO1tMf/egaJb4IutXd7UywvXEW+g==} + '@playwright/test@1.50.0': + resolution: {integrity: sha512-ZGNXbt+d65EGjBORQHuYKj+XhCewlwpnSd/EDuLPZGSiEWmgOJB5RmMCCYGy5aMfTs9wx61RivfDKi8H/hcMvw==} engines: {node: '>=18'} hasBin: true @@ -1812,10 +1810,11 @@ packages: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} - bits-ui@0.22.0: - resolution: {integrity: sha512-r7Fw1HNgA4YxZBRcozl7oP0bheQ8EHh+kfMBZJgyFISix8t4p/nqDcHLmBgIiJ3T5XjYnJRorYDjIWaCfhb5fw==} + bits-ui@1.0.0-next.74: + resolution: {integrity: sha512-cazru5+NBKBCeK9KCV/OFy5I/B1zxOJGl5WpInzPTEPla5G9qZK9nrnXr6BbExKdhgusTiMm3h4Yvq4E5WHGJA==} + engines: {node: '>=18', pnpm: '>=8.7.0'} peerDependencies: - svelte: ^4.0.0 || ^5.0.0 + svelte: ^5.0.0 brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} @@ -2456,9 +2455,6 @@ packages: flatted@3.3.2: resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==} - focus-trap@7.6.4: - resolution: {integrity: sha512-xx560wGBk7seZ6y933idtjJQc1l+ck+pI3sKvhKozdBV1dRZoKhkW5xoCaFv9tQiX5RH1xfSxjuNu6g+lmN/gw==} - for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} @@ -2614,6 +2610,9 @@ packages: inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + inline-style-parser@0.2.4: + resolution: {integrity: sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==} + is-arguments@1.2.0: resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==} engines: {node: '>= 0.4'} @@ -2876,11 +2875,6 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - nanoid@5.0.9: - resolution: {integrity: sha512-Aooyr6MXU6HpvvWXKoVoXwKMs/KyVakWwg7xQfv5/S/RIgJMy0Ifa45H9qqYy7pTCszrHzP21Uk4PZq2HpEM8Q==} - engines: {node: ^18 || >=20} - hasBin: true - natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} @@ -3027,13 +3021,13 @@ packages: resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} engines: {node: '>= 6'} - playwright-core@1.49.1: - resolution: {integrity: sha512-BzmpVcs4kE2CH15rWfzpjzVGhWERJfmnXmniSyKeRZUs9Ws65m+RGIi7mjJK/euCegfn3i7jvqWeWyHe9y3Vgg==} + playwright-core@1.50.0: + resolution: {integrity: sha512-CXkSSlr4JaZs2tZHI40DsZUN/NIwgaUPsyLuOAaIZp2CyF2sN5MM5NJsyB188lFSSozFxQ5fPT4qM+f0tH/6wQ==} engines: {node: '>=18'} hasBin: true - playwright@1.49.1: - resolution: {integrity: sha512-VYL8zLoNTBxVOrJBbDuRgDWa3i+mfQgDTrL8Ah9QXZ7ax4Dsj0MSq5bYgytRnDVVe+njoKnfsYkH3HzqVj5UZA==} + playwright@1.50.0: + resolution: {integrity: sha512-+GinGfGTrd2IfX1TA4N2gNmeIksSb+IAe589ZH+FlmpV3MYTx6+buChGIuDLQwrGNCw2lWibqV50fU510N7S+w==} engines: {node: '>=18'} hasBin: true @@ -3237,6 +3231,11 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + runed@0.15.4: + resolution: {integrity: sha512-kmbpstUd7v2FdlBM+MT78IyuOVd38tq/e7MHvVb0fnVCsPSPMD/m2Xh+wUhzg9qCJgxRjBbIKu68DlH/x5VXJA==} + peerDependencies: + svelte: ^5.0.0-next.1 + rxjs@7.8.1: resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} @@ -3481,6 +3480,9 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} + style-to-object@1.0.8: + resolution: {integrity: sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g==} + sucrase@3.35.0: resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} engines: {node: '>=16 || 14 >=14.17'} @@ -3558,6 +3560,12 @@ packages: typescript: optional: true + svelte-toolbelt@0.4.6: + resolution: {integrity: sha512-k8OUvXBUifHZcAlWeY/HLg/4J0v5m2iOfOhn8fDmjt4AP8ZluaDh9eBFus9lFiLX6O5l6vKqI1dKL5wy7090NQ==} + engines: {node: '>=18', pnpm: '>=8.7.0'} + peerDependencies: + svelte: ^5.0.0-next.126 + svelte2tsx@0.7.34: resolution: {integrity: sha512-WTMhpNhFf8/h3SMtR5dkdSy2qfveomkhYei/QW9gSPccb0/b82tjHvLop6vT303ZkGswU/da1s6XvrLgthQPCw==} peerDependencies: @@ -3584,9 +3592,6 @@ packages: resolution: {integrity: sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==} engines: {node: ^14.18.0 || >=16.0.0} - tabbable@6.2.0: - resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} - tailwind-merge@2.5.4: resolution: {integrity: sha512-0q8cfZHMu9nuYP/b5Shb7Y7Sh1B7Nnl5GqNr1U+n2p6+mybvRtayrQ+0042Z5byvTA8ihjlP8Odo8/VnHbZu4Q==} @@ -4562,16 +4567,6 @@ snapshots: '@types/react': 19.0.8 react: 18.3.1 - '@melt-ui/svelte@0.76.2(svelte@5.19.2)': - dependencies: - '@floating-ui/core': 1.6.9 - '@floating-ui/dom': 1.6.13 - '@internationalized/date': 3.7.0 - dequal: 2.0.3 - focus-trap: 7.6.4 - nanoid: 5.0.9 - svelte: 5.19.2 - '@noble/hashes@1.7.1': {} '@nodelib/fs.scandir@2.1.5': @@ -4595,9 +4590,9 @@ snapshots: '@pkgr/core@0.1.1': {} - '@playwright/test@1.49.1': + '@playwright/test@1.50.0': dependencies: - playwright: 1.49.1 + playwright: 1.50.0 '@polka/url@1.0.0-next.28': {} @@ -5336,12 +5331,15 @@ snapshots: binary-extensions@2.3.0: {} - bits-ui@0.22.0(svelte@5.19.2): + bits-ui@1.0.0-next.74(svelte@5.19.2): dependencies: + '@floating-ui/core': 1.6.9 + '@floating-ui/dom': 1.6.13 '@internationalized/date': 3.7.0 - '@melt-ui/svelte': 0.76.2(svelte@5.19.2) - nanoid: 5.0.9 + esm-env: 1.2.2 + runed: 0.15.4(svelte@5.19.2) svelte: 5.19.2 + svelte-toolbelt: 0.4.6(svelte@5.19.2) brace-expansion@1.1.11: dependencies: @@ -6009,10 +6007,6 @@ snapshots: flatted@3.3.2: {} - focus-trap@7.6.4: - dependencies: - tabbable: 6.2.0 - for-each@0.3.3: dependencies: is-callable: 1.2.7 @@ -6174,6 +6168,8 @@ snapshots: inherits@2.0.4: {} + inline-style-parser@0.2.4: {} + is-arguments@1.2.0: dependencies: call-bound: 1.0.3 @@ -6409,8 +6405,6 @@ snapshots: nanoid@3.3.8: {} - nanoid@5.0.9: {} - natural-compare@1.4.0: {} no-case@3.0.4: @@ -6523,11 +6517,11 @@ snapshots: pirates@4.0.6: {} - playwright-core@1.49.1: {} + playwright-core@1.50.0: {} - playwright@1.49.1: + playwright@1.50.0: dependencies: - playwright-core: 1.49.1 + playwright-core: 1.50.0 optionalDependencies: fsevents: 2.3.2 @@ -6717,6 +6711,11 @@ snapshots: dependencies: queue-microtask: 1.2.3 + runed@0.15.4(svelte@5.19.2): + dependencies: + esm-env: 1.2.2 + svelte: 5.19.2 + rxjs@7.8.1: dependencies: tslib: 2.8.1 @@ -6932,6 +6931,10 @@ snapshots: strip-json-comments@3.1.1: {} + style-to-object@1.0.8: + dependencies: + inline-style-parser: 0.2.4 + sucrase@3.35.0: dependencies: '@jridgewell/gen-mapping': 0.3.8 @@ -6993,6 +6996,12 @@ snapshots: postcss-load-config: 4.0.2(postcss@8.5.1) typescript: 5.7.3 + svelte-toolbelt@0.4.6(svelte@5.19.2): + dependencies: + clsx: 2.1.1 + style-to-object: 1.0.8 + svelte: 5.19.2 + svelte2tsx@0.7.34(svelte@5.19.2)(typescript@5.7.3): dependencies: dedent-js: 1.0.1 @@ -7036,8 +7045,6 @@ snapshots: '@pkgr/core': 0.1.1 tslib: 2.8.1 - tabbable@6.2.0: {} - tailwind-merge@2.5.4: {} tailwind-merge@2.6.0: {}