@idealyst/theme 1.2.29 → 1.2.31
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/package.json +8 -2
- package/src/animation/index.native.ts +62 -0
- package/src/animation/index.ts +68 -0
- package/src/animation/tokens.ts +145 -0
- package/src/animation/transitions.native.ts +219 -0
- package/src/animation/transitions.ts +293 -0
- package/src/animation/types.ts +80 -0
- package/src/babel/plugin.js +114 -2
- package/src/babel/theme-analyzer.js +126 -26
- package/src/builder.ts +6 -0
- package/src/components/CLAUDE.md +1 -1
- package/src/config/generator.ts +2 -2
- package/src/darkTheme.ts +1 -1
- package/src/index.ts +5 -1
- package/src/lightTheme.ts +15 -1
- package/src/styleBuilder.ts +1 -0
- package/src/theme/extensions.ts +3 -1
- package/src/theme/structures.ts +17 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Web-specific animation utilities
|
|
3
|
+
*
|
|
4
|
+
* These utilities generate CSS transition and animation strings
|
|
5
|
+
* from animation tokens for use in web stylesheets.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { durations, easings, presets } from './tokens';
|
|
9
|
+
import type { DurationKey, EasingKey, PresetKey } from './tokens';
|
|
10
|
+
import type {
|
|
11
|
+
Duration,
|
|
12
|
+
Keyframes,
|
|
13
|
+
KeyframeAnimationConfig,
|
|
14
|
+
AnimationIterations,
|
|
15
|
+
AnimationDirection,
|
|
16
|
+
AnimationFillMode,
|
|
17
|
+
} from './types';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Resolve a duration value to milliseconds
|
|
21
|
+
*/
|
|
22
|
+
export function resolveDuration(duration: Duration): number {
|
|
23
|
+
if (typeof duration === 'number') {
|
|
24
|
+
return duration;
|
|
25
|
+
}
|
|
26
|
+
return durations[duration];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Resolve an easing key to CSS string
|
|
31
|
+
*/
|
|
32
|
+
export function resolveEasing(easing: EasingKey): string {
|
|
33
|
+
const easingConfig = easings[easing];
|
|
34
|
+
// Spring configs don't have CSS equivalent, fall back to ease-out
|
|
35
|
+
if ('damping' in easingConfig) {
|
|
36
|
+
return 'ease-out';
|
|
37
|
+
}
|
|
38
|
+
return easingConfig.css;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Generate a CSS transition string from tokens
|
|
43
|
+
*
|
|
44
|
+
* @param properties - CSS property or array of properties to transition
|
|
45
|
+
* @param duration - Duration token key or milliseconds
|
|
46
|
+
* @param easing - Easing token key
|
|
47
|
+
* @returns CSS transition string
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* import { cssTransition } from '@idealyst/theme/animation';
|
|
51
|
+
*
|
|
52
|
+
* // Single property
|
|
53
|
+
* cssTransition('opacity', 'normal', 'easeOut')
|
|
54
|
+
* // => "opacity 200ms ease-out"
|
|
55
|
+
*
|
|
56
|
+
* // Multiple properties
|
|
57
|
+
* cssTransition(['opacity', 'transform'], 'fast', 'standard')
|
|
58
|
+
* // => "opacity 100ms cubic-bezier(0.4, 0, 0.2, 1), transform 100ms cubic-bezier(0.4, 0, 0.2, 1)"
|
|
59
|
+
*
|
|
60
|
+
* // With numeric duration
|
|
61
|
+
* cssTransition('background-color', 150, 'ease')
|
|
62
|
+
* // => "background-color 150ms ease"
|
|
63
|
+
*/
|
|
64
|
+
export function cssTransition(
|
|
65
|
+
properties: string | string[],
|
|
66
|
+
duration: Duration = 'normal',
|
|
67
|
+
easing: EasingKey = 'ease'
|
|
68
|
+
): string {
|
|
69
|
+
const props = Array.isArray(properties) ? properties : [properties];
|
|
70
|
+
const durationMs = resolveDuration(duration);
|
|
71
|
+
const easingValue = resolveEasing(easing);
|
|
72
|
+
|
|
73
|
+
return props.map((prop) => `${prop} ${durationMs}ms ${easingValue}`).join(', ');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Generate a CSS transition string from a preset
|
|
78
|
+
*
|
|
79
|
+
* @param presetName - Preset key from presets
|
|
80
|
+
* @param properties - Optional CSS properties (defaults to 'all')
|
|
81
|
+
* @returns CSS transition string
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* import { cssPreset } from '@idealyst/theme/animation';
|
|
85
|
+
*
|
|
86
|
+
* cssPreset('hover')
|
|
87
|
+
* // => "all 100ms ease"
|
|
88
|
+
*
|
|
89
|
+
* cssPreset('fadeIn', 'opacity')
|
|
90
|
+
* // => "opacity 200ms cubic-bezier(0, 0, 0.2, 1)"
|
|
91
|
+
*/
|
|
92
|
+
export function cssPreset(presetName: PresetKey, properties: string | string[] = 'all'): string {
|
|
93
|
+
const preset = presets[presetName];
|
|
94
|
+
return cssTransition(properties, preset.duration, preset.easing);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Generate CSS @keyframes string
|
|
99
|
+
*
|
|
100
|
+
* @param name - Unique name for the keyframes
|
|
101
|
+
* @param frames - Keyframe definitions
|
|
102
|
+
* @returns CSS @keyframes string
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* import { cssKeyframes } from '@idealyst/theme/animation';
|
|
106
|
+
*
|
|
107
|
+
* const fadeIn = cssKeyframes('fadeIn', {
|
|
108
|
+
* '0%': { opacity: 0 },
|
|
109
|
+
* '100%': { opacity: 1 },
|
|
110
|
+
* });
|
|
111
|
+
* // => "@keyframes fadeIn { 0% { opacity: 0; } 100% { opacity: 1; } }"
|
|
112
|
+
*/
|
|
113
|
+
export function cssKeyframes(name: string, frames: Keyframes): string {
|
|
114
|
+
const frameStrings = Object.entries(frames)
|
|
115
|
+
.map(([key, styles]) => {
|
|
116
|
+
const styleString = Object.entries(styles || {})
|
|
117
|
+
.map(([prop, value]) => {
|
|
118
|
+
// Convert camelCase to kebab-case
|
|
119
|
+
const kebabProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();
|
|
120
|
+
return `${kebabProp}: ${value}`;
|
|
121
|
+
})
|
|
122
|
+
.join('; ');
|
|
123
|
+
return `${key} { ${styleString}; }`;
|
|
124
|
+
})
|
|
125
|
+
.join(' ');
|
|
126
|
+
|
|
127
|
+
return `@keyframes ${name} { ${frameStrings} }`;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Generate CSS animation shorthand string
|
|
132
|
+
*
|
|
133
|
+
* @param name - Animation name (must match @keyframes name)
|
|
134
|
+
* @param config - Animation configuration
|
|
135
|
+
* @returns CSS animation shorthand string
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* import { cssAnimation } from '@idealyst/theme/animation';
|
|
139
|
+
*
|
|
140
|
+
* cssAnimation('fadeIn', { duration: 'normal', easing: 'easeOut' })
|
|
141
|
+
* // => "fadeIn 200ms ease-out"
|
|
142
|
+
*
|
|
143
|
+
* cssAnimation('spin', { duration: 'loop', easing: 'linear', iterations: 'infinite' })
|
|
144
|
+
* // => "spin 1000ms linear infinite"
|
|
145
|
+
*/
|
|
146
|
+
export function cssAnimation(name: string, config: KeyframeAnimationConfig = {}): string {
|
|
147
|
+
const {
|
|
148
|
+
duration = 'normal',
|
|
149
|
+
easing = 'ease',
|
|
150
|
+
delay = 0,
|
|
151
|
+
iterations = 1,
|
|
152
|
+
direction = 'normal',
|
|
153
|
+
fillMode = 'none',
|
|
154
|
+
} = config;
|
|
155
|
+
|
|
156
|
+
const durationMs = resolveDuration(duration);
|
|
157
|
+
const easingValue = resolveEasing(easing);
|
|
158
|
+
|
|
159
|
+
const parts = [
|
|
160
|
+
name,
|
|
161
|
+
`${durationMs}ms`,
|
|
162
|
+
easingValue,
|
|
163
|
+
delay > 0 ? `${delay}ms` : null,
|
|
164
|
+
iterations !== 1 ? iterations : null,
|
|
165
|
+
direction !== 'normal' ? direction : null,
|
|
166
|
+
fillMode !== 'none' ? fillMode : null,
|
|
167
|
+
].filter(Boolean);
|
|
168
|
+
|
|
169
|
+
return parts.join(' ');
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* CSS @property registration for animatable custom properties
|
|
174
|
+
*
|
|
175
|
+
* This CSS should be injected once into the document head to enable
|
|
176
|
+
* smooth gradient animations using CSS custom properties.
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* // Inject in your app's entry point
|
|
180
|
+
* import { gradientPropertyCSS, injectGradientCSS } from '@idealyst/theme/animation';
|
|
181
|
+
*
|
|
182
|
+
* // Option 1: Manual injection
|
|
183
|
+
* const style = document.createElement('style');
|
|
184
|
+
* style.textContent = gradientPropertyCSS;
|
|
185
|
+
* document.head.appendChild(style);
|
|
186
|
+
*
|
|
187
|
+
* // Option 2: Use helper
|
|
188
|
+
* injectGradientCSS();
|
|
189
|
+
*/
|
|
190
|
+
export const gradientPropertyCSS = `
|
|
191
|
+
@property --gradient-angle {
|
|
192
|
+
syntax: '<angle>';
|
|
193
|
+
initial-value: 0deg;
|
|
194
|
+
inherits: false;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
@property --gradient-position {
|
|
198
|
+
syntax: '<percentage>';
|
|
199
|
+
initial-value: 0%;
|
|
200
|
+
inherits: false;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
@keyframes spin-gradient {
|
|
204
|
+
from { --gradient-angle: 0deg; }
|
|
205
|
+
to { --gradient-angle: 360deg; }
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
@keyframes pulse-gradient {
|
|
209
|
+
0%, 100% { opacity: 1; }
|
|
210
|
+
50% { opacity: 0.5; }
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
@keyframes wave-gradient {
|
|
214
|
+
from { --gradient-position: -100%; }
|
|
215
|
+
to { --gradient-position: 200%; }
|
|
216
|
+
}
|
|
217
|
+
`;
|
|
218
|
+
|
|
219
|
+
let gradientCSSInjected = false;
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Inject gradient CSS into document head (idempotent)
|
|
223
|
+
*
|
|
224
|
+
* Call this once in your app to enable gradient border animations.
|
|
225
|
+
* Safe to call multiple times - will only inject once.
|
|
226
|
+
*/
|
|
227
|
+
export function injectGradientCSS(): void {
|
|
228
|
+
if (typeof document === 'undefined' || gradientCSSInjected) {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const style = document.createElement('style');
|
|
233
|
+
style.id = 'idealyst-gradient-animations';
|
|
234
|
+
style.textContent = gradientPropertyCSS;
|
|
235
|
+
document.head.appendChild(style);
|
|
236
|
+
gradientCSSInjected = true;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Generate conic gradient border spinner styles
|
|
241
|
+
*
|
|
242
|
+
* @param colors - Array of gradient colors
|
|
243
|
+
* @param borderWidth - Border thickness in pixels
|
|
244
|
+
* @param duration - Animation duration
|
|
245
|
+
* @returns Style object for animated gradient border
|
|
246
|
+
*
|
|
247
|
+
* @example
|
|
248
|
+
* import { conicSpinnerStyle } from '@idealyst/theme/animation';
|
|
249
|
+
*
|
|
250
|
+
* const spinnerStyle = conicSpinnerStyle(
|
|
251
|
+
* ['#3b82f6', '#8b5cf6', '#ec4899'],
|
|
252
|
+
* 2,
|
|
253
|
+
* 2000
|
|
254
|
+
* );
|
|
255
|
+
*/
|
|
256
|
+
export function conicSpinnerStyle(
|
|
257
|
+
colors: string[],
|
|
258
|
+
borderWidth: number = 2,
|
|
259
|
+
duration: Duration = 2000
|
|
260
|
+
): Record<string, string | number> {
|
|
261
|
+
const durationMs = resolveDuration(duration);
|
|
262
|
+
const colorString = colors.join(', ');
|
|
263
|
+
|
|
264
|
+
return {
|
|
265
|
+
background: `conic-gradient(from var(--gradient-angle), ${colorString})`,
|
|
266
|
+
animation: `spin-gradient ${durationMs}ms linear infinite`,
|
|
267
|
+
// Mask technique for border-only effect
|
|
268
|
+
WebkitMask: 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)',
|
|
269
|
+
WebkitMaskComposite: 'xor',
|
|
270
|
+
maskComposite: 'exclude',
|
|
271
|
+
padding: borderWidth,
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Generate pulse gradient styles
|
|
277
|
+
*
|
|
278
|
+
* @param colors - Array of gradient colors
|
|
279
|
+
* @param duration - Animation duration
|
|
280
|
+
* @returns Style object for pulsing gradient
|
|
281
|
+
*/
|
|
282
|
+
export function pulseGradientStyle(
|
|
283
|
+
colors: string[],
|
|
284
|
+
duration: Duration = 'slowest'
|
|
285
|
+
): Record<string, string | number> {
|
|
286
|
+
const durationMs = resolveDuration(duration);
|
|
287
|
+
const colorString = colors.join(', ');
|
|
288
|
+
|
|
289
|
+
return {
|
|
290
|
+
background: `linear-gradient(135deg, ${colorString})`,
|
|
291
|
+
animation: `pulse-gradient ${durationMs}ms ease-in-out infinite`,
|
|
292
|
+
};
|
|
293
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Animation type definitions for @idealyst/theme
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { durations, easings } from './tokens';
|
|
6
|
+
|
|
7
|
+
// Duration types
|
|
8
|
+
export type DurationKey = keyof typeof durations;
|
|
9
|
+
export type Duration = DurationKey | number;
|
|
10
|
+
|
|
11
|
+
// Easing types
|
|
12
|
+
export type EasingKey = keyof typeof easings;
|
|
13
|
+
export type BezierEasing = readonly [number, number, number, number];
|
|
14
|
+
export type SpringConfig = {
|
|
15
|
+
readonly damping: number;
|
|
16
|
+
readonly stiffness: number;
|
|
17
|
+
readonly mass: number;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type CSSEasing = {
|
|
21
|
+
readonly css: string;
|
|
22
|
+
readonly bezier: BezierEasing;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export type Easing = CSSEasing | SpringConfig;
|
|
26
|
+
|
|
27
|
+
// Animation configuration
|
|
28
|
+
export interface AnimationConfig {
|
|
29
|
+
duration?: Duration;
|
|
30
|
+
easing?: EasingKey;
|
|
31
|
+
delay?: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Transition configuration for CSS
|
|
35
|
+
export interface TransitionConfig extends AnimationConfig {
|
|
36
|
+
properties?: string | string[];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Keyframe types
|
|
40
|
+
export type KeyframeStyles = Record<string, React.CSSProperties>;
|
|
41
|
+
export type KeyframePercentage = `${number}%` | 'from' | 'to';
|
|
42
|
+
export type Keyframes = Partial<Record<KeyframePercentage, React.CSSProperties>>;
|
|
43
|
+
|
|
44
|
+
// Animation iteration
|
|
45
|
+
export type AnimationIterations = number | 'infinite';
|
|
46
|
+
export type AnimationDirection = 'normal' | 'reverse' | 'alternate' | 'alternate-reverse';
|
|
47
|
+
export type AnimationFillMode = 'none' | 'forwards' | 'backwards' | 'both';
|
|
48
|
+
|
|
49
|
+
// Full animation configuration
|
|
50
|
+
export interface KeyframeAnimationConfig extends AnimationConfig {
|
|
51
|
+
iterations?: AnimationIterations;
|
|
52
|
+
direction?: AnimationDirection;
|
|
53
|
+
fillMode?: AnimationFillMode;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Spring types for native
|
|
57
|
+
export type SpringType = 'spring' | 'springStiff' | 'springBouncy';
|
|
58
|
+
|
|
59
|
+
// Timing config for Reanimated
|
|
60
|
+
export interface TimingAnimationConfig {
|
|
61
|
+
duration: number;
|
|
62
|
+
easing: BezierEasing;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Platform-specific options
|
|
66
|
+
export interface PlatformAnimationOptions {
|
|
67
|
+
web?: Partial<TransitionConfig> & { transition?: string };
|
|
68
|
+
native?: Partial<AnimationConfig> & Partial<SpringConfig>;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Gradient animation types
|
|
72
|
+
export type GradientAnimation = 'spin' | 'pulse' | 'wave';
|
|
73
|
+
|
|
74
|
+
export interface GradientBorderConfig {
|
|
75
|
+
colors: string[];
|
|
76
|
+
borderWidth?: number;
|
|
77
|
+
borderRadius?: number;
|
|
78
|
+
duration?: Duration;
|
|
79
|
+
animation?: GradientAnimation;
|
|
80
|
+
}
|
package/src/babel/plugin.js
CHANGED
|
@@ -210,6 +210,14 @@ function expandIterators(t, callback, themeParam, keys, verbose, expandedVariant
|
|
|
210
210
|
}
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
+
// Look for compoundVariants: [ { type: 'filled', selected: true, styles: { ... } }, ... ]
|
|
214
|
+
if (t.isObjectProperty(node) && t.isIdentifier(node.key, { name: 'compoundVariants' })) {
|
|
215
|
+
if (t.isArrayExpression(node.value)) {
|
|
216
|
+
const expanded = expandCompoundVariantsArray(t, node.value, themeParam, keys, verbose, expandedVariants);
|
|
217
|
+
return t.objectProperty(node.key, expanded);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
213
221
|
if (t.isObjectExpression(node)) {
|
|
214
222
|
return t.objectExpression(
|
|
215
223
|
node.properties.map(prop => processNode(prop, depth + 1))
|
|
@@ -352,6 +360,112 @@ function expandVariantsObject(t, variantsObj, themeParam, keys, verbose, expande
|
|
|
352
360
|
return t.objectExpression(newProperties);
|
|
353
361
|
}
|
|
354
362
|
|
|
363
|
+
/**
|
|
364
|
+
* Expand $iterator patterns in compoundVariants arrays.
|
|
365
|
+
*
|
|
366
|
+
* Input:
|
|
367
|
+
* compoundVariants: [
|
|
368
|
+
* { type: 'filled', selected: true, styles: { backgroundColor: theme.$intents.contrast } }
|
|
369
|
+
* ]
|
|
370
|
+
*
|
|
371
|
+
* Output (for intents = ['primary', 'success', 'danger', ...]):
|
|
372
|
+
* compoundVariants: [
|
|
373
|
+
* { type: 'filled', selected: true, intent: 'primary', styles: { backgroundColor: theme.intents.primary.contrast } },
|
|
374
|
+
* { type: 'filled', selected: true, intent: 'success', styles: { backgroundColor: theme.intents.success.contrast } },
|
|
375
|
+
* { type: 'filled', selected: true, intent: 'danger', styles: { backgroundColor: theme.intents.danger.contrast } },
|
|
376
|
+
* ...
|
|
377
|
+
* ]
|
|
378
|
+
*/
|
|
379
|
+
function expandCompoundVariantsArray(t, arrayNode, themeParam, keys, verbose, expandedVariants) {
|
|
380
|
+
const newElements = [];
|
|
381
|
+
|
|
382
|
+
verbose(` expandCompoundVariantsArray: processing ${arrayNode.elements?.length || 0} compound variants`);
|
|
383
|
+
|
|
384
|
+
for (const element of arrayNode.elements) {
|
|
385
|
+
if (!t.isObjectExpression(element)) {
|
|
386
|
+
newElements.push(element);
|
|
387
|
+
continue;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// Find the 'styles' property in this compound variant entry
|
|
391
|
+
let stylesProperty = null;
|
|
392
|
+
const otherProperties = [];
|
|
393
|
+
|
|
394
|
+
for (const prop of element.properties) {
|
|
395
|
+
if (t.isObjectProperty(prop)) {
|
|
396
|
+
const keyName = t.isIdentifier(prop.key) ? prop.key.name :
|
|
397
|
+
t.isStringLiteral(prop.key) ? prop.key.value : null;
|
|
398
|
+
if (keyName === 'styles') {
|
|
399
|
+
stylesProperty = prop;
|
|
400
|
+
} else {
|
|
401
|
+
otherProperties.push(prop);
|
|
402
|
+
}
|
|
403
|
+
} else {
|
|
404
|
+
otherProperties.push(prop);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
if (!stylesProperty) {
|
|
409
|
+
// No styles property, keep as-is
|
|
410
|
+
newElements.push(element);
|
|
411
|
+
continue;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// Check if the styles object contains $iterator patterns
|
|
415
|
+
const iteratorInfo = findIteratorPattern(t, stylesProperty.value, themeParam);
|
|
416
|
+
|
|
417
|
+
if (!iteratorInfo) {
|
|
418
|
+
// No $iterator pattern, keep as-is
|
|
419
|
+
newElements.push(element);
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
verbose(` Found $iterator in compoundVariant styles: ${iteratorInfo.type}`);
|
|
424
|
+
|
|
425
|
+
// Get keys to expand
|
|
426
|
+
let keysToExpand = [];
|
|
427
|
+
let variantKeyName = 'intent'; // Default for intents
|
|
428
|
+
|
|
429
|
+
if (iteratorInfo.type === 'intents') {
|
|
430
|
+
keysToExpand = keys?.intents || [];
|
|
431
|
+
variantKeyName = 'intent';
|
|
432
|
+
} else if (iteratorInfo.type === 'typography') {
|
|
433
|
+
keysToExpand = keys?.typography || [];
|
|
434
|
+
variantKeyName = 'typography';
|
|
435
|
+
} else if (iteratorInfo.type === 'sizes' && iteratorInfo.componentName) {
|
|
436
|
+
keysToExpand = keys?.sizes?.[iteratorInfo.componentName] || [];
|
|
437
|
+
variantKeyName = 'size';
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
if (keysToExpand.length === 0) {
|
|
441
|
+
// No keys to expand, keep as-is
|
|
442
|
+
newElements.push(element);
|
|
443
|
+
continue;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
verbose(` Expanding compoundVariant for ${keysToExpand.length} ${variantKeyName} keys`);
|
|
447
|
+
|
|
448
|
+
// Expand this compound variant for each key
|
|
449
|
+
for (const key of keysToExpand) {
|
|
450
|
+
// Replace $iterator refs in the styles
|
|
451
|
+
const expandedStyles = replaceIteratorRefs(t, stylesProperty.value, themeParam, iteratorInfo, key);
|
|
452
|
+
|
|
453
|
+
// Create new compound variant entry with the variant key added as a condition
|
|
454
|
+
const newProps = [
|
|
455
|
+
...otherProperties.map(p => t.cloneDeep(p)),
|
|
456
|
+
t.objectProperty(t.identifier(variantKeyName), t.stringLiteral(key)),
|
|
457
|
+
t.objectProperty(t.identifier('styles'), expandedStyles),
|
|
458
|
+
];
|
|
459
|
+
|
|
460
|
+
newElements.push(t.objectExpression(newProps));
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
expandedVariants.push({ variant: 'compoundVariants', iterator: iteratorInfo.type });
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
return t.arrayExpression(newElements);
|
|
467
|
+
}
|
|
468
|
+
|
|
355
469
|
function findIteratorPattern(t, node, themeParam, debugLog = () => {}) {
|
|
356
470
|
let result = null;
|
|
357
471
|
|
|
@@ -578,8 +692,6 @@ module.exports = function idealystStylesPlugin({ types: t }) {
|
|
|
578
692
|
}
|
|
579
693
|
}
|
|
580
694
|
|
|
581
|
-
// Plugin initialization logged in debug mode only
|
|
582
|
-
|
|
583
695
|
return {
|
|
584
696
|
name: 'idealyst-styles',
|
|
585
697
|
|