@svelte-atoms/core 1.0.0-alpha.31 → 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 +289 -853
- package/dist/attachments/index.d.ts +1 -0
- package/dist/attachments/index.js +1 -0
- package/dist/components/accordion/accordion-root.svelte +65 -65
- package/dist/components/accordion/accordion.stories.svelte +70 -70
- package/dist/components/accordion/item/accordion-item-body.svelte +44 -44
- package/dist/components/accordion/item/accordion-item-header.svelte +51 -51
- package/dist/components/accordion/item/accordion-item-indicator.svelte +51 -51
- package/dist/components/accordion/item/accordion-item-root.svelte +66 -66
- package/dist/components/alert/alert-close-button.svelte +66 -66
- package/dist/components/alert/alert-description.svelte +42 -42
- package/dist/components/alert/alert-root.svelte +68 -68
- package/dist/components/atom/html-atom.svelte +26 -194
- 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/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/calendar/calendar-day.svelte +101 -101
- package/dist/components/checkbox/checkbox.svelte +159 -159
- package/dist/components/collapsible/bond.svelte.js +2 -1
- package/dist/components/collapsible/collapsible-body.svelte +3 -2
- 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.stories.svelte +50 -0
- package/dist/components/combobox/combobox.stories.svelte.d.ts +3 -0
- package/dist/components/datagrid/tr/datagrid-tr.svelte +90 -90
- 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 +67 -67
- package/dist/components/dialog/bond.svelte.js +5 -20
- package/dist/components/dialog/dialog-content.svelte +44 -44
- package/dist/components/dialog/dialog-root.svelte +91 -91
- package/dist/components/drawer/bond.svelte.d.ts +18 -16
- package/dist/components/drawer/bond.svelte.js +8 -18
- package/dist/components/drawer/drawer-content.svelte +49 -49
- package/dist/components/drawer/drawer-root.svelte +5 -4
- package/dist/components/drawer/drawer.stories.svelte +141 -144
- package/dist/components/drawer/motion.js +1 -1
- 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 +21 -22
- package/dist/components/dropdown/bond.svelte.js +29 -53
- package/dist/components/dropdown/dropdown-root.svelte +65 -59
- 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 +83 -80
- package/dist/components/dropdown/index.d.ts +1 -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/list/list-item.svelte +20 -20
- package/dist/components/menu/atoms.d.ts +8 -3
- package/dist/components/menu/atoms.js +8 -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 +1 -0
- package/dist/components/menu/index.js +1 -0
- 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 +33 -33
- package/dist/components/menu/types.d.ts +0 -7
- package/dist/components/popover/bond.svelte.d.ts +11 -14
- package/dist/components/popover/bond.svelte.js +27 -44
- package/dist/components/popover/popover-content.svelte +137 -137
- package/dist/components/popover/popover.stories.svelte +37 -49
- package/dist/components/portal/active-portal.svelte +29 -29
- package/dist/components/portal/portal-root.svelte +76 -76
- package/dist/components/portal/teleport.svelte +49 -49
- package/dist/components/radio/radio.svelte +109 -109
- 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/root/l0-portal.svelte.d.ts +26 -0
- 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 +17 -18
- 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/sidebar/motion.svelte.js +3 -3
- package/dist/components/sidebar/sidebar-content.svelte +40 -40
- package/dist/components/textarea/textarea-input.svelte +9 -9
- package/dist/components/textarea/textarea-root.svelte +9 -9
- package/dist/components/tooltip/tooltip-trigger.svelte +39 -39
- 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/context/preset.svelte.d.ts +3 -1
- package/dist/icons/icon-copy.svelte +6 -6
- 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 -2
- 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 -69
- package/dist/components/menu/menu-item.svelte.d.ts +0 -37
- package/dist/utils/markdown-to-llm.d.ts +0 -28
- package/dist/utils/markdown-to-llm.js +0 -76
|
@@ -3,13 +3,19 @@
|
|
|
3
3
|
import type { Base, HtmlAtomProps, SnippetBase } from './types';
|
|
4
4
|
import { RootBond } from '../root';
|
|
5
5
|
import { HtmlElement } from '../element';
|
|
6
|
-
import { cn, type ClassValue, type VariantDefinition } from '../../utils';
|
|
7
6
|
import { getPreset } from '../../context';
|
|
8
7
|
import type { PresetModuleName } from '../../context/preset.svelte';
|
|
9
|
-
import type { Bond } from '../../shared';
|
|
10
8
|
import SnippetRenderer from './snippet-renderer.svelte';
|
|
11
9
|
import type { Component } from 'svelte';
|
|
12
|
-
import {
|
|
10
|
+
import type { ClassValue } from '../../utils';
|
|
11
|
+
import {
|
|
12
|
+
resolvePreset,
|
|
13
|
+
resolveLocalVariants,
|
|
14
|
+
mergeVariants,
|
|
15
|
+
mergeClassesWithPreset,
|
|
16
|
+
extractRestProps,
|
|
17
|
+
isSnippetBase
|
|
18
|
+
} from './utils';
|
|
13
19
|
|
|
14
20
|
type Element = HTMLElementTagNameMap[E];
|
|
15
21
|
|
|
@@ -26,128 +32,41 @@
|
|
|
26
32
|
...restProps
|
|
27
33
|
}: HtmlAtomProps<E, B> & Omit<HTMLAttributes<Element>, 'children'> = $props();
|
|
28
34
|
|
|
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
35
|
// Memoize preset resolution - only recompute when presetKey or bond changes
|
|
37
36
|
const preset = $derived.by(() => {
|
|
38
37
|
if (!presetKey) return undefined;
|
|
39
38
|
const result = getPreset(presetKey as PresetModuleName)?.apply?.(bond, [bond]);
|
|
40
|
-
|
|
41
|
-
return call(result);
|
|
39
|
+
return resolvePreset(result);
|
|
42
40
|
});
|
|
43
41
|
|
|
44
|
-
const
|
|
42
|
+
const presetVariantsProps = $derived(preset?.variants);
|
|
45
43
|
|
|
46
44
|
// Resolve local variants - either VariantDefinition or function
|
|
47
|
-
const localVariants = $derived
|
|
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
|
-
});
|
|
45
|
+
const localVariants = $derived(resolveLocalVariants(variants, bond, restProps));
|
|
58
46
|
|
|
59
47
|
// Merge preset variants with local variants
|
|
60
48
|
// Memoized to avoid recomputation when inputs haven't changed
|
|
61
49
|
const mergedVariants = $derived.by(() => {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
|
50
|
+
return mergeVariants(
|
|
51
|
+
presetVariantsProps,
|
|
52
|
+
preset?.class,
|
|
53
|
+
preset?.compounds,
|
|
54
|
+
preset?.defaults,
|
|
55
|
+
localVariants,
|
|
56
|
+
bond,
|
|
57
|
+
restProps
|
|
132
58
|
);
|
|
133
59
|
});
|
|
134
60
|
|
|
61
|
+
const _klass = $derived(
|
|
62
|
+
mergeClassesWithPreset(klass, preset?.class, mergedVariants?.class as ClassValue)
|
|
63
|
+
);
|
|
64
|
+
|
|
135
65
|
const _base = $derived(base ?? preset?.base);
|
|
136
66
|
const _as = $derived(as ?? preset?.as);
|
|
137
|
-
const _restProps = $derived
|
|
138
|
-
const {
|
|
139
|
-
class: klassPreset,
|
|
140
|
-
base,
|
|
141
|
-
as,
|
|
142
|
-
variants: presetProps,
|
|
143
|
-
...restPresetProps
|
|
144
|
-
} = preset ?? {};
|
|
145
|
-
const { class: variantClass, ...variantsRestProps } = mergedVariants ?? {};
|
|
67
|
+
const _restProps = $derived(extractRestProps(preset, mergedVariants, restProps));
|
|
146
68
|
|
|
147
|
-
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
const isSnippet = $derived(typeof _base === 'function' && _base.length === 1 && !_base.prototype);
|
|
69
|
+
const isSnippet = $derived(isSnippetBase(_base));
|
|
151
70
|
|
|
152
71
|
const snippet = $derived(_base as SnippetBase);
|
|
153
72
|
|
|
@@ -165,93 +84,6 @@
|
|
|
165
84
|
props: { class: _klass, as: _as, ..._restProps }
|
|
166
85
|
};
|
|
167
86
|
}) 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
87
|
</script>
|
|
256
88
|
|
|
257
89
|
<renderer.component {...renderer.props}>
|
|
@@ -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?:
|
|
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 {};
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { cn } from '../../utils';
|
|
2
|
+
import { call } from '../../utils/function';
|
|
3
|
+
/**
|
|
4
|
+
* Cache for resolved variants to avoid recomputation
|
|
5
|
+
* Key: JSON stringified combination of variant props
|
|
6
|
+
*/
|
|
7
|
+
const variantCache = new Map();
|
|
8
|
+
/**
|
|
9
|
+
* Maximum cache size to prevent memory leaks
|
|
10
|
+
*/
|
|
11
|
+
const MAX_CACHE_SIZE = 100;
|
|
12
|
+
/**
|
|
13
|
+
* Resolves preset to its final value, handling both direct values and factory functions
|
|
14
|
+
*/
|
|
15
|
+
export function resolvePreset(preset) {
|
|
16
|
+
if (!preset)
|
|
17
|
+
return undefined;
|
|
18
|
+
const result = call(preset);
|
|
19
|
+
// If call returns a function, call it again (handle deferred preset)
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
21
|
+
return typeof result === 'function' ? result() : result;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Pure function to resolve variant definition to props
|
|
25
|
+
* Caches results to avoid recomputation with same inputs
|
|
26
|
+
*/
|
|
27
|
+
export function resolveVariants(def, bond, props) {
|
|
28
|
+
const { variants: variantMap, compounds, defaults, class: baseClass } = def;
|
|
29
|
+
// Merge props with defaults
|
|
30
|
+
const finalProps = { ...defaults, ...props };
|
|
31
|
+
// Create cache key from final props (only variant-related props)
|
|
32
|
+
const variantKeys = variantMap ? Object.keys(variantMap) : [];
|
|
33
|
+
const relevantProps = Object.fromEntries(Object.entries(finalProps).filter(([key]) => variantKeys.includes(key)));
|
|
34
|
+
const cacheKey = JSON.stringify({ relevantProps, baseClass, compounds });
|
|
35
|
+
// Check cache
|
|
36
|
+
if (variantCache.has(cacheKey)) {
|
|
37
|
+
return variantCache.get(cacheKey);
|
|
38
|
+
}
|
|
39
|
+
const classes = [];
|
|
40
|
+
const attributes = {};
|
|
41
|
+
// Add base class
|
|
42
|
+
if (baseClass)
|
|
43
|
+
classes.push(baseClass);
|
|
44
|
+
// Add variant classes
|
|
45
|
+
if (variantMap) {
|
|
46
|
+
for (const [key, value] of Object.entries(finalProps)) {
|
|
47
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
48
|
+
const variantValue = variantMap[key]?.[value];
|
|
49
|
+
if (variantValue !== undefined) {
|
|
50
|
+
const resolved = typeof variantValue === 'function' ? variantValue(bond) : variantValue;
|
|
51
|
+
if (typeof resolved === 'string') {
|
|
52
|
+
classes.push(resolved);
|
|
53
|
+
}
|
|
54
|
+
else if (typeof resolved === 'object' && resolved !== null) {
|
|
55
|
+
if ('class' in resolved) {
|
|
56
|
+
classes.push(resolved.class);
|
|
57
|
+
}
|
|
58
|
+
// Add other attributes (including Symbol-based attachment keys)
|
|
59
|
+
Object.getOwnPropertySymbols(resolved).forEach((sym) => {
|
|
60
|
+
attributes[sym] = resolved[sym];
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Add compound variants
|
|
67
|
+
if (compounds) {
|
|
68
|
+
for (const compound of compounds) {
|
|
69
|
+
const { class: compoundClass, ...compoundProps } = compound;
|
|
70
|
+
const matches = Object.entries(compoundProps).every(([key, value]) => finalProps[key] === value);
|
|
71
|
+
if (matches) {
|
|
72
|
+
if (compoundClass)
|
|
73
|
+
classes.push(compoundClass);
|
|
74
|
+
// Add compound attributes
|
|
75
|
+
Object.entries(compound).forEach(([k, v]) => {
|
|
76
|
+
if (k !== 'class' && !Object.keys(compoundProps).includes(k)) {
|
|
77
|
+
attributes[k] = v;
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const result = {
|
|
84
|
+
class: classes,
|
|
85
|
+
...attributes
|
|
86
|
+
};
|
|
87
|
+
// Store in cache (limit cache size to prevent memory leaks)
|
|
88
|
+
if (variantCache.size >= MAX_CACHE_SIZE) {
|
|
89
|
+
// Clear oldest entry (first in Map)
|
|
90
|
+
const firstKey = variantCache.keys().next().value;
|
|
91
|
+
if (firstKey)
|
|
92
|
+
variantCache.delete(firstKey);
|
|
93
|
+
}
|
|
94
|
+
variantCache.set(cacheKey, result);
|
|
95
|
+
return result;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Pure function to merge preset and local variant definitions
|
|
99
|
+
* Returns merged variant props with local overriding preset
|
|
100
|
+
*/
|
|
101
|
+
export function mergeVariants(
|
|
102
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
103
|
+
presetVariants, presetClass,
|
|
104
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
105
|
+
presetCompounds,
|
|
106
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
107
|
+
presetDefaults, localVariants, bond, props) {
|
|
108
|
+
// No variants at all
|
|
109
|
+
if (!presetVariants && !localVariants)
|
|
110
|
+
return undefined;
|
|
111
|
+
// Only preset variants (raw object from preset)
|
|
112
|
+
if (presetVariants && !localVariants) {
|
|
113
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
114
|
+
const variantDef = {
|
|
115
|
+
class: presetClass ?? '',
|
|
116
|
+
variants: presetVariants,
|
|
117
|
+
compounds: presetCompounds ?? [],
|
|
118
|
+
defaults: presetDefaults ?? {}
|
|
119
|
+
};
|
|
120
|
+
return resolveVariants(variantDef, bond, props);
|
|
121
|
+
}
|
|
122
|
+
// Only local variants
|
|
123
|
+
if (!presetVariants && localVariants) {
|
|
124
|
+
return localVariants;
|
|
125
|
+
}
|
|
126
|
+
// Both exist - merge them
|
|
127
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
128
|
+
const presetVariantDef = {
|
|
129
|
+
class: presetClass ?? '',
|
|
130
|
+
variants: presetVariants ?? {},
|
|
131
|
+
compounds: presetCompounds ?? [],
|
|
132
|
+
defaults: presetDefaults ?? {}
|
|
133
|
+
};
|
|
134
|
+
const presetResolved = resolveVariants(presetVariantDef, bond, props);
|
|
135
|
+
// Merge the resolved variant props
|
|
136
|
+
// Local variant classes and attributes override preset
|
|
137
|
+
const presetClasses = Array.isArray(presetResolved.class)
|
|
138
|
+
? presetResolved.class
|
|
139
|
+
: [presetResolved.class];
|
|
140
|
+
const localClasses = Array.isArray(localVariants?.class)
|
|
141
|
+
? localVariants.class
|
|
142
|
+
: [localVariants?.class];
|
|
143
|
+
return {
|
|
144
|
+
class: [...presetClasses, ...localClasses].filter(Boolean),
|
|
145
|
+
...presetResolved,
|
|
146
|
+
...localVariants
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Pure function to merge classes with $preset placeholder support
|
|
151
|
+
* Handles the special $preset placeholder for precise positioning of preset classes
|
|
152
|
+
*/
|
|
153
|
+
export function mergeClassesWithPreset(userClass, presetClass, variantClass) {
|
|
154
|
+
const klassStr = cn(userClass ?? '');
|
|
155
|
+
// Check for $preset placeholder first
|
|
156
|
+
if (!klassStr.includes('$preset')) {
|
|
157
|
+
// No placeholder - normal merge: variants override direct class
|
|
158
|
+
return cn(userClass, variantClass ?? '');
|
|
159
|
+
}
|
|
160
|
+
// Has placeholder - calculate position and inject preset classes
|
|
161
|
+
const parts = klassStr.split('$preset');
|
|
162
|
+
// Only keep the last $preset placeholder
|
|
163
|
+
const beforeLastPlaceholder = parts.slice(0, -1).join('');
|
|
164
|
+
const afterLastPlaceholder = parts[parts.length - 1];
|
|
165
|
+
const presetClassString = cn(presetClass);
|
|
166
|
+
// Merge: before + preset + variants + after
|
|
167
|
+
return cn(beforeLastPlaceholder, presetClassString, variantClass ?? '', afterLastPlaceholder);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Pure function to resolve local variants
|
|
171
|
+
* Handles both function-based and VariantDefinition-based variants
|
|
172
|
+
*/
|
|
173
|
+
export function resolveLocalVariants(
|
|
174
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
175
|
+
variants, bond, props) {
|
|
176
|
+
if (!variants)
|
|
177
|
+
return undefined;
|
|
178
|
+
// If it's a function, call it directly
|
|
179
|
+
if (typeof variants === 'function') {
|
|
180
|
+
return variants(bond, props);
|
|
181
|
+
}
|
|
182
|
+
// Otherwise it's a VariantDefinition, resolve it
|
|
183
|
+
return resolveVariants(variants, bond, props);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Pure function to extract rest props by filtering out preset and variant-specific props
|
|
187
|
+
*/
|
|
188
|
+
export function extractRestProps(
|
|
189
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
190
|
+
preset, mergedVariants, restProps) {
|
|
191
|
+
const presetProps = { ...preset };
|
|
192
|
+
const presetKeysToRemove = ['class', 'base', 'as', 'variants', 'compounds', 'defaults'];
|
|
193
|
+
for (const key of presetKeysToRemove) {
|
|
194
|
+
delete presetProps[key];
|
|
195
|
+
}
|
|
196
|
+
const variantsRestProps = { ...mergedVariants };
|
|
197
|
+
const variantKeysToRemove = ['class', 'variants', 'compounds', 'defaults'];
|
|
198
|
+
for (const key of variantKeysToRemove) {
|
|
199
|
+
delete variantsRestProps[key];
|
|
200
|
+
}
|
|
201
|
+
return { ...presetProps, ...variantsRestProps, ...restProps };
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Pure function to check if a base is a snippet
|
|
205
|
+
*/
|
|
206
|
+
export function isSnippetBase(base) {
|
|
207
|
+
return typeof base === 'function' && base.length === 1 && !base.prototype;
|
|
208
|
+
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
<script module>
|
|
2
|
-
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
3
|
-
import { Breadcrumb as BreadcrumbModule } from '.';
|
|
4
|
-
|
|
5
|
-
const { Story } = defineMeta({
|
|
6
|
-
title: 'ATOMS/Breadcrumb'
|
|
7
|
-
});
|
|
8
|
-
</script>
|
|
9
|
-
|
|
10
|
-
<Story name="Breadcrumb">
|
|
11
|
-
<BreadcrumbModule.Root>
|
|
12
|
-
<BreadcrumbModule.Item href="/">Home</BreadcrumbModule.Item>
|
|
13
|
-
<BreadcrumbModule.Separator>/</BreadcrumbModule.Separator>
|
|
14
|
-
<BreadcrumbModule.Item href="/vehicles">Vehicles</BreadcrumbModule.Item>
|
|
15
|
-
</BreadcrumbModule.Root>
|
|
16
|
-
</Story>
|
|
1
|
+
<script module>
|
|
2
|
+
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
3
|
+
import { Breadcrumb as BreadcrumbModule } from '.';
|
|
4
|
+
|
|
5
|
+
const { Story } = defineMeta({
|
|
6
|
+
title: 'ATOMS/Breadcrumb'
|
|
7
|
+
});
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<Story name="Breadcrumb">
|
|
11
|
+
<BreadcrumbModule.Root>
|
|
12
|
+
<BreadcrumbModule.Item href="/">Home</BreadcrumbModule.Item>
|
|
13
|
+
<BreadcrumbModule.Separator>/</BreadcrumbModule.Separator>
|
|
14
|
+
<BreadcrumbModule.Item href="/vehicles">Vehicles</BreadcrumbModule.Item>
|
|
15
|
+
</BreadcrumbModule.Root>
|
|
16
|
+
</Story>
|