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

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 (176) hide show
  1. package/README.md +3 -2
  2. package/dist/attachments/clickout.svelte.d.ts +1 -1
  3. package/dist/attachments/clickout.svelte.js +2 -2
  4. package/dist/components/accordion/accordion-root.svelte +65 -61
  5. package/dist/components/accordion/accordion-root.svelte.d.ts +1 -1
  6. package/dist/components/accordion/accordion.stories.svelte +70 -134
  7. package/dist/components/accordion/item/accordion-item-body.svelte +44 -42
  8. package/dist/components/accordion/item/accordion-item-header.svelte +51 -50
  9. package/dist/components/accordion/item/accordion-item-indicator.svelte +51 -50
  10. package/dist/components/accordion/item/accordion-item-root.svelte +66 -65
  11. package/dist/components/accordion/item/bond.svelte.d.ts +2 -0
  12. package/dist/components/accordion/item/index.d.ts +3 -0
  13. package/dist/components/accordion/item/index.js +3 -0
  14. package/dist/components/accordion/item/motion.svelte.d.ts +15 -0
  15. package/dist/components/accordion/item/motion.svelte.js +30 -0
  16. package/dist/components/accordion/item/types.d.ts +7 -24
  17. package/dist/components/alert/alert-close-button.svelte +66 -70
  18. package/dist/components/alert/alert-description.svelte +42 -42
  19. package/dist/components/alert/alert-description.svelte.d.ts +3 -6
  20. package/dist/components/alert/alert-root.svelte +68 -103
  21. package/dist/components/alert/alert-root.svelte.d.ts +2 -2
  22. package/dist/components/alert/alert.stories.svelte +10 -11
  23. package/dist/components/alert/bond.svelte.d.ts +0 -13
  24. package/dist/components/alert/bond.svelte.js +0 -32
  25. package/dist/components/alert/types.d.ts +8 -32
  26. package/dist/components/atom/html-atom.svelte +261 -207
  27. package/dist/components/avatar/avatar.stories.svelte +8 -13
  28. package/dist/components/badge/badge.stories.svelte +1 -6
  29. package/dist/components/badge/badge.svelte +1 -1
  30. package/dist/components/breadcrumb/breadcrumb.stories.svelte +16 -21
  31. package/dist/components/button/button.stories.svelte +1 -34
  32. package/dist/components/calendar/calendar-day.svelte +9 -4
  33. package/dist/components/calendar/calendar-header.svelte +29 -29
  34. package/dist/components/calendar/calendar-root.svelte +206 -206
  35. package/dist/components/calendar/calendar.stories.svelte +26 -31
  36. package/dist/components/card/card-body.svelte +1 -1
  37. package/dist/components/card/card-footer.svelte +1 -1
  38. package/dist/components/card/card-root.svelte +1 -1
  39. package/dist/components/card/card.stories.svelte +92 -104
  40. package/dist/components/checkbox/checkbox.stories.svelte +4 -9
  41. package/dist/components/checkbox/checkbox.svelte +159 -157
  42. package/dist/components/collapsible/collapsible.stories.svelte +2 -3
  43. package/dist/components/combobox/atoms.d.ts +1 -1
  44. package/dist/components/combobox/atoms.js +1 -1
  45. package/dist/components/combobox/combobox-root.svelte +1 -1
  46. package/dist/components/combobox/compobox.stories.svelte +19 -22
  47. package/dist/components/combobox/index.d.ts +1 -0
  48. package/dist/components/container/container.stories.svelte +8 -11
  49. package/dist/components/container/container.svelte.d.ts +1 -1
  50. package/dist/components/datagrid/datagrid-root.svelte +59 -59
  51. package/dist/components/datagrid/datagrid.css +5 -5
  52. package/dist/components/datagrid/datagrid.stories.svelte +47 -50
  53. package/dist/components/datagrid/tr/bond.svelte.d.ts +4 -2
  54. package/dist/components/datagrid/tr/bond.svelte.js +9 -7
  55. package/dist/components/datagrid/tr/datagrid-tr.svelte +90 -88
  56. package/dist/components/date-picker/date-picker-calendar.svelte +2 -2
  57. package/dist/components/date-picker/date-picker-header.svelte +100 -100
  58. package/dist/components/date-picker/date-picker-months.svelte +142 -142
  59. package/dist/components/date-picker/date-picker-root.svelte +95 -95
  60. package/dist/components/date-picker/date-picker-years.svelte +205 -205
  61. package/dist/components/date-picker/date-picker.stories.svelte +35 -42
  62. package/dist/components/dialog/bond.svelte.d.ts +13 -3
  63. package/dist/components/dialog/bond.svelte.js +66 -5
  64. package/dist/components/dialog/dialog-content.svelte +2 -20
  65. package/dist/components/dialog/dialog-root.svelte +91 -110
  66. package/dist/components/dialog/dialog.stories.svelte +34 -37
  67. package/dist/components/dialog/motion.svelte.d.ts +13 -0
  68. package/dist/components/dialog/motion.svelte.js +44 -0
  69. package/dist/components/drawer/attachments.svelte.d.ts +1 -1
  70. package/dist/components/drawer/attachments.svelte.js +7 -10
  71. package/dist/components/drawer/bond.svelte.d.ts +24 -5
  72. package/dist/components/drawer/bond.svelte.js +77 -11
  73. package/dist/components/drawer/drawer-content.svelte +49 -42
  74. package/dist/components/drawer/drawer.stories.svelte +144 -224
  75. package/dist/components/drawer/index.d.ts +2 -0
  76. package/dist/components/drawer/index.js +2 -0
  77. package/dist/components/drawer/motion.d.ts +15 -0
  78. package/dist/components/drawer/motion.js +28 -0
  79. package/dist/components/dropdown/atoms.d.ts +1 -1
  80. package/dist/components/dropdown/atoms.js +1 -1
  81. package/dist/components/dropdown/bond.svelte.d.ts +5 -1
  82. package/dist/components/dropdown/dropdown-root.svelte +1 -1
  83. package/dist/components/dropdown/dropdown.stories.svelte +38 -41
  84. package/dist/components/dropdown/index.d.ts +1 -0
  85. package/dist/components/form/form.stories.svelte +58 -61
  86. package/dist/components/image/image.stories.svelte +9 -12
  87. package/dist/components/input/input.stories.svelte +11 -14
  88. package/dist/components/label/label.stories.svelte +1 -12
  89. package/dist/components/label/label.stories.svelte.d.ts +24 -4
  90. package/dist/components/lazy/lazy.stories.svelte +28 -35
  91. package/dist/components/lazy/lazy.svelte +28 -28
  92. package/dist/components/link/link.stories.svelte +1 -12
  93. package/dist/components/link/link.stories.svelte.d.ts +24 -4
  94. package/dist/components/list/list-item.svelte +20 -20
  95. package/dist/components/menu/atoms.d.ts +1 -0
  96. package/dist/components/menu/atoms.js +1 -0
  97. package/dist/components/menu/index.d.ts +2 -1
  98. package/dist/components/menu/index.js +1 -1
  99. package/dist/components/menu/menu-item.svelte +69 -51
  100. package/dist/components/menu/menu-item.svelte.d.ts +1 -0
  101. package/dist/components/menu/menu-list.svelte +40 -40
  102. package/dist/components/menu/menu.stories.svelte +9 -12
  103. package/dist/components/popover/bond.svelte.d.ts +20 -7
  104. package/dist/components/popover/bond.svelte.js +104 -45
  105. package/dist/components/popover/motion.d.ts +6 -0
  106. package/dist/components/popover/motion.js +56 -0
  107. package/dist/components/popover/popover-arrow.svelte +4 -4
  108. package/dist/components/popover/popover-content.svelte +137 -178
  109. package/dist/components/popover/popover-indicator.svelte +2 -1
  110. package/dist/components/popover/popover-root.svelte +1 -1
  111. package/dist/components/popover/popover.stories.svelte +49 -52
  112. package/dist/components/popover/types.d.ts +9 -7
  113. package/dist/components/portal/active-portal.svelte +29 -22
  114. package/dist/components/portal/active-portal.svelte.d.ts +2 -9
  115. package/dist/components/portal/portal-root.svelte +76 -83
  116. package/dist/components/portal/portal-root.svelte.d.ts +4 -6
  117. package/dist/components/portal/teleport.svelte +49 -50
  118. package/dist/components/portal/teleport.svelte.d.ts +3 -4
  119. package/dist/components/qr-code/qr-code.stories.svelte +18 -27
  120. package/dist/components/qr-code/qr-code.svelte +75 -75
  121. package/dist/components/radio/radio-group.stories.svelte +21 -30
  122. package/dist/components/radio/radio.stories.svelte +1 -10
  123. package/dist/components/radio/radio.svelte +109 -109
  124. package/dist/components/radio/types.d.ts +98 -0
  125. package/dist/components/radio/types.js +2 -0
  126. package/dist/components/root/root.svelte +104 -121
  127. package/dist/components/scrollable/scrollable-root.svelte.d.ts +2 -2
  128. package/dist/components/scrollable/scrollable.stories.svelte +95 -105
  129. package/dist/components/sidebar/index.d.ts +2 -0
  130. package/dist/components/sidebar/index.js +2 -0
  131. package/dist/components/sidebar/motion.svelte.d.ts +11 -0
  132. package/dist/components/sidebar/motion.svelte.js +16 -0
  133. package/dist/components/sidebar/sidebar-content.svelte +3 -2
  134. package/dist/components/sidebar/sidebar-root.svelte +39 -41
  135. package/dist/components/sidebar/sidebar.stories.svelte +43 -54
  136. package/dist/components/sidebar/types.d.ts +3 -12
  137. package/dist/components/tabs/tab/bond.svelte.d.ts +4 -1
  138. package/dist/components/tabs/tab/bond.svelte.js +4 -1
  139. package/dist/components/tabs/tabs.stories.svelte +31 -34
  140. package/dist/components/textarea/atoms.d.ts +1 -0
  141. package/dist/components/textarea/atoms.js +1 -0
  142. package/dist/components/textarea/textarea-input.svelte +9 -6
  143. package/dist/components/textarea/textarea-root.svelte +9 -9
  144. package/dist/components/textarea/textarea-root.svelte.d.ts +2 -0
  145. package/dist/components/tooltip/tooltip-trigger.svelte +39 -37
  146. package/dist/components/tooltip/tooltip-trigger.svelte.d.ts +1 -0
  147. package/dist/components/tooltip/tooltip.stories.svelte +7 -10
  148. package/dist/components/tree/tree.stories.svelte +102 -94
  149. package/dist/context/preset.svelte.d.ts +3 -3
  150. package/dist/icons/icon-copy.svelte +6 -0
  151. package/dist/{components/radio/types.svelte.d.ts → icons/icon-copy.svelte.d.ts} +3 -3
  152. package/dist/utils/function.d.ts +2 -0
  153. package/dist/utils/function.js +6 -0
  154. package/dist/utils/markdown-to-llm.d.ts +28 -0
  155. package/dist/utils/markdown-to-llm.js +76 -0
  156. package/package.json +6 -10
  157. package/dist/actions/animation.svelte.d.ts +0 -6
  158. package/dist/actions/animation.svelte.js +0 -14
  159. package/dist/actions/clickout.svelte.d.ts +0 -2
  160. package/dist/actions/clickout.svelte.js +0 -15
  161. package/dist/actions/popover.svelte.d.ts +0 -19
  162. package/dist/actions/popover.svelte.js +0 -81
  163. package/dist/actions/portal.svelte.d.ts +0 -8
  164. package/dist/actions/portal.svelte.js +0 -32
  165. package/dist/attachments/gsap.svelte.d.ts +0 -2
  166. package/dist/attachments/gsap.svelte.js +0 -26
  167. package/dist/components/radio/types.svelte +0 -0
  168. package/llm/composition.md +0 -395
  169. package/llm/crafting.md +0 -838
  170. package/llm/motion.md +0 -970
  171. package/llm/philosophy.md +0 -23
  172. package/llm/preset-variant-integration.md +0 -516
  173. package/llm/preset.md +0 -383
  174. package/llm/styling.md +0 -216
  175. package/llm/usage.md +0 -46
  176. package/llm/variants.md +0 -1259
@@ -1,9 +1,8 @@
1
1
  <script lang="ts" generics="E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base">
2
- import { animate as motion } from 'motion';
3
- import { DURATION } from '../../shared';
4
2
  import { HtmlAtom, type Base } from '../atom';
5
3
  import { DialogBond } from './bond.svelte';
6
4
  import type { DialogContentProps } from './types';
5
+ import { animateDialogContent } from './motion.svelte';
7
6
 
8
7
  const bond = DialogBond.get();
9
8
 
@@ -12,7 +11,7 @@
12
11
  children = undefined,
13
12
  onmount = undefined,
14
13
  ondestroy = undefined,
15
- animate = _animate,
14
+ animate = animateDialogContent(),
16
15
  enter = undefined,
17
16
  exit = undefined,
18
17
  initial = undefined,
@@ -23,23 +22,6 @@
23
22
  ...bond?.content({}),
24
23
  ...restProps
25
24
  });
26
-
27
- const open = $derived(bond?.state?.props?.open ?? false);
28
-
29
- function _animate(node: HTMLElement) {
30
- if (open) {
31
- bond?.elements.root?.show?.();
32
- }
33
-
34
- motion(
35
- node,
36
- { scale: 0.9 + 0.1 * +open, opacity: +open },
37
- {
38
- duration: DURATION.normal / 1000,
39
- ease: 'anticipate'
40
- }
41
- );
42
- }
43
25
  </script>
44
26
 
45
27
  <HtmlAtom
@@ -1,110 +1,91 @@
1
- <script lang="ts" generics="E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base">
2
- import { animate as motion } from 'motion';
3
- import { Teleport, ActivePortal } from '../portal';
4
- import { defineProperty, defineState } from '../../utils';
5
- import type { Base } from '../atom';
6
- import { DURATION } from '../../shared';
7
- import { DialogBond, DialogBondState, type DialogBondProps } from './bond.svelte';
8
- import type { DialogProps } from './types';
9
-
10
- let {
11
- class: klass = '',
12
- open = $bindable(false),
13
- disabled = false,
14
- as = 'dialog' as E,
15
- portal = undefined,
16
- factory = _factory,
17
- onmount = undefined,
18
- ondestroy = undefined,
19
- animate = _animate,
20
- enter = undefined,
21
- exit = undefined,
22
- initial = undefined,
23
- children = undefined,
24
- ...restProps
25
- }: DialogProps<E, B> = $props();
26
-
27
- const bondProps = defineState<DialogBondProps>(
28
- [
29
- defineProperty(
30
- 'open',
31
- () => open,
32
- (v) => {
33
- open = v;
34
- }
35
- )
36
- ],
37
- () => ({ disabled })
38
- );
39
- const bond = _factory(bondProps).share();
40
-
41
- const rootProps = $derived({
42
- ...bond?.root({}),
43
- ...restProps
44
- });
45
-
46
- function _factory(props: typeof bondProps) {
47
- const bondState = new DialogBondState(() => props);
48
- return new DialogBond(bondState);
49
- }
50
-
51
- function _animate(node: HTMLDialogElement) {
52
- motion(
53
- node,
54
- {
55
- opacity: +open
56
- },
57
- {
58
- duration: DURATION.normal / 1000,
59
- ease: 'anticipate',
60
- onComplete: () => {
61
- if (!open) {
62
- node?.close?.();
63
- }
64
- }
65
- }
66
- );
67
- }
68
-
69
- function onclickDialogElement(ev: MouseEvent) {
70
- if (bond?.elements?.content?.contains(ev.target)) {
71
- return;
72
- }
73
-
74
- // Clicked the backdrop
75
- bond.state.close();
76
- }
77
-
78
- export function getBond() {
79
- return bond;
80
- }
81
- </script>
82
-
83
- <Teleport
84
- {as}
85
- {bond}
86
- preset="dialog"
87
- portal={portal ?? 'root.l1'}
88
- class={[
89
- 'border-border pointer-events-auto fixed top-0 left-0 flex h-full w-full items-center justify-center bg-neutral-900/10 opacity-0',
90
- !open && 'pointer-events-none',
91
- '$preset',
92
- klass
93
- ]}
94
- enter={enter?.bind(bond.state)}
95
- exit={exit?.bind(bond.state)}
96
- initial={initial?.bind(bond.state)}
97
- animate={animate?.bind(bond.state)}
98
- onmount={onmount?.bind(bond.state)}
99
- ondestroy={ondestroy?.bind(bond.state)}
100
- onclick={onclickDialogElement}
101
- oncancel={(ev) => {
102
- ev.preventDefault();
103
- open = false;
104
- }}
105
- {...rootProps}
106
- >
107
- <ActivePortal portal={portal ?? 'root.l1'}>
108
- {@render children?.({ dialog: bond })}
109
- </ActivePortal>
110
- </Teleport>
1
+ <script lang="ts" generics="E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base">
2
+ import { Teleport, ActivePortal } from '../portal';
3
+ import { defineProperty, defineState } from '../../utils';
4
+ import type { Base } from '../atom';
5
+ import { DialogBond, DialogBondState, type DialogBondProps } from './bond.svelte';
6
+ import type { DialogProps } from './types';
7
+ import { animateDialogRoot } from './motion.svelte';
8
+
9
+ let {
10
+ class: klass = '',
11
+ open = $bindable(false),
12
+ disabled = false,
13
+ as = 'dialog' as E,
14
+ portal = undefined,
15
+ factory = _factory,
16
+ onmount = undefined,
17
+ ondestroy = undefined,
18
+ animate = animateDialogRoot(),
19
+ enter = undefined,
20
+ exit = undefined,
21
+ initial = undefined,
22
+ children = undefined,
23
+ ...restProps
24
+ }: DialogProps<E, B> = $props();
25
+
26
+ const bondProps = defineState<DialogBondProps>(
27
+ [
28
+ defineProperty(
29
+ 'open',
30
+ () => open,
31
+ (v) => {
32
+ open = v;
33
+ }
34
+ )
35
+ ],
36
+ () => ({ disabled })
37
+ );
38
+ const bond = _factory(bondProps).share();
39
+
40
+ const rootProps = $derived({
41
+ ...bond?.root(),
42
+ ...restProps
43
+ });
44
+
45
+ function _factory(props: typeof bondProps) {
46
+ const bondState = new DialogBondState(() => props);
47
+ return new DialogBond(bondState);
48
+ }
49
+
50
+ function onclickDialogElement(ev: MouseEvent) {
51
+ if (bond?.elements?.content?.contains(ev.target)) {
52
+ return;
53
+ }
54
+
55
+ // Clicked the backdrop
56
+ bond.state.close();
57
+ }
58
+
59
+ export function getBond() {
60
+ return bond;
61
+ }
62
+ </script>
63
+
64
+ <Teleport
65
+ {as}
66
+ {bond}
67
+ preset="dialog"
68
+ portal={portal ?? 'root.l1'}
69
+ class={[
70
+ 'border-border pointer-events-auto fixed top-0 left-0 flex h-full w-full items-center justify-center bg-neutral-900/10 opacity-0',
71
+ !open && 'pointer-events-none',
72
+ '$preset',
73
+ klass
74
+ ]}
75
+ enter={enter?.bind(bond.state)}
76
+ exit={exit?.bind(bond.state)}
77
+ initial={initial?.bind(bond.state)}
78
+ animate={animate?.bind(bond.state)}
79
+ onmount={onmount?.bind(bond.state)}
80
+ ondestroy={ondestroy?.bind(bond.state)}
81
+ onclick={onclickDialogElement}
82
+ oncancel={(ev) => {
83
+ ev.preventDefault();
84
+ open = false;
85
+ }}
86
+ {...rootProps}
87
+ >
88
+ <ActivePortal portal={portal ?? 'root.l1'}>
89
+ {@render children?.({ dialog: bond })}
90
+ </ActivePortal>
91
+ </Teleport>
@@ -2,7 +2,6 @@
2
2
  import { defineMeta } from '@storybook/addon-svelte-csf';
3
3
  import { Dialog as ADialog } from '.';
4
4
  import { Dropdown } from '../dropdown';
5
- import Root from '../root/root.svelte';
6
5
  import { dialog } from './attachements.svelte';
7
6
 
8
7
  // More on how to set up stories at: https://storybook.js.org/docs/writing-stories
@@ -24,44 +23,42 @@
24
23
  </script>
25
24
 
26
25
  <Story name="Dialog" args={{}}>
27
- <Root class="p-4">
28
- <div class="size-10 bg-red-500"></div>
29
- <button onclick={() => (isDialogOpen = !isDialogOpen)}>Open Dialog</button>
26
+ <div class="size-10 bg-red-500"></div>
27
+ <button onclick={() => (isDialogOpen = !isDialogOpen)}>Open Dialog</button>
30
28
 
31
- <ADialog.Root class="bg-neutral-900/20" bind:open={isDialogOpen}>
32
- <ADialog.Content>
33
- <ADialog.Header>
34
- <div>Open Popover</div>
35
- <ADialog.CloseButton class="ml-auto"></ADialog.CloseButton>
36
- </ADialog.Header>
29
+ <ADialog.Root class="bg-neutral-900/20" bind:open={isDialogOpen}>
30
+ <ADialog.Content>
31
+ <ADialog.Header>
32
+ <div>Open Popover</div>
33
+ <ADialog.CloseButton class="ml-auto"></ADialog.CloseButton>
34
+ </ADialog.Header>
37
35
 
38
- <ADialog.Body>
39
- <p
40
- {@attach dialog((node, atom) => {
41
- console.log(atom);
42
- })}
43
- >
44
- Mauris et habitasse cubilia potenti at condimentum iaculis nam. Ante fusce litora
45
- tristique letius libero. Curabitur vitae cursus consectetur feugiat aenean viverra vel
46
- dolor diam nascetur.
47
- </p>
36
+ <ADialog.Body>
37
+ <p
38
+ {@attach dialog((node, atom) => {
39
+ console.log(atom);
40
+ })}
41
+ >
42
+ Mauris et habitasse cubilia potenti at condimentum iaculis nam. Ante fusce litora
43
+ tristique letius libero. Curabitur vitae cursus consectetur feugiat aenean viverra vel
44
+ dolor diam nascetur.
45
+ </p>
48
46
 
49
- <Dropdown.Root open={isDialogOpen && isDropdownOpen} class="w-full">
50
- <Dropdown.Trigger>Hello World</Dropdown.Trigger>
51
- <Dropdown.List>
52
- <Dropdown.Item id="ar">Arabic</Dropdown.Item>
53
- <Dropdown.Item id="en">English</Dropdown.Item>
54
- <Dropdown.Item id="sp">Spanish</Dropdown.Item>
55
- <Dropdown.Item id="it">Italian</Dropdown.Item>
56
- </Dropdown.List>
57
- </Dropdown.Root>
58
- </ADialog.Body>
47
+ <Dropdown.Root open={isDialogOpen && isDropdownOpen} class="w-full">
48
+ <Dropdown.Trigger>Hello World</Dropdown.Trigger>
49
+ <Dropdown.List>
50
+ <Dropdown.Item id="ar">Arabic</Dropdown.Item>
51
+ <Dropdown.Item id="en">English</Dropdown.Item>
52
+ <Dropdown.Item id="sp">Spanish</Dropdown.Item>
53
+ <Dropdown.Item id="it">Italian</Dropdown.Item>
54
+ </Dropdown.List>
55
+ </Dropdown.Root>
56
+ </ADialog.Body>
59
57
 
60
- <ADialog.Footer class="gap-4">
61
- <button onclick={() => (isDialogOpen = false)}>Cancel</button>
62
- <button>Save</button>
63
- </ADialog.Footer>
64
- </ADialog.Content>
65
- </ADialog.Root>
66
- </Root>
58
+ <ADialog.Footer class="gap-4">
59
+ <button onclick={() => (isDialogOpen = false)}>Cancel</button>
60
+ <button>Save</button>
61
+ </ADialog.Footer>
62
+ </ADialog.Content>
63
+ </ADialog.Root>
67
64
  </Story>
@@ -0,0 +1,13 @@
1
+ type AnimateDialogRootParams = {
2
+ duration?: number;
3
+ delay?: number;
4
+ ease?: string;
5
+ };
6
+ export declare function animateDialogRoot(params?: AnimateDialogRootParams): (node: HTMLElement) => void;
7
+ type AnimateDialogContentParams = {
8
+ duration?: number;
9
+ delay?: number;
10
+ ease?: string;
11
+ };
12
+ export declare function animateDialogContent(params?: AnimateDialogContentParams): (node: HTMLElement) => void;
13
+ export {};
@@ -0,0 +1,44 @@
1
+ import { DURATION } from '../../shared';
2
+ import { animate } from 'motion';
3
+ import { DialogBond } from './bond.svelte';
4
+ export function animateDialogRoot(params = {}) {
5
+ const { duration = DURATION.fast / 1000, delay = 0, ease = 'anticipate' } = params;
6
+ return (node) => {
7
+ const bond = DialogBond.get();
8
+ const isOpen = bond?.state.props.open ?? false;
9
+ if (node instanceof HTMLDialogElement) {
10
+ node.show();
11
+ }
12
+ animate(node, {
13
+ opacity: +isOpen
14
+ }, {
15
+ duration,
16
+ delay,
17
+ ease
18
+ });
19
+ };
20
+ }
21
+ export function animateDialogContent(params = {}) {
22
+ const { duration = DURATION.fast / 1000, delay = 0, ease = 'anticipate' } = params;
23
+ const bond = DialogBond.get();
24
+ return (node) => {
25
+ const isOpen = bond?.state.props.open ?? false;
26
+ if (!bond?.elements.root.open) {
27
+ if (node instanceof HTMLDialogElement) {
28
+ node.show();
29
+ }
30
+ }
31
+ animate(node, { scale: 0.9 + 0.1 * +isOpen, opacity: +isOpen }, {
32
+ duration,
33
+ easing: ease,
34
+ delay,
35
+ onComplete: () => {
36
+ if (!isOpen) {
37
+ if (node instanceof HTMLDialogElement) {
38
+ node.close();
39
+ }
40
+ }
41
+ }
42
+ });
43
+ };
44
+ }
@@ -3,4 +3,4 @@ export declare function drawer(callback: (node: HTMLElement, bond?: DrawerBond)
3
3
  export declare function toggleDrawer(onclick?: (ev: MouseEvent) => void): (node: HTMLElement) => () => void;
4
4
  export declare function openDrawer(onclick?: (ev: MouseEvent) => void): (node: HTMLElement) => () => void;
5
5
  export declare function closeDrawer(onclick?: (ev: MouseEvent) => void): (node: HTMLElement) => (() => void) | undefined;
6
- export declare function clickoutDrawer(onclickout?: (ev: PointerEvent) => void): (node: Element) => () => void;
6
+ export declare function clickoutDrawer(onclickout?: (ev: PointerEvent, bond?: DrawerBond) => void): (node: Element) => () => void;
@@ -1,4 +1,3 @@
1
- import { on } from '../../attachments/event.svelte';
2
1
  import { clickout } from '../../attachments/clickout.svelte';
3
2
  import { DrawerBond } from './bond.svelte';
4
3
  export function drawer(callback) {
@@ -65,18 +64,16 @@ export function clickoutDrawer(onclickout) {
65
64
  return;
66
65
  }
67
66
  const target = ev.target;
68
- if (!bond.elements.root.contains(target)) {
67
+ if (bond.elements.content?.contains(target)) {
69
68
  return;
70
69
  }
71
- if (bond.elements.content?.contains(target)) {
70
+ onclickout?.(ev, bond);
71
+ if (ev.defaultPrevented) {
72
72
  return;
73
73
  }
74
- onclickout?.(ev);
75
- return on('click', (ev, bond) => {
76
- if (bond?.elements?.content?.contains(ev.target)) {
77
- return;
78
- }
79
- bond?.state?.close?.();
80
- }, DrawerBond.get);
74
+ bond.state.close();
75
+ }, {
76
+ capture: true,
77
+ passive: true
81
78
  });
82
79
  }
@@ -18,16 +18,27 @@ export type DrawerBondElements = {
18
18
  export declare class DrawerBond<Props extends DrawerBondProps = DrawerBondProps, State extends DrawerBondState<Props> = DrawerBondState<Props>> extends Bond<Props, State, DrawerBondElements> {
19
19
  static CONTEXT_KEY: string;
20
20
  constructor(state: State);
21
- root(props?: Record<string, unknown>): {
21
+ root(props?: Record<string, unknown> & {
22
+ onclick?: (ev: MouseEvent) => void;
23
+ onkeydown?: (ev: KeyboardEvent) => void;
24
+ }): {
25
+ onclick?: (ev: MouseEvent) => void;
26
+ onkeydown: (ev: KeyboardEvent) => void;
22
27
  id: string;
23
- 'aria-expanded': boolean;
24
- 'aria-disabled': boolean;
28
+ role: string;
29
+ 'aria-modal': boolean;
25
30
  'aria-labelledby': string | undefined;
31
+ 'aria-describedby': string | undefined;
32
+ 'aria-hidden': boolean;
33
+ inert: string | undefined;
34
+ tabindex: number;
26
35
  'data-active': boolean;
36
+ 'data-open': boolean;
27
37
  'data-kind': string;
28
38
  };
29
39
  content(props?: Record<string, unknown>): {
30
40
  id: string;
41
+ role: string;
31
42
  'data-kind': string;
32
43
  };
33
44
  body(props?: Record<string, unknown>): {
@@ -42,6 +53,8 @@ export declare class DrawerBond<Props extends DrawerBondProps = DrawerBondProps,
42
53
  };
43
54
  title(props?: Record<string, unknown>): {
44
55
  id: string;
56
+ role: string;
57
+ 'aria-level': number;
45
58
  'data-kind': string;
46
59
  };
47
60
  description(props?: Record<string, unknown>): {
@@ -50,10 +63,16 @@ export declare class DrawerBond<Props extends DrawerBondProps = DrawerBondProps,
50
63
  };
51
64
  footer(props?: Record<string, unknown>): {
52
65
  id: string;
66
+ role: string;
53
67
  'data-kind': string;
54
68
  };
55
- backdrop(): {
56
- [x: symbol]: (node: HTMLElement) => void;
69
+ backdrop(props?: Record<string, unknown> & {
70
+ onclick?: (ev: MouseEvent) => void;
71
+ }): {
72
+ onclick: (ev: MouseEvent) => void;
73
+ role: string;
74
+ 'aria-hidden': boolean;
75
+ 'data-kind': string;
57
76
  };
58
77
  share(): this;
59
78
  static get(): DrawerBond | undefined;
@@ -19,27 +19,77 @@ export class DrawerBond extends Bond {
19
19
  }
20
20
  root(props = {}) {
21
21
  const id = getElementId(this.id, DRAWER_ELEMENTS_KIND.root);
22
- const drawerHeaderId = getElementId(this.id, DRAWER_ELEMENTS_KIND.header);
23
22
  const drawerTitleId = getElementId(this.id, DRAWER_ELEMENTS_KIND.title);
24
- const haveHeaderElement = !!this.elements.header;
23
+ const drawerDescriptionId = getElementId(this.id, DRAWER_ELEMENTS_KIND.description);
24
+ const haveDescriptionElement = !!this.elements.description;
25
25
  const haveTitleElement = !!this.elements.title;
26
26
  const isOpen = this.state?.props?.open ?? false;
27
27
  const isDisabled = this.state?.props?.disabled ?? false;
28
28
  const isActive = isOpen && !isDisabled;
29
+ // Focus trap handler
30
+ const focusTrap = (ev) => {
31
+ const node = ev.currentTarget;
32
+ if (ev.key === 'Tab') {
33
+ const focusableElements = node.querySelectorAll('a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])');
34
+ const firstElement = focusableElements[0];
35
+ const lastElement = focusableElements[focusableElements.length - 1];
36
+ if (focusableElements.length === 0)
37
+ return;
38
+ if (ev.shiftKey && document.activeElement === firstElement) {
39
+ ev.preventDefault();
40
+ lastElement?.focus();
41
+ }
42
+ else if (!ev.shiftKey && document.activeElement === lastElement) {
43
+ ev.preventDefault();
44
+ firstElement?.focus();
45
+ }
46
+ }
47
+ };
48
+ let previousActiveElement = null;
29
49
  return {
30
50
  id: id,
31
- 'aria-expanded': isOpen,
32
- 'aria-disabled': isDisabled,
33
- 'aria-labelledby': haveTitleElement
34
- ? drawerTitleId
35
- : haveHeaderElement
36
- ? drawerHeaderId
37
- : undefined,
51
+ role: 'dialog',
52
+ 'aria-modal': true,
53
+ 'aria-labelledby': haveTitleElement ? drawerTitleId : undefined,
54
+ 'aria-describedby': haveDescriptionElement ? drawerDescriptionId : undefined,
55
+ 'aria-hidden': !isActive,
56
+ inert: !isActive ? '' : undefined,
57
+ tabindex: -1,
38
58
  'data-active': isActive,
59
+ 'data-open': isOpen,
39
60
  'data-kind': DRAWER_ELEMENTS_KIND.root,
61
+ onkeydown: (ev) => {
62
+ focusTrap(ev);
63
+ // Close on Escape key
64
+ if (ev.key === 'Escape' && !isDisabled) {
65
+ ev.preventDefault();
66
+ this.state.close();
67
+ }
68
+ props.onkeydown?.(ev);
69
+ },
40
70
  ...props,
41
71
  [createAttachmentKey()]: (node) => {
42
72
  this.elements.root = node;
73
+ if (this.state.props.open) {
74
+ // Store current focus
75
+ previousActiveElement = document.activeElement;
76
+ // Focus first focusable element or drawer itself
77
+ setTimeout(() => {
78
+ const firstFocusable = node.querySelector('a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])');
79
+ if (firstFocusable) {
80
+ firstFocusable.focus();
81
+ }
82
+ else {
83
+ node.focus();
84
+ }
85
+ }, 0);
86
+ }
87
+ else {
88
+ // Restore focus to previous element
89
+ if (previousActiveElement instanceof HTMLElement) {
90
+ previousActiveElement.focus();
91
+ }
92
+ }
43
93
  }
44
94
  };
45
95
  }
@@ -47,6 +97,7 @@ export class DrawerBond extends Bond {
47
97
  const id = getElementId(this.id, DRAWER_ELEMENTS_KIND.content);
48
98
  return {
49
99
  id: id,
100
+ role: 'document',
50
101
  'data-kind': DRAWER_ELEMENTS_KIND.content,
51
102
  ...props,
52
103
  [createAttachmentKey()]: (node) => {
@@ -70,7 +121,7 @@ export class DrawerBond extends Bond {
70
121
  const id = getElementId(this.id, DRAWER_ELEMENTS_KIND.header);
71
122
  return {
72
123
  id: id,
73
- role: 'heading',
124
+ role: 'banner',
74
125
  'data-kind': DRAWER_ELEMENTS_KIND.header,
75
126
  ...props,
76
127
  [createAttachmentKey()]: (node) => {
@@ -82,6 +133,8 @@ export class DrawerBond extends Bond {
82
133
  const id = getElementId(this.id, DRAWER_ELEMENTS_KIND.title);
83
134
  return {
84
135
  id: id,
136
+ role: 'heading',
137
+ 'aria-level': 2,
85
138
  'data-kind': DRAWER_ELEMENTS_KIND.title,
86
139
  ...props,
87
140
  [createAttachmentKey()]: (node) => {
@@ -104,6 +157,7 @@ export class DrawerBond extends Bond {
104
157
  const id = getElementId(this.id, DRAWER_ELEMENTS_KIND.footer);
105
158
  return {
106
159
  id: id,
160
+ role: 'contentinfo',
107
161
  'data-kind': DRAWER_ELEMENTS_KIND.footer,
108
162
  ...props,
109
163
  [createAttachmentKey()]: (node) => {
@@ -111,8 +165,20 @@ export class DrawerBond extends Bond {
111
165
  }
112
166
  };
113
167
  }
114
- backdrop() {
168
+ backdrop(props = {}) {
169
+ const isDisabled = this.state?.props?.disabled ?? false;
115
170
  return {
171
+ role: 'presentation',
172
+ 'aria-hidden': true,
173
+ 'data-kind': DRAWER_ELEMENTS_KIND.backdrop,
174
+ onclick: (ev) => {
175
+ // Close drawer on backdrop click
176
+ if (!isDisabled) {
177
+ this.state.close();
178
+ }
179
+ props.onclick?.(ev);
180
+ },
181
+ ...props,
116
182
  [createAttachmentKey()]: (node) => {
117
183
  this.elements.backdrop = node;
118
184
  }