@svelte-atoms/core 1.0.0-alpha.32 → 1.0.0-alpha.34

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.
Files changed (127) hide show
  1. package/dist/components/atom/html-atom.svelte +95 -93
  2. package/dist/components/atom/html-atom.svelte.d.ts +1 -1
  3. package/dist/components/button/button.svelte +31 -31
  4. package/dist/components/chip/chip.svelte +41 -0
  5. package/dist/components/chip/chip.svelte.d.ts +6 -0
  6. package/dist/components/chip/index.d.ts +1 -0
  7. package/dist/components/chip/index.js +1 -0
  8. package/dist/components/chip/types.d.ts +11 -0
  9. package/dist/components/chip/types.js +1 -0
  10. package/dist/components/combobox/atoms.d.ts +2 -1
  11. package/dist/components/combobox/atoms.js +2 -1
  12. package/dist/components/combobox/bond.svelte.d.ts +16 -13
  13. package/dist/components/combobox/bond.svelte.js +57 -13
  14. package/dist/components/combobox/combobox-control.svelte +27 -13
  15. package/dist/components/combobox/combobox-control.svelte.d.ts +2 -10
  16. package/dist/components/combobox/combobox-item.svelte +3 -3
  17. package/dist/components/combobox/combobox-root.svelte +65 -65
  18. package/dist/components/combobox/combobox-root.svelte.d.ts +4 -4
  19. package/dist/components/combobox/combobox-selections.svelte +17 -0
  20. package/dist/components/combobox/combobox-selections.svelte.d.ts +4 -0
  21. package/dist/components/combobox/combobox.stories.svelte +25 -12
  22. package/dist/components/combobox/types.d.ts +17 -3
  23. package/dist/components/date-picker/bond.svelte.js +2 -1
  24. package/dist/components/date-picker/date-picker-calendar.svelte +60 -67
  25. package/dist/components/dropdown/atoms.d.ts +2 -3
  26. package/dist/components/dropdown/atoms.js +3 -3
  27. package/dist/components/dropdown/bond.svelte.d.ts +4 -4
  28. package/dist/components/dropdown/bond.svelte.js +10 -11
  29. package/dist/components/dropdown/dropdown-query.svelte +43 -54
  30. package/dist/components/dropdown/dropdown-query.svelte.d.ts +3 -34
  31. package/dist/components/dropdown/dropdown-root.svelte +15 -2
  32. package/dist/components/dropdown/dropdown-root.svelte.d.ts +4 -16
  33. package/dist/components/dropdown/dropdown-selection.svelte +55 -0
  34. package/dist/components/dropdown/{dropdown-value.svelte.d.ts → dropdown-selection.svelte.d.ts} +5 -15
  35. package/dist/components/dropdown/dropdown-selections.svelte +62 -0
  36. package/dist/components/dropdown/dropdown-selections.svelte.d.ts +5 -0
  37. package/dist/components/dropdown/dropdown.stories.svelte +93 -49
  38. package/dist/components/dropdown/index.d.ts +5 -1
  39. package/dist/components/dropdown/index.js +5 -1
  40. package/dist/components/dropdown/item/controller.svelte.d.ts +1 -1
  41. package/dist/components/dropdown/item/controller.svelte.js +2 -2
  42. package/dist/components/dropdown/item/dropdown-item.svelte +0 -2
  43. package/dist/components/dropdown/runes.svelte.d.ts +6 -2
  44. package/dist/components/dropdown/runes.svelte.js +1 -1
  45. package/dist/components/dropdown/types.d.ts +34 -2
  46. package/dist/components/index.d.ts +2 -0
  47. package/dist/components/index.js +2 -0
  48. package/dist/components/menu/bond.svelte.js +4 -2
  49. package/dist/components/menu/item/controller.svelte.d.ts +1 -0
  50. package/dist/components/menu/item/controller.svelte.js +5 -0
  51. package/dist/components/popover/bond.svelte.js +1 -2
  52. package/dist/components/root/root.css +119 -119
  53. package/dist/components/stepper/README.md +38 -0
  54. package/dist/components/stepper/atoms.d.ts +5 -0
  55. package/dist/components/stepper/atoms.js +5 -0
  56. package/dist/components/stepper/attachments.svelte.d.ts +2 -0
  57. package/dist/components/stepper/attachments.svelte.js +5 -0
  58. package/dist/components/stepper/bond.svelte.d.ts +56 -0
  59. package/dist/components/stepper/bond.svelte.js +99 -0
  60. package/dist/components/stepper/index.d.ts +3 -0
  61. package/dist/components/stepper/index.js +3 -0
  62. package/dist/components/stepper/step/README.md +97 -0
  63. package/dist/components/stepper/step/atoms.d.ts +7 -0
  64. package/dist/components/stepper/step/atoms.js +7 -0
  65. package/dist/components/stepper/step/attachments.svelte.d.ts +2 -0
  66. package/dist/components/stepper/step/attachments.svelte.js +5 -0
  67. package/dist/components/stepper/step/bond.svelte.d.ts +99 -0
  68. package/dist/components/stepper/step/bond.svelte.js +153 -0
  69. package/dist/components/stepper/step/index.d.ts +3 -0
  70. package/dist/components/stepper/step/index.js +2 -0
  71. package/dist/components/stepper/step/step-body.svelte +39 -0
  72. package/dist/components/stepper/step/step-body.svelte.d.ts +26 -0
  73. package/dist/components/stepper/step/step-description.svelte +33 -0
  74. package/dist/components/stepper/step/step-description.svelte.d.ts +26 -0
  75. package/dist/components/stepper/step/step-header.svelte +34 -0
  76. package/dist/components/stepper/step/step-header.svelte.d.ts +26 -0
  77. package/dist/components/stepper/step/step-indicator.svelte +63 -0
  78. package/dist/components/stepper/step/step-indicator.svelte.d.ts +26 -0
  79. package/dist/components/stepper/step/step-root.svelte +42 -0
  80. package/dist/components/stepper/step/step-root.svelte.d.ts +31 -0
  81. package/dist/components/stepper/step/step-separator.svelte +48 -0
  82. package/dist/components/stepper/step/step-separator.svelte.d.ts +26 -0
  83. package/dist/components/stepper/step/step-title.svelte +33 -0
  84. package/dist/components/stepper/step/step-title.svelte.d.ts +26 -0
  85. package/dist/components/stepper/step/types.d.ts +91 -0
  86. package/dist/components/stepper/step/types.js +1 -0
  87. package/dist/components/stepper/stepper-body.svelte +43 -0
  88. package/dist/components/stepper/stepper-body.svelte.d.ts +26 -0
  89. package/dist/components/stepper/stepper-content.svelte +45 -0
  90. package/dist/components/stepper/stepper-content.svelte.d.ts +26 -0
  91. package/dist/components/stepper/stepper-footer.svelte +31 -0
  92. package/dist/components/stepper/stepper-footer.svelte.d.ts +26 -0
  93. package/dist/components/stepper/stepper-header.svelte +39 -0
  94. package/dist/components/stepper/stepper-header.svelte.d.ts +26 -0
  95. package/dist/components/stepper/stepper-root.svelte +60 -0
  96. package/dist/components/stepper/stepper-root.svelte.d.ts +31 -0
  97. package/dist/components/stepper/stepper.stories.svelte +264 -0
  98. package/dist/components/stepper/stepper.stories.svelte.d.ts +4 -0
  99. package/dist/components/stepper/types.d.ts +63 -0
  100. package/dist/components/stepper/types.js +1 -0
  101. package/dist/components/tabs/atoms.d.ts +1 -0
  102. package/dist/components/tabs/atoms.js +1 -0
  103. package/dist/components/tabs/bond.svelte.d.ts +18 -5
  104. package/dist/components/tabs/bond.svelte.js +13 -0
  105. package/dist/components/tabs/tab/bond.svelte.d.ts +7 -7
  106. package/dist/components/tabs/tab/bond.svelte.js +9 -15
  107. package/dist/components/tabs/tab/tab-body.svelte +43 -52
  108. package/dist/components/tabs/tab/tab-description.svelte +33 -41
  109. package/dist/components/tabs/tab/tab-header.svelte +61 -71
  110. package/dist/components/tabs/tab/tab-header.svelte.d.ts +1 -1
  111. package/dist/components/tabs/tab/tab-root.svelte +51 -86
  112. package/dist/components/tabs/tab/tab-root.svelte.d.ts +1 -7
  113. package/dist/components/tabs/tabs-body.svelte +35 -41
  114. package/dist/components/tabs/tabs-body.svelte.d.ts +2 -11
  115. package/dist/components/tabs/tabs-content.svelte +51 -0
  116. package/dist/components/tabs/tabs-content.svelte.d.ts +26 -0
  117. package/dist/components/tabs/tabs-header.svelte +32 -40
  118. package/dist/components/tabs/tabs-header.svelte.d.ts +2 -10
  119. package/dist/components/tabs/tabs-root.svelte +55 -66
  120. package/dist/components/tabs/tabs-root.svelte.d.ts +5 -16
  121. package/dist/components/tabs/tabs.stories.svelte +70 -56
  122. package/dist/components/tabs/types.d.ts +24 -29
  123. package/dist/context/preset.svelte.d.ts +1 -1
  124. package/package.json +33 -6
  125. package/dist/components/dropdown/dropdown-value.svelte +0 -60
  126. package/dist/components/dropdown/dropdown-values.svelte +0 -17
  127. package/dist/components/dropdown/dropdown-values.svelte.d.ts +0 -5
@@ -1,11 +1,14 @@
1
1
  <script lang="ts" generics="T">
2
2
  import { defineProperty, defineState } from '../../utils';
3
3
  import { DropdownBond, DropdownBondState, type DropdownStateProps } from './bond.svelte';
4
+ import type { DropdownRootProps } from './types';
4
5
 
5
6
  let {
6
7
  open = $bindable(false),
7
8
  value = $bindable(),
8
9
  values = $bindable(),
10
+ labels = $bindable(),
11
+ label = $bindable(),
9
12
  multiple = false,
10
13
  disabled = false,
11
14
  placements = ['bottom-start', 'bottom-end', 'top-start', 'top-end'],
@@ -16,7 +19,7 @@
16
19
  children = undefined,
17
20
  onquerychange = undefined,
18
21
  ...restProps
19
- } = $props();
22
+ }: DropdownRootProps<T> = $props();
20
23
 
21
24
  const bondProps = defineState<DropdownStateProps>(
22
25
  [
@@ -35,6 +38,16 @@
35
38
  value = v[0];
36
39
  }
37
40
  ),
41
+ defineProperty(
42
+ 'label',
43
+ () => label,
44
+ (v) => (label = v)
45
+ ),
46
+ defineProperty(
47
+ 'labels',
48
+ () => labels,
49
+ (v) => (labels = v)
50
+ ),
38
51
  defineProperty('multiple', () => multiple),
39
52
  defineProperty('disabled', () => disabled),
40
53
  defineProperty('placement', () => placement),
@@ -42,7 +55,7 @@
42
55
  defineProperty('placements', () => placements ?? []),
43
56
  defineProperty('keys', () => keys ?? [])
44
57
  ],
45
- () => ({ onquerychange })
58
+ () => ({})
46
59
  );
47
60
  const bond = factory(bondProps).share();
48
61
 
@@ -1,23 +1,11 @@
1
1
  import { DropdownBond, DropdownBondState, type DropdownStateProps } from './bond.svelte';
2
+ import type { DropdownRootProps } from './types';
2
3
  declare function $$render<T>(): {
3
- props: {
4
- open?: boolean;
5
- value?: any;
6
- values?: any;
7
- multiple?: boolean;
8
- disabled?: boolean;
9
- placements?: any[];
10
- placement?: string;
11
- offset?: number;
12
- keys?: any[];
13
- factory?: (props: DropdownStateProps) => DropdownBond<DropdownStateProps, DropdownBondState<DropdownStateProps>, import("./bond.svelte").DropdownBondElements>;
14
- children?: any;
15
- onquerychange?: any;
16
- } & Record<string, any>;
4
+ props: DropdownRootProps<T>;
17
5
  exports: {
18
6
  getBond: () => DropdownBond<DropdownStateProps, DropdownBondState<DropdownStateProps>, import("./bond.svelte").DropdownBondElements>;
19
7
  };
20
- bindings: "values" | "value" | "open";
8
+ bindings: "values" | "value" | "label" | "open" | "labels";
21
9
  slots: {};
22
10
  events: {};
23
11
  };
@@ -25,7 +13,7 @@ declare class __sveltets_Render<T> {
25
13
  props(): ReturnType<typeof $$render<T>>['props'];
26
14
  events(): ReturnType<typeof $$render<T>>['events'];
27
15
  slots(): ReturnType<typeof $$render<T>>['slots'];
28
- bindings(): "values" | "value" | "open";
16
+ bindings(): "values" | "value" | "label" | "open" | "labels";
29
17
  exports(): {
30
18
  getBond: () => DropdownBond<DropdownStateProps, DropdownBondState<DropdownStateProps>, import("./bond.svelte").DropdownBondElements>;
31
19
  };
@@ -0,0 +1,55 @@
1
+ <script lang="ts" generics="T extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base">
2
+ import { type Base } from '../atom';
3
+ import { DropdownBond } from './bond.svelte';
4
+ import type { DropdownSelectionProps } from './types';
5
+ import { Chip } from '../chip';
6
+ import { HtmlAtom as Atom } from '../atom';
7
+
8
+ const bond = DropdownBond.get();
9
+
10
+ if (!bond) {
11
+ throw new Error('DropdownValue must be used within a Dropdown');
12
+ }
13
+
14
+ const isMultiple = $derived(bond.state.props.multiple);
15
+
16
+ let {
17
+ class: klass = '',
18
+ as = 'div' as T,
19
+ base = undefined,
20
+ selection,
21
+ children,
22
+ onclose,
23
+ ...restProps
24
+ }: DropdownSelectionProps<T, B> = $props();
25
+
26
+ const _base = $derived((base ?? isMultiple) ? Chip : undefined);
27
+
28
+ function handleClose(ev: Event) {
29
+ onclose?.(ev);
30
+
31
+ if (ev.defaultPrevented) return;
32
+
33
+ selection.unselect();
34
+ }
35
+ </script>
36
+
37
+ <Atom
38
+ {as}
39
+ {bond}
40
+ base={_base}
41
+ preset="dropdown.value"
42
+ class={[
43
+ 'dropdown-value border-border inline-flex h-6 flex-nowrap items-center gap-1 rounded-sm px-2 whitespace-nowrap',
44
+ '$preset',
45
+ klass
46
+ ]}
47
+ onclose={handleClose}
48
+ {...restProps}
49
+ >
50
+ {#if children}
51
+ {@render children?.()}
52
+ {:else}
53
+ {selection.label}
54
+ {/if}
55
+ </Atom>
@@ -1,17 +1,7 @@
1
1
  import { type Base } from '../atom';
2
+ import type { DropdownSelectionProps } from './types';
2
3
  declare function $$render<T extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base>(): {
3
- props: {
4
- class?: string;
5
- as?: T;
6
- value: any;
7
- children: any;
8
- onmount?: any;
9
- ondestroy?: any;
10
- animate?: any;
11
- enter?: any;
12
- exit?: any;
13
- initial?: any;
14
- } & Record<string, any>;
4
+ props: DropdownSelectionProps<T, B>;
15
5
  exports: {};
16
6
  bindings: "";
17
7
  slots: {};
@@ -31,6 +21,6 @@ interface $$IsomorphicComponent {
31
21
  <T extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base>(internal: unknown, props: ReturnType<__sveltets_Render<T, B>['props']> & {}): ReturnType<__sveltets_Render<T, B>['exports']>;
32
22
  z_$$bindings?: ReturnType<__sveltets_Render<any, any>['bindings']>;
33
23
  }
34
- declare const DropdownValue: $$IsomorphicComponent;
35
- type DropdownValue<T extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base> = InstanceType<typeof DropdownValue<T, B>>;
36
- export default DropdownValue;
24
+ declare const DropdownSelection: $$IsomorphicComponent;
25
+ type DropdownSelection<T extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base> = InstanceType<typeof DropdownSelection<T, B>>;
26
+ export default DropdownSelection;
@@ -0,0 +1,62 @@
1
+ <script lang="ts">
2
+ import { HtmlAtom as Atom } from '../atom';
3
+ import DropdownSelection from './dropdown-selection.svelte';
4
+ import { DropdownBond } from './bond.svelte';
5
+ import type { DropdownSelectionsProps } from './types';
6
+ import type { Component } from 'svelte';
7
+
8
+ const bond = DropdownBond.get();
9
+
10
+ if (!bond) {
11
+ throw new Error('DropdownValue must be used within a Dropdown');
12
+ }
13
+
14
+ let {
15
+ class: klass = '',
16
+ children,
17
+ getSelections = undefined,
18
+ Selection = DropdownSelection as unknown as Component,
19
+ ...restProps
20
+ }: DropdownSelectionsProps = $props();
21
+
22
+ const selections = $derived.by(() => {
23
+ if (getSelections) {
24
+ return getSelections(bond);
25
+ }
26
+
27
+ return bond.state.selections.map((controller) => ({
28
+ id: controller.id,
29
+ value: controller.value,
30
+ get label() {
31
+ return controller.label;
32
+ },
33
+ unselect() {
34
+ controller.unselect();
35
+ },
36
+ get createdAt() {
37
+ return controller.createdAt;
38
+ },
39
+ controller
40
+ }));
41
+ });
42
+ const isMultiple = $derived(bond.state.props.multiple);
43
+ </script>
44
+
45
+ {#if isMultiple && selections.length}
46
+ <Atom class={['flex flex-wrap items-center gap-2', klass]} {...restProps}>
47
+ {#if children}
48
+ {@render children?.({ selections: selections, selection: selections[0] })}
49
+ {:else}
50
+ {#each selections as selection (selection.id)}
51
+ <Selection {selection}>
52
+ {selection.label}
53
+ </Selection>
54
+ {/each}
55
+ {/if}
56
+ </Atom>
57
+ {:else if children && selections[0]}
58
+ {@render children?.({ selections: selections, selection: selections[0] })}
59
+ {:else if selections[0]}
60
+ {@const selection = selections[0]}
61
+ {selection.label}
62
+ {/if}
@@ -0,0 +1,5 @@
1
+ import type { DropdownSelectionsProps } from './types';
2
+ import type { Component } from 'svelte';
3
+ declare const DropdownSelections: Component<DropdownSelectionsProps, {}, "">;
4
+ type DropdownSelections = ReturnType<typeof DropdownSelections>;
5
+ export default DropdownSelections;
@@ -3,7 +3,7 @@
3
3
  import { Dropdown as ADropdown } from '.';
4
4
  import { Input } from '../input';
5
5
  import { flip } from 'svelte/animate';
6
- import { filter } from './runes.svelte';
6
+ import { filterDropdownData } from './runes.svelte';
7
7
 
8
8
  // More on how to set up stories at: https://storybook.js.org/docs/writing-stories
9
9
  const { Story } = defineMeta({
@@ -22,62 +22,106 @@
22
22
  let open = $state(false);
23
23
 
24
24
  const data = $state([
25
- { id: 1, value: 'apple', text: 'Apple' },
26
- { id: 2, value: 'banana', text: 'Banana' },
27
- { id: 3, value: 'cherry', text: 'Cherry' },
28
- { id: 4, value: 'date', text: 'Date' },
29
- { id: 5, value: 'elderberry', text: 'Elderberry' }
25
+ { id: 1, value: 'apple', label: 'Apple' },
26
+ { id: 2, value: 'banana', label: 'Banana' },
27
+ { id: 3, value: 'cherry', label: 'Cherry' },
28
+ { id: 4, value: 'date', label: 'Date' },
29
+ { id: 5, value: 'elderberry', label: 'Elderberry' }
30
30
  ]);
31
31
 
32
- const dd = filter(
32
+ const dd = filterDropdownData(
33
33
  () => data,
34
- (query, item) => item.text.toLowerCase().includes(query.toLowerCase())
34
+ (query, item) => item.label.toLowerCase().includes(query.toLowerCase())
35
35
  );
36
36
  </script>
37
37
 
38
38
  <Story name="Dropdown" args={{}}>
39
39
  <!-- Multi-select dropdown with search functionality -->
40
- <ADropdown.Root
41
- bind:open
42
- keys={data.map((item) => item.value)}
43
- multiple
44
- onquerychange={(q) => (dd.query = q)}
45
- >
46
- {#snippet children({ dropdown })}
47
- <!-- Compose ADropdown.Trigger with Input.Root for a custom trigger -->
48
- <ADropdown.Trigger
49
- base={Input.Root}
50
- class="flex h-auto min-h-12 max-w-sm min-w-sm flex-col items-start gap-1 rounded-sm px-4 transition-colors duration-200"
51
- onclick={(ev) => {
52
- ev.preventDefault();
40
+ <div class="flex flex-col gap-4">
41
+ <ADropdown.Root bind:open keys={data.map((item) => item.value)} multiple>
42
+ {#snippet children({ dropdown })}
43
+ <!-- Compose ADropdown.Trigger with Input.Root for a custom trigger -->
44
+ <ADropdown.Trigger
45
+ base={Input.Root}
46
+ class="flex h-auto min-h-12 max-w-sm min-w-sm flex-col items-start gap-1 rounded-sm px-4 transition-colors duration-200"
47
+ onclick={(ev) => {
48
+ ev.preventDefault();
53
49
 
54
- dropdown.state.open();
55
- }}
56
- >
57
- <!-- Inline search input within the trigger -->
58
- <ADropdown.Query class="flex-1 px-1" placeholder="Search for fruits..." />
59
- <!-- Display selected values with animation -->
60
- {#if dropdown?.state?.selectedItems?.length}
61
- <div class="flex flex-wrap gap-1">
62
- {#each dropdown?.state?.selectedItems ?? [] as item (item.id)}
63
- <div animate:flip={{ duration: 200 }}>
64
- <ADropdown.Value value={item.value} class="text-foreground/80">
65
- {item.text}
66
- </ADropdown.Value>
67
- </div>
68
- {/each}
69
- </div>
70
- {/if}
71
- </ADropdown.Trigger>
50
+ dropdown.state.open();
51
+ }}
52
+ >
53
+ <!-- Inline search input within the trigger -->
54
+ <input
55
+ class="w-full flex-1 px-1 outline-none"
56
+ placeholder="Search for fruits..."
57
+ bind:value={dd.query}
58
+ />
72
59
 
73
- <!-- ADropdown list with filtered items -->
74
- <ADropdown.List>
75
- {#each dd.current as item (item.id)}
76
- <div animate:flip={{ duration: 200 }}>
77
- <ADropdown.Item value={item.value}>{item.text}</ADropdown.Item>
78
- </div>
79
- {/each}
80
- </ADropdown.List>
81
- {/snippet}
82
- </ADropdown.Root>
60
+ <!-- Default usage -->
61
+ <!-- <ADropdown.Selections class="flex flex-wrap gap-1" /> -->
62
+
63
+ <!-- Display selected values with animation -->
64
+ <ADropdown.Selections class="flex flex-wrap gap-1">
65
+ {#snippet children({ selections })}
66
+ {#each selections as selection (selection.id)}
67
+ <div animate:flip={{ duration: 200 }}>
68
+ <ADropdown.Selection {selection} />
69
+ </div>
70
+ {/each}
71
+ {/snippet}
72
+ </ADropdown.Selections>
73
+ </ADropdown.Trigger>
74
+
75
+ <!-- ADropdown list with filtered items -->
76
+ <ADropdown.Content>
77
+ {#each dd.current as item (item.id)}
78
+ <div animate:flip={{ duration: 200 }}>
79
+ <ADropdown.Item value={item.value}>{item.label}</ADropdown.Item>
80
+ </div>
81
+ {/each}
82
+ </ADropdown.Content>
83
+ {/snippet}
84
+ </ADropdown.Root>
85
+
86
+ <ADropdown.Root keys={data.map((item) => item.value)}>
87
+ {#snippet children({ dropdown })}
88
+ <!-- Compose ADropdown.Trigger with Input.Root for a custom trigger -->
89
+ <ADropdown.Trigger
90
+ base={Input.Root}
91
+ class="flex h-auto min-h-12 max-w-sm min-w-sm gap-1 rounded-sm px-4 transition-colors duration-200"
92
+ onclick={(ev) => {
93
+ ev.preventDefault();
94
+
95
+ dropdown.state.open();
96
+ }}
97
+ >
98
+ <!-- Display selected values with animation -->
99
+ <ADropdown.Selections class="flex flex-wrap gap-1" />
100
+
101
+ <!-- Ability to customize the display of selected item -->
102
+ <!-- <ADropdown.Selections class="flex flex-wrap gap-1" >
103
+ {#snippet children({selection})}
104
+ {selection?.text}
105
+ {/snippet}
106
+ </ADropdown.Selections> -->
107
+ </ADropdown.Trigger>
108
+
109
+ <!-- ADropdown list with filtered items -->
110
+ <ADropdown.Content>
111
+ <!-- Inline search input within the trigger -->
112
+ <input
113
+ bind:value={dd.query}
114
+ class="border-border flex-1 border-b px-4 py-3"
115
+ placeholder="Search for fruits..."
116
+ />
117
+
118
+ {#each dd.current as item (item.id)}
119
+ <div animate:flip={{ duration: 200 }}>
120
+ <ADropdown.Item value={item.value}>{item.label}</ADropdown.Item>
121
+ </div>
122
+ {/each}
123
+ </ADropdown.Content>
124
+ {/snippet}
125
+ </ADropdown.Root>
126
+ </div>
83
127
  </Story>
@@ -1,6 +1,10 @@
1
1
  export * as Dropdown from './atoms';
2
2
  export { DropdownBond, type DropdownBondElements, DropdownBondState, type DropdownStateProps } from './bond.svelte';
3
3
  export * from './item';
4
- export { filter } from './runes.svelte';
4
+ export { filterDropdownData } from './runes.svelte';
5
+ /**
6
+ * @deprecated Use `filterDropdownData` instead.
7
+ */
8
+ export { filterDropdownData as filter } from './runes.svelte';
5
9
  export * from './types';
6
10
  export type { AnimatePopoverContentParams as AnimateDropdownContentParams, animatePopoverContent as animateDropdownContent } from '../popover/motion';
@@ -1,5 +1,9 @@
1
1
  export * as Dropdown from './atoms';
2
2
  export { DropdownBond, DropdownBondState } from './bond.svelte';
3
3
  export * from './item';
4
- export { filter } from './runes.svelte';
4
+ export { filterDropdownData } from './runes.svelte';
5
+ /**
6
+ * @deprecated Use `filterDropdownData` instead.
7
+ */
8
+ export { filterDropdownData as filter } from './runes.svelte';
5
9
  export * from './types';
@@ -13,7 +13,7 @@ export declare class DropdownItemController<T = unknown> extends MenuItemControl
13
13
  get data(): any;
14
14
  get element(): HTMLElement | null;
15
15
  get dropdown(): DropdownBond<DropdownStateProps, DropdownBondState<DropdownStateProps>, import("..").DropdownBondElements> | undefined;
16
- get text(): string;
16
+ get label(): string;
17
17
  get isHighlighted(): boolean;
18
18
  get isSelected(): boolean;
19
19
  select(): void;
@@ -26,8 +26,8 @@ export class DropdownItemController extends MenuItemController {
26
26
  get dropdown() {
27
27
  return this.#dropdown;
28
28
  }
29
- get text() {
30
- const element = (this.#element?.querySelector('[data-text]') ?? this.#element);
29
+ get label() {
30
+ const element = (this.#element?.querySelector('[data-label]') ?? this.#element);
31
31
  return element?.innerText ?? '';
32
32
  }
33
33
  get isHighlighted() {
@@ -44,8 +44,6 @@
44
44
  ...restProps
45
45
  });
46
46
 
47
- const ID = $props.id();
48
-
49
47
  function _factory() {
50
48
  const existing = (dropdown?.state as any)?.item?.(value);
51
49
 
@@ -1,5 +1,9 @@
1
- type Predicate<T> = ((query: string, value: T) => boolean) | ((query: string, value: T, index: number) => boolean) | ((query: string, value: T, index: number, array: T[]) => boolean);
2
- export declare function filter<T>(data: () => T[], predicate: Predicate<T>, initialQuery?: string): {
1
+ type Predicate<T> = {
2
+ (query: string, value: T): boolean;
3
+ (query: string, value: T, index: number): boolean;
4
+ (query: string, value: T, index: number, array: T[]): boolean;
5
+ };
6
+ export declare function filterDropdownData<T>(data: () => T[], predicate: Predicate<T>, initialQuery?: string): {
3
7
  query: string;
4
8
  readonly current: T[];
5
9
  };
@@ -1,4 +1,4 @@
1
- export function filter(data, predicate, initialQuery = '') {
1
+ export function filterDropdownData(data, predicate, initialQuery = '') {
2
2
  let query = $state(initialQuery);
3
3
  const results = $derived(data().filter((...args) => predicate(query, ...args)));
4
4
  return {
@@ -1,8 +1,10 @@
1
- import type { Snippet } from 'svelte';
1
+ import type { Component, Snippet } from 'svelte';
2
2
  import type { HtmlAtomProps, Base } from '../atom';
3
3
  import type { Factory, Override } from '../../types';
4
4
  import type { DropdownBond } from './bond.svelte';
5
5
  import type { PopoverTriggerProps } from '../popover';
6
+ import type { ClassValue } from 'svelte/elements';
7
+ import type { DropdownItemController } from './item';
6
8
  /**
7
9
  * Extend this interface to add custom dropdown properties in your application.
8
10
  */
@@ -13,10 +15,12 @@ export interface DropdownExtendProps {
13
15
  */
14
16
  export interface DropdownTriggerExtendProps {
15
17
  }
16
- export interface DropdownRootProps<E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base, T = any> extends Omit<HtmlAtomProps<E, B>, 'children'>, DropdownExtendProps {
18
+ export interface DropdownRootProps<T = any> extends DropdownExtendProps {
17
19
  open?: boolean;
18
20
  value?: T;
19
21
  values?: T[];
22
+ label?: string;
23
+ labels?: string[];
20
24
  multiple?: boolean;
21
25
  disabled?: boolean;
22
26
  placements?: string[];
@@ -35,3 +39,31 @@ export interface DropdownTriggerProps<E extends keyof HTMLElementTagNameMap = 'd
35
39
  }]>;
36
40
  }>, DropdownTriggerExtendProps {
37
41
  }
42
+ export interface DropdownSelectionsProps {
43
+ class?: ClassValue;
44
+ Selection?: Component | undefined;
45
+ children?: Snippet<[
46
+ {
47
+ selections: DropdownSelection[];
48
+ selection?: DropdownSelection | undefined;
49
+ }
50
+ ]>;
51
+ getSelections?: <T extends DropdownBond>(bond: T) => DropdownSelection[];
52
+ }
53
+ export interface DropdownSelectionProps<E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base> extends HtmlAtomProps<E, B> {
54
+ selection: DropdownSelection;
55
+ children?: Snippet;
56
+ onclose?: (event: Event) => void;
57
+ }
58
+ export interface DropdownQueryProps extends HtmlAtomProps<'input'> {
59
+ value?: string;
60
+ children?: Snippet;
61
+ }
62
+ export interface DropdownSelection {
63
+ readonly id: string;
64
+ readonly value?: string;
65
+ readonly label: string;
66
+ readonly createdAt: Date;
67
+ unselect: () => void;
68
+ controller?: DropdownItemController<unknown>;
69
+ }
@@ -32,6 +32,7 @@ export * from './textarea';
32
32
  export * from './tree';
33
33
  export * from './dropdown';
34
34
  export * from './stack';
35
+ export * from './stepper';
35
36
  export * from './element';
36
37
  export * from './atom';
37
38
  export * from './container';
@@ -39,3 +40,4 @@ export * from './calendar';
39
40
  export * from './date-picker';
40
41
  export * from './qr-code';
41
42
  export * from './lazy';
43
+ export * from './chip';
@@ -32,6 +32,7 @@ export * from './textarea';
32
32
  export * from './tree';
33
33
  export * from './dropdown';
34
34
  export * from './stack';
35
+ export * from './stepper';
35
36
  export * from './element';
36
37
  export * from './atom';
37
38
  export * from './container';
@@ -39,3 +40,4 @@ export * from './calendar';
39
40
  export * from './date-picker';
40
41
  export * from './qr-code';
41
42
  export * from './lazy';
43
+ export * from './chip';
@@ -33,14 +33,16 @@ export class MenuBond extends PopoverBond {
33
33
  return {
34
34
  ...superProps,
35
35
  'aria-haspopup': 'menu',
36
- 'onkeydown': (ev) => {
36
+ onkeydown: (ev) => {
37
37
  if (ev.key === 'ArrowDown') {
38
38
  this.state.navigation.next();
39
39
  }
40
40
  if (ev.key === 'ArrowUp') {
41
41
  this.state.navigation.previous();
42
42
  }
43
- if ((ev.key === 'Enter' || ev.key === ' ') && this.state.props.open && this.state.highlightedItem) {
43
+ if ((ev.key === 'Enter' || ev.key === ' ') &&
44
+ this.state.props.open &&
45
+ this.state.highlightedItem) {
44
46
  if (ev.key === ' ') {
45
47
  ev.preventDefault();
46
48
  }
@@ -7,6 +7,7 @@ export declare class MenuItemController {
7
7
  static CONTEXT_KEY: string;
8
8
  constructor(props?: () => MenuItemControllerProps);
9
9
  get id(): string;
10
+ get createdAt(): Date;
10
11
  get props(): MenuItemControllerProps;
11
12
  get element(): HTMLElement | null;
12
13
  get menu(): MenuBond<MenuBondProps, MenuBondState<MenuBondProps>, import("..").PopoverDomElements> | undefined;
@@ -9,6 +9,8 @@ export class MenuItemController {
9
9
  #element = null;
10
10
  #menu;
11
11
  #unmount;
12
+ // eslint-disable-next-line svelte/prefer-svelte-reactivity
13
+ #createdAt = new Date();
12
14
  constructor(props = () => ({})) {
13
15
  this.#props = props;
14
16
  this.#id = this.props.id ?? nanoid();
@@ -20,6 +22,9 @@ export class MenuItemController {
20
22
  get id() {
21
23
  return this.#id;
22
24
  }
25
+ get createdAt() {
26
+ return this.#createdAt;
27
+ }
23
28
  get props() {
24
29
  return this.#props();
25
30
  }
@@ -122,8 +122,7 @@ export class PopoverBond extends Bond {
122
122
  // check if trigger contains a focusable element and the focus is already inside
123
123
  // check if the in-focus element is an input, textarea or select to avoid stealing focus
124
124
  const activeElement = document.activeElement;
125
- const triggerContainsFocus = ['input', 'textarea'].includes(activeElement.tagName.toLowerCase()) ||
126
- triggerElement === activeElement ||
125
+ const triggerContainsFocus = ['input', 'textarea'].includes(activeElement.tagName.toLowerCase()) &&
127
126
  triggerElement.contains(activeElement);
128
127
  // Move focus to popover when opened
129
128
  if (!triggerContainsFocus) {