@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.
Files changed (221) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +176 -739
  3. package/dist/attachments/index.d.ts +1 -0
  4. package/dist/attachments/index.js +1 -0
  5. package/dist/components/accordion/accordion-root.svelte +65 -61
  6. package/dist/components/accordion/accordion.stories.svelte +70 -145
  7. package/dist/components/accordion/item/accordion-item-body.svelte +6 -4
  8. package/dist/components/accordion/item/accordion-item-header.svelte +2 -1
  9. package/dist/components/accordion/item/accordion-item-indicator.svelte +2 -1
  10. package/dist/components/accordion/item/accordion-item-root.svelte +2 -1
  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 +32 -36
  18. package/dist/components/alert/alert-description.svelte +1 -1
  19. package/dist/components/alert/alert-description.svelte.d.ts +3 -6
  20. package/dist/components/alert/alert-root.svelte +3 -38
  21. package/dist/components/alert/alert-root.svelte.d.ts +2 -2
  22. package/dist/components/alert/alert.stories.svelte +400 -400
  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 +93 -261
  27. package/dist/components/atom/types.d.ts +3 -2
  28. package/dist/components/atom/utils.d.ts +37 -0
  29. package/dist/components/atom/utils.js +208 -0
  30. package/dist/components/avatar/avatar.stories.svelte +22 -22
  31. package/dist/components/badge/badge.stories.svelte +12 -12
  32. package/dist/components/badge/badge.svelte +19 -19
  33. package/dist/components/breadcrumb/breadcrumb-item.svelte +1 -1
  34. package/dist/components/breadcrumb/breadcrumb-separator.svelte +5 -1
  35. package/dist/components/breadcrumb/breadcrumb.stories.svelte +16 -16
  36. package/dist/components/button/button.stories.svelte +27 -27
  37. package/dist/components/calendar/calendar-day.svelte +9 -4
  38. package/dist/components/calendar/calendar.stories.svelte +26 -26
  39. package/dist/components/card/card-body.svelte +39 -39
  40. package/dist/components/card/card-footer.svelte +41 -41
  41. package/dist/components/card/card-root.svelte +91 -91
  42. package/dist/components/card/card.stories.svelte +133 -133
  43. package/dist/components/checkbox/checkbox.stories.svelte +22 -22
  44. package/dist/components/checkbox/checkbox.svelte +159 -155
  45. package/dist/components/collapsible/bond.svelte.js +2 -1
  46. package/dist/components/collapsible/collapsible-body.svelte +3 -2
  47. package/dist/components/collapsible/collapsible.stories.svelte +172 -172
  48. package/dist/components/collapsible/motion.svelte.d.ts +6 -0
  49. package/dist/components/collapsible/motion.svelte.js +15 -0
  50. package/dist/components/combobox/atoms.d.ts +3 -3
  51. package/dist/components/combobox/atoms.js +3 -3
  52. package/dist/components/combobox/bond.svelte.d.ts +6 -6
  53. package/dist/components/combobox/bond.svelte.js +3 -26
  54. package/dist/components/combobox/combobox-control.svelte +52 -52
  55. package/dist/components/combobox/{compobox-item.svelte → combobox-item.svelte} +62 -68
  56. package/dist/components/combobox/combobox-item.svelte.d.ts +12 -0
  57. package/dist/components/combobox/combobox-root.svelte +65 -65
  58. package/dist/components/combobox/combobox.stories.svelte +50 -0
  59. package/dist/components/combobox/combobox.stories.svelte.d.ts +3 -0
  60. package/dist/components/combobox/index.d.ts +1 -0
  61. package/dist/components/container/container.stories.svelte +20 -20
  62. package/dist/components/container/container.svelte.d.ts +1 -1
  63. package/dist/components/datagrid/datagrid.stories.svelte +72 -72
  64. package/dist/components/datagrid/tr/bond.svelte.d.ts +4 -2
  65. package/dist/components/datagrid/tr/bond.svelte.js +9 -7
  66. package/dist/components/datagrid/tr/datagrid-tr.svelte +9 -7
  67. package/dist/components/date-picker/bond.svelte.d.ts +15 -5
  68. package/dist/components/date-picker/bond.svelte.js +5 -11
  69. package/dist/components/date-picker/date-picker-calendar.svelte +2 -2
  70. package/dist/components/date-picker/date-picker-root.svelte +95 -95
  71. package/dist/components/date-picker/date-picker.stories.svelte +35 -35
  72. package/dist/components/dialog/bond.svelte.d.ts +13 -3
  73. package/dist/components/dialog/bond.svelte.js +52 -6
  74. package/dist/components/dialog/dialog-content.svelte +2 -20
  75. package/dist/components/dialog/dialog-root.svelte +3 -22
  76. package/dist/components/dialog/dialog.stories.svelte +64 -64
  77. package/dist/components/dialog/motion.svelte.d.ts +13 -0
  78. package/dist/components/dialog/motion.svelte.js +44 -0
  79. package/dist/components/drawer/attachments.svelte.d.ts +1 -1
  80. package/dist/components/drawer/attachments.svelte.js +1 -3
  81. package/dist/components/drawer/bond.svelte.d.ts +30 -9
  82. package/dist/components/drawer/bond.svelte.js +80 -24
  83. package/dist/components/drawer/drawer-content.svelte +49 -57
  84. package/dist/components/drawer/drawer-root.svelte +5 -4
  85. package/dist/components/drawer/drawer.stories.svelte +141 -212
  86. package/dist/components/drawer/index.d.ts +2 -0
  87. package/dist/components/drawer/index.js +2 -0
  88. package/dist/components/drawer/motion.d.ts +15 -0
  89. package/dist/components/drawer/motion.js +28 -0
  90. package/dist/components/dropdown/atoms.d.ts +1 -1
  91. package/dist/components/dropdown/atoms.js +1 -1
  92. package/dist/components/dropdown/bond.svelte.d.ts +22 -19
  93. package/dist/components/dropdown/bond.svelte.js +29 -53
  94. package/dist/components/dropdown/dropdown-root.svelte +7 -1
  95. package/dist/components/dropdown/dropdown-values.svelte +17 -17
  96. package/dist/components/dropdown/dropdown-values.svelte.d.ts +1 -2
  97. package/dist/components/dropdown/dropdown.stories.svelte +13 -10
  98. package/dist/components/dropdown/index.d.ts +2 -0
  99. package/dist/components/dropdown/index.js +1 -0
  100. package/dist/components/dropdown/item/attachments.svelte.d.ts +2 -2
  101. package/dist/components/dropdown/item/attachments.svelte.js +2 -2
  102. package/dist/components/dropdown/item/controller.svelte.d.ts +34 -0
  103. package/dist/components/dropdown/item/controller.svelte.js +82 -0
  104. package/dist/components/dropdown/item/dropdown-item.svelte +109 -102
  105. package/dist/components/dropdown/item/dropdown-item.svelte.d.ts +13 -28
  106. package/dist/components/dropdown/item/index.d.ts +3 -0
  107. package/dist/components/dropdown/item/index.js +3 -0
  108. package/dist/components/dropdown/item/types.d.ts +29 -0
  109. package/dist/components/dropdown/item/types.js +1 -0
  110. package/dist/components/form/form.stories.svelte +96 -96
  111. package/dist/components/image/image.stories.svelte +20 -20
  112. package/dist/components/input/input.stories.svelte +35 -35
  113. package/dist/components/label/label.stories.svelte +15 -15
  114. package/dist/components/lazy/lazy.stories.svelte +28 -28
  115. package/dist/components/link/link.stories.svelte +15 -15
  116. package/dist/components/list/list-item.svelte +2 -2
  117. package/dist/components/menu/atoms.d.ts +9 -3
  118. package/dist/components/menu/atoms.js +9 -3
  119. package/dist/components/menu/bond.svelte.d.ts +54 -0
  120. package/dist/components/menu/bond.svelte.js +132 -0
  121. package/dist/components/menu/index.d.ts +3 -1
  122. package/dist/components/menu/index.js +2 -1
  123. package/dist/components/menu/item/controller.svelte.d.ts +26 -0
  124. package/dist/components/menu/item/controller.svelte.js +69 -0
  125. package/dist/components/menu/item/index.d.ts +2 -0
  126. package/dist/components/menu/item/index.js +2 -0
  127. package/dist/components/menu/item/menu-item.svelte +103 -0
  128. package/dist/components/menu/item/menu-item.svelte.d.ts +31 -0
  129. package/dist/components/menu/item/types.d.ts +62 -0
  130. package/dist/components/menu/item/types.js +1 -0
  131. package/dist/components/menu/{menu-list.svelte → menu-content.svelte} +40 -40
  132. package/dist/components/menu/{menu-list.svelte.d.ts → menu-content.svelte.d.ts} +3 -3
  133. package/dist/components/menu/menu-root.svelte +15 -0
  134. package/dist/components/menu/menu-root.svelte.d.ts +8 -0
  135. package/dist/components/menu/menu.stories.svelte +5 -5
  136. package/dist/components/menu/types.d.ts +0 -7
  137. package/dist/components/popover/bond.svelte.d.ts +18 -8
  138. package/dist/components/popover/bond.svelte.js +76 -40
  139. package/dist/components/popover/motion.d.ts +6 -0
  140. package/dist/components/popover/motion.js +56 -0
  141. package/dist/components/popover/popover-arrow.svelte +111 -111
  142. package/dist/components/popover/popover-content.svelte +137 -175
  143. package/dist/components/popover/popover-indicator.svelte +44 -44
  144. package/dist/components/popover/popover-root.svelte +48 -48
  145. package/dist/components/popover/popover.stories.svelte +37 -49
  146. package/dist/components/popover/types.d.ts +9 -7
  147. package/dist/components/portal/active-portal.svelte +12 -5
  148. package/dist/components/portal/active-portal.svelte.d.ts +2 -9
  149. package/dist/components/portal/portal-root.svelte +1 -8
  150. package/dist/components/portal/portal-root.svelte.d.ts +4 -6
  151. package/dist/components/portal/teleport.svelte +1 -2
  152. package/dist/components/portal/teleport.svelte.d.ts +3 -4
  153. package/dist/components/qr-code/qr-code.stories.svelte +18 -18
  154. package/dist/components/radio/radio-group.stories.svelte +41 -41
  155. package/dist/components/radio/radio.stories.svelte +17 -17
  156. package/dist/components/radio/radio.svelte +109 -109
  157. package/dist/components/radio/types.d.ts +98 -0
  158. package/dist/components/radio/types.js +2 -0
  159. package/dist/components/root/index.d.ts +1 -0
  160. package/dist/components/root/index.js +1 -0
  161. package/dist/components/root/l0-portal.svelte +8 -0
  162. package/dist/components/{radio/types.svelte.d.ts → root/l0-portal.svelte.d.ts} +3 -3
  163. package/dist/components/root/l1-portal.svelte +7 -0
  164. package/dist/components/root/l1-portal.svelte.d.ts +26 -0
  165. package/dist/components/root/root.css +119 -119
  166. package/dist/components/root/root.svelte +26 -44
  167. package/dist/components/root/root.svelte.d.ts +2 -6
  168. package/dist/components/root/toasts-portal.svelte +7 -0
  169. package/dist/components/root/toasts-portal.svelte.d.ts +26 -0
  170. package/dist/components/root/types.d.ts +17 -0
  171. package/dist/components/scrollable/scrollable-root.svelte.d.ts +2 -2
  172. package/dist/components/scrollable/scrollable.stories.svelte +116 -116
  173. package/dist/components/sidebar/index.d.ts +2 -0
  174. package/dist/components/sidebar/index.js +2 -0
  175. package/dist/components/sidebar/motion.svelte.d.ts +11 -0
  176. package/dist/components/sidebar/motion.svelte.js +16 -0
  177. package/dist/components/sidebar/sidebar-content.svelte +40 -50
  178. package/dist/components/sidebar/sidebar-root.svelte +39 -39
  179. package/dist/components/sidebar/sidebar.stories.svelte +43 -43
  180. package/dist/components/sidebar/types.d.ts +2 -12
  181. package/dist/components/tabs/tabs.stories.svelte +56 -56
  182. package/dist/components/textarea/atoms.d.ts +1 -0
  183. package/dist/components/textarea/atoms.js +1 -0
  184. package/dist/components/textarea/textarea-input.svelte +4 -1
  185. package/dist/components/textarea/textarea-root.svelte +2 -2
  186. package/dist/components/textarea/textarea-root.svelte.d.ts +2 -0
  187. package/dist/components/tooltip/tooltip-trigger.svelte +39 -39
  188. package/dist/components/tooltip/tooltip-trigger.svelte.d.ts +1 -0
  189. package/dist/components/tooltip/tooltip.stories.svelte +32 -32
  190. package/dist/components/tree/index.d.ts +1 -0
  191. package/dist/components/tree/index.js +1 -0
  192. package/dist/components/tree/motion.svelte.d.ts +6 -0
  193. package/dist/components/tree/motion.svelte.js +14 -0
  194. package/dist/components/tree/tree-body.svelte +4 -3
  195. package/dist/components/tree/tree.stories.svelte +142 -142
  196. package/dist/context/preset.svelte.d.ts +3 -1
  197. package/dist/icons/icon-copy.svelte +6 -0
  198. package/dist/icons/icon-copy.svelte.d.ts +26 -0
  199. package/dist/utils/dom.svelte.d.ts +2 -0
  200. package/dist/utils/dom.svelte.js +21 -0
  201. package/dist/utils/function.d.ts +1 -1
  202. package/dist/utils/promise.svelte.d.ts +5 -0
  203. package/dist/utils/promise.svelte.js +20 -0
  204. package/package.json +4 -3
  205. package/dist/components/combobox/compobox-item.svelte.d.ts +0 -34
  206. package/dist/components/combobox/compobox.stories.svelte +0 -51
  207. package/dist/components/combobox/compobox.stories.svelte.d.ts +0 -3
  208. package/dist/components/dropdown/item/bond.svelte.d.ts +0 -42
  209. package/dist/components/dropdown/item/bond.svelte.js +0 -99
  210. package/dist/components/menu/menu-item.svelte +0 -51
  211. package/dist/components/menu/menu-item.svelte.d.ts +0 -36
  212. package/dist/components/radio/types.svelte +0 -0
  213. package/llm/composition.md +0 -395
  214. package/llm/crafting.md +0 -838
  215. package/llm/motion.md +0 -970
  216. package/llm/philosophy.md +0 -23
  217. package/llm/preset-variant-integration.md +0 -516
  218. package/llm/preset.md +0 -383
  219. package/llm/styling.md +0 -216
  220. package/llm/usage.md +0 -46
  221. package/llm/variants.md +0 -1259
@@ -1,8 +1,5 @@
1
1
  import { Bond, BondState, type BondStateProps } from '../../shared/bond.svelte';
2
2
  export type AlertBondProps = BondStateProps & {
3
- variant?: 'info' | 'success' | 'warning' | 'error';
4
- dismissible?: boolean;
5
- dismissed?: boolean;
6
3
  disabled?: boolean;
7
4
  extend?: Record<string, unknown>;
8
5
  };
@@ -25,9 +22,6 @@ export declare class AlertBond<State extends AlertBondState<AlertBondProps> = Al
25
22
  'aria-labelledby': string;
26
23
  'aria-describedby': string;
27
24
  'aria-disabled': boolean;
28
- 'data-variant': "success" | "error" | "info" | "warning";
29
- 'data-dismissed': boolean;
30
- 'data-dismissible': boolean;
31
25
  };
32
26
  icon(props?: Record<string, unknown>): {
33
27
  id: string;
@@ -49,17 +43,10 @@ export declare class AlertBond<State extends AlertBondState<AlertBondProps> = Al
49
43
  id: string;
50
44
  type: string;
51
45
  'aria-label': string;
52
- 'aria-expanded': boolean;
53
- onclick: () => void;
54
46
  };
55
47
  static get(): AlertBond | undefined;
56
48
  static set(bond: AlertBond): AlertBond;
57
49
  }
58
50
  export declare class AlertBondState<Props extends AlertBondProps> extends BondState<Props> {
59
51
  constructor(props: () => Props);
60
- dismiss(): void;
61
- restore(): void;
62
- get isDismissed(): boolean;
63
- get isDismissible(): boolean;
64
- get variant(): "success" | "error" | "info" | "warning";
65
52
  }
@@ -10,8 +10,6 @@ export class AlertBond extends Bond {
10
10
  return AlertBond.set(this);
11
11
  }
12
12
  root(props = {}) {
13
- const variant = this.state.props.variant ?? 'info';
14
- const dismissed = this.state.props.dismissed ?? false;
15
13
  const disabled = this.state.props.disabled ?? false;
16
14
  return {
17
15
  id: `alert-root-${this.id}`,
@@ -19,9 +17,6 @@ export class AlertBond extends Bond {
19
17
  'aria-labelledby': `alert-title-${this.id}`,
20
18
  'aria-describedby': `alert-description-${this.id}`,
21
19
  'aria-disabled': disabled,
22
- 'data-variant': variant,
23
- 'data-dismissed': dismissed,
24
- 'data-dismissible': this.state.props.dismissible ?? false,
25
20
  ...props,
26
21
  [createAttachmentKey()]: (node) => {
27
22
  this.elements.root = node;
@@ -75,13 +70,10 @@ export class AlertBond extends Bond {
75
70
  };
76
71
  }
77
72
  closeButton(props = {}) {
78
- const dismissed = this.state.props.dismissed ?? false;
79
73
  return {
80
74
  id: `alert-close-button-${this.id}`,
81
75
  type: 'button',
82
76
  'aria-label': 'Dismiss alert',
83
- 'aria-expanded': !dismissed,
84
- onclick: () => this.state.dismiss(),
85
77
  ...props,
86
78
  [createAttachmentKey()]: (node) => {
87
79
  this.elements.closeButton = node;
@@ -99,28 +91,4 @@ export class AlertBondState extends BondState {
99
91
  constructor(props) {
100
92
  super(props);
101
93
  }
102
- dismiss() {
103
- if (this.props.dismissible && !this.props.disabled) {
104
- // Update the dismissed state through props if mutable
105
- const props = this.props;
106
- if ('dismissed' in props) {
107
- props.dismissed = true;
108
- }
109
- }
110
- }
111
- restore() {
112
- const props = this.props;
113
- if ('dismissed' in props) {
114
- props.dismissed = false;
115
- }
116
- }
117
- get isDismissed() {
118
- return this.props.dismissed ?? false;
119
- }
120
- get isDismissible() {
121
- return this.props.dismissible ?? false;
122
- }
123
- get variant() {
124
- return this.props.variant ?? 'info';
125
- }
126
94
  }
@@ -1,6 +1,6 @@
1
1
  import type { Snippet } from 'svelte';
2
2
  import type { HtmlAtomProps, Base } from '../atom';
3
- import type { Factory, Override } from '../../types';
3
+ import type { Factory } from '../../types';
4
4
  import type { AlertBond } from './bond.svelte';
5
5
  /**
6
6
  * Extend this interface to add custom alert root properties in your application.
@@ -37,7 +37,7 @@ export interface AlertActionsExtendProps {
37
37
  */
38
38
  export interface AlertCloseButtonExtendProps {
39
39
  }
40
- export interface AlertRootProps<E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base> extends Omit<HtmlAtomProps<E, B>, 'children'>, AlertRootExtendProps {
40
+ export interface AlertRootProps<E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base> extends HtmlAtomProps<E, B>, AlertRootExtendProps {
41
41
  dismissible?: boolean;
42
42
  dismissed?: boolean;
43
43
  disabled?: boolean;
@@ -47,39 +47,15 @@ export interface AlertRootProps<E extends keyof HTMLElementTagNameMap = 'div', B
47
47
  alert: AlertBond;
48
48
  }]>;
49
49
  }
50
- export interface AlertContentProps<E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base> extends Override<HtmlAtomProps<E, B>, {
51
- children?: Snippet<[{
52
- alert: AlertBond;
53
- }]>;
54
- }>, AlertContentExtendProps {
50
+ export interface AlertContentProps<E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base> extends HtmlAtomProps<E, B>, AlertContentExtendProps {
55
51
  }
56
- export interface AlertTitleProps<E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base> extends Override<HtmlAtomProps<E, B>, {
57
- children?: Snippet<[{
58
- alert: AlertBond;
59
- }]>;
60
- }>, AlertTitleExtendProps {
52
+ export interface AlertTitleProps<E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base> extends HtmlAtomProps<E, B>, AlertTitleExtendProps {
61
53
  }
62
- export interface AlertDescriptionProps<E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base> extends Override<HtmlAtomProps<E, B>, {
63
- children?: Snippet<[{
64
- alert: AlertBond;
65
- }]>;
66
- }>, AlertDescriptionExtendProps {
54
+ export interface AlertDescriptionProps<E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base> extends HtmlAtomProps<E, B>, AlertDescriptionExtendProps {
67
55
  }
68
- export interface AlertIconProps<E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base> extends Override<HtmlAtomProps<E, B>, {
69
- children?: Snippet<[{
70
- alert: AlertBond;
71
- }]>;
72
- }>, AlertIconExtendProps {
56
+ export interface AlertIconProps<E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base> extends HtmlAtomProps<E, B>, AlertIconExtendProps {
73
57
  }
74
- export interface AlertActionsProps<E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base> extends Override<HtmlAtomProps<E, B>, {
75
- children?: Snippet<[{
76
- alert: AlertBond;
77
- }]>;
78
- }>, AlertActionsExtendProps {
58
+ export interface AlertActionsProps<E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base> extends HtmlAtomProps<E, B>, AlertActionsExtendProps {
79
59
  }
80
- export interface AlertCloseButtonProps<E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base> extends Override<HtmlAtomProps<E, B>, {
81
- children?: Snippet<[{
82
- alert: AlertBond;
83
- }]>;
84
- }>, AlertCloseButtonExtendProps {
60
+ export interface AlertCloseButtonProps<E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base> extends HtmlAtomProps<E, B>, AlertCloseButtonExtendProps {
85
61
  }
@@ -1,261 +1,93 @@
1
- <script lang="ts" generics="E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base">
2
- import type { HTMLAttributes } from 'svelte/elements';
3
- import type { Base, HtmlAtomProps, SnippetBase } from './types';
4
- import { RootBond } from '../root';
5
- import { HtmlElement } from '../element';
6
- import { cn, type ClassValue, type VariantDefinition } from '../../utils';
7
- import { getPreset } from '../../context';
8
- import type { PresetModuleName } from '../../context/preset.svelte';
9
- import type { Bond } from '../../shared';
10
- import SnippetRenderer from './snippet-renderer.svelte';
11
- import type { Component } from 'svelte';
12
- import { call } from '../../utils/function';
13
-
14
- type Element = HTMLElementTagNameMap[E];
15
-
16
- const rootBond = RootBond.get();
17
-
18
- let {
19
- class: klass = '',
20
- as = 'div',
21
- base = undefined,
22
- preset: presetKey = undefined,
23
- bond = undefined,
24
- variants = undefined,
25
- children: childrenProp = undefined,
26
- ...restProps
27
- }: HtmlAtomProps<E, B> & Omit<HTMLAttributes<Element>, 'children'> = $props();
28
-
29
- /**
30
- * Resolve variant definition to props
31
- */
32
- // Cache for resolved variants to avoid recomputation
33
- // Key: JSON stringified combination of variant props
34
- const variantCache = new Map<string, Record<string, any>>();
35
-
36
- // Memoize preset resolution - only recompute when presetKey or bond changes
37
- const preset = $derived.by(() => {
38
- if (!presetKey) return undefined;
39
- const result = getPreset(presetKey as PresetModuleName)?.apply?.(bond, [bond]);
40
- // Handle deferred preset result (factory function)
41
- return call(result);
42
- });
43
-
44
- const presetProps = $derived(preset?.variants);
45
-
46
- // Resolve local variants - either VariantDefinition or function
47
- const localVariants = $derived.by(() => {
48
- if (!variants) return undefined;
49
-
50
- // If it's a function, call it directly
51
- if (typeof variants === 'function') {
52
- return variants(bond as Bond, restProps);
53
- }
54
-
55
- // Otherwise it's a VariantDefinition, resolve it
56
- return resolveVariants(variants, bond as Bond, restProps);
57
- });
58
-
59
- // Merge preset variants with local variants
60
- // Memoized to avoid recomputation when inputs haven't changed
61
- const mergedVariants = $derived.by(() => {
62
- // No variants at all
63
- if (!presetProps && !localVariants) return undefined;
64
-
65
- // Only preset variants (raw object from preset)
66
- if (presetProps && !localVariants) {
67
- // Convert preset variants to VariantDefinition-like structure
68
- const variantDef: VariantDefinition<any> = {
69
- class: preset?.class ?? '',
70
- variants: presetProps,
71
- compounds: preset?.compounds ?? [],
72
- defaults: preset?.defaults ?? {}
73
- };
74
- return resolveVariants(variantDef, bond as Bond, restProps);
75
- }
76
-
77
- // Only local variants
78
- if (!presetProps && localVariants) {
79
- return localVariants;
80
- }
81
-
82
- // Both exist - merge them
83
- // When both preset and local variants exist, we need to merge the resolved props
84
- const presetVariantDef: VariantDefinition<any> = {
85
- class: preset?.class ?? '',
86
- variants: presetProps ?? {},
87
- compounds: preset?.compounds ?? [],
88
- defaults: preset?.defaults ?? {}
89
- };
90
-
91
- const presetResolved = resolveVariants(presetVariantDef, bond as Bond, restProps);
92
-
93
- // Merge the resolved variant props
94
- // Local variant classes and attributes override preset
95
- const presetClasses = Array.isArray(presetResolved.class)
96
- ? presetResolved.class
97
- : [presetResolved.class];
98
- const localClasses = Array.isArray(localVariants?.class)
99
- ? localVariants.class
100
- : [localVariants?.class];
101
-
102
- return {
103
- class: [...presetClasses, ...localClasses].filter(Boolean),
104
- ...presetResolved,
105
- ...localVariants
106
- };
107
- });
108
-
109
- const presetClassString = $derived(cn(preset?.class));
110
-
111
- const _klass = $derived.by(() => {
112
- const klassStr = cn(klass ?? '');
113
- // Check for $preset placeholder first
114
- if (!klassStr.includes('$preset')) {
115
- // No placeholder - normal merge: variants override direct class
116
- return cn(klass, mergedVariants?.class ?? '');
117
- }
118
-
119
- // Has placeholder - calculate position and inject preset classes
120
- const parts = klassStr.split('$preset');
121
-
122
- // Only keep the last $preset placeholder
123
- const beforeLastPlaceholder = parts.slice(0, -1).join('');
124
- const afterLastPlaceholder = parts[parts.length - 1];
125
-
126
- // Merge: before + preset + variants + after
127
- return cn(
128
- beforeLastPlaceholder,
129
- presetClassString,
130
- mergedVariants?.class ?? '',
131
- afterLastPlaceholder
132
- );
133
- });
134
-
135
- const _base = $derived(base ?? preset?.base);
136
- const _as = $derived(as ?? preset?.as);
137
- const _restProps = $derived.by(() => {
138
- const {
139
- class: klassPreset,
140
- base,
141
- as,
142
- variants: presetProps,
143
- ...restPresetProps
144
- } = preset ?? {};
145
- const { class: variantClass, ...variantsRestProps } = mergedVariants ?? {};
146
-
147
- return { ...restPresetProps, ...variantsRestProps, ...restProps };
148
- });
149
-
150
- const isSnippet = $derived(typeof _base === 'function' && _base.length === 1 && !_base.prototype);
151
-
152
- const snippet = $derived(_base as SnippetBase);
153
-
154
- const atom = rootBond?.state?.props?.renderers?.html ?? HtmlElement;
155
-
156
- const renderer = $derived.by(() => {
157
- if (isSnippet)
158
- return {
159
- component: SnippetRenderer,
160
- props: { snippet: snippet, class: _klass, as: _as, children: childrenProp, ..._restProps }
161
- };
162
-
163
- return {
164
- component: base ?? atom,
165
- props: { class: _klass, as: _as, ..._restProps }
166
- };
167
- }) as { component: Component; props: Record<string, any> };
168
-
169
- function resolveVariants(
170
- def: VariantDefinition<any>,
171
- bond: Bond | null | undefined,
172
- props: Record<string, any>
173
- ): Record<string, any> {
174
- const { variants: variantMap, compounds, defaults, class: baseClass } = def;
175
-
176
- // Merge props with defaults
177
- const finalProps = { ...defaults, ...props };
178
-
179
- // Create cache key from final props (only variant-related props)
180
- const variantKeys = variantMap ? Object.keys(variantMap) : [];
181
- const relevantProps = Object.fromEntries(
182
- Object.entries(finalProps).filter(([key]) => variantKeys.includes(key))
183
- );
184
- const cacheKey = JSON.stringify({ relevantProps, baseClass, compounds });
185
-
186
- // Check cache
187
- if (variantCache.has(cacheKey)) {
188
- return variantCache.get(cacheKey)!;
189
- }
190
-
191
- const classes: ClassValue[] = [];
192
- const attributes: Record<string, any> = {};
193
-
194
- // Add base class
195
- if (baseClass) classes.push(baseClass);
196
-
197
- // Add variant classes
198
- if (variantMap) {
199
- for (const [key, value] of Object.entries(finalProps)) {
200
- const variantValue = variantMap[key]?.[value as string];
201
- if (variantValue !== undefined) {
202
- const resolved = typeof variantValue === 'function' ? variantValue(bond) : variantValue;
203
-
204
- if (typeof resolved === 'string') {
205
- classes.push(resolved);
206
- } else if (typeof resolved === 'object' && resolved !== null) {
207
- if ('class' in resolved) {
208
- classes.push(resolved.class);
209
- }
210
- // Add other attributes
211
- Object.entries(resolved).forEach(([k, v]) => {
212
- if (k !== 'class') {
213
- attributes[k] = v;
214
- }
215
- });
216
- }
217
- }
218
- }
219
- }
220
-
221
- // Add compound variants
222
- if (compounds) {
223
- for (const compound of compounds) {
224
- const { class: compoundClass, ...compoundProps } = compound;
225
- const matches = Object.entries(compoundProps).every(
226
- ([key, value]) => finalProps[key] === value
227
- );
228
- if (matches) {
229
- if (compoundClass) classes.push(compoundClass);
230
- // Add compound attributes
231
- Object.entries(compound).forEach(([k, v]) => {
232
- if (k !== 'class' && !Object.keys(compoundProps).includes(k)) {
233
- attributes[k] = v;
234
- }
235
- });
236
- }
237
- }
238
- }
239
-
240
- const result = {
241
- class: classes,
242
- ...attributes
243
- };
244
-
245
- // Store in cache (limit cache size to prevent memory leaks)
246
- if (variantCache.size > 100) {
247
- // Clear oldest entry (first in Map)
248
- const firstKey = variantCache.keys().next().value;
249
- if (firstKey) variantCache.delete(firstKey);
250
- }
251
- variantCache.set(cacheKey, result);
252
-
253
- return result;
254
- }
255
- </script>
256
-
257
- <renderer.component {...renderer.props}>
258
- {#snippet children(args: any)}
259
- {@render (childrenProp as any)?.(args)}
260
- {/snippet}
261
- </renderer.component>
1
+ <script lang="ts" generics="E extends keyof HTMLElementTagNameMap = 'div', B extends Base = Base">
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ import type { Base, HtmlAtomProps, SnippetBase } from './types';
4
+ import { RootBond } from '../root';
5
+ import { HtmlElement } from '../element';
6
+ import { getPreset } from '../../context';
7
+ import type { PresetModuleName } from '../../context/preset.svelte';
8
+ import SnippetRenderer from './snippet-renderer.svelte';
9
+ import type { Component } from 'svelte';
10
+ import type { ClassValue } from '../../utils';
11
+ import {
12
+ resolvePreset,
13
+ resolveLocalVariants,
14
+ mergeVariants,
15
+ mergeClassesWithPreset,
16
+ extractRestProps,
17
+ isSnippetBase
18
+ } from './utils';
19
+
20
+ type Element = HTMLElementTagNameMap[E];
21
+
22
+ const rootBond = RootBond.get();
23
+
24
+ let {
25
+ class: klass = '',
26
+ as = 'div',
27
+ base = undefined,
28
+ preset: presetKey = undefined,
29
+ bond = undefined,
30
+ variants = undefined,
31
+ children: childrenProp = undefined,
32
+ ...restProps
33
+ }: HtmlAtomProps<E, B> & Omit<HTMLAttributes<Element>, 'children'> = $props();
34
+
35
+ // Memoize preset resolution - only recompute when presetKey or bond changes
36
+ const preset = $derived.by(() => {
37
+ if (!presetKey) return undefined;
38
+ const result = getPreset(presetKey as PresetModuleName)?.apply?.(bond, [bond]);
39
+ return resolvePreset(result);
40
+ });
41
+
42
+ const presetVariantsProps = $derived(preset?.variants);
43
+
44
+ // Resolve local variants - either VariantDefinition or function
45
+ const localVariants = $derived(resolveLocalVariants(variants, bond, restProps));
46
+
47
+ // Merge preset variants with local variants
48
+ // Memoized to avoid recomputation when inputs haven't changed
49
+ const mergedVariants = $derived.by(() => {
50
+ return mergeVariants(
51
+ presetVariantsProps,
52
+ preset?.class,
53
+ preset?.compounds,
54
+ preset?.defaults,
55
+ localVariants,
56
+ bond,
57
+ restProps
58
+ );
59
+ });
60
+
61
+ const _klass = $derived(
62
+ mergeClassesWithPreset(klass, preset?.class, mergedVariants?.class as ClassValue)
63
+ );
64
+
65
+ const _base = $derived(base ?? preset?.base);
66
+ const _as = $derived(as ?? preset?.as);
67
+ const _restProps = $derived(extractRestProps(preset, mergedVariants, restProps));
68
+
69
+ const isSnippet = $derived(isSnippetBase(_base));
70
+
71
+ const snippet = $derived(_base as SnippetBase);
72
+
73
+ const atom = rootBond?.state?.props?.renderers?.html ?? HtmlElement;
74
+
75
+ const renderer = $derived.by(() => {
76
+ if (isSnippet)
77
+ return {
78
+ component: SnippetRenderer,
79
+ props: { snippet: snippet, class: _klass, as: _as, children: childrenProp, ..._restProps }
80
+ };
81
+
82
+ return {
83
+ component: base ?? atom,
84
+ props: { class: _klass, as: _as, ..._restProps }
85
+ };
86
+ }) as { component: Component; props: Record<string, any> };
87
+ </script>
88
+
89
+ <renderer.component {...renderer.props}>
90
+ {#snippet children(args: any)}
91
+ {@render (childrenProp as any)?.(args)}
92
+ {/snippet}
93
+ </renderer.component>
@@ -12,15 +12,16 @@ export type Base<Args = any> = Args extends Record<string, any> ? ComponentBase
12
12
  */
13
13
  export interface HtmlAtomExtendProps {
14
14
  }
15
+ type Variants = VariantDefinition<any> | ((bond: Bond, variantProps: Record<string, any>) => Record<string, any>);
15
16
  export interface HtmlAtomProps<E extends HtmlElementTagName = HtmlElementTagName, B extends Base<any> = Base> extends HtmlElementProps<E>, HtmlAtomExtendProps {
16
17
  bond?: Bond;
17
- base?: B;
18
+ base?: B | undefined;
18
19
  preset?: PresetModuleName | (string & {});
19
20
  /**
20
21
  * Variant definition or function to resolve variants
21
22
  * - VariantDefinition: Static variant config with base, variants, compoundVariants, defaultVariants
22
23
  * - Function: Dynamic function that receives bond and props, returns props (legacy)
23
24
  */
24
- variants?: VariantDefinition<any> | ((bond: Bond, variantProps: Record<string, any>) => Record<string, any>);
25
+ variants?: Variants;
25
26
  }
26
27
  export type { ElementType };
@@ -0,0 +1,37 @@
1
+ import type { Bond } from '../../shared';
2
+ import { type ClassValue, type VariantDefinition } from '../../utils';
3
+ type ResolvedProps = Record<string, unknown>;
4
+ type AnyVariantDefinition = VariantDefinition<any>;
5
+ /**
6
+ * Resolves preset to its final value, handling both direct values and factory functions
7
+ */
8
+ export declare function resolvePreset<T>(preset: T | (() => T) | undefined): T | undefined;
9
+ /**
10
+ * Pure function to resolve variant definition to props
11
+ * Caches results to avoid recomputation with same inputs
12
+ */
13
+ export declare function resolveVariants(def: AnyVariantDefinition, bond: Bond | null | undefined, props: Record<string, unknown>): ResolvedProps;
14
+ /**
15
+ * Pure function to merge preset and local variant definitions
16
+ * Returns merged variant props with local overriding preset
17
+ */
18
+ export declare function mergeVariants(presetVariants: Record<string, any> | undefined, presetClass: ClassValue | undefined, presetCompounds: Array<Record<string, any>> | undefined, presetDefaults: Record<string, any> | undefined, localVariants: ResolvedProps | undefined, bond: Bond | null | undefined, props: Record<string, unknown>): ResolvedProps | undefined;
19
+ /**
20
+ * Pure function to merge classes with $preset placeholder support
21
+ * Handles the special $preset placeholder for precise positioning of preset classes
22
+ */
23
+ export declare function mergeClassesWithPreset(userClass: string | ClassValue | undefined, presetClass: ClassValue | undefined, variantClass: ClassValue | undefined): string;
24
+ /**
25
+ * Pure function to resolve local variants
26
+ * Handles both function-based and VariantDefinition-based variants
27
+ */
28
+ export declare function resolveLocalVariants(variants: any, bond: Bond | null | undefined, props: Record<string, unknown>): ResolvedProps | undefined;
29
+ /**
30
+ * Pure function to extract rest props by filtering out preset and variant-specific props
31
+ */
32
+ export declare function extractRestProps(preset: Record<string, any> | undefined, mergedVariants: ResolvedProps | undefined, restProps: Record<string, unknown>): Record<string, unknown>;
33
+ /**
34
+ * Pure function to check if a base is a snippet
35
+ */
36
+ export declare function isSnippetBase(base: unknown): boolean;
37
+ export {};