@svelte-atoms/core 1.0.0-alpha.30 → 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.
- package/README.md +853 -852
- package/dist/components/accordion/accordion-root.svelte +7 -3
- package/dist/components/accordion/accordion.stories.svelte +7 -82
- package/dist/components/accordion/item/accordion-item-body.svelte +44 -42
- package/dist/components/accordion/item/accordion-item-header.svelte +51 -50
- package/dist/components/accordion/item/accordion-item-indicator.svelte +51 -50
- package/dist/components/accordion/item/accordion-item-root.svelte +66 -65
- package/dist/components/accordion/item/bond.svelte.d.ts +2 -0
- package/dist/components/accordion/item/index.d.ts +3 -0
- package/dist/components/accordion/item/index.js +3 -0
- package/dist/components/accordion/item/motion.svelte.d.ts +15 -0
- package/dist/components/accordion/item/motion.svelte.js +30 -0
- package/dist/components/accordion/item/types.d.ts +7 -24
- package/dist/components/alert/alert-close-button.svelte +66 -70
- package/dist/components/alert/alert-description.svelte +42 -42
- package/dist/components/alert/alert-description.svelte.d.ts +3 -6
- package/dist/components/alert/alert-root.svelte +68 -103
- package/dist/components/alert/alert-root.svelte.d.ts +2 -2
- package/dist/components/alert/alert.stories.svelte +400 -400
- package/dist/components/alert/bond.svelte.d.ts +0 -13
- package/dist/components/alert/bond.svelte.js +0 -32
- package/dist/components/alert/types.d.ts +8 -32
- package/dist/components/atom/html-atom.svelte +261 -261
- package/dist/components/avatar/avatar.stories.svelte +22 -22
- package/dist/components/badge/badge.stories.svelte +12 -12
- package/dist/components/badge/badge.svelte +19 -19
- package/dist/components/breadcrumb/breadcrumb.stories.svelte +5 -5
- package/dist/components/button/button.stories.svelte +27 -27
- package/dist/components/calendar/calendar-day.svelte +101 -96
- package/dist/components/calendar/calendar.stories.svelte +26 -26
- package/dist/components/card/card-body.svelte +39 -39
- package/dist/components/card/card-footer.svelte +41 -41
- package/dist/components/card/card-root.svelte +91 -91
- package/dist/components/card/card.stories.svelte +133 -133
- package/dist/components/checkbox/checkbox.stories.svelte +22 -22
- package/dist/components/checkbox/checkbox.svelte +6 -2
- package/dist/components/collapsible/collapsible.stories.svelte +172 -172
- package/dist/components/combobox/atoms.d.ts +1 -1
- package/dist/components/combobox/atoms.js +1 -1
- package/dist/components/combobox/combobox-root.svelte +65 -65
- package/dist/components/combobox/compobox.stories.svelte +51 -51
- package/dist/components/combobox/index.d.ts +1 -0
- package/dist/components/container/container.stories.svelte +20 -20
- package/dist/components/container/container.svelte.d.ts +1 -1
- package/dist/components/datagrid/datagrid.stories.svelte +72 -72
- package/dist/components/datagrid/tr/bond.svelte.d.ts +4 -2
- package/dist/components/datagrid/tr/bond.svelte.js +9 -7
- package/dist/components/datagrid/tr/datagrid-tr.svelte +90 -88
- package/dist/components/date-picker/date-picker-calendar.svelte +67 -67
- package/dist/components/date-picker/date-picker-root.svelte +95 -95
- package/dist/components/date-picker/date-picker.stories.svelte +35 -35
- package/dist/components/dialog/bond.svelte.d.ts +13 -3
- package/dist/components/dialog/bond.svelte.js +66 -5
- package/dist/components/dialog/dialog-content.svelte +44 -62
- package/dist/components/dialog/dialog-root.svelte +91 -110
- package/dist/components/dialog/dialog.stories.svelte +64 -64
- package/dist/components/dialog/motion.svelte.d.ts +13 -0
- package/dist/components/dialog/motion.svelte.js +44 -0
- package/dist/components/drawer/attachments.svelte.d.ts +1 -1
- package/dist/components/drawer/attachments.svelte.js +1 -3
- package/dist/components/drawer/bond.svelte.d.ts +24 -5
- package/dist/components/drawer/bond.svelte.js +77 -11
- package/dist/components/drawer/drawer-content.svelte +6 -14
- package/dist/components/drawer/drawer.stories.svelte +27 -95
- package/dist/components/drawer/index.d.ts +2 -0
- package/dist/components/drawer/index.js +2 -0
- package/dist/components/drawer/motion.d.ts +15 -0
- package/dist/components/drawer/motion.js +28 -0
- package/dist/components/dropdown/atoms.d.ts +1 -1
- package/dist/components/dropdown/atoms.js +1 -1
- package/dist/components/dropdown/bond.svelte.d.ts +5 -1
- package/dist/components/dropdown/dropdown-root.svelte +59 -59
- package/dist/components/dropdown/dropdown.stories.svelte +80 -80
- package/dist/components/dropdown/index.d.ts +1 -0
- package/dist/components/form/form.stories.svelte +96 -96
- package/dist/components/image/image.stories.svelte +20 -20
- package/dist/components/input/input.stories.svelte +35 -35
- package/dist/components/label/label.stories.svelte +15 -15
- package/dist/components/lazy/lazy.stories.svelte +28 -28
- package/dist/components/link/link.stories.svelte +15 -15
- package/dist/components/list/list-item.svelte +20 -20
- package/dist/components/menu/atoms.d.ts +1 -0
- package/dist/components/menu/atoms.js +1 -0
- package/dist/components/menu/index.d.ts +2 -1
- package/dist/components/menu/index.js +1 -1
- package/dist/components/menu/menu-item.svelte +69 -51
- package/dist/components/menu/menu-item.svelte.d.ts +1 -0
- package/dist/components/menu/menu.stories.svelte +33 -33
- package/dist/components/popover/bond.svelte.d.ts +20 -7
- package/dist/components/popover/bond.svelte.js +80 -27
- package/dist/components/popover/motion.d.ts +6 -0
- package/dist/components/popover/motion.js +56 -0
- package/dist/components/popover/popover-arrow.svelte +111 -111
- package/dist/components/popover/popover-content.svelte +34 -72
- package/dist/components/popover/popover-indicator.svelte +44 -44
- package/dist/components/popover/popover-root.svelte +48 -48
- package/dist/components/popover/popover.stories.svelte +3 -3
- package/dist/components/popover/types.d.ts +9 -7
- package/dist/components/portal/active-portal.svelte +29 -22
- package/dist/components/portal/active-portal.svelte.d.ts +2 -9
- package/dist/components/portal/portal-root.svelte +76 -83
- package/dist/components/portal/portal-root.svelte.d.ts +4 -6
- package/dist/components/portal/teleport.svelte +49 -50
- package/dist/components/portal/teleport.svelte.d.ts +3 -4
- package/dist/components/qr-code/qr-code.stories.svelte +18 -18
- package/dist/components/radio/radio-group.stories.svelte +41 -41
- package/dist/components/radio/radio.stories.svelte +17 -17
- package/dist/components/radio/radio.svelte +1 -1
- package/dist/components/radio/types.d.ts +98 -0
- package/dist/components/radio/types.js +2 -0
- package/dist/components/root/root.svelte +13 -30
- package/dist/components/root/root.svelte.d.ts +1 -1
- package/dist/components/scrollable/scrollable-root.svelte.d.ts +2 -2
- package/dist/components/scrollable/scrollable.stories.svelte +116 -116
- package/dist/components/sidebar/index.d.ts +2 -0
- package/dist/components/sidebar/index.js +2 -0
- package/dist/components/sidebar/motion.svelte.d.ts +11 -0
- package/dist/components/sidebar/motion.svelte.js +16 -0
- package/dist/components/sidebar/sidebar-content.svelte +3 -13
- package/dist/components/sidebar/sidebar-root.svelte +39 -39
- package/dist/components/sidebar/sidebar.stories.svelte +43 -43
- package/dist/components/sidebar/types.d.ts +2 -12
- package/dist/components/tabs/tabs.stories.svelte +56 -56
- package/dist/components/textarea/atoms.d.ts +1 -0
- package/dist/components/textarea/atoms.js +1 -0
- package/dist/components/textarea/textarea-input.svelte +9 -6
- package/dist/components/textarea/textarea-root.svelte +9 -9
- package/dist/components/textarea/textarea-root.svelte.d.ts +2 -0
- package/dist/components/tooltip/tooltip-trigger.svelte +2 -2
- package/dist/components/tooltip/tooltip-trigger.svelte.d.ts +1 -0
- package/dist/components/tooltip/tooltip.stories.svelte +32 -32
- package/dist/components/tree/tree.stories.svelte +142 -142
- package/dist/icons/icon-copy.svelte +6 -0
- package/dist/{components/radio/types.svelte.d.ts → icons/icon-copy.svelte.d.ts} +3 -3
- package/dist/utils/markdown-to-llm.d.ts +28 -0
- package/dist/utils/markdown-to-llm.js +76 -0
- package/package.json +1 -2
- package/dist/components/radio/types.svelte +0 -0
- package/llm/composition.md +0 -395
- package/llm/crafting.md +0 -838
- package/llm/motion.md +0 -970
- package/llm/philosophy.md +0 -23
- package/llm/preset-variant-integration.md +0 -516
- package/llm/preset.md +0 -383
- package/llm/styling.md +0 -216
- package/llm/usage.md +0 -46
- package/llm/variants.md +0 -1259
|
@@ -1,110 +1,91 @@
|
|
|
1
|
-
<script lang="ts" generics="E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base">
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import type
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
() =>
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
...
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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>
|
|
@@ -1,64 +1,64 @@
|
|
|
1
|
-
<script module>
|
|
2
|
-
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
3
|
-
import { Dialog as ADialog } from '.';
|
|
4
|
-
import { Dropdown } from '../dropdown';
|
|
5
|
-
import { dialog } from './attachements.svelte';
|
|
6
|
-
|
|
7
|
-
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
|
|
8
|
-
const { Story } = defineMeta({
|
|
9
|
-
title: 'Atoms/Dialog',
|
|
10
|
-
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
|
|
11
|
-
|
|
12
|
-
parameters: {
|
|
13
|
-
// More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
|
|
14
|
-
layout: 'fullscreen'
|
|
15
|
-
},
|
|
16
|
-
args: {}
|
|
17
|
-
});
|
|
18
|
-
</script>
|
|
19
|
-
|
|
20
|
-
<script lang="ts">
|
|
21
|
-
let isDialogOpen = $state(false);
|
|
22
|
-
let isDropdownOpen = $state(false);
|
|
23
|
-
</script>
|
|
24
|
-
|
|
25
|
-
<Story name="Dialog" args={{}}>
|
|
26
|
-
<div class="size-10 bg-red-500"></div>
|
|
27
|
-
<button onclick={() => (isDialogOpen = !isDialogOpen)}>Open Dialog</button>
|
|
28
|
-
|
|
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>
|
|
35
|
-
|
|
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>
|
|
46
|
-
|
|
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>
|
|
57
|
-
|
|
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>
|
|
64
|
-
</Story>
|
|
1
|
+
<script module>
|
|
2
|
+
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
3
|
+
import { Dialog as ADialog } from '.';
|
|
4
|
+
import { Dropdown } from '../dropdown';
|
|
5
|
+
import { dialog } from './attachements.svelte';
|
|
6
|
+
|
|
7
|
+
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
|
|
8
|
+
const { Story } = defineMeta({
|
|
9
|
+
title: 'Atoms/Dialog',
|
|
10
|
+
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
|
|
11
|
+
|
|
12
|
+
parameters: {
|
|
13
|
+
// More on how to position stories at: https://storybook.js.org/docs/configure/story-layout
|
|
14
|
+
layout: 'fullscreen'
|
|
15
|
+
},
|
|
16
|
+
args: {}
|
|
17
|
+
});
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<script lang="ts">
|
|
21
|
+
let isDialogOpen = $state(false);
|
|
22
|
+
let isDropdownOpen = $state(false);
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<Story name="Dialog" args={{}}>
|
|
26
|
+
<div class="size-10 bg-red-500"></div>
|
|
27
|
+
<button onclick={() => (isDialogOpen = !isDialogOpen)}>Open Dialog</button>
|
|
28
|
+
|
|
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>
|
|
35
|
+
|
|
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>
|
|
46
|
+
|
|
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>
|
|
57
|
+
|
|
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>
|
|
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) {
|
|
@@ -68,8 +67,7 @@ export function clickoutDrawer(onclickout) {
|
|
|
68
67
|
if (bond.elements.content?.contains(target)) {
|
|
69
68
|
return;
|
|
70
69
|
}
|
|
71
|
-
|
|
72
|
-
onclickout?.(ev);
|
|
70
|
+
onclickout?.(ev, bond);
|
|
73
71
|
if (ev.defaultPrevented) {
|
|
74
72
|
return;
|
|
75
73
|
}
|
|
@@ -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
|
-
|
|
24
|
-
'aria-
|
|
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
|
-
|
|
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
|
|
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
|
-
'
|
|
32
|
-
'aria-
|
|
33
|
-
'aria-labelledby': haveTitleElement
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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: '
|
|
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
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<script lang="ts" generics="E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base">
|
|
2
2
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
-
import { HtmlAtom, type Base } from '../atom';
|
|
3
|
+
import { HtmlAtom as Atom, type Base } from '../atom';
|
|
4
4
|
import type { SlideoverContentProps } from './types';
|
|
5
5
|
import { DrawerBond } from './bond.svelte';
|
|
6
|
-
import {
|
|
6
|
+
import { animateDrawerContent } from './motion';
|
|
7
7
|
|
|
8
8
|
type Element = HTMLElementTagNameMap[E];
|
|
9
9
|
|
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
children = undefined,
|
|
16
16
|
onmount = undefined,
|
|
17
17
|
ondestroy = undefined,
|
|
18
|
-
animate =
|
|
18
|
+
animate = animateDrawerContent({ ease: 'easeOut', side: 'left' }),
|
|
19
19
|
enter = undefined,
|
|
20
20
|
exit = undefined,
|
|
21
|
-
initial =
|
|
21
|
+
initial = animateDrawerContent({ ease: 'easeOut', side: 'left', duration: 0 }),
|
|
22
22
|
...restProps
|
|
23
23
|
}: SlideoverContentProps<E, B> & HTMLAttributes<Element> = $props();
|
|
24
24
|
|
|
@@ -26,17 +26,9 @@
|
|
|
26
26
|
...bond?.content(),
|
|
27
27
|
...restProps
|
|
28
28
|
});
|
|
29
|
-
|
|
30
|
-
function _initial(node: HTMLElement) {
|
|
31
|
-
motion(node, { x: isOpen ? 0 : -100 + '%', left: 0 }, { duration: 0.3, ease: 'anticipate' });
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function _animate(node: HTMLElement) {
|
|
35
|
-
motion(node, { x: isOpen ? 0 : -100 + '%', left: 0 }, { duration: 0.3, ease: 'anticipate' });
|
|
36
|
-
}
|
|
37
29
|
</script>
|
|
38
30
|
|
|
39
|
-
<
|
|
31
|
+
<Atom
|
|
40
32
|
preset="drawer.content"
|
|
41
33
|
class={[
|
|
42
34
|
'bg-card text-foreground border-border pointer-events-none absolute',
|
|
@@ -54,4 +46,4 @@
|
|
|
54
46
|
{...contentProps}
|
|
55
47
|
>
|
|
56
48
|
{@render children?.({ drawer: bond })}
|
|
57
|
-
</
|
|
49
|
+
</Atom>
|