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

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 +6 -11
  39. package/dist/components/date-picker/date-picker-calendar.svelte +1 -8
  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
@@ -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
+ }
@@ -0,0 +1,69 @@
1
+ import { getContext, setContext } from 'svelte';
2
+ import { createAttachmentKey } from 'svelte/attachments';
3
+ import { nanoid } from 'nanoid';
4
+ import { MenuBond, MenuBondState } from '../bond.svelte';
5
+ export class MenuItemController {
6
+ static CONTEXT_KEY = '@atoms/context/menu/item';
7
+ #id;
8
+ #props;
9
+ #element = null;
10
+ #menu;
11
+ #unmount;
12
+ constructor(props = () => ({})) {
13
+ this.#props = props;
14
+ this.#id = this.props.id ?? nanoid();
15
+ this.#menu = MenuBond.get();
16
+ if (!this.#menu) {
17
+ throw new Error('MenuItem must be used within a Menu context');
18
+ }
19
+ }
20
+ get id() {
21
+ return this.#id;
22
+ }
23
+ get props() {
24
+ return this.#props();
25
+ }
26
+ get element() {
27
+ return this.#element;
28
+ }
29
+ get menu() {
30
+ return this.#menu;
31
+ }
32
+ get isHighlighted() {
33
+ return this.#menu?.state.highlightedId === this.#id;
34
+ }
35
+ mount() {
36
+ this.#unmount = this.#menu?.state?.mountItem?.(this.#id, this) ?? undefined;
37
+ return this.unmount;
38
+ }
39
+ unmount() {
40
+ this.#unmount?.();
41
+ }
42
+ destroy() {
43
+ this.unmount();
44
+ }
45
+ share() {
46
+ return MenuItemController.set(this);
47
+ }
48
+ elementProps() {
49
+ const itemId = `item-${this.id}`;
50
+ return {
51
+ id: itemId,
52
+ role: 'menuitem',
53
+ 'data-highlighted': this.isHighlighted,
54
+ [createAttachmentKey()]: (node) => {
55
+ this.#element = node;
56
+ return () => {
57
+ // this.#unmount?.();
58
+ this.#element = null;
59
+ };
60
+ }
61
+ };
62
+ }
63
+ static get() {
64
+ return getContext(MenuItemController.CONTEXT_KEY);
65
+ }
66
+ static set(item) {
67
+ return setContext(MenuItemController.CONTEXT_KEY, item);
68
+ }
69
+ }
@@ -0,0 +1,2 @@
1
+ export { MenuItemController, type MenuItemControllerProps } from './controller.svelte';
2
+ export * from './types';
@@ -0,0 +1,2 @@
1
+ export { MenuItemController } from './controller.svelte';
2
+ export * from './types';
@@ -0,0 +1,103 @@
1
+ <script
2
+ lang="ts"
3
+ generics="D, E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base"
4
+ >
5
+ import { defineProperty, defineState } from '../../../utils';
6
+ import type { Base } from '../../atom';
7
+ import { MenuItemController, type MenuItemControllerProps } from './controller.svelte';
8
+ import { MenuBond } from '../bond.svelte';
9
+ import { List } from '../../list';
10
+ import type { MenuItemProps } from './types';
11
+
12
+ const menu = MenuBond.get();
13
+
14
+ if (!menu) {
15
+ throw new Error('<MenuItem> must be used within a <Menu>.');
16
+ }
17
+
18
+ const ID = $props.id();
19
+
20
+ let {
21
+ class: klass = '',
22
+ id = ID,
23
+ preset: presetKey = 'menu.item',
24
+ children = undefined,
25
+ onclick = undefined,
26
+ disabled = undefined,
27
+ onmount = undefined,
28
+ ondestroy = undefined,
29
+ animate = undefined,
30
+ enter = undefined,
31
+ exit = undefined,
32
+ initial = undefined,
33
+ factory = _factory,
34
+ ...restProps
35
+ }: MenuItemProps = $props();
36
+
37
+ const controller = factory().share();
38
+
39
+ const itemProps = $derived({
40
+ ...menu?.item?.(),
41
+ ...controller?.elementProps(),
42
+ ...restProps
43
+ });
44
+
45
+ $effect(() => {
46
+ return () => {
47
+ controller.destroy();
48
+ };
49
+ });
50
+
51
+ function _factory() {
52
+ const item = menu?.state?.item?.(id);
53
+
54
+ if (item) {
55
+ return item as MenuItemController;
56
+ }
57
+
58
+ const bondProps = defineState<MenuItemControllerProps>([defineProperty('id', () => id)]);
59
+ const controller = new MenuItemController(() => bondProps);
60
+
61
+ controller.mount();
62
+
63
+ return controller;
64
+ }
65
+
66
+ function handleClick(ev: MouseEvent) {
67
+ onclick?.(ev);
68
+
69
+ if (ev.defaultPrevented) {
70
+ return;
71
+ }
72
+
73
+ ev.preventDefault();
74
+
75
+ controller?.menu?.state.close();
76
+ }
77
+
78
+ export function getController() {
79
+ return controller;
80
+ }
81
+ </script>
82
+
83
+ <List.Item
84
+ bond={controller}
85
+ preset={presetKey}
86
+ class={[
87
+ 'border-border last:border-b-none hover:bg-foreground/5 active:bg-foreground/10 outline-primary cursor-pointer border-b',
88
+ '$preset',
89
+ klass
90
+ ]}
91
+ onmount={onmount?.bind(controller) as any}
92
+ ondestroy={ondestroy?.bind(controller) as any}
93
+ enter={enter?.bind(controller) as any}
94
+ exit={exit?.bind(controller) as any}
95
+ initial={initial?.bind(controller) as any}
96
+ animate={animate?.bind(controller) as any}
97
+ aria-disabled={disabled ? true : undefined}
98
+ tabIndex={disabled ? -1 : 0}
99
+ onclick={handleClick}
100
+ {...itemProps}
101
+ >
102
+ {@render children?.({ menuItem: controller })}
103
+ </List.Item>
@@ -0,0 +1,31 @@
1
+ import type { Base } from '../../atom';
2
+ import { MenuItemController } from './controller.svelte';
3
+ import type { MenuItemProps } from './types';
4
+ declare function $$render<D, E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base>(): {
5
+ props: MenuItemProps;
6
+ exports: {
7
+ getController: () => MenuItemController;
8
+ };
9
+ bindings: "";
10
+ slots: {};
11
+ events: {};
12
+ };
13
+ declare class __sveltets_Render<D, E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base> {
14
+ props(): ReturnType<typeof $$render<D, E, B>>['props'];
15
+ events(): ReturnType<typeof $$render<D, E, B>>['events'];
16
+ slots(): ReturnType<typeof $$render<D, E, B>>['slots'];
17
+ bindings(): "";
18
+ exports(): {
19
+ getController: () => MenuItemController;
20
+ };
21
+ }
22
+ interface $$IsomorphicComponent {
23
+ 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']>> & {
24
+ $$bindings?: ReturnType<__sveltets_Render<D, E, B>['bindings']>;
25
+ } & ReturnType<__sveltets_Render<D, E, B>['exports']>;
26
+ <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']>;
27
+ z_$$bindings?: ReturnType<__sveltets_Render<any, any, any>['bindings']>;
28
+ }
29
+ declare const MenuItem: $$IsomorphicComponent;
30
+ type MenuItem<D, E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base> = InstanceType<typeof MenuItem<D, E, B>>;
31
+ export default MenuItem;
@@ -0,0 +1,62 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { MenuItemController } from './controller.svelte';
3
+ import type { ClassValue } from '../../../utils';
4
+ import type { Base, HtmlAtomProps } from '../../atom';
5
+ /**
6
+ * Extend this interface to add custom menu list properties in your application.
7
+ */
8
+ export interface MenuItemExtendProps {
9
+ }
10
+ export interface MenuItemProps<E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base> extends HtmlAtomProps<E, B>, MenuItemExtendProps {
11
+ /**
12
+ * Custom CSS class(es) to apply to the menu item
13
+ */
14
+ class?: ClassValue;
15
+ /**
16
+ * Preset key for styling
17
+ * @default 'menu.item'
18
+ */
19
+ preset?: string;
20
+ /**
21
+ * Whether the menu item is disabled
22
+ */
23
+ disabled?: boolean;
24
+ /**
25
+ * Click event handler
26
+ */
27
+ onclick?: (event: MouseEvent) => void;
28
+ /**
29
+ * Mount lifecycle callback
30
+ */
31
+ onmount?: (this: MenuItemController) => void;
32
+ /**
33
+ * Destroy lifecycle callback
34
+ */
35
+ ondestroy?: (this: MenuItemController) => void;
36
+ /**
37
+ * Animation configuration
38
+ */
39
+ animate?: (this: MenuItemController) => any;
40
+ /**
41
+ * Enter animation configuration
42
+ */
43
+ enter?: (this: MenuItemController) => any;
44
+ /**
45
+ * Exit animation configuration
46
+ */
47
+ exit?: (this: MenuItemController) => any;
48
+ /**
49
+ * Initial state configuration
50
+ */
51
+ initial?: (this: MenuItemController) => any;
52
+ /**
53
+ * Factory function to create a custom MenuItemController instance
54
+ */
55
+ factory?: () => MenuItemController;
56
+ /**
57
+ * Render prop for children
58
+ */
59
+ children?: Snippet<[{
60
+ menuItem: MenuItemController;
61
+ }]>;
62
+ }
@@ -0,0 +1 @@
1
+ export {};