@svelte-atoms/core 1.0.0-alpha.23 → 1.0.0-alpha.25

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 (56) hide show
  1. package/README.md +645 -645
  2. package/dist/components/accordion/accordion-root.svelte.d.ts +2 -2
  3. package/dist/components/alert/alert-actions.svelte.d.ts +1 -0
  4. package/dist/components/alert/alert-close-button.svelte.d.ts +1 -0
  5. package/dist/components/alert/alert-content.svelte.d.ts +1 -0
  6. package/dist/components/atom/html-atom.svelte +151 -4
  7. package/dist/components/atom/html-atom.svelte.d.ts +4 -2
  8. package/dist/components/atom/types.d.ts +7 -0
  9. package/dist/components/button/button.stories.svelte +57 -17
  10. package/dist/components/button/button.stories.svelte.d.ts +6 -14
  11. package/dist/components/checkbox/checkbox.svelte.d.ts +1 -1
  12. package/dist/components/combobox/combobox-root.svelte.d.ts +2 -2
  13. package/dist/components/datagrid/datagrid.stories.svelte +75 -75
  14. package/dist/components/drawer/drawer-backdrop.svelte.d.ts +1 -0
  15. package/dist/components/icon/icon.svelte.d.ts +1 -0
  16. package/dist/components/input/input-placeholder.svelte +56 -56
  17. package/dist/components/input/input-placeholder.svelte.d.ts +1 -0
  18. package/dist/components/input/input-root.svelte +79 -79
  19. package/dist/components/input/input-root.svelte.d.ts +1 -0
  20. package/dist/components/input/input-value.svelte +113 -113
  21. package/dist/components/input/input-value.svelte.d.ts +1 -1
  22. package/dist/components/input/input.stories.svelte +38 -38
  23. package/dist/components/label/label.svelte.d.ts +1 -0
  24. package/dist/components/layer/layer-inner.svelte.d.ts +1 -0
  25. package/dist/components/layer/layer-root.svelte.d.ts +1 -0
  26. package/dist/components/popover/popover-arrow.svelte.d.ts +1 -0
  27. package/dist/components/portal/portal-inner.svelte.d.ts +1 -0
  28. package/dist/components/portal/portal-root.svelte.d.ts +1 -0
  29. package/dist/components/portal/teleport.svelte.d.ts +1 -0
  30. package/dist/components/radio/radio.svelte.d.ts +2 -2
  31. package/dist/components/root/root.svelte +121 -103
  32. package/dist/components/root/root.svelte.d.ts +1 -0
  33. package/dist/components/stack/stack-root.svelte.d.ts +1 -0
  34. package/dist/components/toast/toast-description.svelte.d.ts +1 -0
  35. package/dist/components/toast/toast-root.svelte.d.ts +1 -0
  36. package/dist/components/toast/toast-title.svelte.d.ts +1 -0
  37. package/dist/components/tree/tree-header.svelte.d.ts +1 -0
  38. package/dist/context/preset.svelte.d.ts +3 -0
  39. package/dist/runes/index.d.ts +3 -0
  40. package/dist/runes/index.js +3 -0
  41. package/dist/runes/reduced-motion.svelte.d.ts +23 -0
  42. package/dist/runes/reduced-motion.svelte.js +41 -0
  43. package/dist/utils/index.d.ts +1 -0
  44. package/dist/utils/index.js +1 -0
  45. package/dist/utils/variant.d.ts +213 -0
  46. package/dist/utils/variant.js +137 -0
  47. package/llm/composition.md +395 -0
  48. package/llm/crafting.md +838 -0
  49. package/llm/motion.md +970 -0
  50. package/llm/philosophy.md +23 -0
  51. package/llm/preset-variant-integration.md +516 -0
  52. package/llm/preset.md +383 -0
  53. package/llm/styling.md +216 -0
  54. package/llm/usage.md +46 -0
  55. package/llm/variants.md +712 -0
  56. package/package.json +2 -1
@@ -14,7 +14,7 @@ declare function $$render<B extends Base = Base>(): {
14
14
  checkedContent?: any;
15
15
  } & Record<string, any>;
16
16
  exports: {};
17
- bindings: "group" | "value";
17
+ bindings: "value" | "group";
18
18
  slots: {};
19
19
  events: {};
20
20
  };
@@ -22,7 +22,7 @@ declare class __sveltets_Render<B extends Base = Base> {
22
22
  props(): ReturnType<typeof $$render<B>>['props'];
23
23
  events(): ReturnType<typeof $$render<B>>['events'];
24
24
  slots(): ReturnType<typeof $$render<B>>['slots'];
25
- bindings(): "group" | "value";
25
+ bindings(): "value" | "group";
26
26
  exports(): {};
27
27
  }
28
28
  interface $$IsomorphicComponent {
@@ -1,103 +1,121 @@
1
- <script module lang="ts">
2
- export type RootPortals = 'root.l0' | 'root.l1' | 'root.l2' | 'root.l3';
3
- </script>
4
-
5
- <script lang="ts">
6
- import { cn, defineState, defineProperty } from '../../utils';
7
- import { RootBond, RootBondState, type RootStateProps } from './bond.svelte';
8
- import { Portal, ActivePortal, Portals } from '../portal';
9
- import { Stack } from '../stack';
10
- import { HtmlAtom } from '../atom';
11
- import { HtmlElement, MathmlElement, SvgElement } from '../element';
12
-
13
- let { class: klass = '', children = undefined, portals = undefined, ...restProps } = $props();
14
-
15
- let html: typeof HtmlElement | undefined = HtmlElement;
16
- let svg: typeof SvgElement | undefined = undefined;
17
- let mathml: typeof MathmlElement | undefined = undefined;
18
-
19
- type Renderers = {
20
- html?: typeof HtmlElement;
21
- svg?: typeof SvgElement;
22
- mathml?: typeof MathmlElement;
23
- };
24
-
25
- const renderers = defineState<Renderers>([
26
- defineProperty('html', () => {
27
- if (!html) {
28
- import('../element/html-element.svelte').then((mod) => {
29
- html = mod.default;
30
- });
31
- }
32
-
33
- return html;
34
- }),
35
- defineProperty('svg', () => {
36
- if (!svg) {
37
- import('../element/svg-element.svelte').then((mod) => {
38
- svg = mod.default;
39
- });
40
- }
41
-
42
- return svg;
43
- }),
44
- defineProperty('mathml', () => {
45
- if (!mathml) {
46
- import('../element/mathml-element.svelte').then((mod) => {
47
- mathml = mod.default;
48
- });
49
- }
50
-
51
- return mathml;
52
- })
53
- ]);
54
-
55
- const bondProps = defineState<RootStateProps>([defineProperty('renderers', () => renderers)]);
56
-
57
- const bondState = new RootBondState(() => bondProps);
58
- const bond = new RootBond(bondState).share();
59
- </script>
60
-
61
- <HtmlAtom
62
- {@attach (node) => {
63
- bond.rootElement = node;
64
- }}
65
- preset="root"
66
- class={cn(
67
- 'atom-root bg-background text-foreground relative flex w-full flex-1 flex-col items-start font-sans',
68
- '$preset',
69
- klass
70
- )}
71
- {...restProps}
72
- >
73
- <Portals id="root">
74
- {#if portals}
75
- {@render portals?.()}
76
- {:else}
77
- <Stack.Root
78
- preset="root.portals"
79
- class={['portals pointer-events-none absolute inset-0 z-1 overflow-hidden', '$preset']}
80
- >
81
- <Portal.Outer base={Stack.Item} id="root.l0">
82
- <Portal.Inner />
83
- </Portal.Outer>
84
-
85
- <Portal.Outer base={Stack.Item} id="root.l1">
86
- <Portal.Inner />
87
- </Portal.Outer>
88
-
89
- <Portal.Outer base={Stack.Item} id="root.l2">
90
- <Portal.Inner />
91
- </Portal.Outer>
92
-
93
- <Portal.Outer base={Stack.Item} id="root.l3">
94
- <Portal.Inner />
95
- </Portal.Outer>
96
- </Stack.Root>
97
- {/if}
98
-
99
- <ActivePortal id="root.l0">
100
- {@render children?.()}
101
- </ActivePortal>
102
- </Portals>
103
- </HtmlAtom>
1
+ <script module lang="ts">
2
+ export type RootPortals = 'root.l0' | 'root.l1' | 'root.l2' | 'root.l3';
3
+ </script>
4
+
5
+ <script lang="ts">
6
+ import { cn, defineState, defineProperty } from '../../utils';
7
+ import { RootBond, RootBondState, type RootStateProps } from './bond.svelte';
8
+ import { Portal, ActivePortal, Portals } from '../portal';
9
+ import { Stack } from '../stack';
10
+ import { HtmlAtom } from '../atom';
11
+ import { HtmlElement, MathmlElement, SvgElement } from '../element';
12
+
13
+ let {
14
+ class: klass = '',
15
+ base = undefined,
16
+ children = undefined,
17
+ portals = undefined,
18
+ ...restProps
19
+ } = $props();
20
+
21
+ let html: typeof HtmlElement | undefined = HtmlElement;
22
+ let svg: typeof SvgElement | undefined = undefined;
23
+ let mathml: typeof MathmlElement | undefined = undefined;
24
+
25
+ type Renderers = {
26
+ html?: typeof HtmlElement;
27
+ svg?: typeof SvgElement;
28
+ mathml?: typeof MathmlElement;
29
+ };
30
+
31
+ const renderers = defineState<Renderers>([
32
+ defineProperty('html', () => {
33
+ if (!html) {
34
+ import('../element/html-element.svelte').then((mod) => {
35
+ html = mod.default;
36
+ });
37
+ }
38
+
39
+ return html;
40
+ }),
41
+ defineProperty('svg', () => {
42
+ if (!svg) {
43
+ import('../element/svg-element.svelte').then((mod) => {
44
+ svg = mod.default;
45
+ });
46
+ }
47
+
48
+ return svg;
49
+ }),
50
+ defineProperty('mathml', () => {
51
+ if (!mathml) {
52
+ import('../element/mathml-element.svelte').then((mod) => {
53
+ mathml = mod.default;
54
+ });
55
+ }
56
+
57
+ return mathml;
58
+ })
59
+ ]);
60
+
61
+ const bondProps = defineState<RootStateProps>([defineProperty('renderers', () => renderers)]);
62
+
63
+ const bondState = new RootBondState(() => bondProps);
64
+ const bond = new RootBond(bondState).share();
65
+ </script>
66
+
67
+ <Portals id="root">
68
+ <HtmlAtom
69
+ {@attach (node) => {
70
+ bond.rootElement = node;
71
+ }}
72
+ {base}
73
+ preset="root"
74
+ class={cn(
75
+ 'atom-root bg-background text-foreground relative flex w-full flex-1 flex-col items-start font-sans',
76
+ '$preset',
77
+ klass
78
+ )}
79
+ {...restProps}
80
+ >
81
+ {#if portals}
82
+ {@render portals?.()}
83
+ {:else}
84
+ <Portal.Outer
85
+ base={Stack.Item}
86
+ id="root.l0"
87
+ class="pointer-events-none absolute inset-0 z-10 overflow-hidden"
88
+ >
89
+ <Portal.Inner />
90
+ </Portal.Outer>
91
+
92
+ <Portal.Outer
93
+ base={Stack.Item}
94
+ id="root.l1"
95
+ class="pointer-events-none absolute inset-0 z-10 overflow-hidden"
96
+ >
97
+ <Portal.Inner />
98
+ </Portal.Outer>
99
+
100
+ <Portal.Outer
101
+ base={Stack.Item}
102
+ id="root.l2"
103
+ class="pointer-events-none absolute inset-0 z-10 overflow-hidden"
104
+ >
105
+ <Portal.Inner />
106
+ </Portal.Outer>
107
+
108
+ <Portal.Outer
109
+ base={Stack.Item}
110
+ id="root.l3"
111
+ class="pointer-events-none absolute inset-0 z-10 overflow-hidden"
112
+ >
113
+ <Portal.Inner />
114
+ </Portal.Outer>
115
+ {/if}
116
+
117
+ <ActivePortal id="root.l0">
118
+ {@render children?.()}
119
+ </ActivePortal>
120
+ </HtmlAtom>
121
+ </Portals>
@@ -1,6 +1,7 @@
1
1
  export type RootPortals = 'root.l0' | 'root.l1' | 'root.l2' | 'root.l3';
2
2
  declare const Root: import("svelte").Component<{
3
3
  class?: string;
4
+ base?: any;
4
5
  children?: any;
5
6
  portals?: any;
6
7
  } & Record<string, any>, {}, "">;
@@ -18,6 +18,7 @@ declare function $$render<E extends keyof HTMLElementTagNameMap = 'div', B exten
18
18
  bond?: import("../..").Bond;
19
19
  base?: B | undefined;
20
20
  preset?: import("../..").ModuleName | (string & {});
21
+ variants?: import("../..").VariantDefinition<any> | ((bond: import("../..").Bond, variantProps: Record<string, any>) => Record<string, any>);
21
22
  } & HTMLAttributes<ElementType<E>>;
22
23
  exports: {};
23
24
  bindings: "";
@@ -25,6 +25,7 @@ declare function $$render<T extends keyof HTMLElementTagNameMap>(): {
25
25
  bond?: import("../..").Bond;
26
26
  base?: import("../atom").ComponentBase | import("../atom").SnippetBase | undefined;
27
27
  preset?: import("../..").ModuleName | (string & {});
28
+ variants?: import("../..").VariantDefinition<any> | ((bond: import("../..").Bond, variantProps: Record<string, any>) => Record<string, any>);
28
29
  } & {
29
30
  as?: T | undefined;
30
31
  children?: Snippet<[{
@@ -30,6 +30,7 @@ declare function $$render<T extends keyof HTMLElementTagNameMap>(): {
30
30
  bond?: import("../..").Bond;
31
31
  base?: import("../atom").ComponentBase | import("../atom").SnippetBase | undefined;
32
32
  preset?: import("../..").ModuleName | (string & {});
33
+ variants?: import("../../utils").VariantDefinition<any> | ((bond: import("../..").Bond, variantProps: Record<string, any>) => Record<string, any>);
33
34
  } & {
34
35
  as?: T | undefined;
35
36
  open?: boolean;
@@ -26,6 +26,7 @@ declare function $$render<T extends keyof HTMLElementTagNameMap>(): {
26
26
  bond?: import("../..").Bond;
27
27
  base?: import("../atom").ComponentBase | import("../atom").SnippetBase | undefined;
28
28
  preset?: import("../..").ModuleName | (string & {});
29
+ variants?: import("../..").VariantDefinition<any> | ((bond: import("../..").Bond, variantProps: Record<string, any>) => Record<string, any>);
29
30
  } & {
30
31
  as?: T | undefined;
31
32
  class?: string;
@@ -27,6 +27,7 @@ declare function $$render<E extends keyof HTMLElementTagNameMap = 'div', B exten
27
27
  bond?: import("../..").Bond;
28
28
  base?: B | undefined;
29
29
  preset?: import("../..").ModuleName | (string & {});
30
+ variants?: import("../..").VariantDefinition<any> | ((bond: import("../..").Bond, variantProps: Record<string, any>) => Record<string, any>);
30
31
  } & {
31
32
  class?: string;
32
33
  open?: boolean;
@@ -7,6 +7,9 @@ export type PresetEntryRecord = {
7
7
  class?: ClassValue;
8
8
  as?: string;
9
9
  base?: Base;
10
+ variants?: Record<string, Record<string, any>>;
11
+ compounds?: Array<Record<string, any>>;
12
+ defaults?: Record<string, any>;
10
13
  };
11
14
  export type PresetEntry = (this: Bond | undefined | null, bond: Bond | undefined | null, ...args: any[]) => PresetEntryRecord;
12
15
  export type Preset = Record<PresetModuleName, PresetEntry>;
@@ -1,2 +1,5 @@
1
1
  export { colorScheme, type ColorScheme } from './color-scheme.svelte';
2
+ export { reducedMotion } from './reduced-motion.svelte';
3
+ export { container } from './container.svelte';
4
+ export { type Viewport, viewport } from './viewport.svelte';
2
5
  export { mounted } from './lifecycles.svelte';
@@ -1,2 +1,5 @@
1
1
  export { colorScheme } from './color-scheme.svelte';
2
+ export { reducedMotion } from './reduced-motion.svelte';
3
+ export { container } from './container.svelte';
4
+ export { viewport } from './viewport.svelte';
2
5
  export { mounted } from './lifecycles.svelte';
@@ -0,0 +1,23 @@
1
+ /**
2
+ * A rune that tracks the user's motion preferences via the `prefers-reduced-motion` media query.
3
+ *
4
+ * @returns An object with a `current` getter that returns `true` if the user prefers reduced motion, `false` otherwise.
5
+ *
6
+ * @example
7
+ * ```svelte
8
+ * <script>
9
+ * import { reducedMotion } from '@svelte-atoms/core';
10
+ *
11
+ * const motion = reducedMotion();
12
+ * </script>
13
+ *
14
+ * {#if motion.current}
15
+ * <div>Animations disabled</div>
16
+ * {:else}
17
+ * <div class="animated">Animations enabled</div>
18
+ * {/if}
19
+ * ```
20
+ */
21
+ export declare function reducedMotion(): {
22
+ readonly current: boolean;
23
+ };
@@ -0,0 +1,41 @@
1
+ /**
2
+ * A rune that tracks the user's motion preferences via the `prefers-reduced-motion` media query.
3
+ *
4
+ * @returns An object with a `current` getter that returns `true` if the user prefers reduced motion, `false` otherwise.
5
+ *
6
+ * @example
7
+ * ```svelte
8
+ * <script>
9
+ * import { reducedMotion } from '@svelte-atoms/core';
10
+ *
11
+ * const motion = reducedMotion();
12
+ * </script>
13
+ *
14
+ * {#if motion.current}
15
+ * <div>Animations disabled</div>
16
+ * {:else}
17
+ * <div class="animated">Animations enabled</div>
18
+ * {/if}
19
+ * ```
20
+ */
21
+ export function reducedMotion() {
22
+ let prefersReduced = $state(false);
23
+ $effect(() => {
24
+ if (typeof window === 'undefined')
25
+ return;
26
+ const handleChange = (ev) => {
27
+ prefersReduced = ev.matches;
28
+ };
29
+ const media = window.matchMedia('(prefers-reduced-motion: reduce)');
30
+ media.addEventListener('change', handleChange);
31
+ prefersReduced = media.matches;
32
+ return () => {
33
+ media.removeEventListener('change', handleChange);
34
+ };
35
+ });
36
+ return {
37
+ get current() {
38
+ return prefersReduced;
39
+ }
40
+ };
41
+ }
@@ -1,4 +1,5 @@
1
1
  export { type StateDefiner, defineProperty, defineState } from './state';
2
+ export { defineVariants, type VariantDefinition, type VariantProps, type VariantValue, type ExtractVariants, type VariantPropsType } from './variant';
2
3
  import type { ClassValue as SvelteClassValue } from 'svelte/elements';
3
4
  export type ClassValueFunction = <T = unknown>(bond: T, ...args: unknown[]) => SvelteClassValue;
4
5
  export type ClassValue = SvelteClassValue | ClassValueFunction | undefined;
@@ -1,4 +1,5 @@
1
1
  export { defineProperty, defineState } from './state';
2
+ export { defineVariants } from './variant';
2
3
  import clsx from 'clsx';
3
4
  import { twMerge } from 'tailwind-merge';
4
5
  export function cn(...inputs) {
@@ -0,0 +1,213 @@
1
+ /**
2
+ * Variant System for @svelte-atoms/core
3
+ *
4
+ * A simple, single-function approach to defining component variants.
5
+ * Define variants once, use everywhere with full type safety and bond state access.
6
+ *
7
+ * Goals:
8
+ * 1. Single function returns all variants for a component
9
+ * 2. Access internal component state (via bond) for reactive variants
10
+ * 3. Return both classes AND other attributes (aria, data, etc.)
11
+ * 4. Type-safe with autocompletion
12
+ * 5. No context, no complexity
13
+ */
14
+ import type { ClassValue } from 'svelte/elements';
15
+ import type { Bond } from '../shared';
16
+ /**
17
+ * Variant value can be a static value or a function that receives bond
18
+ */
19
+ export type VariantValue<T = any> = T | ((bond?: Bond | null) => T);
20
+ /**
21
+ * Variant definition - maps variant keys to their possible values
22
+ * Each value can return classes and/or attributes
23
+ */
24
+ export type VariantDefinition<V extends Record<string, Record<string, any>>> = {
25
+ /** Base classes applied to all variants */
26
+ class?: ClassValue;
27
+ /** Variant definitions - each key maps to possible values */
28
+ variants: V;
29
+ /** Compound variants - apply when multiple conditions match */
30
+ compounds?: Array<Partial<{
31
+ [K in keyof V]: keyof V[K];
32
+ }> & {
33
+ class?: ClassValue;
34
+ [key: string]: any;
35
+ }>;
36
+ /** Default values for variants */
37
+ defaults?: Partial<{
38
+ [K in keyof V]: keyof V[K];
39
+ }>;
40
+ };
41
+ /**
42
+ * Props type for variant function
43
+ */
44
+ export type VariantProps<V extends Record<string, Record<string, any>>> = Partial<{
45
+ [K in keyof V]: keyof V[K];
46
+ }> & {
47
+ bond?: Bond | null;
48
+ };
49
+ /**
50
+ * Define variants for a component
51
+ * Returns a function that takes variant props and returns classes + attributes
52
+ *
53
+ * @example
54
+ * ```ts
55
+ * // Option 1: Static config (no bond access needed)
56
+ * const buttonVariants = defineVariants({
57
+ * class: 'rounded-md font-medium transition-colors',
58
+ * variants: {
59
+ * variant: {
60
+ * primary: 'bg-blue-500 text-white hover:bg-blue-600',
61
+ * secondary: 'bg-gray-500 text-white hover:bg-gray-600'
62
+ * },
63
+ * size: {
64
+ * sm: 'px-2 py-1 text-sm',
65
+ * md: 'px-4 py-2 text-base',
66
+ * lg: 'px-6 py-3 text-lg'
67
+ * }
68
+ * },
69
+ * compounds: [
70
+ * {
71
+ * variant: 'primary',
72
+ * size: 'lg',
73
+ * class: 'shadow-lg'
74
+ * }
75
+ * ],
76
+ * defaults: {
77
+ * variant: 'primary',
78
+ * size: 'md'
79
+ * }
80
+ * });
81
+ *
82
+ * // Option 2: Dynamic config (with bond access)
83
+ * const buttonVariants = defineVariants((bond) => ({
84
+ * class: 'rounded-md font-medium transition-colors',
85
+ * variants: {
86
+ * variant: {
87
+ * primary: 'bg-blue-500 text-white hover:bg-blue-600',
88
+ * secondary: 'bg-gray-500 text-white hover:bg-gray-600',
89
+ * danger: bond?.state?.disabled
90
+ * ? 'bg-red-300 text-white'
91
+ * : 'bg-red-500 text-white hover:bg-red-600'
92
+ * },
93
+ * size: {
94
+ * sm: 'px-2 py-1 text-sm',
95
+ * md: 'px-4 py-2 text-base',
96
+ * lg: 'px-6 py-3 text-lg'
97
+ * }
98
+ * },
99
+ * compounds: [
100
+ * {
101
+ * variant: 'primary',
102
+ * size: 'lg',
103
+ * class: 'shadow-lg'
104
+ * }
105
+ * ],
106
+ * defaults: {
107
+ * variant: 'primary',
108
+ * size: 'md'
109
+ * }
110
+ * }));
111
+ *
112
+ * // Usage in component:
113
+ * const props = buttonVariants({ variant: 'primary', size: 'lg', bond });
114
+ * // Returns: { class: '...' }
115
+ * ```
116
+ */
117
+ export declare function defineVariants<V extends Record<string, Record<string, any>>>(config: VariantDefinition<V> | ((bond?: Bond | null) => VariantDefinition<V>)): (bond: Bond, props?: VariantProps<V>) => Record<string, any>;
118
+ /**
119
+ * Example 1: Simple button variants (static config)
120
+ *
121
+ * ```ts
122
+ * const buttonVariants = defineVariants({
123
+ * class: 'rounded-md font-medium transition-colors focus:outline-none focus:ring-2',
124
+ * variants: {
125
+ * variant: {
126
+ * primary: 'bg-blue-500 text-white hover:bg-blue-600',
127
+ * secondary: 'bg-gray-200 text-gray-900 hover:bg-gray-300',
128
+ * ghost: 'hover:bg-gray-100'
129
+ * },
130
+ * size: {
131
+ * sm: 'px-2 py-1 text-sm',
132
+ * md: 'px-4 py-2',
133
+ * lg: 'px-6 py-3 text-lg'
134
+ * }
135
+ * },
136
+ * defaultVariants: {
137
+ * variant: 'primary',
138
+ * size: 'md'
139
+ * }
140
+ * });
141
+ *
142
+ * // In component:
143
+ * let { variant, size, ...rest } = $props();
144
+ * const variantProps = buttonVariants({ variant, size });
145
+ *
146
+ * <button class={variantProps.class} {...rest}>Click me</button>
147
+ * ```
148
+ */
149
+ /**
150
+ * Example 2: Reactive variants with bond state (function-based config)
151
+ *
152
+ * ```ts
153
+ * const buttonVariants = defineVariants((bond) => ({
154
+ * class: 'rounded-md font-medium transition-colors',
155
+ * variants: {
156
+ * variant: {
157
+ * primary: 'bg-blue-500 text-white hover:bg-blue-600',
158
+ * secondary: 'bg-gray-500 text-white hover:bg-gray-600',
159
+ * // Access bond in the config function itself
160
+ * danger: bond?.state?.disabled
161
+ * ? 'bg-red-300 text-white'
162
+ * : 'bg-red-500 text-white hover:bg-red-600'
163
+ * },
164
+ * size: {
165
+ * sm: 'px-2 py-1 text-sm',
166
+ * md: 'px-4 py-2',
167
+ * lg: 'px-6 py-3 text-lg'
168
+ * }
169
+ * },
170
+ * defaults: {
171
+ * variant: 'primary',
172
+ * size: 'md'
173
+ * }
174
+ * }));
175
+ *
176
+ * // In component:
177
+ * const bond = ButtonBond.get();
178
+ * const variantProps = buttonVariants({ variant: 'danger', size: 'md', bond });
179
+ *
180
+ * <button class={variantProps.class}>Click me</button>
181
+ * ```
182
+ */
183
+ /**
184
+ * Example 3: Accordion with per-variant bond access
185
+ *
186
+ * ```ts
187
+ * const accordionVariants = defineVariants({
188
+ * class: 'border rounded-md transition-all',
189
+ * variants: {
190
+ * state: {
191
+ * // Each variant can also be a function receiving bond
192
+ * open: (bond) => ({
193
+ * class: bond?.state?.isOpen ? 'bg-blue-50 border-blue-200' : 'bg-white',
194
+ * 'aria-expanded': bond?.state?.isOpen,
195
+ * 'data-state': bond?.state?.isOpen ? 'open' : 'closed'
196
+ * }),
197
+ * disabled: (bond) => ({
198
+ * class: bond?.state?.disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer',
199
+ * 'aria-disabled': bond?.state?.disabled
200
+ * })
201
+ * }
202
+ * }
203
+ * });
204
+ *
205
+ * // In component:
206
+ * const bond = AccordionBond.get();
207
+ * const variantProps = accordionVariants({ state: 'open', bond });
208
+ *
209
+ * <div {...variantProps}>Content</div>
210
+ * ```
211
+ */
212
+ export type ExtractVariants<T extends (...args: any[]) => any> = Parameters<T>[0];
213
+ export type VariantPropsType<T> = T extends VariantDefinition<infer V> ? VariantProps<V> : Record<string, any>;