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

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 (136) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +289 -853
  3. package/dist/attachments/index.d.ts +1 -0
  4. package/dist/attachments/index.js +1 -0
  5. package/dist/components/accordion/accordion-root.svelte +65 -65
  6. package/dist/components/accordion/accordion.stories.svelte +70 -70
  7. package/dist/components/accordion/item/accordion-item-body.svelte +44 -44
  8. package/dist/components/accordion/item/accordion-item-header.svelte +51 -51
  9. package/dist/components/accordion/item/accordion-item-indicator.svelte +51 -51
  10. package/dist/components/accordion/item/accordion-item-root.svelte +66 -66
  11. package/dist/components/alert/alert-close-button.svelte +66 -66
  12. package/dist/components/alert/alert-description.svelte +42 -42
  13. package/dist/components/alert/alert-root.svelte +68 -68
  14. package/dist/components/atom/html-atom.svelte +26 -194
  15. package/dist/components/atom/types.d.ts +3 -2
  16. package/dist/components/atom/utils.d.ts +37 -0
  17. package/dist/components/atom/utils.js +208 -0
  18. package/dist/components/breadcrumb/breadcrumb-item.svelte +1 -1
  19. package/dist/components/breadcrumb/breadcrumb-separator.svelte +5 -1
  20. package/dist/components/breadcrumb/breadcrumb.stories.svelte +16 -16
  21. package/dist/components/calendar/calendar-day.svelte +101 -101
  22. package/dist/components/checkbox/checkbox.svelte +159 -159
  23. package/dist/components/collapsible/bond.svelte.js +2 -1
  24. package/dist/components/collapsible/collapsible-body.svelte +3 -2
  25. package/dist/components/collapsible/motion.svelte.d.ts +6 -0
  26. package/dist/components/collapsible/motion.svelte.js +15 -0
  27. package/dist/components/combobox/atoms.d.ts +3 -3
  28. package/dist/components/combobox/atoms.js +3 -3
  29. package/dist/components/combobox/bond.svelte.d.ts +6 -6
  30. package/dist/components/combobox/bond.svelte.js +3 -26
  31. package/dist/components/combobox/combobox-control.svelte +52 -52
  32. package/dist/components/combobox/{compobox-item.svelte → combobox-item.svelte} +62 -68
  33. package/dist/components/combobox/combobox-item.svelte.d.ts +12 -0
  34. package/dist/components/combobox/combobox.stories.svelte +50 -0
  35. package/dist/components/combobox/combobox.stories.svelte.d.ts +3 -0
  36. package/dist/components/datagrid/tr/datagrid-tr.svelte +90 -90
  37. package/dist/components/date-picker/bond.svelte.d.ts +15 -5
  38. package/dist/components/date-picker/bond.svelte.js +5 -11
  39. package/dist/components/date-picker/date-picker-calendar.svelte +67 -67
  40. package/dist/components/dialog/bond.svelte.js +5 -20
  41. package/dist/components/dialog/dialog-content.svelte +44 -44
  42. package/dist/components/dialog/dialog-root.svelte +91 -91
  43. package/dist/components/drawer/bond.svelte.d.ts +18 -16
  44. package/dist/components/drawer/bond.svelte.js +8 -18
  45. package/dist/components/drawer/drawer-content.svelte +49 -49
  46. package/dist/components/drawer/drawer-root.svelte +5 -4
  47. package/dist/components/drawer/drawer.stories.svelte +141 -144
  48. package/dist/components/drawer/motion.js +1 -1
  49. package/dist/components/dropdown/atoms.d.ts +1 -1
  50. package/dist/components/dropdown/atoms.js +1 -1
  51. package/dist/components/dropdown/bond.svelte.d.ts +21 -22
  52. package/dist/components/dropdown/bond.svelte.js +29 -53
  53. package/dist/components/dropdown/dropdown-root.svelte +65 -59
  54. package/dist/components/dropdown/dropdown-values.svelte +17 -17
  55. package/dist/components/dropdown/dropdown-values.svelte.d.ts +1 -2
  56. package/dist/components/dropdown/dropdown.stories.svelte +83 -80
  57. package/dist/components/dropdown/index.d.ts +1 -0
  58. package/dist/components/dropdown/index.js +1 -0
  59. package/dist/components/dropdown/item/attachments.svelte.d.ts +2 -2
  60. package/dist/components/dropdown/item/attachments.svelte.js +2 -2
  61. package/dist/components/dropdown/item/controller.svelte.d.ts +34 -0
  62. package/dist/components/dropdown/item/controller.svelte.js +82 -0
  63. package/dist/components/dropdown/item/dropdown-item.svelte +109 -102
  64. package/dist/components/dropdown/item/dropdown-item.svelte.d.ts +13 -28
  65. package/dist/components/dropdown/item/index.d.ts +3 -0
  66. package/dist/components/dropdown/item/index.js +3 -0
  67. package/dist/components/dropdown/item/types.d.ts +29 -0
  68. package/dist/components/dropdown/item/types.js +1 -0
  69. package/dist/components/list/list-item.svelte +20 -20
  70. package/dist/components/menu/atoms.d.ts +8 -3
  71. package/dist/components/menu/atoms.js +8 -3
  72. package/dist/components/menu/bond.svelte.d.ts +54 -0
  73. package/dist/components/menu/bond.svelte.js +132 -0
  74. package/dist/components/menu/index.d.ts +1 -0
  75. package/dist/components/menu/index.js +1 -0
  76. package/dist/components/menu/item/controller.svelte.d.ts +26 -0
  77. package/dist/components/menu/item/controller.svelte.js +69 -0
  78. package/dist/components/menu/item/index.d.ts +2 -0
  79. package/dist/components/menu/item/index.js +2 -0
  80. package/dist/components/menu/item/menu-item.svelte +103 -0
  81. package/dist/components/menu/item/menu-item.svelte.d.ts +31 -0
  82. package/dist/components/menu/item/types.d.ts +62 -0
  83. package/dist/components/menu/item/types.js +1 -0
  84. package/dist/components/menu/{menu-list.svelte → menu-content.svelte} +40 -40
  85. package/dist/components/menu/{menu-list.svelte.d.ts → menu-content.svelte.d.ts} +3 -3
  86. package/dist/components/menu/menu-root.svelte +15 -0
  87. package/dist/components/menu/menu-root.svelte.d.ts +8 -0
  88. package/dist/components/menu/menu.stories.svelte +33 -33
  89. package/dist/components/menu/types.d.ts +0 -7
  90. package/dist/components/popover/bond.svelte.d.ts +11 -14
  91. package/dist/components/popover/bond.svelte.js +27 -44
  92. package/dist/components/popover/popover-content.svelte +137 -137
  93. package/dist/components/popover/popover.stories.svelte +37 -49
  94. package/dist/components/portal/active-portal.svelte +29 -29
  95. package/dist/components/portal/portal-root.svelte +76 -76
  96. package/dist/components/portal/teleport.svelte +49 -49
  97. package/dist/components/radio/radio.svelte +109 -109
  98. package/dist/components/root/index.d.ts +1 -0
  99. package/dist/components/root/index.js +1 -0
  100. package/dist/components/root/l0-portal.svelte +8 -0
  101. package/dist/components/root/l0-portal.svelte.d.ts +26 -0
  102. package/dist/components/root/l1-portal.svelte +7 -0
  103. package/dist/components/root/l1-portal.svelte.d.ts +26 -0
  104. package/dist/components/root/root.css +119 -119
  105. package/dist/components/root/root.svelte +17 -18
  106. package/dist/components/root/root.svelte.d.ts +2 -6
  107. package/dist/components/root/toasts-portal.svelte +7 -0
  108. package/dist/components/root/toasts-portal.svelte.d.ts +26 -0
  109. package/dist/components/root/types.d.ts +17 -0
  110. package/dist/components/sidebar/motion.svelte.js +3 -3
  111. package/dist/components/sidebar/sidebar-content.svelte +40 -40
  112. package/dist/components/textarea/textarea-input.svelte +9 -9
  113. package/dist/components/textarea/textarea-root.svelte +9 -9
  114. package/dist/components/tooltip/tooltip-trigger.svelte +39 -39
  115. package/dist/components/tree/index.d.ts +1 -0
  116. package/dist/components/tree/index.js +1 -0
  117. package/dist/components/tree/motion.svelte.d.ts +6 -0
  118. package/dist/components/tree/motion.svelte.js +14 -0
  119. package/dist/components/tree/tree-body.svelte +4 -3
  120. package/dist/context/preset.svelte.d.ts +3 -1
  121. package/dist/icons/icon-copy.svelte +6 -6
  122. package/dist/utils/dom.svelte.d.ts +2 -0
  123. package/dist/utils/dom.svelte.js +21 -0
  124. package/dist/utils/function.d.ts +1 -1
  125. package/dist/utils/promise.svelte.d.ts +5 -0
  126. package/dist/utils/promise.svelte.js +20 -0
  127. package/package.json +4 -2
  128. package/dist/components/combobox/compobox-item.svelte.d.ts +0 -34
  129. package/dist/components/combobox/compobox.stories.svelte +0 -51
  130. package/dist/components/combobox/compobox.stories.svelte.d.ts +0 -3
  131. package/dist/components/dropdown/item/bond.svelte.d.ts +0 -42
  132. package/dist/components/dropdown/item/bond.svelte.js +0 -99
  133. package/dist/components/menu/menu-item.svelte +0 -69
  134. package/dist/components/menu/menu-item.svelte.d.ts +0 -37
  135. package/dist/utils/markdown-to-llm.d.ts +0 -28
  136. package/dist/utils/markdown-to-llm.js +0 -76
@@ -1,102 +1,109 @@
1
- <script
2
- lang="ts"
3
- generics="D, E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base"
4
- >
5
- import { nanoid } from 'nanoid';
6
- import {
7
- DropdownItemBond,
8
- DropdownItemBondState,
9
- type DropdownItemBondProps
10
- } from './bond.svelte';
11
- import { DropdownBond } from '../bond.svelte';
12
- import { Item } from '../../menu/atoms';
13
- import { defineProperty, defineState } from '../../../utils';
14
- import type { Base } from '../../atom';
15
-
16
- const dropdown = DropdownBond.get();
17
-
18
- if (!dropdown) {
19
- throw new Error('<DropdownItem> must be used within a <Dropdown>.');
20
- }
21
-
22
- let {
23
- class: klass = '',
24
- preset = 'dropdown.item',
25
- value = nanoid(),
26
- data = undefined,
27
- factory = _factory,
28
- children = undefined,
29
- onclick = undefined,
30
- onmount = undefined,
31
- ondestroy = undefined,
32
- animate = undefined,
33
- enter = undefined,
34
- exit = undefined,
35
- initial = undefined,
36
- ...restProps
37
- } = $props();
38
-
39
- const bond = factory().share();
40
-
41
- const unmount = bond.mount();
42
- $effect(() => unmount);
43
-
44
- const rootProps = $derived({
45
- ...bond?.root?.(),
46
- ...restProps
47
- });
48
-
49
- function _factory() {
50
- const item = dropdown?.state.item(value);
51
-
52
- if (item) {
53
- return item as DropdownItemBond;
54
- }
55
-
56
- const bondProps = defineState<DropdownItemBondProps<D>>([
57
- defineProperty('value', () => value),
58
- defineProperty('data', () => data)
59
- ]);
60
- const bondState = new DropdownItemBondState(() => bondProps);
61
- return new DropdownItemBond(bondState);
62
- }
63
-
64
- function handleClick(ev: MouseEvent) {
65
- onclick?.(ev);
66
-
67
- if (ev.defaultPrevented) {
68
- return;
69
- }
70
-
71
- ev.preventDefault();
72
-
73
- bond.state.toggle();
74
-
75
- if (bond.state.dropdown) {
76
- bond.state.dropdown.query = '';
77
- }
78
-
79
- bond.state.close();
80
- }
81
- </script>
82
-
83
- <Item
84
- {bond}
85
- {preset}
86
- class={[
87
- bond.state.isHighlighted && 'bg-foreground/5',
88
- bond.state.isSelected && 'bg-primary/5 hover:bg-primary/10 active:bg-primary/15',
89
- '$preset',
90
- klass
91
- ]}
92
- enter={enter?.bind(bond.state)}
93
- exit={exit?.bind(bond.state)}
94
- initial={initial?.bind(bond.state)}
95
- animate={animate?.bind(bond.state)}
96
- onmount={onmount?.bind(bond.state)}
97
- ondestroy={ondestroy?.bind(bond.state)}
98
- onclick={handleClick}
99
- {...rootProps}
100
- >
101
- {@render children?.({ dropdownItem: bond })}
102
- </Item>
1
+ <script lang="ts" generics="D">
2
+ import { nanoid } from 'nanoid';
3
+ import { defineProperty, defineState } from '../../../utils';
4
+ import {
5
+ DropdownItemController,
6
+ type DropdownItemProps as ControllerProps
7
+ } from './controller.svelte';
8
+ import type { DropdownItemProps } from './types';
9
+ import { DropdownBond } from '../bond.svelte';
10
+ import Item from '../../menu/item/menu-item.svelte';
11
+
12
+ const dropdown = DropdownBond.get();
13
+
14
+ if (!dropdown) {
15
+ throw new Error('<DropdownItem> must be used within a <Dropdown>.');
16
+ }
17
+
18
+ let {
19
+ class: klass = '',
20
+ preset = 'dropdown.item',
21
+ value = nanoid(),
22
+ data = undefined,
23
+ factory = _factory,
24
+ children = undefined,
25
+ onclick = undefined,
26
+ onmount = undefined,
27
+ ondestroy = undefined,
28
+ animate = undefined,
29
+ enter = undefined,
30
+ exit = undefined,
31
+ initial = undefined,
32
+ ...restProps
33
+ }: DropdownItemProps<D> = $props();
34
+
35
+ let item: typeof Item = $state(undefined);
36
+ const controller = $derived(item?.getController());
37
+ const isHighlighted = $derived(controller?.isHighlighted ?? false);
38
+ const isSelected = $derived(controller?.isSelected ?? false);
39
+
40
+ // const item = factory().share();
41
+
42
+ const rootProps = $derived({
43
+ ...controller?.elementProps(),
44
+ ...restProps
45
+ });
46
+
47
+ const ID = $props.id();
48
+
49
+ function _factory() {
50
+ const existing = (dropdown?.state as any)?.item?.(value);
51
+
52
+ if (existing) {
53
+ return existing as DropdownItemController<D>;
54
+ }
55
+
56
+ const itemProps = defineState<ControllerProps<D>>([
57
+ defineProperty('value', () => value),
58
+ defineProperty('data', () => data),
59
+ defineProperty('id', () => value)
60
+ ]);
61
+ const controller = new DropdownItemController<D>(() => itemProps);
62
+
63
+ controller.mount();
64
+
65
+ return controller;
66
+ }
67
+
68
+ function handleClick(ev: MouseEvent) {
69
+ onclick?.(ev);
70
+
71
+ if (ev.defaultPrevented) {
72
+ return;
73
+ }
74
+
75
+ ev.preventDefault();
76
+
77
+ controller.toggle();
78
+
79
+ if (controller.dropdown?.state) {
80
+ controller.dropdown.state.query = '';
81
+ }
82
+
83
+ controller.close();
84
+ }
85
+ </script>
86
+
87
+ <Item
88
+ bind:this={item}
89
+ {preset}
90
+ class={[
91
+ isHighlighted && 'bg-foreground/5',
92
+ isSelected && 'bg-primary/5 hover:bg-primary/10 active:bg-primary/15',
93
+ '$preset',
94
+ klass
95
+ ]
96
+ .filter(Boolean)
97
+ .join(' ')}
98
+ enter={enter?.bind(controller)}
99
+ exit={exit?.bind(controller)}
100
+ initial={initial?.bind(controller)}
101
+ animate={animate?.bind(controller)}
102
+ onmount={onmount?.bind(controller)}
103
+ ondestroy={ondestroy?.bind(controller)}
104
+ onclick={handleClick}
105
+ {factory}
106
+ {...rootProps}
107
+ >
108
+ {@render children?.({ dropdownItem: controller })}
109
+ </Item>
@@ -1,40 +1,25 @@
1
- import { DropdownItemBond } from './bond.svelte';
2
- import type { Base } from '../../atom';
3
- declare function $$render<D, E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base>(): {
4
- props: {
5
- class?: string;
6
- preset?: string;
7
- value?: any;
8
- data?: any;
9
- factory?: () => DropdownItemBond<unknown>;
10
- children?: any;
11
- onclick?: any;
12
- onmount?: any;
13
- ondestroy?: any;
14
- animate?: any;
15
- enter?: any;
16
- exit?: any;
17
- initial?: any;
18
- } & Record<string, any>;
1
+ import type { DropdownItemProps } from './types';
2
+ declare function $$render<D>(): {
3
+ props: DropdownItemProps<D>;
19
4
  exports: {};
20
5
  bindings: "";
21
6
  slots: {};
22
7
  events: {};
23
8
  };
24
- declare class __sveltets_Render<D, E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base> {
25
- props(): ReturnType<typeof $$render<D, E, B>>['props'];
26
- events(): ReturnType<typeof $$render<D, E, B>>['events'];
27
- slots(): ReturnType<typeof $$render<D, E, B>>['slots'];
9
+ declare class __sveltets_Render<D> {
10
+ props(): ReturnType<typeof $$render<D>>['props'];
11
+ events(): ReturnType<typeof $$render<D>>['events'];
12
+ slots(): ReturnType<typeof $$render<D>>['slots'];
28
13
  bindings(): "";
29
14
  exports(): {};
30
15
  }
31
16
  interface $$IsomorphicComponent {
32
- new <D, E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<D, E, B>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<D, E, B>['props']>, ReturnType<__sveltets_Render<D, E, B>['events']>, ReturnType<__sveltets_Render<D, E, B>['slots']>> & {
33
- $$bindings?: ReturnType<__sveltets_Render<D, E, B>['bindings']>;
34
- } & ReturnType<__sveltets_Render<D, E, B>['exports']>;
35
- <D, E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base>(internal: unknown, props: ReturnType<__sveltets_Render<D, E, B>['props']> & {}): ReturnType<__sveltets_Render<D, E, B>['exports']>;
36
- z_$$bindings?: ReturnType<__sveltets_Render<any, any, any>['bindings']>;
17
+ new <D>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<D>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<D>['props']>, ReturnType<__sveltets_Render<D>['events']>, ReturnType<__sveltets_Render<D>['slots']>> & {
18
+ $$bindings?: ReturnType<__sveltets_Render<D>['bindings']>;
19
+ } & ReturnType<__sveltets_Render<D>['exports']>;
20
+ <D>(internal: unknown, props: ReturnType<__sveltets_Render<D>['props']> & {}): ReturnType<__sveltets_Render<D>['exports']>;
21
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
37
22
  }
38
23
  declare const DropdownItem: $$IsomorphicComponent;
39
- type DropdownItem<D, E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base> = InstanceType<typeof DropdownItem<D, E, B>>;
24
+ type DropdownItem<D> = InstanceType<typeof DropdownItem<D>>;
40
25
  export default DropdownItem;
@@ -0,0 +1,3 @@
1
+ export * from './attachments.svelte';
2
+ export { DropdownItemController } from './controller.svelte';
3
+ export { default as DropdownItem } from './dropdown-item.svelte';
@@ -0,0 +1,3 @@
1
+ export * from './attachments.svelte';
2
+ export { DropdownItemController } from './controller.svelte';
3
+ export { default as DropdownItem } from './dropdown-item.svelte';
@@ -0,0 +1,29 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { MenuItemProps } from '../../menu/item/types';
3
+ import type { DropdownItemController } from './controller.svelte';
4
+ export interface DropdownItemProps<T = unknown> extends Omit<MenuItemProps, 'factory' | 'children' | 'preset'> {
5
+ /**
6
+ * Preset key for styling
7
+ * @default 'dropdown.item'
8
+ */
9
+ preset?: string;
10
+ /**
11
+ * The value of the dropdown item
12
+ * @default nanoid()
13
+ */
14
+ value?: string;
15
+ /**
16
+ * Custom data associated with the item
17
+ */
18
+ data?: T;
19
+ /**
20
+ * Factory function to create a custom DropdownItemController instance
21
+ */
22
+ factory?: () => DropdownItemController<T>;
23
+ /**
24
+ * Render prop for children
25
+ */
26
+ children?: Snippet<[{
27
+ dropdownItem: DropdownItemController<T>;
28
+ }]>;
29
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,20 +1,20 @@
1
- <script lang="ts" generics="T extends keyof HTMLElementTagNameMap = 'li', B extends Base = Base">
2
- import { HtmlAtom, type Base } from '../atom';
3
-
4
- let {
5
- class: klass = '',
6
- as = 'li' as T,
7
- preset = 'list.item',
8
- children = undefined,
9
- ...restProps
10
- } = $props();
11
- </script>
12
-
13
- <HtmlAtom
14
- {as}
15
- {preset}
16
- class={['border-border flex w-full gap-2 px-4 py-1', '$preset', klass]}
17
- {...restProps}
18
- >
19
- {@render children?.()}
20
- </HtmlAtom>
1
+ <script lang="ts" generics="T extends keyof HTMLElementTagNameMap = 'li', B extends Base = Base">
2
+ import { HtmlAtom, type Base } from '../atom';
3
+
4
+ let {
5
+ class: klass = '',
6
+ as = 'li' as T,
7
+ preset = 'list.item',
8
+ children = undefined,
9
+ ...restProps
10
+ } = $props();
11
+ </script>
12
+
13
+ <HtmlAtom
14
+ {as}
15
+ {preset}
16
+ class={['border-border flex w-full gap-2 px-4 py-1', '$preset', klass]}
17
+ {...restProps}
18
+ >
19
+ {@render children?.()}
20
+ </HtmlAtom>
@@ -1,4 +1,9 @@
1
- export { Root, Trigger, Arrow, Indicator } from '../popover/atoms';
2
- export { default as List } from './menu-list.svelte';
3
- export { default as Item } from './menu-item.svelte';
1
+ export { default as Root } from './menu-root.svelte';
2
+ export { default as Content } from './menu-content.svelte';
3
+ /**
4
+ * @deprecated Use Menu.Content instead
5
+ */
6
+ export { default as List } from './menu-content.svelte';
7
+ export { default as Item } from './item/menu-item.svelte';
8
+ export { Trigger, Arrow, Indicator } from '../popover/atoms';
4
9
  export { Divider, Group, Title } from '../list/atoms';
@@ -1,4 +1,9 @@
1
- export { Root, Trigger, Arrow, Indicator } from '../popover/atoms';
2
- export { default as List } from './menu-list.svelte';
3
- export { default as Item } from './menu-item.svelte';
1
+ export { default as Root } from './menu-root.svelte';
2
+ export { default as Content } from './menu-content.svelte';
3
+ /**
4
+ * @deprecated Use Menu.Content instead
5
+ */
6
+ export { default as List } from './menu-content.svelte';
7
+ export { default as Item } from './item/menu-item.svelte';
8
+ export { Trigger, Arrow, Indicator } from '../popover/atoms';
4
9
  export { Divider, Group, Title } from '../list/atoms';
@@ -0,0 +1,54 @@
1
+ import { PopoverBond, PopoverState, type PopoverDomElements, type PopoverStateProps } from '../popover/bond.svelte';
2
+ import type { MenuItemController } from './item/controller.svelte';
3
+ export type MenuBondProps = PopoverStateProps;
4
+ export type MenuBondElements = PopoverDomElements;
5
+ export declare class MenuBond<Props extends MenuBondProps = MenuBondProps, State extends MenuBondState<Props> = MenuBondState<Props>, Elements extends MenuBondElements = MenuBondElements> extends PopoverBond<Props, State, Elements> {
6
+ constructor(state: State);
7
+ content(): {
8
+ role: string;
9
+ 'aria-activedescendant': string | undefined;
10
+ 'aria-orientation': "vertical";
11
+ onkeydown: (ev: KeyboardEvent) => void;
12
+ id: string;
13
+ 'aria-modal': boolean;
14
+ 'aria-labelledby': string;
15
+ inert: boolean | undefined;
16
+ tabindex: number;
17
+ 'data-atom': string;
18
+ 'data-kind': string;
19
+ 'data-active': boolean;
20
+ };
21
+ trigger(): {
22
+ 'aria-haspopup': "menu";
23
+ onkeydown: (ev: KeyboardEvent) => void;
24
+ id: string;
25
+ role: string;
26
+ disabled: boolean | undefined;
27
+ tabindex: number;
28
+ 'aria-expanded': boolean;
29
+ 'aria-disabled': boolean;
30
+ 'aria-controls': string;
31
+ 'data-kind': string;
32
+ onclick: (ev: PointerEvent) => void;
33
+ };
34
+ item(): {
35
+ role: string;
36
+ onkeyup: (ev: KeyboardEvent) => void;
37
+ };
38
+ static get<Props extends MenuBondProps = MenuBondProps, State extends MenuBondState<Props> = MenuBondState<Props>, Elements extends MenuBondElements = MenuBondElements>(): MenuBond<Props, State, Elements> | undefined;
39
+ static set<Props extends MenuBondProps = MenuBondProps, State extends MenuBondState<Props> = MenuBondState<Props>, Elements extends MenuBondElements = MenuBondElements>(context: MenuBond<Props, State, Elements>): MenuBond<Props, State, Elements>;
40
+ }
41
+ export declare class MenuBondState<Props extends MenuBondProps = MenuBondProps> extends PopoverState<Props> {
42
+ #private;
43
+ constructor(props: () => Props);
44
+ get items(): Map<string, MenuItemController>;
45
+ get highlightedId(): string | null;
46
+ get highlightedItem(): MenuItemController | null;
47
+ get navigation(): {
48
+ next: () => MenuItemController | null;
49
+ previous: () => MenuItemController | null;
50
+ };
51
+ mountItem(id: string, item: MenuItemController): () => void;
52
+ unmountItem(id: string): void;
53
+ item(id: string): MenuItemController | undefined;
54
+ }
@@ -0,0 +1,132 @@
1
+ import { SvelteMap, SvelteSet } from 'svelte/reactivity';
2
+ import { PopoverBond, PopoverState } from '../popover/bond.svelte';
3
+ export class MenuBond extends PopoverBond {
4
+ constructor(state) {
5
+ super(state);
6
+ }
7
+ content() {
8
+ const superProps = super.content();
9
+ const onkeydown = superProps.onkeydown;
10
+ const highlightedId = this.state.highlightedId;
11
+ return {
12
+ ...superProps,
13
+ role: 'menu',
14
+ 'aria-activedescendant': highlightedId ? `item-${highlightedId}` : undefined,
15
+ 'aria-orientation': 'vertical',
16
+ onkeydown: (ev) => {
17
+ // Call any additional onkeydown handler
18
+ onkeydown?.(ev);
19
+ if (ev.defaultPrevented)
20
+ return;
21
+ // Handle arrow key navigation
22
+ if (ev.key === 'ArrowDown') {
23
+ this.state.navigation.next();
24
+ }
25
+ if (ev.key === 'ArrowUp') {
26
+ this.state.navigation.previous();
27
+ }
28
+ }
29
+ };
30
+ }
31
+ trigger() {
32
+ const superProps = super.trigger();
33
+ return {
34
+ ...superProps,
35
+ 'aria-haspopup': 'menu',
36
+ 'onkeydown': (ev) => {
37
+ if (ev.key === 'ArrowDown') {
38
+ this.state.navigation.next();
39
+ }
40
+ if (ev.key === 'ArrowUp') {
41
+ this.state.navigation.previous();
42
+ }
43
+ if ((ev.key === 'Enter' || ev.key === ' ') && this.state.props.open && this.state.highlightedItem) {
44
+ if (ev.key === ' ') {
45
+ ev.preventDefault();
46
+ }
47
+ this.state.highlightedItem?.element?.click();
48
+ }
49
+ // Call any additional onkeydown handler
50
+ superProps.onkeydown?.(ev);
51
+ }
52
+ };
53
+ }
54
+ item() {
55
+ return {
56
+ role: 'menuitem',
57
+ onkeyup: (ev) => {
58
+ const currentTarget = ev.currentTarget;
59
+ const disabled = currentTarget.getAttribute('disabled') ||
60
+ currentTarget.getAttribute('aria-disabled') === 'true';
61
+ if (disabled)
62
+ return;
63
+ // Activate on Enter or Space
64
+ if (ev.key === 'Enter' || ev.key === ' ') {
65
+ ev.preventDefault();
66
+ // Call the click handler if provided
67
+ // cast to any to avoid strict event-type mismatch when forwarding
68
+ this?.state.close();
69
+ }
70
+ }
71
+ };
72
+ }
73
+ static get() {
74
+ return PopoverBond.get();
75
+ }
76
+ static set(context) {
77
+ return PopoverBond.set(context);
78
+ }
79
+ }
80
+ export class MenuBondState extends PopoverState {
81
+ #keys = new SvelteSet();
82
+ #items = new SvelteMap();
83
+ #itemsAsArray = $derived(Array.from(this.#items.values()));
84
+ #index = $state(-1);
85
+ #highlightedId = $derived(Array.from(this.#items.keys())[this.#index] ?? null);
86
+ #highlightedItem = $derived(this.#itemsAsArray[this.#index] ?? null);
87
+ constructor(props) {
88
+ super(props);
89
+ }
90
+ get items() {
91
+ return this.#items;
92
+ }
93
+ get highlightedId() {
94
+ return this.#highlightedId;
95
+ }
96
+ get highlightedItem() {
97
+ return this.#highlightedItem;
98
+ }
99
+ get navigation() {
100
+ return {
101
+ next: () => {
102
+ if (this.#index < 0) {
103
+ this.#index = 0;
104
+ return this.#highlightedItem;
105
+ }
106
+ const length = this.#items.size;
107
+ this.#index = Math.min((this.#index + 1) % length, length - 1);
108
+ return this.#highlightedItem;
109
+ },
110
+ previous: () => {
111
+ if (this.#index <= 0) {
112
+ this.#index = this.#items.size - 1;
113
+ return this.#highlightedItem;
114
+ }
115
+ this.#index = Math.max(this.#index - 1, 0);
116
+ return this.#highlightedItem;
117
+ }
118
+ };
119
+ }
120
+ mountItem(id, item) {
121
+ this.#items.set(id, item);
122
+ return () => this.unmountItem(id);
123
+ }
124
+ unmountItem(id) {
125
+ if (this.#keys.has(id))
126
+ return; // keep the item if it's still in the data source
127
+ this.#items.delete(id);
128
+ }
129
+ item(id) {
130
+ return this.#items.get(id);
131
+ }
132
+ }
@@ -2,3 +2,4 @@ export * as Menu from './atoms';
2
2
  export * from './types';
3
3
  export { PopoverBond, type PopoverDomElements, type PopoverParams, PopoverState, type PopoverStateProps, type TriggerParams } from '../popover';
4
4
  export type { AnimatePopoverContentParams as AnimateMenuContentParams, animatePopoverContent as animateMenuContent } from '../popover/motion';
5
+ export * from './item';
@@ -1,3 +1,4 @@
1
1
  export * as Menu from './atoms';
2
2
  export * from './types';
3
3
  export { PopoverBond, PopoverState } from '../popover';
4
+ export * from './item';
@@ -0,0 +1,26 @@
1
+ import { MenuBond, MenuBondState, type MenuBondProps } from '../bond.svelte';
2
+ export type MenuItemControllerProps = {
3
+ id?: string;
4
+ };
5
+ export declare class MenuItemController {
6
+ #private;
7
+ static CONTEXT_KEY: string;
8
+ constructor(props?: () => MenuItemControllerProps);
9
+ get id(): string;
10
+ get props(): MenuItemControllerProps;
11
+ get element(): HTMLElement | null;
12
+ get menu(): MenuBond<MenuBondProps, MenuBondState<MenuBondProps>, import("..").PopoverDomElements> | undefined;
13
+ get isHighlighted(): boolean;
14
+ mount(): () => void;
15
+ unmount(): void;
16
+ destroy(): void;
17
+ share(): MenuItemController;
18
+ elementProps(): {
19
+ readonly [x: symbol]: (node: HTMLElement) => () => void;
20
+ readonly id: string;
21
+ readonly role: "menuitem";
22
+ readonly 'data-highlighted': boolean;
23
+ };
24
+ static get(): MenuItemController | undefined;
25
+ static set(item: MenuItemController): MenuItemController;
26
+ }