diff --git a/package.json b/package.json index 5504f708..57b3a145 100644 --- a/package.json +++ b/package.json @@ -306,6 +306,10 @@ "types": "./dist/forms/search/Search.svelte.d.ts", "svelte": "./dist/forms/search/Search.svelte" }, + "./MultiSelect.svelte": { + "types": "./dist/forms/select/MultiSelect.svelte.d.ts", + "svelte": "./dist/forms/select/MultiSelect.svelte" + }, "./Select.svelte": { "types": "./dist/forms/select/Select.svelte.d.ts", "svelte": "./dist/forms/select/Select.svelte" diff --git a/src/lib/forms/select/MultiSelect.svelte b/src/lib/forms/select/MultiSelect.svelte new file mode 100644 index 00000000..fb71f527 --- /dev/null +++ b/src/lib/forms/select/MultiSelect.svelte @@ -0,0 +1,129 @@ + + + + + +{#snippet defaultBadge({ item, clear, disabled }: { item: T, clear: () => void, disabled: boolean })} + + {item.name} + +{/snippet} + +
show = !disabled && !show} onfocusout={() => show = false} {onkeydown} tabindex="0" role="listbox" class={multiSelectClass}> + {#if !selectedItems.length} + {placeholder} + {/if} + + {#each selectedItems as item (item.value)} + {@render badge({ item, clear: () => clearOption(item), disabled: item.disabled || disabled })} + {/each} + +
+ {#if selectedItems.length} + + {/if} +
+ +
+ + {#if show} +
(e.stopPropagation(), onclick?.(e))} role="presentation" class={multiSelectDropdown}> + {#each items as item (item.value)} +
selectOption(item)} role="presentation" class={twMerge(itemsClass, selectedItems.includes(item) && itemsSelectedClass, activeItem === item && activeItemClass, item.disabled && disabledItemClass)}> + {item.name} +
+ {/each} +
+ {/if} +
diff --git a/src/lib/forms/select/Select.svelte b/src/lib/forms/select/Select.svelte index da4419f4..06a617ef 100644 --- a/src/lib/forms/select/Select.svelte +++ b/src/lib/forms/select/Select.svelte @@ -1,7 +1,7 @@ - @@ -12,8 +12,8 @@ {/if} {#if items} - {#each items as { value, name }} - + {#each items as { value, name, disabled }} + {/each} {/if} diff --git a/src/lib/forms/select/index.ts b/src/lib/forms/select/index.ts index 04f551ea..437b6053 100644 --- a/src/lib/forms/select/index.ts +++ b/src/lib/forms/select/index.ts @@ -1,30 +1,33 @@ import Select from './Select.svelte'; import type { Snippet } from 'svelte'; import type { HTMLSelectAttributes, HTMLAttributes } from 'svelte/elements'; -import { select } from './theme'; +import { select, multiSelect } from './theme'; type SelectOptionType = { name: string | number; value: T; + disabled?: boolean; }; -interface SelectProps extends Omit { +interface SelectProps extends Omit { children?: Snippet; - items?: SelectOptionType[]; - value?: any; + items?: SelectOptionType[]; + value?: T; underline?: boolean; size?: 'sm' | 'md' | 'lg'; placeholder?: string; } -interface MultiSelectProps extends HTMLAttributes { - children?: Snippet; - items?: SelectOptionType[]; - value?: (string | number)[]; +interface MultiSelectProps> extends Omit, "children" | "onclick"> { + badge?: Snippet<[{ item: T, clear: () => void, disabled: boolean }]>; + items: T[]; + value?: V[]; size?: 'sm' | 'md' | 'lg'; + disabled?: boolean; dropdownClass?: string; placeholder?: string; change?: (event: Event) => void; + onclick?: (event: MouseEvent & { currentTarget: EventTarget & HTMLDivElement }) => void; } -export { Select, select, type SelectProps, type SelectOptionType, type MultiSelectProps }; +export { Select, select, multiSelect, type SelectProps, type SelectOptionType, type MultiSelectProps }; diff --git a/src/lib/forms/select/theme.ts b/src/lib/forms/select/theme.ts index a987f3f0..19372579 100644 --- a/src/lib/forms/select/theme.ts +++ b/src/lib/forms/select/theme.ts @@ -18,3 +18,21 @@ export const select = tv({ size: 'md' } }); + +export const multiSelect = tv({ + variants: { + size: { + sm: 'px-2 py-1 min-h-[2.4rem]', + md: 'px-3 py-1 min-h-[2.7rem]', + lg: 'px-4 py-2 min-h-[3.2rem]' + }, + disabled: { + true: 'opacity-50 cursor-not-allowed', + false: 'focus-within:ring-1 focus-within:border-primary-500 dark:focus-within:border-primary-500' + } + }, + defaultVariants: { + size: 'md', + disabled: false + } +}); diff --git a/src/routes/forms/select/+page.svelte b/src/routes/forms/select/+page.svelte index 20e0e3f2..b89e90db 100644 --- a/src/routes/forms/select/+page.svelte +++ b/src/routes/forms/select/+page.svelte @@ -1,6 +1,6 @@ + + + {#snippet badge({ item, clear })} + + {item.name} + + {/snippet} + \ No newline at end of file diff --git a/src/routes/forms/select/md/default-multiselect.md b/src/routes/forms/select/md/default-multiselect.md new file mode 100644 index 00000000..f0037295 --- /dev/null +++ b/src/routes/forms/select/md/default-multiselect.md @@ -0,0 +1,14 @@ + + \ No newline at end of file diff --git a/src/routes/forms/select/md/disabled-multiselect.md b/src/routes/forms/select/md/disabled-multiselect.md new file mode 100644 index 00000000..a6312377 --- /dev/null +++ b/src/routes/forms/select/md/disabled-multiselect.md @@ -0,0 +1,12 @@ + + \ No newline at end of file diff --git a/src/routes/forms/select/md/disabled-options-multiselect.md b/src/routes/forms/select/md/disabled-options-multiselect.md new file mode 100644 index 00000000..bae1bd11 --- /dev/null +++ b/src/routes/forms/select/md/disabled-options-multiselect.md @@ -0,0 +1,10 @@ + + \ No newline at end of file diff --git a/src/routes/forms/select/md/multiselect-preselect.md b/src/routes/forms/select/md/multiselect-preselect.md new file mode 100644 index 00000000..135554c3 --- /dev/null +++ b/src/routes/forms/select/md/multiselect-preselect.md @@ -0,0 +1,14 @@ + + \ No newline at end of file diff --git a/src/routes/forms/select/md/setup.md b/src/routes/forms/select/md/setup.md index 92284d8c..19b06755 100644 --- a/src/routes/forms/select/md/setup.md +++ b/src/routes/forms/select/md/setup.md @@ -1,6 +1,6 @@