@human-kit/svelte-components 1.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/combobox/TODO.md +175 -0
- package/dist/combobox/button/combobox-button.svelte +57 -0
- package/dist/combobox/button/combobox-button.svelte.d.ts +9 -0
- package/dist/combobox/index.d.ts +14 -0
- package/dist/combobox/index.js +18 -0
- package/dist/combobox/index.parts.d.ts +10 -0
- package/dist/combobox/index.parts.js +11 -0
- package/dist/combobox/input/combobox-input.svelte +98 -0
- package/dist/combobox/input/combobox-input.svelte.d.ts +13 -0
- package/dist/combobox/item/combobox-item-implicit-text-test.svelte +21 -0
- package/dist/combobox/item/combobox-item-implicit-text-test.svelte.d.ts +3 -0
- package/dist/combobox/item/combobox-listboxitem.svelte +136 -0
- package/dist/combobox/item/combobox-listboxitem.svelte.d.ts +18 -0
- package/dist/combobox/item-indicator/combobox-item-indicator.svelte +63 -0
- package/dist/combobox/item-indicator/combobox-item-indicator.svelte.d.ts +17 -0
- package/dist/combobox/list/combobox-listbox.svelte +76 -0
- package/dist/combobox/list/combobox-listbox.svelte.d.ts +47 -0
- package/dist/combobox/popover/combobox-popover.svelte +69 -0
- package/dist/combobox/popover/combobox-popover.svelte.d.ts +12 -0
- package/dist/combobox/root/combobox-filtered-test.svelte +51 -0
- package/dist/combobox/root/combobox-filtered-test.svelte.d.ts +7 -0
- package/dist/combobox/root/combobox-multiselect-test.svelte +76 -0
- package/dist/combobox/root/combobox-multiselect-test.svelte.d.ts +13 -0
- package/dist/combobox/root/combobox-numeric-string-id-test.svelte +20 -0
- package/dist/combobox/root/combobox-numeric-string-id-test.svelte.d.ts +3 -0
- package/dist/combobox/root/combobox-test.svelte +43 -0
- package/dist/combobox/root/combobox-test.svelte.d.ts +9 -0
- package/dist/combobox/root/combobox.svelte +696 -0
- package/dist/combobox/root/combobox.svelte.d.ts +58 -0
- package/dist/combobox/root/context.d.ts +90 -0
- package/dist/combobox/root/context.js +15 -0
- package/dist/combobox/tag/combobox-tag.svelte +58 -0
- package/dist/combobox/tag/combobox-tag.svelte.d.ts +22 -0
- package/dist/combobox/tag/tag-context-provider.svelte +36 -0
- package/dist/combobox/tag/tag-context-provider.svelte.d.ts +14 -0
- package/dist/combobox/tag-remove/combobox-tag-remove.svelte +53 -0
- package/dist/combobox/tag-remove/combobox-tag-remove.svelte.d.ts +14 -0
- package/dist/combobox/tags/combobox-tags.svelte +50 -0
- package/dist/combobox/tags/combobox-tags.svelte.d.ts +20 -0
- package/dist/dialog/content/dialog-content.svelte +121 -0
- package/dist/dialog/content/dialog-content.svelte.d.ts +19 -0
- package/dist/dialog/index.d.ts +10 -0
- package/dist/dialog/index.js +15 -0
- package/dist/dialog/index.parts.d.ts +5 -0
- package/dist/dialog/index.parts.js +6 -0
- package/dist/dialog/overlay/dialog-overlay.svelte +39 -0
- package/dist/dialog/overlay/dialog-overlay.svelte.d.ts +12 -0
- package/dist/dialog/portal/dialog-portal.svelte +32 -0
- package/dist/dialog/portal/dialog-portal.svelte.d.ts +12 -0
- package/dist/dialog/root/context.d.ts +25 -0
- package/dist/dialog/root/context.js +8 -0
- package/dist/dialog/root/dialog-root.svelte +99 -0
- package/dist/dialog/root/dialog-root.svelte.d.ts +21 -0
- package/dist/dialog/root/dialog-stack.d.ts +32 -0
- package/dist/dialog/root/dialog-stack.js +55 -0
- package/dist/dialog/root/dialog-test.svelte +38 -0
- package/dist/dialog/root/dialog-test.svelte.d.ts +10 -0
- package/dist/dialog/root/dialog-with-combobox-test.svelte +61 -0
- package/dist/dialog/root/dialog-with-combobox-test.svelte.d.ts +7 -0
- package/dist/dialog/root/nested-dialog-test.svelte +63 -0
- package/dist/dialog/root/nested-dialog-test.svelte.d.ts +8 -0
- package/dist/dialog/root/types.d.ts +10 -0
- package/dist/dialog/root/types.js +1 -0
- package/dist/dialog/trigger/dialog-trigger.svelte +71 -0
- package/dist/dialog/trigger/dialog-trigger.svelte.d.ts +12 -0
- package/dist/hooks/use-virtual-focus.svelte.d.ts +55 -0
- package/dist/hooks/use-virtual-focus.svelte.js +201 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +19 -0
- package/dist/input/index.d.ts +3 -0
- package/dist/input/index.js +3 -0
- package/dist/input/input.svelte +19 -0
- package/dist/input/input.svelte.d.ts +8 -0
- package/dist/label/index.d.ts +3 -0
- package/dist/label/index.js +3 -0
- package/dist/label/label.svelte +21 -0
- package/dist/label/label.svelte.d.ts +8 -0
- package/dist/listbox/index.d.ts +6 -0
- package/dist/listbox/index.js +10 -0
- package/dist/listbox/index.parts.d.ts +2 -0
- package/dist/listbox/index.parts.js +3 -0
- package/dist/listbox/item/listbox-item.svelte +186 -0
- package/dist/listbox/item/listbox-item.svelte.d.ts +34 -0
- package/dist/listbox/root/context.d.ts +73 -0
- package/dist/listbox/root/context.js +249 -0
- package/dist/listbox/root/listbox-numeric-id-test.svelte +18 -0
- package/dist/listbox/root/listbox-numeric-id-test.svelte.d.ts +3 -0
- package/dist/listbox/root/listbox-test.svelte +27 -0
- package/dist/listbox/root/listbox-test.svelte.d.ts +8 -0
- package/dist/listbox/root/listbox.svelte +146 -0
- package/dist/listbox/root/listbox.svelte.d.ts +54 -0
- package/dist/popover/content/popover-content-test.svelte +43 -0
- package/dist/popover/content/popover-content-test.svelte.d.ts +12 -0
- package/dist/popover/content/popover-content.svelte +167 -0
- package/dist/popover/content/popover-content.svelte.d.ts +38 -0
- package/dist/popover/index.d.ts +8 -0
- package/dist/popover/index.js +14 -0
- package/dist/popover/index.parts.d.ts +4 -0
- package/dist/popover/index.parts.js +5 -0
- package/dist/popover/root/context.d.ts +24 -0
- package/dist/popover/root/context.js +10 -0
- package/dist/popover/root/popover-root.svelte +87 -0
- package/dist/popover/root/popover-root.svelte.d.ts +20 -0
- package/dist/popover/root/popover-test.svelte +40 -0
- package/dist/popover/root/popover-test.svelte.d.ts +11 -0
- package/dist/popover/trigger/popover-trigger-button.svelte +42 -0
- package/dist/popover/trigger/popover-trigger-button.svelte.d.ts +12 -0
- package/dist/popover/trigger/popover-trigger-in-dialog-test.svelte +29 -0
- package/dist/popover/trigger/popover-trigger-in-dialog-test.svelte.d.ts +18 -0
- package/dist/popover/trigger/popover-trigger.svelte +71 -0
- package/dist/popover/trigger/popover-trigger.svelte.d.ts +12 -0
- package/dist/portal/index.d.ts +1 -0
- package/dist/portal/index.js +1 -0
- package/dist/portal/portal.svelte +44 -0
- package/dist/portal/portal.svelte.d.ts +10 -0
- package/dist/primitives/aria-hide-outside.d.ts +38 -0
- package/dist/primitives/aria-hide-outside.js +152 -0
- package/dist/primitives/click-outside.d.ts +26 -0
- package/dist/primitives/click-outside.js +66 -0
- package/dist/primitives/floating.d.ts +57 -0
- package/dist/primitives/floating.js +179 -0
- package/dist/primitives/focus-trap.d.ts +19 -0
- package/dist/primitives/focus-trap.js +102 -0
- package/dist/primitives/index.d.ts +6 -0
- package/dist/primitives/index.js +7 -0
- package/dist/primitives/keyboard-navigation.d.ts +88 -0
- package/dist/primitives/keyboard-navigation.js +274 -0
- package/dist/primitives/scroll-lock.d.ts +19 -0
- package/dist/primitives/scroll-lock.js +62 -0
- package/dist/test-mocks/app-environment.d.ts +7 -0
- package/dist/test-mocks/app-environment.js +7 -0
- package/dist/test-mocks/app-navigation.d.ts +11 -0
- package/dist/test-mocks/app-navigation.js +11 -0
- package/dist/test-mocks/app-stores.d.ts +16 -0
- package/dist/test-mocks/app-stores.js +18 -0
- package/dist/utils/cn.d.ts +2 -0
- package/dist/utils/cn.js +5 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/package.json +99 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
<script lang="ts" generics="T extends object = object">
|
|
2
|
+
import type { ComponentProps, Snippet } from 'svelte';
|
|
3
|
+
import { useComboBoxContext } from '../root/context';
|
|
4
|
+
import { ListBoxRoot as ListBox, type ListBoxContext } from '../../listbox';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* ComboBox.ListBox - The list wrapper with selection management.
|
|
8
|
+
* Extends ListBox props, controlling selection internally.
|
|
9
|
+
* Supports both static children and dynamic items rendering.
|
|
10
|
+
*/
|
|
11
|
+
type ComboBoxListBoxProps = Omit<
|
|
12
|
+
ComponentProps<typeof ListBox>,
|
|
13
|
+
// Props controlled internally by ComboBox
|
|
14
|
+
| 'selectionMode'
|
|
15
|
+
| 'selectionBehavior'
|
|
16
|
+
| 'value'
|
|
17
|
+
| 'defaultValue'
|
|
18
|
+
| 'onChange'
|
|
19
|
+
| 'context'
|
|
20
|
+
| 'element'
|
|
21
|
+
| 'children'
|
|
22
|
+
| 'items'
|
|
23
|
+
| 'id'
|
|
24
|
+
> & {
|
|
25
|
+
/** Optional items for dynamic rendering - overrides items from ComboBox context */
|
|
26
|
+
items?: Iterable<T>;
|
|
27
|
+
/** Content of the listbox. Receives item in dynamic mode. */
|
|
28
|
+
children?: Snippet<[T]> | Snippet;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
let {
|
|
32
|
+
'aria-label': ariaLabel = 'Options',
|
|
33
|
+
children,
|
|
34
|
+
items,
|
|
35
|
+
...props
|
|
36
|
+
}: ComboBoxListBoxProps = $props();
|
|
37
|
+
|
|
38
|
+
const ctx = useComboBoxContext();
|
|
39
|
+
let listboxCtx: ListBoxContext | undefined = $state();
|
|
40
|
+
let listboxElement: HTMLElement | undefined = $state();
|
|
41
|
+
|
|
42
|
+
// Wire listbox context to combobox context when available
|
|
43
|
+
$effect(() => {
|
|
44
|
+
if (listboxCtx) {
|
|
45
|
+
ctx.setListboxCtx(listboxCtx);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Wire listbox element ref to combobox context
|
|
50
|
+
$effect(() => {
|
|
51
|
+
if (listboxElement) {
|
|
52
|
+
ctx.setListboxRef(listboxElement);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
function handleSelectionChange(selection: Set<string | number>) {
|
|
57
|
+
const selectedId = Array.from(selection)[0];
|
|
58
|
+
if (selectedId !== undefined) {
|
|
59
|
+
const label = ctx.itemLabels.get(selectedId) ?? String(selectedId);
|
|
60
|
+
ctx.select(selectedId, label);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
</script>
|
|
64
|
+
|
|
65
|
+
<ListBox
|
|
66
|
+
{...props}
|
|
67
|
+
bind:context={listboxCtx}
|
|
68
|
+
bind:element={listboxElement}
|
|
69
|
+
id={`combobox-listbox-${ctx.instanceId}`}
|
|
70
|
+
items={items ?? (ctx.items as T[] | undefined)}
|
|
71
|
+
{children}
|
|
72
|
+
selectionMode={ctx.selectionMode}
|
|
73
|
+
value={ctx.selectedValue}
|
|
74
|
+
onChange={handleSelectionChange}
|
|
75
|
+
aria-label={ariaLabel}
|
|
76
|
+
/>
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import { type ListBoxContext } from '../../listbox';
|
|
3
|
+
declare function $$render<T extends object = object>(): {
|
|
4
|
+
props: Omit<{
|
|
5
|
+
selectionBehavior?: "toggle" | "replace";
|
|
6
|
+
emptyPlaceholder?: string | Snippet;
|
|
7
|
+
items?: Iterable<object> | undefined;
|
|
8
|
+
disabledIds?: Iterable<string | number>;
|
|
9
|
+
selectionMode?: "single" | "multiple";
|
|
10
|
+
value?: Iterable<string | number>;
|
|
11
|
+
defaultValue?: Iterable<string | number>;
|
|
12
|
+
children?: Snippet<[]> | Snippet<[object]> | undefined;
|
|
13
|
+
class?: string;
|
|
14
|
+
id?: string;
|
|
15
|
+
'aria-label'?: string;
|
|
16
|
+
onChange?: ((value: Set<string | number>) => void) | undefined;
|
|
17
|
+
} & {
|
|
18
|
+
context?: ListBoxContext;
|
|
19
|
+
element?: HTMLElement;
|
|
20
|
+
}, "selectionMode" | "selectionBehavior" | "id" | "value" | "defaultValue" | "onChange" | "items" | "children" | "context" | "element"> & {
|
|
21
|
+
/** Optional items for dynamic rendering - overrides items from ComboBox context */
|
|
22
|
+
items?: Iterable<T>;
|
|
23
|
+
/** Content of the listbox. Receives item in dynamic mode. */
|
|
24
|
+
children?: Snippet<[T]> | Snippet;
|
|
25
|
+
};
|
|
26
|
+
exports: {};
|
|
27
|
+
bindings: "";
|
|
28
|
+
slots: {};
|
|
29
|
+
events: {};
|
|
30
|
+
};
|
|
31
|
+
declare class __sveltets_Render<T extends object = object> {
|
|
32
|
+
props(): ReturnType<typeof $$render<T>>['props'];
|
|
33
|
+
events(): ReturnType<typeof $$render<T>>['events'];
|
|
34
|
+
slots(): ReturnType<typeof $$render<T>>['slots'];
|
|
35
|
+
bindings(): "";
|
|
36
|
+
exports(): {};
|
|
37
|
+
}
|
|
38
|
+
interface $$IsomorphicComponent {
|
|
39
|
+
new <T extends object = object>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
|
|
40
|
+
$$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
|
|
41
|
+
} & ReturnType<__sveltets_Render<T>['exports']>;
|
|
42
|
+
<T extends object = object>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
|
|
43
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
44
|
+
}
|
|
45
|
+
declare const ComboboxListbox: $$IsomorphicComponent;
|
|
46
|
+
type ComboboxListbox<T extends object = object> = InstanceType<typeof ComboboxListbox<T>>;
|
|
47
|
+
export default ComboboxListbox;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import { useComboBoxContext } from '../root/context';
|
|
4
|
+
import { Popover } from '../../popover';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* ComboBox.Popover - Just the floating container wrapper.
|
|
8
|
+
* Should contain ComboBox.ListBox as a child.
|
|
9
|
+
*/
|
|
10
|
+
type ComboBoxPopoverProps = {
|
|
11
|
+
class?: string;
|
|
12
|
+
children?: Snippet;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
let { class: className = '', children }: ComboBoxPopoverProps = $props();
|
|
16
|
+
|
|
17
|
+
const ctx = useComboBoxContext();
|
|
18
|
+
|
|
19
|
+
function handleOpenChange(open: boolean) {
|
|
20
|
+
ctx.onOpenChange(open);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Prevent wheel/scroll events from propagating to the page
|
|
25
|
+
* This keeps the page from scrolling when scrolling over the popover
|
|
26
|
+
* But allows internal scrolling when the popover has overflow
|
|
27
|
+
*/
|
|
28
|
+
function handleWheel(event: WheelEvent) {
|
|
29
|
+
const element = event.currentTarget as HTMLElement;
|
|
30
|
+
if (!element) return;
|
|
31
|
+
|
|
32
|
+
const { scrollTop, scrollHeight, clientHeight } = element;
|
|
33
|
+
const isScrollingDown = event.deltaY > 0;
|
|
34
|
+
const isScrollingUp = event.deltaY < 0;
|
|
35
|
+
|
|
36
|
+
// Check if we can scroll in the direction of the wheel
|
|
37
|
+
const canScrollDown = scrollTop < scrollHeight - clientHeight;
|
|
38
|
+
const canScrollUp = scrollTop > 0;
|
|
39
|
+
|
|
40
|
+
// If we can scroll internally in this direction, allow it
|
|
41
|
+
if ((isScrollingDown && canScrollDown) || (isScrollingUp && canScrollUp)) {
|
|
42
|
+
// Allow internal scroll, but stop propagation to page
|
|
43
|
+
event.stopPropagation();
|
|
44
|
+
} else {
|
|
45
|
+
// Can't scroll internally, prevent both default and propagation
|
|
46
|
+
event.preventDefault();
|
|
47
|
+
event.stopPropagation();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
$effect(() => {
|
|
52
|
+
if (ctx.isOpen) {
|
|
53
|
+
ctx.inputRef?.focus();
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
</script>
|
|
57
|
+
|
|
58
|
+
<Popover.Root open={ctx.isOpen} triggerRef={ctx.triggerRef} onOpenChange={handleOpenChange}>
|
|
59
|
+
<Popover.Content
|
|
60
|
+
isNonModal={true}
|
|
61
|
+
placement="bottom-start"
|
|
62
|
+
class={className}
|
|
63
|
+
onwheel={handleWheel}
|
|
64
|
+
>
|
|
65
|
+
{#if children}
|
|
66
|
+
{@render children()}
|
|
67
|
+
{/if}
|
|
68
|
+
</Popover.Content>
|
|
69
|
+
</Popover.Root>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
/**
|
|
3
|
+
* ComboBox.Popover - Just the floating container wrapper.
|
|
4
|
+
* Should contain ComboBox.ListBox as a child.
|
|
5
|
+
*/
|
|
6
|
+
type ComboBoxPopoverProps = {
|
|
7
|
+
class?: string;
|
|
8
|
+
children?: Snippet;
|
|
9
|
+
};
|
|
10
|
+
declare const ComboboxPopover: import("svelte").Component<ComboBoxPopoverProps, {}, "">;
|
|
11
|
+
type ComboboxPopover = ReturnType<typeof ComboboxPopover>;
|
|
12
|
+
export default ComboboxPopover;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import ComboBox from '../index';
|
|
3
|
+
|
|
4
|
+
type Props = {
|
|
5
|
+
onInputChange?: (value: string) => void;
|
|
6
|
+
trigger?: 'focus' | 'input' | 'press';
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
let { onInputChange, trigger = 'focus' }: Props = $props();
|
|
10
|
+
|
|
11
|
+
const countries = [
|
|
12
|
+
{ id: 'ar', name: 'Argentina' },
|
|
13
|
+
{ id: 'br', name: 'Brazil' },
|
|
14
|
+
{ id: 'ca', name: 'Canada' },
|
|
15
|
+
{ id: 'fr', name: 'France' },
|
|
16
|
+
{ id: 'de', name: 'Germany' },
|
|
17
|
+
{ id: 'it', name: 'Italy' },
|
|
18
|
+
{ id: 'jp', name: 'Japan' },
|
|
19
|
+
{ id: 'mx', name: 'Mexico' },
|
|
20
|
+
{ id: 'es', name: 'Spain' },
|
|
21
|
+
{ id: 'us', name: 'United States' }
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
let filterValue = $state('');
|
|
25
|
+
let selectedValue = $state<string | number | undefined>();
|
|
26
|
+
|
|
27
|
+
const filteredCountries = $derived(
|
|
28
|
+
filterValue === ''
|
|
29
|
+
? countries
|
|
30
|
+
: countries.filter((c) => c.name.toLowerCase().includes(filterValue.toLowerCase()))
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
function handleInputChange(val: string) {
|
|
34
|
+
filterValue = val;
|
|
35
|
+
onInputChange?.(val);
|
|
36
|
+
}
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<ComboBox.Root bind:value={selectedValue} {trigger} onInputChange={handleInputChange}>
|
|
40
|
+
<ComboBox.Input placeholder="Search countries..." />
|
|
41
|
+
|
|
42
|
+
<ComboBox.Popover>
|
|
43
|
+
<ComboBox.List emptyPlaceholder="No countries found">
|
|
44
|
+
{#each filteredCountries as country (country.id)}
|
|
45
|
+
<ComboBox.Item id={country.id} textValue={country.name}>
|
|
46
|
+
{country.name}
|
|
47
|
+
</ComboBox.Item>
|
|
48
|
+
{/each}
|
|
49
|
+
</ComboBox.List>
|
|
50
|
+
</ComboBox.Popover>
|
|
51
|
+
</ComboBox.Root>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
type Props = {
|
|
2
|
+
onInputChange?: (value: string) => void;
|
|
3
|
+
trigger?: 'focus' | 'input' | 'press';
|
|
4
|
+
};
|
|
5
|
+
declare const ComboboxFilteredTest: import("svelte").Component<Props, {}, "">;
|
|
6
|
+
type ComboboxFilteredTest = ReturnType<typeof ComboboxFilteredTest>;
|
|
7
|
+
export default ComboboxFilteredTest;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import ComboBox from '../index.js';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
items?: { id: string; name: string }[];
|
|
6
|
+
value?: (string | number)[];
|
|
7
|
+
onValueChange?: (value: (string | number)[]) => void;
|
|
8
|
+
trigger?: 'focus' | 'input' | 'press';
|
|
9
|
+
closeOnSelect?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let {
|
|
13
|
+
items = [
|
|
14
|
+
{ id: 'apple', name: 'Apple' },
|
|
15
|
+
{ id: 'banana', name: 'Banana' },
|
|
16
|
+
{ id: 'cherry', name: 'Cherry' },
|
|
17
|
+
{ id: 'date', name: 'Date' },
|
|
18
|
+
{ id: 'elderberry', name: 'Elderberry' }
|
|
19
|
+
],
|
|
20
|
+
value = $bindable([]),
|
|
21
|
+
onValueChange,
|
|
22
|
+
trigger = 'press',
|
|
23
|
+
closeOnSelect = false
|
|
24
|
+
}: Props = $props();
|
|
25
|
+
|
|
26
|
+
function handleChange(newValue: string | number | (string | number)[] | undefined) {
|
|
27
|
+
if (Array.isArray(newValue)) {
|
|
28
|
+
onValueChange?.(newValue);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<ComboBox.Root
|
|
34
|
+
bind:value
|
|
35
|
+
selectionMode="multiple"
|
|
36
|
+
{trigger}
|
|
37
|
+
{closeOnSelect}
|
|
38
|
+
onChange={handleChange}
|
|
39
|
+
>
|
|
40
|
+
<div class="combobox-container">
|
|
41
|
+
<ComboBox.Tags>
|
|
42
|
+
{#snippet children({ item })}
|
|
43
|
+
<ComboBox.Tag>
|
|
44
|
+
{item.label}
|
|
45
|
+
<ComboBox.TagRemove />
|
|
46
|
+
</ComboBox.Tag>
|
|
47
|
+
{/snippet}
|
|
48
|
+
</ComboBox.Tags>
|
|
49
|
+
<ComboBox.Input placeholder="Search fruits..." />
|
|
50
|
+
<ComboBox.Button>▼</ComboBox.Button>
|
|
51
|
+
</div>
|
|
52
|
+
|
|
53
|
+
<ComboBox.Popover>
|
|
54
|
+
<ComboBox.List>
|
|
55
|
+
{#each items as item (item.id)}
|
|
56
|
+
<ComboBox.Item id={item.id} textValue={item.name}>
|
|
57
|
+
{item.name}
|
|
58
|
+
<ComboBox.ItemIndicator />
|
|
59
|
+
</ComboBox.Item>
|
|
60
|
+
{/each}
|
|
61
|
+
</ComboBox.List>
|
|
62
|
+
</ComboBox.Popover>
|
|
63
|
+
</ComboBox.Root>
|
|
64
|
+
|
|
65
|
+
<style>
|
|
66
|
+
.combobox-container {
|
|
67
|
+
display: flex;
|
|
68
|
+
flex-wrap: wrap;
|
|
69
|
+
align-items: center;
|
|
70
|
+
gap: 4px;
|
|
71
|
+
border: 1px solid #ccc;
|
|
72
|
+
border-radius: 4px;
|
|
73
|
+
padding: 4px;
|
|
74
|
+
min-height: 38px;
|
|
75
|
+
}
|
|
76
|
+
</style>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
items?: {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
}[];
|
|
6
|
+
value?: (string | number)[];
|
|
7
|
+
onValueChange?: (value: (string | number)[]) => void;
|
|
8
|
+
trigger?: 'focus' | 'input' | 'press';
|
|
9
|
+
closeOnSelect?: boolean;
|
|
10
|
+
}
|
|
11
|
+
declare const ComboboxMultiselectTest: import("svelte").Component<Props, {}, "value">;
|
|
12
|
+
type ComboboxMultiselectTest = ReturnType<typeof ComboboxMultiselectTest>;
|
|
13
|
+
export default ComboboxMultiselectTest;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { ComboBox } from '../index';
|
|
3
|
+
|
|
4
|
+
let selected = $state<string | number | undefined>();
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<ComboBox.Root bind:value={selected}>
|
|
8
|
+
<ComboBox.Input placeholder="Search codes..." />
|
|
9
|
+
<ComboBox.Button />
|
|
10
|
+
|
|
11
|
+
<ComboBox.Popover>
|
|
12
|
+
<ComboBox.List emptyPlaceholder="No codes found">
|
|
13
|
+
<ComboBox.Item id="01" textValue="Code 01">Code 01</ComboBox.Item>
|
|
14
|
+
<ComboBox.Item id="02" textValue="Code 02">Code 02</ComboBox.Item>
|
|
15
|
+
</ComboBox.List>
|
|
16
|
+
</ComboBox.Popover>
|
|
17
|
+
</ComboBox.Root>
|
|
18
|
+
|
|
19
|
+
<div data-testid="selected">{selected === undefined ? '' : String(selected)}</div>
|
|
20
|
+
<div data-testid="selected-type">{selected === undefined ? '' : typeof selected}</div>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import ComboBox from '../index';
|
|
3
|
+
|
|
4
|
+
type Props = {
|
|
5
|
+
id?: string;
|
|
6
|
+
isDisabled?: boolean;
|
|
7
|
+
isReadOnly?: boolean;
|
|
8
|
+
trigger?: 'focus' | 'input' | 'press';
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
let { id, isDisabled = false, isReadOnly = false, trigger = 'press' }: Props = $props();
|
|
12
|
+
|
|
13
|
+
const countries = [
|
|
14
|
+
{ id: 'ar', name: 'Argentina' },
|
|
15
|
+
{ id: 'br', name: 'Brazil' },
|
|
16
|
+
{ id: 'ca', name: 'Canada' },
|
|
17
|
+
{ id: 'fr', name: 'France' },
|
|
18
|
+
{ id: 'de', name: 'Germany' },
|
|
19
|
+
{ id: 'it', name: 'Italy' },
|
|
20
|
+
{ id: 'jp', name: 'Japan' },
|
|
21
|
+
{ id: 'mx', name: 'Mexico' },
|
|
22
|
+
{ id: 'es', name: 'Spain' },
|
|
23
|
+
{ id: 'us', name: 'United States' }
|
|
24
|
+
];
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<ComboBox.Root {id} {isDisabled} {isReadOnly} {trigger}>
|
|
28
|
+
<ComboBox.Input placeholder="Search countries..." />
|
|
29
|
+
<ComboBox.Button />
|
|
30
|
+
|
|
31
|
+
<ComboBox.Popover>
|
|
32
|
+
<ComboBox.List emptyPlaceholder="No countries found">
|
|
33
|
+
{#each countries as country (country.id)}
|
|
34
|
+
<ComboBox.Item id={country.id} textValue={country.name}>
|
|
35
|
+
{country.name}
|
|
36
|
+
</ComboBox.Item>
|
|
37
|
+
{/each}
|
|
38
|
+
</ComboBox.List>
|
|
39
|
+
</ComboBox.Popover>
|
|
40
|
+
</ComboBox.Root>
|
|
41
|
+
|
|
42
|
+
<!-- Button outside the combobox for testing blur behavior -->
|
|
43
|
+
<button type="button" data-testid="outside-button">Outside</button>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
type Props = {
|
|
2
|
+
id?: string;
|
|
3
|
+
isDisabled?: boolean;
|
|
4
|
+
isReadOnly?: boolean;
|
|
5
|
+
trigger?: 'focus' | 'input' | 'press';
|
|
6
|
+
};
|
|
7
|
+
declare const ComboboxTest: import("svelte").Component<Props, {}, "">;
|
|
8
|
+
type ComboboxTest = ReturnType<typeof ComboboxTest>;
|
|
9
|
+
export default ComboboxTest;
|