@svelte-atoms/core 1.0.0-alpha.24 → 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.
- package/README.md +645 -645
- package/dist/components/accordion/accordion-root.svelte.d.ts +2 -2
- package/dist/components/alert/alert-actions.svelte.d.ts +1 -0
- package/dist/components/alert/alert-close-button.svelte.d.ts +1 -0
- package/dist/components/alert/alert-content.svelte.d.ts +1 -0
- package/dist/components/atom/html-atom.svelte +217 -70
- package/dist/components/atom/html-atom.svelte.d.ts +4 -2
- package/dist/components/atom/types.d.ts +7 -0
- package/dist/components/button/button.stories.svelte +57 -17
- package/dist/components/button/button.stories.svelte.d.ts +6 -14
- package/dist/components/checkbox/checkbox.svelte.d.ts +1 -1
- package/dist/components/combobox/combobox-root.svelte.d.ts +2 -2
- package/dist/components/datagrid/datagrid.stories.svelte +75 -75
- package/dist/components/drawer/drawer-backdrop.svelte.d.ts +1 -0
- package/dist/components/icon/icon.svelte.d.ts +1 -0
- package/dist/components/input/input-placeholder.svelte +56 -56
- package/dist/components/input/input-placeholder.svelte.d.ts +1 -0
- package/dist/components/input/input-root.svelte.d.ts +1 -0
- package/dist/components/input/input-value.svelte +113 -113
- package/dist/components/input/input-value.svelte.d.ts +1 -1
- package/dist/components/label/label.svelte.d.ts +1 -0
- package/dist/components/layer/layer-inner.svelte.d.ts +1 -0
- package/dist/components/layer/layer-root.svelte.d.ts +1 -0
- package/dist/components/popover/popover-arrow.svelte.d.ts +1 -0
- package/dist/components/portal/portal-inner.svelte.d.ts +1 -0
- package/dist/components/portal/portal-root.svelte.d.ts +1 -0
- package/dist/components/portal/teleport.svelte.d.ts +1 -0
- package/dist/components/radio/radio.svelte.d.ts +2 -2
- package/dist/components/stack/stack-root.svelte.d.ts +1 -0
- package/dist/components/toast/toast-description.svelte.d.ts +1 -0
- package/dist/components/toast/toast-root.svelte.d.ts +1 -0
- package/dist/components/toast/toast-title.svelte.d.ts +1 -0
- package/dist/components/tree/tree-header.svelte.d.ts +1 -0
- package/dist/context/preset.svelte.d.ts +3 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/variant.d.ts +213 -0
- package/dist/utils/variant.js +137 -0
- package/llm/composition.md +395 -0
- package/llm/crafting.md +838 -0
- package/llm/motion.md +970 -0
- package/llm/philosophy.md +23 -0
- package/llm/preset-variant-integration.md +516 -0
- package/llm/preset.md +383 -0
- package/llm/styling.md +216 -0
- package/llm/usage.md +46 -0
- package/llm/variants.md +712 -0
- package/package.json +437 -436
|
@@ -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>;
|
|
@@ -0,0 +1,137 @@
|
|
|
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
|
+
/**
|
|
15
|
+
* Define variants for a component
|
|
16
|
+
* Returns a function that takes variant props and returns classes + attributes
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* // Option 1: Static config (no bond access needed)
|
|
21
|
+
* const buttonVariants = defineVariants({
|
|
22
|
+
* class: 'rounded-md font-medium transition-colors',
|
|
23
|
+
* variants: {
|
|
24
|
+
* variant: {
|
|
25
|
+
* primary: 'bg-blue-500 text-white hover:bg-blue-600',
|
|
26
|
+
* secondary: 'bg-gray-500 text-white hover:bg-gray-600'
|
|
27
|
+
* },
|
|
28
|
+
* size: {
|
|
29
|
+
* sm: 'px-2 py-1 text-sm',
|
|
30
|
+
* md: 'px-4 py-2 text-base',
|
|
31
|
+
* lg: 'px-6 py-3 text-lg'
|
|
32
|
+
* }
|
|
33
|
+
* },
|
|
34
|
+
* compounds: [
|
|
35
|
+
* {
|
|
36
|
+
* variant: 'primary',
|
|
37
|
+
* size: 'lg',
|
|
38
|
+
* class: 'shadow-lg'
|
|
39
|
+
* }
|
|
40
|
+
* ],
|
|
41
|
+
* defaults: {
|
|
42
|
+
* variant: 'primary',
|
|
43
|
+
* size: 'md'
|
|
44
|
+
* }
|
|
45
|
+
* });
|
|
46
|
+
*
|
|
47
|
+
* // Option 2: Dynamic config (with bond access)
|
|
48
|
+
* const buttonVariants = defineVariants((bond) => ({
|
|
49
|
+
* class: 'rounded-md font-medium transition-colors',
|
|
50
|
+
* variants: {
|
|
51
|
+
* variant: {
|
|
52
|
+
* primary: 'bg-blue-500 text-white hover:bg-blue-600',
|
|
53
|
+
* secondary: 'bg-gray-500 text-white hover:bg-gray-600',
|
|
54
|
+
* danger: bond?.state?.disabled
|
|
55
|
+
* ? 'bg-red-300 text-white'
|
|
56
|
+
* : 'bg-red-500 text-white hover:bg-red-600'
|
|
57
|
+
* },
|
|
58
|
+
* size: {
|
|
59
|
+
* sm: 'px-2 py-1 text-sm',
|
|
60
|
+
* md: 'px-4 py-2 text-base',
|
|
61
|
+
* lg: 'px-6 py-3 text-lg'
|
|
62
|
+
* }
|
|
63
|
+
* },
|
|
64
|
+
* compounds: [
|
|
65
|
+
* {
|
|
66
|
+
* variant: 'primary',
|
|
67
|
+
* size: 'lg',
|
|
68
|
+
* class: 'shadow-lg'
|
|
69
|
+
* }
|
|
70
|
+
* ],
|
|
71
|
+
* defaults: {
|
|
72
|
+
* variant: 'primary',
|
|
73
|
+
* size: 'md'
|
|
74
|
+
* }
|
|
75
|
+
* }));
|
|
76
|
+
*
|
|
77
|
+
* // Usage in component:
|
|
78
|
+
* const props = buttonVariants({ variant: 'primary', size: 'lg', bond });
|
|
79
|
+
* // Returns: { class: '...' }
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
export function defineVariants(config) {
|
|
83
|
+
return (bond, props) => {
|
|
84
|
+
// Get config (either static or dynamic based on bond)
|
|
85
|
+
const resolvedConfig = typeof config === 'function' ? config(bond) : config;
|
|
86
|
+
// Merge with defaults
|
|
87
|
+
const finalProps = { ...resolvedConfig.defaults, ...props };
|
|
88
|
+
// Collect classes and attributes
|
|
89
|
+
const classes = [];
|
|
90
|
+
const attributes = {};
|
|
91
|
+
// Add base class
|
|
92
|
+
if (resolvedConfig.class)
|
|
93
|
+
classes.push(resolvedConfig.class);
|
|
94
|
+
// Add variant classes and attributes
|
|
95
|
+
for (const [key, value] of Object.entries(finalProps)) {
|
|
96
|
+
const variantValue = resolvedConfig.variants?.[key]?.[value];
|
|
97
|
+
if (variantValue !== undefined) {
|
|
98
|
+
const resolved = typeof variantValue === 'function' ? variantValue(bond) : variantValue;
|
|
99
|
+
if (typeof resolved === 'string') {
|
|
100
|
+
classes.push(resolved);
|
|
101
|
+
}
|
|
102
|
+
else if (typeof resolved === 'object' && resolved !== null) {
|
|
103
|
+
if ('class' in resolved) {
|
|
104
|
+
classes.push(resolved.class);
|
|
105
|
+
}
|
|
106
|
+
// Add other attributes (aria-*, data-*, etc.)
|
|
107
|
+
Object.entries(resolved).forEach(([k, v]) => {
|
|
108
|
+
if (k !== 'class') {
|
|
109
|
+
attributes[k] = v;
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Add compound variants
|
|
116
|
+
if (resolvedConfig.compounds) {
|
|
117
|
+
for (const compound of resolvedConfig.compounds) {
|
|
118
|
+
const { class: compoundClass, ...compoundProps } = compound;
|
|
119
|
+
const matches = Object.entries(compoundProps).every(([key, value]) => finalProps[key] === value);
|
|
120
|
+
if (matches) {
|
|
121
|
+
if (compoundClass)
|
|
122
|
+
classes.push(compoundClass);
|
|
123
|
+
// Add compound attributes
|
|
124
|
+
Object.entries(compound).forEach(([k, v]) => {
|
|
125
|
+
if (k !== 'class' && !Object.keys(compoundProps).includes(k)) {
|
|
126
|
+
attributes[k] = v;
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return {
|
|
133
|
+
class: classes,
|
|
134
|
+
...attributes
|
|
135
|
+
};
|
|
136
|
+
};
|
|
137
|
+
}
|