chaincss 2.0.6 → 2.1.0

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 (159) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/CODE_OF_CONDUCT.md +21 -0
  3. package/CONTRIBUTING.md +28 -0
  4. package/README.md +454 -231
  5. package/demo/demo/node_modules/caniuse-db/fulldata-json/data-2.0.json +1 -0
  6. package/demo/index.html +16 -0
  7. package/demo/package.json +20 -0
  8. package/demo/src/App.tsx +117 -0
  9. package/demo/src/chaincss-barrel.ts +9 -0
  10. package/demo/src/main.tsx +8 -0
  11. package/demo/src/styles.chain.ts +300 -0
  12. package/demo/vite.config.ts +46 -0
  13. package/dist/cli/commands/build.d.ts +0 -1
  14. package/dist/cli/commands/cache.d.ts +1 -0
  15. package/dist/cli/commands/init.d.ts +6 -3
  16. package/dist/cli/commands/timeline.d.ts +0 -1
  17. package/dist/cli/commands/watch.d.ts +0 -1
  18. package/dist/cli/index.d.ts +0 -1
  19. package/dist/cli/index.js +3213 -5296
  20. package/dist/cli/types.d.ts +51 -20
  21. package/dist/cli/utils/config-loader.d.ts +0 -1
  22. package/dist/cli/utils/file-utils.d.ts +27 -3
  23. package/dist/cli/utils/logger.d.ts +0 -1
  24. package/dist/compiler/Chain.d.ts +215 -0
  25. package/dist/compiler/animations.d.ts +76 -0
  26. package/dist/compiler/atomic-optimizer.d.ts +47 -12
  27. package/dist/compiler/breakpoints.d.ts +46 -0
  28. package/dist/compiler/btt.d.ts +36 -60
  29. package/dist/compiler/cache-manager.d.ts +58 -4
  30. package/dist/compiler/commonProps.d.ts +0 -1
  31. package/dist/compiler/content-addressable-cache.d.ts +78 -0
  32. package/dist/compiler/helpers.d.ts +54 -0
  33. package/dist/compiler/index.d.ts +16 -9
  34. package/dist/compiler/index.js +4450 -4316
  35. package/dist/compiler/prefixer.d.ts +17 -1
  36. package/dist/compiler/shorthands.d.ts +28 -0
  37. package/dist/compiler/suggestions.d.ts +43 -0
  38. package/dist/compiler/theme-contract.d.ts +16 -27
  39. package/dist/compiler/token-resolver.d.ts +69 -0
  40. package/dist/compiler/tokens.d.ts +33 -8
  41. package/dist/core/auto-detector.d.ts +34 -0
  42. package/dist/core/common-utils.d.ts +97 -0
  43. package/dist/core/compiler.d.ts +63 -23
  44. package/dist/core/constants.d.ts +137 -36
  45. package/dist/core/smart-chain.d.ts +3 -0
  46. package/dist/core/types.d.ts +122 -15
  47. package/dist/core/utils.d.ts +134 -17
  48. package/dist/index.d.ts +52 -8
  49. package/dist/index.js +7090 -5578
  50. package/dist/plugins/vite.d.ts +7 -5
  51. package/dist/plugins/vite.js +2964 -25641
  52. package/dist/plugins/webpack.d.ts +24 -1
  53. package/dist/plugins/webpack.js +209 -72
  54. package/dist/runtime/Chain.d.ts +32 -0
  55. package/dist/runtime/auto-hooks.d.ts +11 -0
  56. package/dist/runtime/hmr.d.ts +22 -2
  57. package/dist/runtime/index.d.ts +3 -2
  58. package/dist/runtime/index.js +3649 -301
  59. package/dist/runtime/injector.d.ts +39 -71
  60. package/dist/runtime/react.d.ts +17 -12
  61. package/dist/runtime/svelte.d.ts +15 -0
  62. package/dist/runtime/types.d.ts +126 -4
  63. package/dist/runtime/utils.d.ts +0 -1
  64. package/dist/runtime/vue.d.ts +34 -14
  65. package/package.json +59 -66
  66. package/src/cli/commands/build.ts +133 -0
  67. package/src/cli/commands/cache.ts +371 -0
  68. package/src/cli/commands/init.ts +230 -0
  69. package/src/cli/commands/timeline.ts +435 -0
  70. package/src/cli/commands/watch.ts +211 -0
  71. package/src/cli/index.ts +226 -0
  72. package/src/cli/types.ts +100 -0
  73. package/src/cli/utils/config-loader.ts +174 -0
  74. package/src/cli/utils/file-utils.ts +139 -0
  75. package/src/cli/utils/logger.ts +74 -0
  76. package/src/compiler/Chain.ts +831 -0
  77. package/src/compiler/animations.ts +517 -0
  78. package/src/compiler/atomic-optimizer.ts +786 -0
  79. package/src/compiler/breakpoints.ts +347 -0
  80. package/src/compiler/btt.ts +1147 -0
  81. package/src/compiler/cache-manager.ts +446 -0
  82. package/src/compiler/commonProps.ts +18 -0
  83. package/src/compiler/content-addressable-cache.ts +478 -0
  84. package/src/compiler/helpers.ts +407 -0
  85. package/src/compiler/index.ts +72 -0
  86. package/src/compiler/prefixer.ts +724 -0
  87. package/src/compiler/shorthands.ts +558 -0
  88. package/src/compiler/suggestions.ts +436 -0
  89. package/src/compiler/theme-contract.ts +197 -0
  90. package/src/compiler/token-resolver.ts +241 -0
  91. package/src/compiler/tokens.ts +612 -0
  92. package/src/core/auto-detector.ts +187 -0
  93. package/src/core/common-utils.ts +423 -0
  94. package/src/core/compiler.ts +835 -0
  95. package/src/core/constants.ts +424 -0
  96. package/src/core/index.ts +107 -0
  97. package/src/core/smart-chain.ts +163 -0
  98. package/src/core/types.ts +257 -0
  99. package/src/core/utils.ts +598 -0
  100. package/src/index.ts +208 -0
  101. package/src/plugins/vite.d.ts +316 -0
  102. package/src/plugins/vite.ts +424 -0
  103. package/src/plugins/webpack.d.ts +289 -0
  104. package/src/plugins/webpack.ts +416 -0
  105. package/src/runtime/Chain.ts +242 -0
  106. package/src/runtime/auto-hooks.tsx +127 -0
  107. package/src/runtime/auto-vue.ts +72 -0
  108. package/src/runtime/hmr.ts +212 -0
  109. package/src/runtime/index.ts +82 -0
  110. package/src/runtime/injector.ts +273 -0
  111. package/src/runtime/react.tsx +269 -0
  112. package/src/runtime/svelte.ts +15 -0
  113. package/src/runtime/types.ts +256 -0
  114. package/src/runtime/utils.ts +128 -0
  115. package/src/runtime/vite-env.d.ts +120 -0
  116. package/src/runtime/vue.ts +231 -0
  117. package/tsconfig.build.json +41 -0
  118. package/tsconfig.json +25 -0
  119. package/tsconfig.runtimes.json +18 -0
  120. package/dist/cli/cli.cjs +0 -7
  121. package/dist/cli/commands/build.d.ts.map +0 -1
  122. package/dist/cli/commands/compile.d.ts +0 -3
  123. package/dist/cli/commands/compile.d.ts.map +0 -1
  124. package/dist/cli/commands/init.d.ts.map +0 -1
  125. package/dist/cli/commands/timeline.d.ts.map +0 -1
  126. package/dist/cli/commands/watch.d.ts.map +0 -1
  127. package/dist/cli/index.d.ts.map +0 -1
  128. package/dist/cli/types.d.ts.map +0 -1
  129. package/dist/cli/utils/config-loader.d.ts.map +0 -1
  130. package/dist/cli/utils/file-utils.d.ts.map +0 -1
  131. package/dist/cli/utils/logger.d.ts.map +0 -1
  132. package/dist/compiler/atomic-optimizer.d.ts.map +0 -1
  133. package/dist/compiler/btt.d.ts.map +0 -1
  134. package/dist/compiler/cache-manager.d.ts.map +0 -1
  135. package/dist/compiler/commonProps.d.ts.map +0 -1
  136. package/dist/compiler/index.d.ts.map +0 -1
  137. package/dist/compiler/prefixer.d.ts.map +0 -1
  138. package/dist/compiler/theme-contract.d.ts.map +0 -1
  139. package/dist/compiler/tokens.d.ts.map +0 -1
  140. package/dist/compiler/types.d.ts +0 -57
  141. package/dist/compiler/types.d.ts.map +0 -1
  142. package/dist/core/compiler.d.ts.map +0 -1
  143. package/dist/core/constants.d.ts.map +0 -1
  144. package/dist/core/index.d.ts +0 -4
  145. package/dist/core/index.d.ts.map +0 -1
  146. package/dist/core/types.d.ts.map +0 -1
  147. package/dist/core/utils.d.ts.map +0 -1
  148. package/dist/index.d.ts.map +0 -1
  149. package/dist/plugins/vite.d.ts.map +0 -1
  150. package/dist/plugins/webpack.d.ts.map +0 -1
  151. package/dist/runtime/hmr.d.ts.map +0 -1
  152. package/dist/runtime/index.d.ts.map +0 -1
  153. package/dist/runtime/injector.d.ts.map +0 -1
  154. package/dist/runtime/react.d.ts.map +0 -1
  155. package/dist/runtime/react.js +0 -270
  156. package/dist/runtime/types.d.ts.map +0 -1
  157. package/dist/runtime/utils.d.ts.map +0 -1
  158. package/dist/runtime/vue.d.ts.map +0 -1
  159. package/dist/runtime/vue.js +0 -232
@@ -0,0 +1,517 @@
1
+ // src/compiler/animations.ts
2
+ export interface AnimationConfig {
3
+ duration?: string;
4
+ delay?: string;
5
+ timing?: string;
6
+ iteration?: string | number;
7
+ direction?: 'normal' | 'reverse' | 'alternate' | 'alternate-reverse';
8
+ fillMode?: 'none' | 'forwards' | 'backwards' | 'both';
9
+ playState?: 'running' | 'paused';
10
+ name?: string; // Custom animation name
11
+ }
12
+
13
+ export interface KeyframeDefinition {
14
+ [key: string]: Record<string, string | number>;
15
+ }
16
+
17
+ // Pre-defined animation keyframes
18
+ export const animationPresets: Record<string, KeyframeDefinition> = {
19
+ // Fades
20
+ fadeIn: {
21
+ '0%': { opacity: 0 },
22
+ '100%': { opacity: 1 }
23
+ },
24
+ fadeOut: {
25
+ '0%': { opacity: 1 },
26
+ '100%': { opacity: 0 }
27
+ },
28
+ fadeInUp: {
29
+ '0%': { opacity: 0, transform: 'translateY(20px)' },
30
+ '100%': { opacity: 1, transform: 'translateY(0)' }
31
+ },
32
+ fadeInDown: {
33
+ '0%': { opacity: 0, transform: 'translateY(-20px)' },
34
+ '100%': { opacity: 1, transform: 'translateY(0)' }
35
+ },
36
+ fadeInLeft: {
37
+ '0%': { opacity: 0, transform: 'translateX(-20px)' },
38
+ '100%': { opacity: 1, transform: 'translateX(0)' }
39
+ },
40
+ fadeInRight: {
41
+ '0%': { opacity: 0, transform: 'translateX(20px)' },
42
+ '100%': { opacity: 1, transform: 'translateX(0)' }
43
+ },
44
+ fadeOutUp: {
45
+ '0%': { opacity: 1, transform: 'translateY(0)' },
46
+ '100%': { opacity: 0, transform: 'translateY(-20px)' }
47
+ },
48
+ fadeOutDown: {
49
+ '0%': { opacity: 1, transform: 'translateY(0)' },
50
+ '100%': { opacity: 0, transform: 'translateY(20px)' }
51
+ },
52
+
53
+ // Slides
54
+ slideInUp: {
55
+ '0%': { transform: 'translateY(100%)' },
56
+ '100%': { transform: 'translateY(0)' }
57
+ },
58
+ slideInDown: {
59
+ '0%': { transform: 'translateY(-100%)' },
60
+ '100%': { transform: 'translateY(0)' }
61
+ },
62
+ slideInLeft: {
63
+ '0%': { transform: 'translateX(-100%)' },
64
+ '100%': { transform: 'translateX(0)' }
65
+ },
66
+ slideInRight: {
67
+ '0%': { transform: 'translateX(100%)' },
68
+ '100%': { transform: 'translateX(0)' }
69
+ },
70
+ slideOutUp: {
71
+ '0%': { transform: 'translateY(0)' },
72
+ '100%': { transform: 'translateY(-100%)' }
73
+ },
74
+ slideOutDown: {
75
+ '0%': { transform: 'translateY(0)' },
76
+ '100%': { transform: 'translateY(100%)' }
77
+ },
78
+
79
+ // Zooms
80
+ zoomIn: {
81
+ '0%': { opacity: 0, transform: 'scale(0.8)' },
82
+ '100%': { opacity: 1, transform: 'scale(1)' }
83
+ },
84
+ zoomOut: {
85
+ '0%': { opacity: 1, transform: 'scale(1)' },
86
+ '100%': { opacity: 0, transform: 'scale(0.8)' }
87
+ },
88
+ zoomInUp: {
89
+ '0%': { opacity: 0, transform: 'scale(0.8) translateY(20px)' },
90
+ '100%': { opacity: 1, transform: 'scale(1) translateY(0)' }
91
+ },
92
+ zoomInDown: {
93
+ '0%': { opacity: 0, transform: 'scale(0.8) translateY(-20px)' },
94
+ '100%': { opacity: 1, transform: 'scale(1) translateY(0)' }
95
+ },
96
+
97
+ // Bounces
98
+ bounce: {
99
+ '0%, 100%': { transform: 'translateY(0)' },
100
+ '50%': { transform: 'translateY(-20px)' }
101
+ },
102
+ bounceIn: {
103
+ '0%': { opacity: 0, transform: 'scale(0.8)' },
104
+ '50%': { transform: 'scale(1.05)' },
105
+ '100%': { opacity: 1, transform: 'scale(1)' }
106
+ },
107
+ bounceOut: {
108
+ '0%': { transform: 'scale(1)' },
109
+ '50%': { transform: 'scale(0.95)' },
110
+ '100%': { opacity: 0, transform: 'scale(0.8)' }
111
+ },
112
+
113
+ // Pulses
114
+ pulse: {
115
+ '0%, 100%': { transform: 'scale(1)' },
116
+ '50%': { transform: 'scale(1.05)' }
117
+ },
118
+ pulseGlow: {
119
+ '0%, 100%': { opacity: 1, filter: 'brightness(1)' },
120
+ '50%': { opacity: 0.8, filter: 'brightness(1.2)' }
121
+ },
122
+
123
+ // Shakes
124
+ shake: {
125
+ '0%, 100%': { transform: 'translateX(0)' },
126
+ '25%': { transform: 'translateX(-5px)' },
127
+ '75%': { transform: 'translateX(5px)' }
128
+ },
129
+ shakeX: {
130
+ '0%, 100%': { transform: 'translateX(0)' },
131
+ '25%, 75%': { transform: 'translateX(-10px)' },
132
+ '50%': { transform: 'translateX(10px)' }
133
+ },
134
+ shakeY: {
135
+ '0%, 100%': { transform: 'translateY(0)' },
136
+ '25%, 75%': { transform: 'translateY(-10px)' },
137
+ '50%': { transform: 'translateY(10px)' }
138
+ },
139
+
140
+ // Rotations
141
+ spin: {
142
+ '0%': { transform: 'rotate(0deg)' },
143
+ '100%': { transform: 'rotate(360deg)' }
144
+ },
145
+ spinReverse: {
146
+ '0%': { transform: 'rotate(0deg)' },
147
+ '100%': { transform: 'rotate(-360deg)' }
148
+ },
149
+ wiggle: {
150
+ '0%, 100%': { transform: 'rotate(-3deg)' },
151
+ '50%': { transform: 'rotate(3deg)' }
152
+ },
153
+ wobble: {
154
+ '0%': { transform: 'translateX(0%)' },
155
+ '15%': { transform: 'translateX(-25%) rotate(-5deg)' },
156
+ '30%': { transform: 'translateX(20%) rotate(3deg)' },
157
+ '45%': { transform: 'translateX(-15%) rotate(-3deg)' },
158
+ '60%': { transform: 'translateX(10%) rotate(2deg)' },
159
+ '75%': { transform: 'translateX(-5%) rotate(-1deg)' },
160
+ '100%': { transform: 'translateX(0%)' }
161
+ },
162
+
163
+ // Flips
164
+ flip: {
165
+ '0%': { transform: 'perspective(400px) rotateY(0)' },
166
+ '100%': { transform: 'perspective(400px) rotateY(180deg)' }
167
+ },
168
+ flipX: {
169
+ '0%': { transform: 'perspective(400px) rotateX(0)' },
170
+ '100%': { transform: 'perspective(400px) rotateX(180deg)' }
171
+ },
172
+
173
+ // Special effects
174
+ blink: {
175
+ '0%, 100%': { opacity: 1 },
176
+ '50%': { opacity: 0 }
177
+ },
178
+ typing: {
179
+ '0%': { width: '0' },
180
+ '100%': { width: '100%' }
181
+ },
182
+ cursor: {
183
+ '0%, 100%': { borderColor: 'transparent' },
184
+ '50%': { borderColor: 'currentColor' }
185
+ },
186
+ shimmer: {
187
+ '0%': { backgroundPosition: '-200% 0' },
188
+ '100%': { backgroundPosition: '200% 0' }
189
+ },
190
+ ripple: {
191
+ '0%': { transform: 'scale(0)', opacity: 0.5 },
192
+ '100%': { transform: 'scale(4)', opacity: 0 }
193
+ },
194
+ float: {
195
+ '0%, 100%': { transform: 'translateY(0)' },
196
+ '50%': { transform: 'translateY(-10px)' }
197
+ },
198
+ sink: {
199
+ '0%, 100%': { transform: 'translateY(0)' },
200
+ '50%': { transform: 'translateY(10px)' }
201
+ },
202
+ swing: {
203
+ '0%, 100%': { transform: 'rotate(0deg)' },
204
+ '25%': { transform: 'rotate(15deg)' },
205
+ '75%': { transform: 'rotate(-15deg)' }
206
+ },
207
+ flash: {
208
+ '0%, 100%': { opacity: 1 },
209
+ '25%, 75%': { opacity: 0.5 },
210
+ '50%': { opacity: 0 }
211
+ },
212
+
213
+ // Text animations
214
+ textReveal: {
215
+ '0%': { clipPath: 'inset(0 100% 0 0)' },
216
+ '100%': { clipPath: 'inset(0 0 0 0)' }
217
+ },
218
+ textGlitch: {
219
+ '0%, 100%': { transform: 'translate(0, 0)' },
220
+ '20%': { transform: 'translate(-2px, 1px)' },
221
+ '40%': { transform: 'translate(2px, -1px)' },
222
+ '60%': { transform: 'translate(-1px, 2px)' },
223
+ '80%': { transform: 'translate(1px, -2px)' }
224
+ }
225
+ };
226
+
227
+ // Default animation timing values
228
+ export const DEFAULT_ANIMATION_CONFIG: Required<AnimationConfig> = {
229
+ name: '', // Add this missing property
230
+ duration: '0.3s',
231
+ delay: '0s',
232
+ timing: 'ease',
233
+ iteration: 1,
234
+ direction: 'normal',
235
+ fillMode: 'both',
236
+ playState: 'running'
237
+ };
238
+
239
+ // Predefined timing functions
240
+ export const timingFunctions = {
241
+ linear: 'linear',
242
+ ease: 'ease',
243
+ easeIn: 'ease-in',
244
+ easeOut: 'ease-out',
245
+ easeInOut: 'ease-in-out',
246
+ bounce: 'cubic-bezier(0.68, -0.55, 0.265, 1.55)',
247
+ elastic: 'cubic-bezier(0.68, -0.55, 0.265, 1.55)',
248
+ smooth: 'cubic-bezier(0.25, 0.1, 0.25, 1)',
249
+ sharp: 'cubic-bezier(0.4, 0, 0.6, 1)'
250
+ };
251
+
252
+ // Helper to create animation style
253
+ export function createAnimation(
254
+ animationName: string,
255
+ config: AnimationConfig = {}
256
+ ): Record<string, any> {
257
+ const {
258
+ duration = DEFAULT_ANIMATION_CONFIG.duration,
259
+ delay = DEFAULT_ANIMATION_CONFIG.delay,
260
+ timing = DEFAULT_ANIMATION_CONFIG.timing,
261
+ iteration = DEFAULT_ANIMATION_CONFIG.iteration,
262
+ direction = DEFAULT_ANIMATION_CONFIG.direction,
263
+ fillMode = DEFAULT_ANIMATION_CONFIG.fillMode,
264
+ playState = DEFAULT_ANIMATION_CONFIG.playState
265
+ } = config;
266
+
267
+ // Build animation shorthand
268
+ const animationValue = `${animationName} ${duration} ${timing} ${delay} ${iteration} ${direction} ${playState}`;
269
+
270
+ return {
271
+ animation: animationValue.trim(),
272
+ animationFillMode: fillMode,
273
+ animationName: animationName,
274
+ animationDuration: duration,
275
+ animationDelay: delay,
276
+ animationTimingFunction: timing,
277
+ animationIterationCount: iteration,
278
+ animationDirection: direction,
279
+ animationPlayState: playState
280
+ };
281
+ }
282
+
283
+ // Create keyframes CSS string
284
+ export function createKeyframesCSS(
285
+ name: string,
286
+ steps: KeyframeDefinition,
287
+ prefix: boolean = true
288
+ ): string {
289
+ let css = `@keyframes ${name} {\n`;
290
+
291
+ for (const [keyframe, styles] of Object.entries(steps)) {
292
+ css += ` ${keyframe} {\n`;
293
+
294
+ for (const [prop, value] of Object.entries(styles)) {
295
+ const kebabProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();
296
+ css += ` ${kebabProp}: ${value};\n`;
297
+ }
298
+
299
+ css += ` }\n`;
300
+ }
301
+
302
+ css += `}\n`;
303
+
304
+ // Add vendor-prefixed version if needed
305
+ if (prefix) {
306
+ css += `@-webkit-keyframes ${name} {\n`;
307
+ for (const [keyframe, styles] of Object.entries(steps)) {
308
+ css += ` ${keyframe} {\n`;
309
+ for (const [prop, value] of Object.entries(styles)) {
310
+ const kebabProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();
311
+ css += ` ${kebabProp}: ${value};\n`;
312
+ }
313
+ css += ` }\n`;
314
+ }
315
+ css += `}\n`;
316
+ }
317
+
318
+ return css;
319
+ }
320
+
321
+ // Get animation preset
322
+ export function getAnimationPreset(name: string): KeyframeDefinition | undefined {
323
+ return animationPresets[name];
324
+ }
325
+
326
+ // Check if animation preset exists
327
+ export function hasAnimationPreset(name: string): boolean {
328
+ return name in animationPresets;
329
+ }
330
+
331
+ // Get all animation preset names
332
+ export function getAnimationPresetNames(): string[] {
333
+ return Object.keys(animationPresets);
334
+ }
335
+
336
+ // Register a custom animation preset
337
+ export function registerAnimationPreset(
338
+ name: string,
339
+ steps: KeyframeDefinition,
340
+ overwrite: boolean = false
341
+ ): boolean {
342
+ if (animationPresets[name] && !overwrite) {
343
+ return false;
344
+ }
345
+
346
+ animationPresets[name] = steps;
347
+ return true;
348
+ }
349
+
350
+ // Register multiple animation presets
351
+ export function registerAnimationPresets(
352
+ presets: Record<string, KeyframeDefinition>,
353
+ overwrite: boolean = false
354
+ ): void {
355
+ for (const [name, steps] of Object.entries(presets)) {
356
+ registerAnimationPreset(name, steps, overwrite);
357
+ }
358
+ }
359
+
360
+ // Create a combined animation from multiple presets
361
+ export function combineAnimations(
362
+ animations: Array<{ name: string; duration?: string; delay?: string }>
363
+ ): Record<string, any> {
364
+ const combined: Record<string, any> = {};
365
+ const animationList: string[] = [];
366
+
367
+ for (const anim of animations) {
368
+ const duration = anim.duration || '0.3s';
369
+ const delay = anim.delay || '0s';
370
+ animationList.push(`${anim.name} ${duration} ${delay}`);
371
+ }
372
+
373
+ combined.animation = animationList.join(', ');
374
+ return combined;
375
+ }
376
+
377
+ // Generate staggered animation delays for children
378
+ export function staggerChildren(
379
+ baseDelay: string = '0s',
380
+ increment: string = '0.1s',
381
+ count: number = 5
382
+ ): Record<number, string> {
383
+ const delays: Record<number, string> = {};
384
+ const baseMs = parseTimeToMs(baseDelay);
385
+ const incMs = parseTimeToMs(increment);
386
+
387
+ for (let i = 0; i < count; i++) {
388
+ delays[i] = `${baseMs + (i * incMs)}ms`;
389
+ }
390
+
391
+ return delays;
392
+ }
393
+
394
+ // Helper to parse time string to milliseconds
395
+ function parseTimeToMs(time: string): number {
396
+ if (time.endsWith('ms')) {
397
+ return parseFloat(time);
398
+ }
399
+ if (time.endsWith('s')) {
400
+ return parseFloat(time) * 1000;
401
+ }
402
+ return parseFloat(time);
403
+ }
404
+
405
+ // Convert milliseconds to time string
406
+ export function msToTime(ms: number): string {
407
+ if (ms >= 1000) {
408
+ return `${ms / 1000}s`;
409
+ }
410
+ return `${ms}ms`;
411
+ }
412
+
413
+ // Create animation sequence
414
+ export interface AnimationStep {
415
+ name: string;
416
+ duration?: string;
417
+ delay?: string;
418
+ }
419
+
420
+ export function createAnimationSequence(steps: AnimationStep[]): Record<string, any> {
421
+ if (steps.length === 0) return {};
422
+
423
+ const animations: string[] = [];
424
+
425
+ for (const step of steps) {
426
+ const duration = step.duration || '0.3s';
427
+ const delay = step.delay || '0s';
428
+ animations.push(`${step.name} ${duration} ${delay}`);
429
+ }
430
+
431
+ return {
432
+ animation: animations.join(', ')
433
+ };
434
+ }
435
+
436
+ // Check if animation is a preset
437
+ export function isValidAnimation(name: string): boolean {
438
+ return hasAnimationPreset(name);
439
+ }
440
+
441
+ // Get animation suggestion for similar names
442
+ export function getAnimationSuggestion(name: string): string | null {
443
+ const presetNames = getAnimationPresetNames();
444
+ const lowerName = name.toLowerCase();
445
+
446
+ // Find exact match
447
+ if (presetNames.includes(name)) return name;
448
+
449
+ // Find partial matches
450
+ const matches = presetNames.filter(n =>
451
+ n.toLowerCase().includes(lowerName) ||
452
+ lowerName.includes(n.toLowerCase())
453
+ );
454
+
455
+ if (matches.length > 0) {
456
+ return matches[0];
457
+ }
458
+
459
+ // Find similar by Levenshtein distance
460
+ let bestMatch: string | null = null;
461
+ let bestDistance = Infinity;
462
+
463
+ for (const preset of presetNames) {
464
+ const distance = levenshteinDistance(name, preset);
465
+ if (distance < bestDistance && distance < 3) {
466
+ bestDistance = distance;
467
+ bestMatch = preset;
468
+ }
469
+ }
470
+
471
+ return bestMatch;
472
+ }
473
+
474
+ // Levenshtein distance for suggestions
475
+ function levenshteinDistance(a: string, b: string): number {
476
+ const matrix: number[][] = [];
477
+
478
+ for (let i = 0; i <= a.length; i++) {
479
+ matrix[i] = [i];
480
+ }
481
+
482
+ for (let j = 0; j <= b.length; j++) {
483
+ matrix[0][j] = j;
484
+ }
485
+
486
+ for (let i = 1; i <= a.length; i++) {
487
+ for (let j = 1; j <= b.length; j++) {
488
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
489
+ matrix[i][j] = Math.min(
490
+ matrix[i - 1][j] + 1,
491
+ matrix[i][j - 1] + 1,
492
+ matrix[i - 1][j - 1] + cost
493
+ );
494
+ }
495
+ }
496
+
497
+ return matrix[a.length][b.length];
498
+ }
499
+
500
+ // Export default animation utilities
501
+ export default {
502
+ animationPresets,
503
+ createAnimation,
504
+ createKeyframesCSS,
505
+ getAnimationPreset,
506
+ hasAnimationPreset,
507
+ getAnimationPresetNames,
508
+ registerAnimationPreset,
509
+ registerAnimationPresets,
510
+ combineAnimations,
511
+ staggerChildren,
512
+ createAnimationSequence,
513
+ isValidAnimation,
514
+ getAnimationSuggestion,
515
+ timingFunctions,
516
+ DEFAULT_ANIMATION_CONFIG
517
+ };