@svelte-atoms/core 1.0.0-alpha.30 → 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.
- package/LICENSE +21 -0
- package/README.md +176 -739
- package/dist/attachments/index.d.ts +1 -0
- package/dist/attachments/index.js +1 -0
- package/dist/components/accordion/accordion-root.svelte +65 -61
- package/dist/components/accordion/accordion.stories.svelte +70 -145
- package/dist/components/accordion/item/accordion-item-body.svelte +6 -4
- package/dist/components/accordion/item/accordion-item-header.svelte +2 -1
- package/dist/components/accordion/item/accordion-item-indicator.svelte +2 -1
- package/dist/components/accordion/item/accordion-item-root.svelte +2 -1
- 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 +32 -36
- package/dist/components/alert/alert-description.svelte +1 -1
- package/dist/components/alert/alert-description.svelte.d.ts +3 -6
- package/dist/components/alert/alert-root.svelte +3 -38
- 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 +93 -261
- package/dist/components/atom/types.d.ts +3 -2
- package/dist/components/atom/utils.d.ts +37 -0
- package/dist/components/atom/utils.js +208 -0
- 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-item.svelte +1 -1
- package/dist/components/breadcrumb/breadcrumb-separator.svelte +5 -1
- package/dist/components/breadcrumb/breadcrumb.stories.svelte +16 -16
- package/dist/components/button/button.stories.svelte +27 -27
- package/dist/components/calendar/calendar-day.svelte +9 -4
- 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 +159 -155
- package/dist/components/collapsible/bond.svelte.js +2 -1
- package/dist/components/collapsible/collapsible-body.svelte +3 -2
- package/dist/components/collapsible/collapsible.stories.svelte +172 -172
- package/dist/components/collapsible/motion.svelte.d.ts +6 -0
- package/dist/components/collapsible/motion.svelte.js +15 -0
- package/dist/components/combobox/atoms.d.ts +3 -3
- package/dist/components/combobox/atoms.js +3 -3
- package/dist/components/combobox/bond.svelte.d.ts +6 -6
- package/dist/components/combobox/bond.svelte.js +3 -26
- package/dist/components/combobox/combobox-control.svelte +52 -52
- package/dist/components/combobox/{compobox-item.svelte → combobox-item.svelte} +62 -68
- package/dist/components/combobox/combobox-item.svelte.d.ts +12 -0
- package/dist/components/combobox/combobox-root.svelte +65 -65
- package/dist/components/combobox/combobox.stories.svelte +50 -0
- package/dist/components/combobox/combobox.stories.svelte.d.ts +3 -0
- 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 +9 -7
- package/dist/components/date-picker/bond.svelte.d.ts +15 -5
- package/dist/components/date-picker/bond.svelte.js +5 -11
- package/dist/components/date-picker/date-picker-calendar.svelte +2 -2
- 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 +52 -6
- package/dist/components/dialog/dialog-content.svelte +2 -20
- package/dist/components/dialog/dialog-root.svelte +3 -22
- 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 +30 -9
- package/dist/components/drawer/bond.svelte.js +80 -24
- package/dist/components/drawer/drawer-content.svelte +49 -57
- package/dist/components/drawer/drawer-root.svelte +5 -4
- package/dist/components/drawer/drawer.stories.svelte +141 -212
- 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 +22 -19
- package/dist/components/dropdown/bond.svelte.js +29 -53
- package/dist/components/dropdown/dropdown-root.svelte +7 -1
- package/dist/components/dropdown/dropdown-values.svelte +17 -17
- package/dist/components/dropdown/dropdown-values.svelte.d.ts +1 -2
- package/dist/components/dropdown/dropdown.stories.svelte +13 -10
- package/dist/components/dropdown/index.d.ts +2 -0
- package/dist/components/dropdown/index.js +1 -0
- package/dist/components/dropdown/item/attachments.svelte.d.ts +2 -2
- package/dist/components/dropdown/item/attachments.svelte.js +2 -2
- package/dist/components/dropdown/item/controller.svelte.d.ts +34 -0
- package/dist/components/dropdown/item/controller.svelte.js +82 -0
- package/dist/components/dropdown/item/dropdown-item.svelte +109 -102
- package/dist/components/dropdown/item/dropdown-item.svelte.d.ts +13 -28
- package/dist/components/dropdown/item/index.d.ts +3 -0
- package/dist/components/dropdown/item/index.js +3 -0
- package/dist/components/dropdown/item/types.d.ts +29 -0
- package/dist/components/dropdown/item/types.js +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 +2 -2
- package/dist/components/menu/atoms.d.ts +9 -3
- package/dist/components/menu/atoms.js +9 -3
- package/dist/components/menu/bond.svelte.d.ts +54 -0
- package/dist/components/menu/bond.svelte.js +132 -0
- package/dist/components/menu/index.d.ts +3 -1
- package/dist/components/menu/index.js +2 -1
- package/dist/components/menu/item/controller.svelte.d.ts +26 -0
- package/dist/components/menu/item/controller.svelte.js +69 -0
- package/dist/components/menu/item/index.d.ts +2 -0
- package/dist/components/menu/item/index.js +2 -0
- package/dist/components/menu/item/menu-item.svelte +103 -0
- package/dist/components/menu/item/menu-item.svelte.d.ts +31 -0
- package/dist/components/menu/item/types.d.ts +62 -0
- package/dist/components/menu/item/types.js +1 -0
- package/dist/components/menu/{menu-list.svelte → menu-content.svelte} +40 -40
- package/dist/components/menu/{menu-list.svelte.d.ts → menu-content.svelte.d.ts} +3 -3
- package/dist/components/menu/menu-root.svelte +15 -0
- package/dist/components/menu/menu-root.svelte.d.ts +8 -0
- package/dist/components/menu/menu.stories.svelte +5 -5
- package/dist/components/menu/types.d.ts +0 -7
- package/dist/components/popover/bond.svelte.d.ts +18 -8
- package/dist/components/popover/bond.svelte.js +76 -40
- 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 +137 -175
- 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 +37 -49
- package/dist/components/popover/types.d.ts +9 -7
- package/dist/components/portal/active-portal.svelte +12 -5
- package/dist/components/portal/active-portal.svelte.d.ts +2 -9
- package/dist/components/portal/portal-root.svelte +1 -8
- package/dist/components/portal/portal-root.svelte.d.ts +4 -6
- package/dist/components/portal/teleport.svelte +1 -2
- 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 +109 -109
- package/dist/components/radio/types.d.ts +98 -0
- package/dist/components/radio/types.js +2 -0
- package/dist/components/root/index.d.ts +1 -0
- package/dist/components/root/index.js +1 -0
- package/dist/components/root/l0-portal.svelte +8 -0
- package/dist/components/{radio/types.svelte.d.ts → root/l0-portal.svelte.d.ts} +3 -3
- package/dist/components/root/l1-portal.svelte +7 -0
- package/dist/components/root/l1-portal.svelte.d.ts +26 -0
- package/dist/components/root/root.css +119 -119
- package/dist/components/root/root.svelte +26 -44
- package/dist/components/root/root.svelte.d.ts +2 -6
- package/dist/components/root/toasts-portal.svelte +7 -0
- package/dist/components/root/toasts-portal.svelte.d.ts +26 -0
- package/dist/components/root/types.d.ts +17 -0
- 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 +40 -50
- 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 +4 -1
- package/dist/components/textarea/textarea-root.svelte +2 -2
- package/dist/components/textarea/textarea-root.svelte.d.ts +2 -0
- package/dist/components/tooltip/tooltip-trigger.svelte +39 -39
- package/dist/components/tooltip/tooltip-trigger.svelte.d.ts +1 -0
- package/dist/components/tooltip/tooltip.stories.svelte +32 -32
- package/dist/components/tree/index.d.ts +1 -0
- package/dist/components/tree/index.js +1 -0
- package/dist/components/tree/motion.svelte.d.ts +6 -0
- package/dist/components/tree/motion.svelte.js +14 -0
- package/dist/components/tree/tree-body.svelte +4 -3
- package/dist/components/tree/tree.stories.svelte +142 -142
- package/dist/context/preset.svelte.d.ts +3 -1
- package/dist/icons/icon-copy.svelte +6 -0
- package/dist/icons/icon-copy.svelte.d.ts +26 -0
- package/dist/utils/dom.svelte.d.ts +2 -0
- package/dist/utils/dom.svelte.js +21 -0
- package/dist/utils/function.d.ts +1 -1
- package/dist/utils/promise.svelte.d.ts +5 -0
- package/dist/utils/promise.svelte.js +20 -0
- package/package.json +4 -3
- package/dist/components/combobox/compobox-item.svelte.d.ts +0 -34
- package/dist/components/combobox/compobox.stories.svelte +0 -51
- package/dist/components/combobox/compobox.stories.svelte.d.ts +0 -3
- package/dist/components/dropdown/item/bond.svelte.d.ts +0 -42
- package/dist/components/dropdown/item/bond.svelte.js +0 -99
- package/dist/components/menu/menu-item.svelte +0 -51
- package/dist/components/menu/menu-item.svelte.d.ts +0 -36
- 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,99 +0,0 @@
|
|
|
1
|
-
import { getContext, setContext } from 'svelte';
|
|
2
|
-
import { Bond, BondState } from '../../../shared/bond.svelte';
|
|
3
|
-
import { DropdownBond, DropdownBondState } from '../bond.svelte';
|
|
4
|
-
import { createAttachmentKey } from 'svelte/attachments';
|
|
5
|
-
export class DropdownItemBond extends Bond {
|
|
6
|
-
static CONTEXT_KEY = '@atoms/context/dropdown/item';
|
|
7
|
-
#dropdown;
|
|
8
|
-
constructor(state) {
|
|
9
|
-
super(state);
|
|
10
|
-
this.#dropdown = DropdownBond.get();
|
|
11
|
-
if (!this.#dropdown) {
|
|
12
|
-
throw new Error('DropdownItemAtom must be used within a DropdownAtom context');
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
get value() {
|
|
16
|
-
return this.state.value;
|
|
17
|
-
}
|
|
18
|
-
get text() {
|
|
19
|
-
const element = (this.elements?.root?.querySelector('[data-text]') ?? this.elements?.root);
|
|
20
|
-
return element?.innerText ?? '';
|
|
21
|
-
}
|
|
22
|
-
get dropdown() {
|
|
23
|
-
return this.#dropdown;
|
|
24
|
-
}
|
|
25
|
-
mount() {
|
|
26
|
-
this.dropdown?.state.mountItem(this.state.value, this);
|
|
27
|
-
return () => this.unmount();
|
|
28
|
-
}
|
|
29
|
-
unmount() {
|
|
30
|
-
this.dropdown?.state.unmountItem(this.state.value);
|
|
31
|
-
}
|
|
32
|
-
share() {
|
|
33
|
-
return DropdownItemBond.set(this);
|
|
34
|
-
}
|
|
35
|
-
root() {
|
|
36
|
-
return {
|
|
37
|
-
'data-selected': this.state.isSelected,
|
|
38
|
-
[createAttachmentKey()]: (node) => {
|
|
39
|
-
this.elements.root = node;
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
static get() {
|
|
44
|
-
return getContext(DropdownItemBond.CONTEXT_KEY);
|
|
45
|
-
}
|
|
46
|
-
static set(bond) {
|
|
47
|
-
return setContext(DropdownItemBond.CONTEXT_KEY, bond);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
export class DropdownItemBondState extends BondState {
|
|
51
|
-
#dropdown;
|
|
52
|
-
constructor(props) {
|
|
53
|
-
super(props);
|
|
54
|
-
this.#dropdown = DropdownBond.get();
|
|
55
|
-
if (!this.#dropdown) {
|
|
56
|
-
throw new Error('DropdownItemState must be used within a DropdownAtom context');
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
get value() {
|
|
60
|
-
return this.props.value;
|
|
61
|
-
}
|
|
62
|
-
get data() {
|
|
63
|
-
return this.props.data;
|
|
64
|
-
}
|
|
65
|
-
get isSelected() {
|
|
66
|
-
return this.dropdown?.props.values?.includes(this.props.value) ?? false;
|
|
67
|
-
}
|
|
68
|
-
set isSelected(val) {
|
|
69
|
-
if (val) {
|
|
70
|
-
this.dropdown?.select([this.props.value]);
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
this.dropdown?.unselect([this.props.value]);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
get isHighlighted() {
|
|
77
|
-
return this.dropdown?.highlightedItem?.id === this.id;
|
|
78
|
-
}
|
|
79
|
-
get dropdown() {
|
|
80
|
-
return this.#dropdown?.state;
|
|
81
|
-
}
|
|
82
|
-
select() {
|
|
83
|
-
this.dropdown?.select([this.value]);
|
|
84
|
-
}
|
|
85
|
-
unselect() {
|
|
86
|
-
this.dropdown?.unselect([this.value]);
|
|
87
|
-
}
|
|
88
|
-
toggle() {
|
|
89
|
-
if (this.isSelected) {
|
|
90
|
-
this.unselect();
|
|
91
|
-
}
|
|
92
|
-
else {
|
|
93
|
-
this.select();
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
close() {
|
|
97
|
-
this.dropdown?.close();
|
|
98
|
-
}
|
|
99
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
<script lang="ts" generics="T extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base">
|
|
2
|
-
import { PopoverBond } from '../popover/bond.svelte';
|
|
3
|
-
import type { Base } from '../atom';
|
|
4
|
-
import { List } from '../list';
|
|
5
|
-
|
|
6
|
-
const bond = PopoverBond.get();
|
|
7
|
-
|
|
8
|
-
let {
|
|
9
|
-
class: klass = '',
|
|
10
|
-
preset: presetKey = 'menu.item',
|
|
11
|
-
children = undefined,
|
|
12
|
-
onclick = undefined,
|
|
13
|
-
onmount = undefined,
|
|
14
|
-
ondestroy = undefined,
|
|
15
|
-
animate = undefined,
|
|
16
|
-
enter = undefined,
|
|
17
|
-
exit = undefined,
|
|
18
|
-
initial = undefined,
|
|
19
|
-
...restProps
|
|
20
|
-
} = $props();
|
|
21
|
-
|
|
22
|
-
function _onclick(ev: MouseEvent) {
|
|
23
|
-
onclick?.(ev);
|
|
24
|
-
|
|
25
|
-
if (ev.defaultPrevented) {
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
bond?.state.close();
|
|
30
|
-
}
|
|
31
|
-
</script>
|
|
32
|
-
|
|
33
|
-
<List.Item
|
|
34
|
-
{bond}
|
|
35
|
-
preset={presetKey}
|
|
36
|
-
class={[
|
|
37
|
-
'border-border last:border-b-none hover:bg-foreground/5 active:bg-foreground/10 cursor-pointer border-b',
|
|
38
|
-
'$preset',
|
|
39
|
-
klass
|
|
40
|
-
]}
|
|
41
|
-
onmount={onmount?.bind(bond.state)}
|
|
42
|
-
ondestroy={ondestroy?.bind(bond.state)}
|
|
43
|
-
enter={enter?.bind(bond.state)}
|
|
44
|
-
exit={exit?.bind(bond.state)}
|
|
45
|
-
initial={initial?.bind(bond.state)}
|
|
46
|
-
animate={animate?.bind(bond.state)}
|
|
47
|
-
onclick={_onclick}
|
|
48
|
-
{...restProps}
|
|
49
|
-
>
|
|
50
|
-
{@render children?.({ menu: bond })}
|
|
51
|
-
</List.Item>
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import type { Base } from '../atom';
|
|
2
|
-
declare function $$render<T extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base>(): {
|
|
3
|
-
props: {
|
|
4
|
-
class?: string;
|
|
5
|
-
preset?: string;
|
|
6
|
-
children?: any;
|
|
7
|
-
onclick?: any;
|
|
8
|
-
onmount?: any;
|
|
9
|
-
ondestroy?: any;
|
|
10
|
-
animate?: any;
|
|
11
|
-
enter?: any;
|
|
12
|
-
exit?: any;
|
|
13
|
-
initial?: any;
|
|
14
|
-
} & Record<string, any>;
|
|
15
|
-
exports: {};
|
|
16
|
-
bindings: "";
|
|
17
|
-
slots: {};
|
|
18
|
-
events: {};
|
|
19
|
-
};
|
|
20
|
-
declare class __sveltets_Render<T extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base> {
|
|
21
|
-
props(): ReturnType<typeof $$render<T, B>>['props'];
|
|
22
|
-
events(): ReturnType<typeof $$render<T, B>>['events'];
|
|
23
|
-
slots(): ReturnType<typeof $$render<T, B>>['slots'];
|
|
24
|
-
bindings(): "";
|
|
25
|
-
exports(): {};
|
|
26
|
-
}
|
|
27
|
-
interface $$IsomorphicComponent {
|
|
28
|
-
new <T extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T, B>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T, B>['props']>, ReturnType<__sveltets_Render<T, B>['events']>, ReturnType<__sveltets_Render<T, B>['slots']>> & {
|
|
29
|
-
$$bindings?: ReturnType<__sveltets_Render<T, B>['bindings']>;
|
|
30
|
-
} & ReturnType<__sveltets_Render<T, B>['exports']>;
|
|
31
|
-
<T extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base>(internal: unknown, props: ReturnType<__sveltets_Render<T, B>['props']> & {}): ReturnType<__sveltets_Render<T, B>['exports']>;
|
|
32
|
-
z_$$bindings?: ReturnType<__sveltets_Render<any, any>['bindings']>;
|
|
33
|
-
}
|
|
34
|
-
declare const MenuItem: $$IsomorphicComponent;
|
|
35
|
-
type MenuItem<T extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base> = InstanceType<typeof MenuItem<T, B>>;
|
|
36
|
-
export default MenuItem;
|
|
File without changes
|
package/llm/composition.md
DELETED
|
@@ -1,395 +0,0 @@
|
|
|
1
|
-
# Component Composition in @svelte-atoms/core
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
|
|
5
|
-
@svelte-atoms/core components are designed to be **composable** — you can combine them to extend both behavior and UI, creating powerful component combinations. This is achieved through three main patterns:
|
|
6
|
-
|
|
7
|
-
1. **Base Prop Composition** - Replace a component's root element with another component
|
|
8
|
-
2. **Bond Pattern** - Access and share component state across nested components
|
|
9
|
-
3. **Nested Children** - Compose components as siblings/parents for complex UIs
|
|
10
|
-
|
|
11
|
-
## 1. Base Prop Composition
|
|
12
|
-
|
|
13
|
-
The `base=` prop allows you to replace a component's root element with another component, **inheriting all the base component's behavior** while adding new functionality.
|
|
14
|
-
|
|
15
|
-
### Basic Pattern
|
|
16
|
-
|
|
17
|
-
```svelte
|
|
18
|
-
<Tooltip.Trigger base={Button}>Open Tooltip</Tooltip.Trigger>
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
The `Tooltip.Trigger` now **behaves as both** a Tooltip trigger AND a Button:
|
|
22
|
-
|
|
23
|
-
- Gets Button's styling, hover states, click handling
|
|
24
|
-
- Gets Tooltip.Trigger's `aria-*` attributes, open/close logic, positioning
|
|
25
|
-
|
|
26
|
-
### Form Field Composition
|
|
27
|
-
|
|
28
|
-
The most powerful example is `Field.Control`, which adapts to any input component:
|
|
29
|
-
|
|
30
|
-
```svelte
|
|
31
|
-
<!-- Text Input -->
|
|
32
|
-
<Field.Control base={Input.Value} placeholder="Enter name" />
|
|
33
|
-
|
|
34
|
-
<!-- Checkbox -->
|
|
35
|
-
<Field.Control base={Checkbox} />
|
|
36
|
-
|
|
37
|
-
<!-- Radio Group -->
|
|
38
|
-
<Field.Control base={RadioGroup}>
|
|
39
|
-
<Radio value="yes" />
|
|
40
|
-
<Radio value="no" />
|
|
41
|
-
</Field.Control>
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
`Field.Control` automatically:
|
|
45
|
-
|
|
46
|
-
- Connects the base component to form validation
|
|
47
|
-
- Syncs the input value with field state
|
|
48
|
-
- Handles validation on blur/change
|
|
49
|
-
- Links labels via `aria-labelledby`
|
|
50
|
-
|
|
51
|
-
### DataGrid Cell Composition
|
|
52
|
-
|
|
53
|
-
Compose table cells with interactive components:
|
|
54
|
-
|
|
55
|
-
```svelte
|
|
56
|
-
<DataGrid.Td base={Dropdown.Root} placement="bottom-end">
|
|
57
|
-
<Dropdown.Trigger>
|
|
58
|
-
<Icon src={MoreVerticalIcon} />
|
|
59
|
-
</Dropdown.Trigger>
|
|
60
|
-
<Dropdown.List>
|
|
61
|
-
<Dropdown.Item value="edit">Edit</Dropdown.Item>
|
|
62
|
-
<Dropdown.Item value="delete">Delete</Dropdown.Item>
|
|
63
|
-
</Dropdown.List>
|
|
64
|
-
</DataGrid.Td>
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
The `DataGrid.Td` now:
|
|
68
|
-
|
|
69
|
-
- Maintains table cell semantics and styling
|
|
70
|
-
- Adds Dropdown positioning, open/close state
|
|
71
|
-
- Handles keyboard navigation and focus management
|
|
72
|
-
|
|
73
|
-
### Menu & Dropdown Triggers
|
|
74
|
-
|
|
75
|
-
```svelte
|
|
76
|
-
<Menu.Root>
|
|
77
|
-
<Menu.Trigger base={Button}>Select Language</Menu.Trigger>
|
|
78
|
-
<Menu.List>
|
|
79
|
-
<Menu.Item>English</Menu.Item>
|
|
80
|
-
<Menu.Item>Spanish</Menu.Item>
|
|
81
|
-
</Menu.List>
|
|
82
|
-
</Menu.Root>
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
`Menu.Trigger` with `base={Button}`:
|
|
86
|
-
|
|
87
|
-
- Button appearance and interaction
|
|
88
|
-
- Menu trigger accessibility (`aria-haspopup`, `aria-expanded`)
|
|
89
|
-
- Menu open/close toggle on click
|
|
90
|
-
|
|
91
|
-
### How Base Prop Works
|
|
92
|
-
|
|
93
|
-
When you write:
|
|
94
|
-
|
|
95
|
-
```svelte
|
|
96
|
-
<Component base={BaseComponent} {...props}>
|
|
97
|
-
{children}
|
|
98
|
-
</Component>
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
Internally, the component renders:
|
|
102
|
-
|
|
103
|
-
```svelte
|
|
104
|
-
<BaseComponent {...props} {...componentSpecificProps}>
|
|
105
|
-
{children}
|
|
106
|
-
</BaseComponent>
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
All props are forwarded, and the component adds its own behavior (event handlers, ARIA attributes, state bindings) to the base component.
|
|
110
|
-
|
|
111
|
-
## 2. Bond Pattern (State Sharing)
|
|
112
|
-
|
|
113
|
-
Components expose their internal state via a **bond** object through the `{#snippet children({ bond })}` pattern. This allows parent components to access and control child component state.
|
|
114
|
-
|
|
115
|
-
### Accessing Component State
|
|
116
|
-
|
|
117
|
-
```svelte
|
|
118
|
-
<Popover.Root>
|
|
119
|
-
{#snippet children({ popover })}
|
|
120
|
-
<Popover.Trigger base={Button}>
|
|
121
|
-
<div>Open Popover</div>
|
|
122
|
-
<!-- Access popover state to show indicator -->
|
|
123
|
-
<Popover.Indicator />
|
|
124
|
-
</Popover.Trigger>
|
|
125
|
-
|
|
126
|
-
<Popover.Content>
|
|
127
|
-
<!-- Can access popover.state.isOpen, popover.state.close(), etc. -->
|
|
128
|
-
</Popover.Content>
|
|
129
|
-
{/snippet}
|
|
130
|
-
</Popover.Root>
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
The `popover` bond provides:
|
|
134
|
-
|
|
135
|
-
- `popover.state.isOpen` - Current open state
|
|
136
|
-
- `popover.state.close()` - Close the popover programmatically
|
|
137
|
-
- `popover.state.toggle()` - Toggle open/close state
|
|
138
|
-
|
|
139
|
-
### Field Validation Access
|
|
140
|
-
|
|
141
|
-
```svelte
|
|
142
|
-
<Field.Root name="firstName" schema={nameSchema}>
|
|
143
|
-
{#snippet children({ field })}
|
|
144
|
-
<Field.Label>First Name</Field.Label>
|
|
145
|
-
|
|
146
|
-
<Input.Root>
|
|
147
|
-
<Field.Control
|
|
148
|
-
base={Input.Value}
|
|
149
|
-
onblur={() => {
|
|
150
|
-
const results = field?.state.validate();
|
|
151
|
-
console.log(results);
|
|
152
|
-
}}
|
|
153
|
-
/>
|
|
154
|
-
</Input.Root>
|
|
155
|
-
|
|
156
|
-
<!-- Access validation errors -->
|
|
157
|
-
{#if field?.state?.errors?.length > 0}
|
|
158
|
-
<div class="text-xs text-red-600">
|
|
159
|
-
{#each field.state.errors as error}
|
|
160
|
-
<div>{error.message}</div>
|
|
161
|
-
{/each}
|
|
162
|
-
</div>
|
|
163
|
-
{/if}
|
|
164
|
-
{/snippet}
|
|
165
|
-
</Field.Root>
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
The `field` bond provides:
|
|
169
|
-
|
|
170
|
-
- `field.state.validate()` - Trigger validation manually
|
|
171
|
-
- `field.state.errors` - Array of validation errors
|
|
172
|
-
- `field.state.value` - Current field value
|
|
173
|
-
|
|
174
|
-
### Collapsible State Control
|
|
175
|
-
|
|
176
|
-
```svelte
|
|
177
|
-
<Collapsible.Root>
|
|
178
|
-
{#snippet children({ collapsible })}
|
|
179
|
-
<Collapsible.Trigger base={Button}>Toggle Content</Collapsible.Trigger>
|
|
180
|
-
|
|
181
|
-
<Collapsible.Content>
|
|
182
|
-
<div>Collapsible content here</div>
|
|
183
|
-
|
|
184
|
-
<!-- Nested button that can control parent collapsible -->
|
|
185
|
-
<Button onclick={() => collapsible.state.close()}>Close from inside</Button>
|
|
186
|
-
</Collapsible.Content>
|
|
187
|
-
{/snippet}
|
|
188
|
-
</Collapsible.Root>
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
### Dropdown State Inspection
|
|
192
|
-
|
|
193
|
-
```svelte
|
|
194
|
-
<Dropdown.Root>
|
|
195
|
-
{#snippet children({ dropdown })}
|
|
196
|
-
<Dropdown.Trigger base={Button}>Select Option</Dropdown.Trigger>
|
|
197
|
-
|
|
198
|
-
<Dropdown.List>
|
|
199
|
-
<Dropdown.Item value="option1">Option 1</Dropdown.Item>
|
|
200
|
-
<Dropdown.Item value="option2">Option 2</Dropdown.Item>
|
|
201
|
-
</Dropdown.List>
|
|
202
|
-
|
|
203
|
-
<!-- Display selected value outside dropdown -->
|
|
204
|
-
<div>Selected: {dropdown.state.value || 'None'}</div>
|
|
205
|
-
{/snippet}
|
|
206
|
-
</Dropdown.Root>
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
### How Bond Pattern Works
|
|
210
|
-
|
|
211
|
-
Components create a **Bond** instance that holds state and methods:
|
|
212
|
-
|
|
213
|
-
```typescript
|
|
214
|
-
// Inside component implementation
|
|
215
|
-
const bond = new PopoverBond();
|
|
216
|
-
bond.state.isOpen = $state(false);
|
|
217
|
-
bond.state.close = () => {
|
|
218
|
-
bond.state.isOpen = false;
|
|
219
|
-
};
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
The bond is passed to children via snippet props, allowing descendants to access and modify component state.
|
|
223
|
-
|
|
224
|
-
## 3. Nested Component Composition
|
|
225
|
-
|
|
226
|
-
Components can be nested as siblings or parent-child to create complex interactions.
|
|
227
|
-
|
|
228
|
-
### Dialog with Nested Dropdown
|
|
229
|
-
|
|
230
|
-
```svelte
|
|
231
|
-
<Dialog.Root>
|
|
232
|
-
{#snippet children({ dialog })}
|
|
233
|
-
<Dialog.Trigger base={Button}>Open Dialog</Dialog.Trigger>
|
|
234
|
-
|
|
235
|
-
<Dialog.Content>
|
|
236
|
-
<Dialog.Header>
|
|
237
|
-
<Dialog.Title>Select an option</Dialog.Title>
|
|
238
|
-
</Dialog.Header>
|
|
239
|
-
|
|
240
|
-
<!-- Dropdown inside Dialog -->
|
|
241
|
-
<Dropdown.Root>
|
|
242
|
-
{#snippet children({ dropdown })}
|
|
243
|
-
<Dropdown.Trigger base={Button}>Choose Language</Dropdown.Trigger>
|
|
244
|
-
<Dropdown.List>
|
|
245
|
-
<Dropdown.Item value="en">English</Dropdown.Item>
|
|
246
|
-
<Dropdown.Item value="es">Spanish</Dropdown.Item>
|
|
247
|
-
</Dropdown.List>
|
|
248
|
-
{/snippet}
|
|
249
|
-
</Dropdown.Root>
|
|
250
|
-
|
|
251
|
-
<Dialog.Footer>
|
|
252
|
-
<Button onclick={() => dialog.state.close()}>Close</Button>
|
|
253
|
-
</Dialog.Footer>
|
|
254
|
-
</Dialog.Content>
|
|
255
|
-
{/snippet}
|
|
256
|
-
</Dialog.Root>
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
Each component manages its own state independently, but both bonds are accessible for coordination.
|
|
260
|
-
|
|
261
|
-
### Scrollable with Nested Content
|
|
262
|
-
|
|
263
|
-
```svelte
|
|
264
|
-
<Scrollable.Root>
|
|
265
|
-
{#snippet children({ scrollable })}
|
|
266
|
-
<Scrollable.Content>
|
|
267
|
-
<!-- Access scroll position -->
|
|
268
|
-
<div>Scroll Y: {scrollable.state.scrollTop}</div>
|
|
269
|
-
|
|
270
|
-
<!-- Nested interactive components -->
|
|
271
|
-
<Accordion.Root>
|
|
272
|
-
<Accordion.Item value="item1">
|
|
273
|
-
<Accordion.Trigger>Section 1</Accordion.Trigger>
|
|
274
|
-
<Accordion.Content>Content 1</Accordion.Content>
|
|
275
|
-
</Accordion.Item>
|
|
276
|
-
</Accordion.Root>
|
|
277
|
-
</Scrollable.Content>
|
|
278
|
-
{/snippet}
|
|
279
|
-
</Scrollable.Root>
|
|
280
|
-
```
|
|
281
|
-
|
|
282
|
-
### Combobox with Custom Trigger
|
|
283
|
-
|
|
284
|
-
```svelte
|
|
285
|
-
<Combobox.Root>
|
|
286
|
-
{#snippet children({ combobox })}
|
|
287
|
-
<Combobox.Trigger base={Input.Root}>
|
|
288
|
-
<Input.Value placeholder="Search..." />
|
|
289
|
-
<Input.Icon src={SearchIcon} />
|
|
290
|
-
</Combobox.Trigger>
|
|
291
|
-
|
|
292
|
-
<Combobox.List>
|
|
293
|
-
<Combobox.Item value="option1">Option 1</Combobox.Item>
|
|
294
|
-
<Combobox.Item value="option2">Option 2</Combobox.Item>
|
|
295
|
-
</Combobox.List>
|
|
296
|
-
{/snippet}
|
|
297
|
-
</Combobox.Root>
|
|
298
|
-
```
|
|
299
|
-
|
|
300
|
-
The `Input.Root` is composed into the trigger, bringing input styling and icon support to the combobox.
|
|
301
|
-
|
|
302
|
-
## Key Principles
|
|
303
|
-
|
|
304
|
-
1. **Base Prop = Behavior Inheritance**: Use `base=` to layer component behaviors (Button + Menu.Trigger = clickable menu opener)
|
|
305
|
-
|
|
306
|
-
2. **Bond = State Access**: Use `{#snippet children({ bond })}` to access component state and methods for coordination
|
|
307
|
-
|
|
308
|
-
3. **Nesting = UI Composition**: Nest components as needed; each maintains independent state while bonds allow communication
|
|
309
|
-
|
|
310
|
-
4. **Forward Everything**: Components forward all props and classes to their base, enabling full customization
|
|
311
|
-
|
|
312
|
-
5. **Type Safety**: TypeScript infers correct props when using `base=`, providing autocompletion for both the component and the base
|
|
313
|
-
|
|
314
|
-
## Common Patterns
|
|
315
|
-
|
|
316
|
-
### Interactive Table Cell
|
|
317
|
-
|
|
318
|
-
```svelte
|
|
319
|
-
<DataGrid.Td base={Dropdown.Root}>
|
|
320
|
-
<Dropdown.Trigger base={Button} variant="ghost" size="sm">Actions</Dropdown.Trigger>
|
|
321
|
-
<Dropdown.List>
|
|
322
|
-
<Dropdown.Item>Edit</Dropdown.Item>
|
|
323
|
-
<Dropdown.Item>Delete</Dropdown.Item>
|
|
324
|
-
</Dropdown.List>
|
|
325
|
-
</DataGrid.Td>
|
|
326
|
-
```
|
|
327
|
-
|
|
328
|
-
**Combines**: Table cell + Dropdown + Button
|
|
329
|
-
|
|
330
|
-
### Validated Form Field
|
|
331
|
-
|
|
332
|
-
```svelte
|
|
333
|
-
<Field.Root name="email" schema={emailSchema}>
|
|
334
|
-
{#snippet children({ field })}
|
|
335
|
-
<Field.Label>Email</Field.Label>
|
|
336
|
-
<Field.Control
|
|
337
|
-
base={Input.Value}
|
|
338
|
-
type="email"
|
|
339
|
-
placeholder="you@example.com"
|
|
340
|
-
onblur={() => field?.state.validate()}
|
|
341
|
-
/>
|
|
342
|
-
{#if field?.state?.errors}
|
|
343
|
-
<Field.Error />
|
|
344
|
-
{/if}
|
|
345
|
-
{/snippet}
|
|
346
|
-
</Field.Root>
|
|
347
|
-
```
|
|
348
|
-
|
|
349
|
-
**Combines**: Form validation + Input + Label + Error display
|
|
350
|
-
|
|
351
|
-
### Tooltip Button
|
|
352
|
-
|
|
353
|
-
```svelte
|
|
354
|
-
<Tooltip.Root>
|
|
355
|
-
<Tooltip.Trigger base={Button} variant="outline">Delete</Tooltip.Trigger>
|
|
356
|
-
<Tooltip.Content>This action cannot be undone</Tooltip.Content>
|
|
357
|
-
</Tooltip.Root>
|
|
358
|
-
```
|
|
359
|
-
|
|
360
|
-
**Combines**: Tooltip positioning + Button interaction
|
|
361
|
-
|
|
362
|
-
### Controlled Popover with Custom Content
|
|
363
|
-
|
|
364
|
-
```svelte
|
|
365
|
-
<Popover.Root bind:open>
|
|
366
|
-
{#snippet children({ popover })}
|
|
367
|
-
<Popover.Trigger base={Button}>
|
|
368
|
-
Open {popover.state.isOpen ? '(Open)' : '(Closed)'}
|
|
369
|
-
</Popover.Trigger>
|
|
370
|
-
|
|
371
|
-
<Popover.Content class="w-80">
|
|
372
|
-
<Card>
|
|
373
|
-
<Card.Header>
|
|
374
|
-
<Card.Title>Settings</Card.Title>
|
|
375
|
-
</Card.Header>
|
|
376
|
-
<Card.Content>
|
|
377
|
-
<!-- Form fields here -->
|
|
378
|
-
</Card.Content>
|
|
379
|
-
<Card.Footer>
|
|
380
|
-
<Button onclick={() => popover.state.close()}>Close</Button>
|
|
381
|
-
</Card.Footer>
|
|
382
|
-
</Card>
|
|
383
|
-
</Popover.Content>
|
|
384
|
-
{/snippet}
|
|
385
|
-
</Popover.Root>
|
|
386
|
-
```
|
|
387
|
-
|
|
388
|
-
**Combines**: Popover positioning + Button trigger + Card layout + Form
|
|
389
|
-
|
|
390
|
-
## Summary
|
|
391
|
-
|
|
392
|
-
- **`base=` prop**: Inherit behavior from another component (Trigger + Button = clickable trigger)
|
|
393
|
-
- **`{#snippet children({ bond })}`**: Access component state for coordination
|
|
394
|
-
- **Nesting**: Compose complex UIs by nesting components as needed
|
|
395
|
-
- **Composition > Configuration**: Combine simple components instead of creating complex ones with many props
|