@enact-ui/animate 0.1.0 → 0.2.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 (82) hide show
  1. package/api-schema.json +206 -0
  2. package/dist/components/CountUp.d.ts +84 -0
  3. package/dist/components/CountUp.d.ts.map +1 -0
  4. package/dist/components/CountUp.js +68 -0
  5. package/dist/components/CountUp.js.map +1 -0
  6. package/dist/components/MotionDiv.d.ts +159 -0
  7. package/dist/components/MotionDiv.d.ts.map +1 -0
  8. package/dist/components/MotionDiv.js +162 -0
  9. package/dist/components/MotionDiv.js.map +1 -0
  10. package/dist/components/StaggerContainer.d.ts +136 -0
  11. package/dist/components/StaggerContainer.d.ts.map +1 -0
  12. package/dist/components/StaggerContainer.js +166 -0
  13. package/dist/components/StaggerContainer.js.map +1 -0
  14. package/dist/hooks/use-component-animation.d.ts +156 -0
  15. package/dist/hooks/use-component-animation.d.ts.map +1 -0
  16. package/dist/hooks/use-component-animation.js +231 -0
  17. package/dist/hooks/use-component-animation.js.map +1 -0
  18. package/dist/hooks/use-count-up.d.ts +111 -0
  19. package/dist/hooks/use-count-up.d.ts.map +1 -0
  20. package/dist/hooks/use-count-up.js +246 -0
  21. package/dist/hooks/use-count-up.js.map +1 -0
  22. package/dist/hooks/use-draw-path.d.ts +96 -0
  23. package/dist/hooks/use-draw-path.d.ts.map +1 -0
  24. package/dist/hooks/use-draw-path.js +227 -0
  25. package/dist/hooks/use-draw-path.js.map +1 -0
  26. package/dist/hooks/use-motion-preset.d.ts.map +1 -1
  27. package/dist/hooks/use-motion-preset.js +17 -16
  28. package/dist/hooks/use-motion-preset.js.map +1 -1
  29. package/dist/hooks/use-stagger.d.ts +174 -0
  30. package/dist/hooks/use-stagger.d.ts.map +1 -0
  31. package/dist/hooks/use-stagger.js +256 -0
  32. package/dist/hooks/use-stagger.js.map +1 -0
  33. package/dist/index.d.ts +17 -1
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +2442 -26
  36. package/dist/index.js.map +1 -1
  37. package/dist/index.mjs +2335 -25
  38. package/dist/index.mjs.map +1 -1
  39. package/dist/presets/component-presets.d.ts +246 -0
  40. package/dist/presets/component-presets.d.ts.map +1 -0
  41. package/dist/presets/component-presets.js +472 -0
  42. package/dist/presets/component-presets.js.map +1 -0
  43. package/dist/presets/micro-interactions.d.ts +451 -0
  44. package/dist/presets/micro-interactions.d.ts.map +1 -0
  45. package/dist/presets/micro-interactions.js +856 -0
  46. package/dist/presets/micro-interactions.js.map +1 -0
  47. package/dist/presets/motion-presets.d.ts.map +1 -1
  48. package/dist/presets/motion-presets.js +0 -1
  49. package/dist/presets/motion-presets.js.map +1 -1
  50. package/dist/presets/motion-styles.d.ts +186 -0
  51. package/dist/presets/motion-styles.d.ts.map +1 -0
  52. package/dist/presets/motion-styles.js +204 -0
  53. package/dist/presets/motion-styles.js.map +1 -0
  54. package/dist/presets/stagger-presets.d.ts +378 -0
  55. package/dist/presets/stagger-presets.d.ts.map +1 -0
  56. package/dist/presets/stagger-presets.js +582 -0
  57. package/dist/presets/stagger-presets.js.map +1 -0
  58. package/dist/showcase/motion-presets.demo.d.ts +25 -0
  59. package/dist/showcase/motion-presets.demo.d.ts.map +1 -0
  60. package/dist/showcase/motion-presets.demo.js +96 -0
  61. package/dist/showcase/motion-presets.demo.js.map +1 -0
  62. package/dist/showcase/motion-presets.story.d.ts +37 -0
  63. package/dist/showcase/motion-presets.story.d.ts.map +1 -0
  64. package/dist/showcase/motion-presets.story.js +151 -0
  65. package/dist/showcase/motion-presets.story.js.map +1 -0
  66. package/dist/utils/easing.d.ts +294 -0
  67. package/dist/utils/easing.d.ts.map +1 -0
  68. package/dist/utils/easing.js +265 -0
  69. package/dist/utils/easing.js.map +1 -0
  70. package/dist/utils/reduced-motion.d.ts +322 -0
  71. package/dist/utils/reduced-motion.d.ts.map +1 -0
  72. package/dist/utils/reduced-motion.js +362 -0
  73. package/dist/utils/reduced-motion.js.map +1 -0
  74. package/dist/utils/select-preset.d.ts +186 -0
  75. package/dist/utils/select-preset.d.ts.map +1 -0
  76. package/dist/utils/select-preset.js +320 -0
  77. package/dist/utils/select-preset.js.map +1 -0
  78. package/dist/utils/spring-configs.d.ts +187 -0
  79. package/dist/utils/spring-configs.d.ts.map +1 -0
  80. package/dist/utils/spring-configs.js +169 -0
  81. package/dist/utils/spring-configs.js.map +1 -0
  82. package/package.json +4 -3
package/dist/index.js CHANGED
@@ -20,17 +20,937 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ CountUp: () => CountUp,
24
+ INSTANT_TRANSITION: () => INSTANT_TRANSITION,
25
+ MotionDiv: () => MotionDiv,
26
+ REDUCED_MOTION_QUERY: () => REDUCED_MOTION_QUERY,
27
+ StaggerContainer: () => StaggerContainer,
23
28
  ambientPaths: () => ambientPaths,
24
29
  applyMotionPreset: () => applyMotionPreset,
30
+ badgePop: () => badgePop,
31
+ boldStyle: () => boldStyle,
32
+ buttonPress: () => buttonPress,
33
+ calculateStaggerDelays: () => calculateStaggerDelays,
34
+ cardHover: () => cardHover,
35
+ cascadeStagger: () => cascadeStagger,
36
+ checkReducedMotion: () => checkReducedMotion,
37
+ checkmarkDraw: () => checkmarkDraw,
38
+ componentPresets: () => componentPresets,
39
+ createAccessibleMotionProps: () => createAccessibleMotionProps,
40
+ createMotionProps: () => createMotionProps,
41
+ createReducedMotionProps: () => createReducedMotionProps,
42
+ createSpring: () => createSpring,
43
+ createSpringFromParams: () => createSpringFromParams,
44
+ createTween: () => createTween,
45
+ createTweenFromParams: () => createTweenFromParams,
46
+ durations: () => durations,
47
+ easeIn: () => easeIn,
48
+ easeInOut: () => easeInOut,
49
+ easeInOutCubic: () => easeInOutCubic,
50
+ easeInOutQuint: () => easeInOutQuint,
51
+ easeOut: () => easeOut,
52
+ easeOutBack: () => easeOutBack,
53
+ easeOutExpo: () => easeOutExpo,
54
+ easeOutQuart: () => easeOutQuart,
55
+ easingPresets: () => easingPresets,
56
+ expand: () => expand,
57
+ explodeStagger: () => explodeStagger,
58
+ fadeIn: () => fadeIn,
59
+ fadeOut: () => fadeOut,
60
+ findPresetsForUseCase: () => findPresetsForUseCase,
61
+ flip: () => flip,
62
+ getAllContexts: () => getAllContexts,
63
+ getAllPresetNames: () => getAllPresetNames,
64
+ getAllUseCases: () => getAllUseCases,
65
+ getComponentPreset: () => getComponentPreset,
66
+ getDefaultPreset: () => getDefaultPreset,
67
+ getDuration: () => getDuration,
68
+ getMicroInteraction: () => getMicroInteraction,
69
+ getMicroInteractionNames: () => getMicroInteractionNames,
70
+ getMotionStyle: () => getMotionStyle,
25
71
  getPreset: () => getPreset,
72
+ getPresetMetadata: () => getPresetMetadata,
73
+ getPresetsByContext: () => getPresetsByContext,
74
+ getPresetsByUseCase: () => getPresetsByUseCase,
75
+ getRecommendations: () => getRecommendations,
76
+ getReducedMotionVariant: () => getReducedMotionVariant,
77
+ getSpringConfig: () => getSpringConfig,
78
+ getStaggerPreset: () => getStaggerPreset,
79
+ glowPulse: () => glowPulse,
80
+ gridStagger: () => gridStagger,
81
+ heartbeat: () => heartbeat,
82
+ iconSpin: () => iconSpin,
26
83
  lightRays: () => lightRays,
27
- useMotionPreset: () => useMotionPreset
84
+ linear: () => linear,
85
+ microInteractions: () => microInteractions,
86
+ motionStyles: () => motionStyles,
87
+ msToSeconds: () => msToSeconds,
88
+ playfulStyle: () => playfulStyle,
89
+ progressFill: () => progressFill,
90
+ pulse: () => pulse,
91
+ rotate: () => rotate,
92
+ rubberBand: () => rubberBand,
93
+ scale: () => scale,
94
+ scaleMicro: () => scale2,
95
+ selectPreset: () => selectPreset,
96
+ shake: () => shake,
97
+ shimmer: () => shimmer,
98
+ slideDown: () => slideDown,
99
+ slideLeft: () => slideLeft,
100
+ slideRight: () => slideRight,
101
+ slideUp: () => slideUp,
102
+ slideUpScale: () => slideUpScale,
103
+ springBouncy: () => springBouncy,
104
+ springGentle: () => springGentle,
105
+ springPresets: () => springPresets,
106
+ springSnappy: () => springSnappy,
107
+ springStiff: () => springStiff,
108
+ staggerCascade: () => staggerCascade,
109
+ staggerCenter: () => staggerCenter,
110
+ staggerGrid: () => staggerGrid,
111
+ staggerPresets: () => staggerPresets,
112
+ staggerRandom: () => staggerRandom,
113
+ staggerReverse: () => staggerReverse,
114
+ staggerSequential: () => staggerSequential,
115
+ staggerWave: () => staggerWave,
116
+ standardStyle: () => standardStyle,
117
+ subtleStyle: () => subtleStyle,
118
+ successFlash: () => successFlash,
119
+ suggestAnimations: () => suggestAnimations,
120
+ tweenPresets: () => tweenPresets,
121
+ useAnimationVariants: () => useAnimationVariants,
122
+ useComponentAnimation: () => useComponentAnimation,
123
+ useCountUp: () => useCountUp,
124
+ useDelayedAnimation: () => useDelayedAnimation,
125
+ useDrawPath: () => useDrawPath,
126
+ useMotionPreset: () => useMotionPreset,
127
+ useReducedMotion: () => useReducedMotion2,
128
+ useStagger: () => useStagger,
129
+ waveStagger: () => waveStagger,
130
+ wiggle: () => wiggle,
131
+ withStagger: () => withStagger,
132
+ zoomIn: () => zoomIn,
133
+ zoomOut: () => zoomOut
28
134
  });
29
135
  module.exports = __toCommonJS(index_exports);
30
136
 
31
- // src/hooks/use-motion-preset.ts
137
+ // src/hooks/use-count-up.ts
32
138
  var import_react = require("react");
33
139
 
140
+ // src/presets/motion-styles.ts
141
+ var subtleStyle = {
142
+ name: "Subtle",
143
+ description: "Gentle, minimal animations ideal for professional UIs",
144
+ duration: {
145
+ fast: 150,
146
+ normal: 200,
147
+ slow: 300
148
+ },
149
+ spring: {
150
+ stiffness: 400,
151
+ damping: 35,
152
+ mass: 0.8
153
+ },
154
+ easing: {
155
+ enter: "easeOut",
156
+ exit: "easeIn",
157
+ interactive: "easeInOut"
158
+ },
159
+ staggerDelay: 30
160
+ };
161
+ var standardStyle = {
162
+ name: "Standard",
163
+ description: "Balanced, professional animations for general use",
164
+ duration: {
165
+ fast: 200,
166
+ normal: 300,
167
+ slow: 400
168
+ },
169
+ spring: {
170
+ stiffness: 300,
171
+ damping: 28,
172
+ mass: 1
173
+ },
174
+ easing: {
175
+ enter: "easeOut",
176
+ exit: "easeIn",
177
+ interactive: "easeInOut"
178
+ },
179
+ staggerDelay: 50
180
+ };
181
+ var boldStyle = {
182
+ name: "Bold",
183
+ description: "Dramatic, attention-grabbing animations for emphasis",
184
+ duration: {
185
+ fast: 250,
186
+ normal: 400,
187
+ slow: 600
188
+ },
189
+ spring: {
190
+ stiffness: 250,
191
+ damping: 22,
192
+ mass: 1.2
193
+ },
194
+ easing: {
195
+ enter: "easeOut",
196
+ exit: "easeIn",
197
+ interactive: "easeInOut"
198
+ },
199
+ staggerDelay: 80
200
+ };
201
+ var playfulStyle = {
202
+ name: "Playful",
203
+ description: "Bouncy, fun animations with elastic spring physics",
204
+ duration: {
205
+ fast: 200,
206
+ normal: 350,
207
+ slow: 500
208
+ },
209
+ spring: {
210
+ stiffness: 200,
211
+ damping: 15,
212
+ mass: 1
213
+ },
214
+ easing: {
215
+ enter: "easeOut",
216
+ exit: "easeIn",
217
+ interactive: "easeInOut"
218
+ },
219
+ staggerDelay: 60
220
+ };
221
+ var motionStyles = {
222
+ subtle: subtleStyle,
223
+ standard: standardStyle,
224
+ bold: boldStyle,
225
+ playful: playfulStyle
226
+ };
227
+ function getMotionStyle(style) {
228
+ return motionStyles[style];
229
+ }
230
+ function getSpringConfig(style) {
231
+ return motionStyles[style].spring;
232
+ }
233
+ function getDuration(style, speed) {
234
+ return motionStyles[style].duration[speed];
235
+ }
236
+ function msToSeconds(ms) {
237
+ return ms / 1e3;
238
+ }
239
+
240
+ // src/hooks/use-count-up.ts
241
+ var easingFunctions = {
242
+ linear: (t) => t,
243
+ easeOut: (t) => 1 - (1 - t) ** 3,
244
+ easeOutExpo: (t) => t === 1 ? 1 : 1 - 2 ** (-10 * t),
245
+ easeInOut: (t) => t < 0.5 ? 4 * t ** 3 : 1 - (-2 * t + 2) ** 3 / 2,
246
+ spring: (t) => {
247
+ const c4 = 2 * Math.PI / 3;
248
+ return t === 0 ? 0 : t === 1 ? 1 : 2 ** (-10 * t) * Math.sin((t * 10 - 0.75) * c4) + 1;
249
+ }
250
+ };
251
+ function useReducedMotion() {
252
+ const [prefersReducedMotion2, setPrefersReducedMotion] = (0, import_react.useState)(() => {
253
+ if (typeof window === "undefined") return false;
254
+ return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
255
+ });
256
+ (0, import_react.useEffect)(() => {
257
+ const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
258
+ setPrefersReducedMotion(mediaQuery.matches);
259
+ const handler = (e) => {
260
+ setPrefersReducedMotion(e.matches);
261
+ };
262
+ mediaQuery.addEventListener("change", handler);
263
+ return () => mediaQuery.removeEventListener("change", handler);
264
+ }, []);
265
+ return prefersReducedMotion2;
266
+ }
267
+ function createDefaultFormatter(decimals, useLocale, locale) {
268
+ return (value) => {
269
+ if (useLocale) {
270
+ return value.toLocaleString(locale, {
271
+ minimumFractionDigits: decimals,
272
+ maximumFractionDigits: decimals
273
+ });
274
+ }
275
+ return value.toFixed(decimals);
276
+ };
277
+ }
278
+ function useCountUp(options) {
279
+ const {
280
+ from = 0,
281
+ to,
282
+ duration: customDuration,
283
+ motionStyle = "standard",
284
+ easing = "easeOutExpo",
285
+ decimals = 0,
286
+ useLocale = true,
287
+ locale,
288
+ formatter: customFormatter,
289
+ delay = 0,
290
+ autoStart = true,
291
+ onComplete,
292
+ onUpdate,
293
+ prefix = "",
294
+ suffix = "",
295
+ enabled = true
296
+ } = options;
297
+ const duration = customDuration ?? getDuration(motionStyle, "slow");
298
+ const [value, setValue] = (0, import_react.useState)(from);
299
+ const [isAnimating, setIsAnimating] = (0, import_react.useState)(false);
300
+ const [isComplete, setIsComplete] = (0, import_react.useState)(false);
301
+ const animationRef = (0, import_react.useRef)(null);
302
+ const startTimeRef = (0, import_react.useRef)(null);
303
+ const pausedTimeRef = (0, import_react.useRef)(null);
304
+ const currentFromRef = (0, import_react.useRef)(from);
305
+ const currentToRef = (0, import_react.useRef)(to);
306
+ const prefersReducedMotion2 = useReducedMotion();
307
+ const formatter = customFormatter ?? createDefaultFormatter(decimals, useLocale, locale);
308
+ const displayValue = `${prefix}${formatter(value)}${suffix}`;
309
+ const cancelAnimation = (0, import_react.useCallback)(() => {
310
+ if (animationRef.current !== null) {
311
+ cancelAnimationFrame(animationRef.current);
312
+ animationRef.current = null;
313
+ }
314
+ }, []);
315
+ const animate = (0, import_react.useCallback)(
316
+ (timestamp) => {
317
+ if (startTimeRef.current === null) {
318
+ startTimeRef.current = timestamp;
319
+ }
320
+ const elapsed = timestamp - startTimeRef.current;
321
+ const progress = Math.min(elapsed / duration, 1);
322
+ const easedProgress = easingFunctions[easing](progress);
323
+ const currentValue = currentFromRef.current + (currentToRef.current - currentFromRef.current) * easedProgress;
324
+ setValue(currentValue);
325
+ onUpdate?.(currentValue);
326
+ if (progress < 1) {
327
+ animationRef.current = requestAnimationFrame(animate);
328
+ } else {
329
+ setIsAnimating(false);
330
+ setIsComplete(true);
331
+ onComplete?.();
332
+ }
333
+ },
334
+ [duration, easing, onComplete, onUpdate]
335
+ );
336
+ const start = (0, import_react.useCallback)(() => {
337
+ if (!enabled) {
338
+ setValue(currentToRef.current);
339
+ setIsComplete(true);
340
+ return;
341
+ }
342
+ if (prefersReducedMotion2) {
343
+ setValue(currentToRef.current);
344
+ setIsComplete(true);
345
+ onComplete?.();
346
+ return;
347
+ }
348
+ cancelAnimation();
349
+ setIsComplete(false);
350
+ startTimeRef.current = null;
351
+ pausedTimeRef.current = null;
352
+ const startAnimation = () => {
353
+ setIsAnimating(true);
354
+ animationRef.current = requestAnimationFrame(animate);
355
+ };
356
+ if (delay > 0) {
357
+ setTimeout(startAnimation, delay);
358
+ } else {
359
+ startAnimation();
360
+ }
361
+ }, [enabled, prefersReducedMotion2, cancelAnimation, animate, delay, onComplete]);
362
+ const pause = (0, import_react.useCallback)(() => {
363
+ if (isAnimating && animationRef.current !== null) {
364
+ pausedTimeRef.current = performance.now();
365
+ cancelAnimation();
366
+ setIsAnimating(false);
367
+ }
368
+ }, [isAnimating, cancelAnimation]);
369
+ const resume = (0, import_react.useCallback)(() => {
370
+ if (!isAnimating && !isComplete && pausedTimeRef.current !== null && startTimeRef.current !== null) {
371
+ const pausedDuration = performance.now() - pausedTimeRef.current;
372
+ startTimeRef.current += pausedDuration;
373
+ pausedTimeRef.current = null;
374
+ setIsAnimating(true);
375
+ animationRef.current = requestAnimationFrame(animate);
376
+ }
377
+ }, [isAnimating, isComplete, animate]);
378
+ const reset = (0, import_react.useCallback)(() => {
379
+ cancelAnimation();
380
+ setValue(currentFromRef.current);
381
+ setIsAnimating(false);
382
+ setIsComplete(false);
383
+ startTimeRef.current = null;
384
+ pausedTimeRef.current = null;
385
+ }, [cancelAnimation]);
386
+ const update = (0, import_react.useCallback)(
387
+ (newTo) => {
388
+ currentFromRef.current = value;
389
+ currentToRef.current = newTo;
390
+ start();
391
+ },
392
+ [value, start]
393
+ );
394
+ (0, import_react.useEffect)(() => {
395
+ if (autoStart) {
396
+ currentFromRef.current = from;
397
+ currentToRef.current = to;
398
+ start();
399
+ }
400
+ return () => {
401
+ cancelAnimation();
402
+ };
403
+ }, []);
404
+ (0, import_react.useEffect)(() => {
405
+ if (to !== currentToRef.current && isComplete) {
406
+ update(to);
407
+ }
408
+ }, [to, isComplete, update]);
409
+ return {
410
+ value,
411
+ displayValue,
412
+ isAnimating,
413
+ isComplete,
414
+ start,
415
+ pause,
416
+ resume,
417
+ reset,
418
+ update,
419
+ prefersReducedMotion: prefersReducedMotion2
420
+ };
421
+ }
422
+
423
+ // src/components/CountUp.tsx
424
+ var import_jsx_runtime = require("react/jsx-runtime");
425
+ var CountUp = ({
426
+ to,
427
+ from = 0,
428
+ duration,
429
+ motionStyle = "standard",
430
+ easing = "easeOutExpo",
431
+ decimals = 0,
432
+ useLocale = true,
433
+ locale,
434
+ formatter,
435
+ delay = 0,
436
+ autoStart = true,
437
+ onComplete,
438
+ onUpdate,
439
+ prefix = "",
440
+ suffix = "",
441
+ enabled = true,
442
+ children,
443
+ ...spanProps
444
+ }) => {
445
+ const hookOptions = {
446
+ from,
447
+ to,
448
+ motionStyle,
449
+ easing,
450
+ decimals,
451
+ useLocale,
452
+ delay,
453
+ autoStart,
454
+ prefix,
455
+ suffix,
456
+ enabled,
457
+ // Only include optional props if they are defined
458
+ ...duration !== void 0 && { duration },
459
+ ...locale !== void 0 && { locale },
460
+ ...formatter !== void 0 && { formatter },
461
+ ...onComplete !== void 0 && { onComplete },
462
+ ...onUpdate !== void 0 && { onUpdate }
463
+ };
464
+ const { value, displayValue, isAnimating } = useCountUp(hookOptions);
465
+ if (typeof children === "function") {
466
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: children({ value, displayValue, isAnimating }) });
467
+ }
468
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { ...spanProps, children: displayValue });
469
+ };
470
+
471
+ // src/components/MotionDiv.tsx
472
+ var import_react3 = require("motion/react");
473
+
474
+ // src/hooks/use-component-animation.ts
475
+ var import_react2 = require("react");
476
+ function useReducedMotion2() {
477
+ const [prefersReducedMotion2, setPrefersReducedMotion] = (0, import_react2.useState)(() => {
478
+ if (typeof window === "undefined") return false;
479
+ return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
480
+ });
481
+ (0, import_react2.useEffect)(() => {
482
+ const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
483
+ setPrefersReducedMotion(mediaQuery.matches);
484
+ const handler = (e) => {
485
+ setPrefersReducedMotion(e.matches);
486
+ };
487
+ mediaQuery.addEventListener("change", handler);
488
+ return () => mediaQuery.removeEventListener("change", handler);
489
+ }, []);
490
+ return prefersReducedMotion2;
491
+ }
492
+ function createDisabledProps(skipInitial) {
493
+ return {
494
+ initial: skipInitial ? false : { opacity: 1 },
495
+ animate: { opacity: 1 },
496
+ exit: { opacity: 1 },
497
+ transition: { type: "tween", duration: 0 }
498
+ };
499
+ }
500
+ function useComponentAnimation(preset, style = "standard", options = {}) {
501
+ const { enabled = true, skipInitial = false, ...presetOptions } = options;
502
+ const prefersReducedMotion2 = useReducedMotion2();
503
+ const memoizedPresetOptions = (0, import_react2.useMemo)(() => presetOptions, [JSON.stringify(presetOptions)]);
504
+ const animationProps = (0, import_react2.useMemo)(() => {
505
+ if (!enabled) {
506
+ return createDisabledProps(skipInitial);
507
+ }
508
+ const props = preset.getProps(style, memoizedPresetOptions);
509
+ if (skipInitial) {
510
+ return {
511
+ ...props,
512
+ initial: false
513
+ };
514
+ }
515
+ return props;
516
+ }, [preset, style, memoizedPresetOptions, enabled, skipInitial]);
517
+ return {
518
+ ...animationProps,
519
+ prefersReducedMotion: prefersReducedMotion2,
520
+ isEnabled: enabled
521
+ };
522
+ }
523
+ function useDelayedAnimation(preset, style = "standard", index, options = {}) {
524
+ const { delayMultiplier = 50, maxDelay = 500, ...restOptions } = options;
525
+ const calculatedDelay = Math.min(index * delayMultiplier, maxDelay);
526
+ return useComponentAnimation(preset, style, {
527
+ ...restOptions,
528
+ delay: (restOptions.delay ?? 0) + calculatedDelay
529
+ });
530
+ }
531
+ function useAnimationVariants(preset, style = "standard", options = {}) {
532
+ const { enabled = true, ...presetOptions } = options;
533
+ const memoizedPresetOptions = (0, import_react2.useMemo)(() => presetOptions, [JSON.stringify(presetOptions)]);
534
+ return (0, import_react2.useMemo)(() => {
535
+ if (!enabled) {
536
+ return {
537
+ variants: {
538
+ initial: { opacity: 0 },
539
+ animate: { opacity: 1 },
540
+ exit: { opacity: 0 }
541
+ },
542
+ transition: { type: "tween", duration: 0.15 }
543
+ };
544
+ }
545
+ const props = preset.getProps(style, memoizedPresetOptions);
546
+ return {
547
+ variants: {
548
+ initial: props.initial,
549
+ animate: props.animate,
550
+ exit: props.exit ?? props.initial
551
+ },
552
+ transition: props.transition
553
+ };
554
+ }, [preset, style, memoizedPresetOptions, enabled]);
555
+ }
556
+
557
+ // src/components/MotionDiv.tsx
558
+ var import_jsx_runtime2 = require("react/jsx-runtime");
559
+ function MotionDiv({
560
+ preset,
561
+ exit: exitPreset,
562
+ as = "div",
563
+ motionStyle = "standard",
564
+ presetOptions,
565
+ enabled = true,
566
+ skipInitial = false,
567
+ children,
568
+ ...motionProps
569
+ }) {
570
+ const animation = useComponentAnimation(preset, motionStyle, {
571
+ ...presetOptions,
572
+ enabled,
573
+ skipInitial
574
+ });
575
+ const exitAnimation = exitPreset && typeof exitPreset === "object" && "getProps" in exitPreset && typeof exitPreset.getProps === "function" ? exitPreset.getProps(motionStyle, presetOptions) : null;
576
+ const { prefersReducedMotion: prefersReducedMotion2, isEnabled, ...animationProps } = animation;
577
+ const exitValue = exitAnimation ? exitAnimation.initial : void 0;
578
+ const MotionComponent = import_react3.motion[as];
579
+ const finalProps = {
580
+ ...motionProps,
581
+ ...animationProps,
582
+ ...exitValue !== void 0 && { exit: exitValue },
583
+ "data-reduced-motion": prefersReducedMotion2,
584
+ "data-animation-enabled": isEnabled
585
+ };
586
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(MotionComponent, { ...finalProps, children });
587
+ }
588
+ function createMotionProps(preset, style = "standard", options) {
589
+ return preset.getProps(style, options);
590
+ }
591
+ function createAccessibleMotionProps(preset, style = "standard", options) {
592
+ return preset.getProps(style, options);
593
+ }
594
+
595
+ // src/components/StaggerContainer.tsx
596
+ var import_react5 = require("react");
597
+
598
+ // src/hooks/use-stagger.ts
599
+ var import_react4 = require("react");
600
+ function calculateDelay(index, total, direction, baseDelay) {
601
+ switch (direction) {
602
+ case "forward":
603
+ return index * baseDelay;
604
+ case "reverse":
605
+ return (total - 1 - index) * baseDelay;
606
+ case "center": {
607
+ const center = (total - 1) / 2;
608
+ const distanceFromCenter = Math.abs(index - center);
609
+ return distanceFromCenter * baseDelay;
610
+ }
611
+ case "edges": {
612
+ const center = (total - 1) / 2;
613
+ const distanceFromCenter = Math.abs(index - center);
614
+ const maxDistance = center;
615
+ return (maxDistance - distanceFromCenter) * baseDelay;
616
+ }
617
+ case "random":
618
+ return Math.random() * total * baseDelay * 0.5;
619
+ default:
620
+ return index * baseDelay;
621
+ }
622
+ }
623
+ function useStagger(style = "standard", options = {}) {
624
+ const { direction = "forward", totalItems = 10, delayMultiplier, maxDelay = 1e3, useSpring = true, getDelay: customGetDelay } = options;
625
+ const styleConfig = getMotionStyle(style);
626
+ const baseDelay = delayMultiplier ?? styleConfig.staggerDelay;
627
+ const result = (0, import_react4.useMemo)(() => {
628
+ const getDelayForIndex = (index) => {
629
+ if (customGetDelay) {
630
+ return Math.min(customGetDelay(index, totalItems), maxDelay);
631
+ }
632
+ return Math.min(calculateDelay(index, totalItems, direction, baseDelay), maxDelay);
633
+ };
634
+ const containerVariants = {
635
+ hidden: { opacity: 0 },
636
+ visible: {
637
+ opacity: 1,
638
+ transition: {
639
+ staggerChildren: msToSeconds(baseDelay),
640
+ delayChildren: 0,
641
+ when: "beforeChildren"
642
+ }
643
+ }
644
+ };
645
+ const itemTransition = useSpring ? {
646
+ type: "spring",
647
+ stiffness: styleConfig.spring.stiffness,
648
+ damping: styleConfig.spring.damping,
649
+ mass: styleConfig.spring.mass
650
+ } : {
651
+ type: "tween",
652
+ duration: msToSeconds(styleConfig.duration.normal),
653
+ ease: [0.25, 0.1, 0.25, 1]
654
+ };
655
+ const itemVariants = {
656
+ hidden: {
657
+ opacity: 0,
658
+ y: 20
659
+ },
660
+ visible: (custom) => ({
661
+ opacity: 1,
662
+ y: 0,
663
+ transition: {
664
+ ...itemTransition,
665
+ delay: msToSeconds(getDelayForIndex(custom))
666
+ }
667
+ })
668
+ };
669
+ const containerProps = {
670
+ initial: "hidden",
671
+ animate: "visible",
672
+ exit: "hidden",
673
+ variants: containerVariants
674
+ };
675
+ const getItemProps = (index) => ({
676
+ variants: itemVariants,
677
+ custom: index
678
+ });
679
+ return {
680
+ containerVariants,
681
+ itemVariants,
682
+ containerProps,
683
+ getItemProps
684
+ };
685
+ }, [direction, totalItems, baseDelay, maxDelay, useSpring, customGetDelay, styleConfig]);
686
+ return result;
687
+ }
688
+ function gridStagger(columns, baseDelay = 50) {
689
+ return (index) => {
690
+ const row = Math.floor(index / columns);
691
+ const col = index % columns;
692
+ return (row + col) * baseDelay;
693
+ };
694
+ }
695
+ function waveStagger(amplitude = 100, frequency = 0.5, baseDelay = 30) {
696
+ return (index) => {
697
+ const wave = Math.sin(index * frequency) * amplitude;
698
+ return index * baseDelay + Math.abs(wave);
699
+ };
700
+ }
701
+ function cascadeStagger(baseDelay = 80, acceleration = 0.8) {
702
+ return (index) => {
703
+ const factor = acceleration ** index;
704
+ return baseDelay * (1 - factor) * (1 / (1 - acceleration));
705
+ };
706
+ }
707
+ function explodeStagger(baseDelay = 20) {
708
+ return (index, total) => {
709
+ const center = (total - 1) / 2;
710
+ const distance = Math.abs(index - center);
711
+ return distance * baseDelay;
712
+ };
713
+ }
714
+
715
+ // src/components/StaggerContainer.tsx
716
+ var import_jsx_runtime3 = require("react/jsx-runtime");
717
+ function StaggerItem({ children, index, variants }) {
718
+ if (!(0, import_react5.isValidElement)(children)) {
719
+ return children;
720
+ }
721
+ const motionProps = {
722
+ variants,
723
+ custom: index,
724
+ initial: "hidden",
725
+ animate: "visible",
726
+ exit: "hidden"
727
+ };
728
+ return (0, import_react5.cloneElement)(children, motionProps);
729
+ }
730
+ function StaggerContainer({
731
+ children,
732
+ style = "standard",
733
+ direction = "forward",
734
+ delay,
735
+ maxDelay = 1e3,
736
+ useSpring = true,
737
+ getDelay,
738
+ className,
739
+ as: Element = "div",
740
+ animate = true
741
+ }) {
742
+ const childArray = import_react5.Children.toArray(children);
743
+ const totalItems = childArray.length;
744
+ const staggerOptions = {
745
+ direction,
746
+ totalItems,
747
+ ...delay !== void 0 && { delayMultiplier: delay },
748
+ maxDelay,
749
+ useSpring,
750
+ ...getDelay !== void 0 && { getDelay }
751
+ };
752
+ const { itemVariants } = useStagger(style, staggerOptions);
753
+ if (!animate) {
754
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Element, { className, children });
755
+ }
756
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Element, { className, children: childArray.map((child, index) => {
757
+ if (!(0, import_react5.isValidElement)(child)) {
758
+ return child;
759
+ }
760
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StaggerItem, { index, variants: itemVariants, children: child }, child.key ?? index);
761
+ }) });
762
+ }
763
+ function withStagger(WrappedComponent) {
764
+ return function StaggerWrapper({
765
+ style = "standard",
766
+ direction = "forward",
767
+ delay,
768
+ maxDelay,
769
+ useSpring,
770
+ getDelay,
771
+ children,
772
+ ...props
773
+ }) {
774
+ const staggerProps = {
775
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(WrappedComponent, { ...props, children }),
776
+ style,
777
+ direction,
778
+ ...delay !== void 0 && { delay },
779
+ ...maxDelay !== void 0 && { maxDelay },
780
+ ...useSpring !== void 0 && { useSpring },
781
+ ...getDelay !== void 0 && { getDelay }
782
+ };
783
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StaggerContainer, { ...staggerProps });
784
+ };
785
+ }
786
+
787
+ // src/hooks/use-draw-path.ts
788
+ var import_react6 = require("react");
789
+ var easingFunctions2 = {
790
+ linear: (t) => t,
791
+ easeOut: (t) => 1 - (1 - t) ** 3,
792
+ easeOutExpo: (t) => t === 1 ? 1 : 1 - 2 ** (-10 * t),
793
+ easeInOut: (t) => t < 0.5 ? 4 * t ** 3 : 1 - (-2 * t + 2) ** 3 / 2,
794
+ spring: (t) => {
795
+ const c4 = 2 * Math.PI / 3;
796
+ return t === 0 ? 0 : t === 1 ? 1 : 2 ** (-10 * t) * Math.sin((t * 10 - 0.75) * c4) + 1;
797
+ }
798
+ };
799
+ function useReducedMotion3() {
800
+ const [prefersReducedMotion2, setPrefersReducedMotion] = (0, import_react6.useState)(() => {
801
+ if (typeof window === "undefined") return false;
802
+ return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
803
+ });
804
+ (0, import_react6.useEffect)(() => {
805
+ const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
806
+ setPrefersReducedMotion(mediaQuery.matches);
807
+ const handler = (e) => {
808
+ setPrefersReducedMotion(e.matches);
809
+ };
810
+ mediaQuery.addEventListener("change", handler);
811
+ return () => mediaQuery.removeEventListener("change", handler);
812
+ }, []);
813
+ return prefersReducedMotion2;
814
+ }
815
+ function useDrawPath(options) {
816
+ const {
817
+ from = 0,
818
+ to,
819
+ duration: customDuration,
820
+ motionStyle = "standard",
821
+ easing = "easeOutExpo",
822
+ delay = 0,
823
+ autoStart = true,
824
+ onComplete,
825
+ onUpdate,
826
+ enabled = true
827
+ } = options;
828
+ const duration = customDuration ?? getDuration(motionStyle, "slow");
829
+ const [pathLength, setPathLength] = (0, import_react6.useState)(from);
830
+ const [isAnimating, setIsAnimating] = (0, import_react6.useState)(false);
831
+ const [isComplete, setIsComplete] = (0, import_react6.useState)(false);
832
+ const animationRef = (0, import_react6.useRef)(null);
833
+ const startTimeRef = (0, import_react6.useRef)(null);
834
+ const pausedTimeRef = (0, import_react6.useRef)(null);
835
+ const currentFromRef = (0, import_react6.useRef)(from);
836
+ const currentToRef = (0, import_react6.useRef)(to);
837
+ const prefersReducedMotion2 = useReducedMotion3();
838
+ const cancelAnimation = (0, import_react6.useCallback)(() => {
839
+ if (animationRef.current !== null) {
840
+ cancelAnimationFrame(animationRef.current);
841
+ animationRef.current = null;
842
+ }
843
+ }, []);
844
+ const animate = (0, import_react6.useCallback)(
845
+ (timestamp) => {
846
+ if (startTimeRef.current === null) {
847
+ startTimeRef.current = timestamp;
848
+ }
849
+ const elapsed = timestamp - startTimeRef.current;
850
+ const progress = Math.min(elapsed / duration, 1);
851
+ const easedProgress = easingFunctions2[easing](progress);
852
+ const currentPathLength = currentFromRef.current + (currentToRef.current - currentFromRef.current) * easedProgress;
853
+ setPathLength(currentPathLength);
854
+ onUpdate?.(currentPathLength);
855
+ if (progress < 1) {
856
+ animationRef.current = requestAnimationFrame(animate);
857
+ } else {
858
+ setIsAnimating(false);
859
+ setIsComplete(true);
860
+ onComplete?.();
861
+ }
862
+ },
863
+ [duration, easing, onComplete, onUpdate]
864
+ );
865
+ const start = (0, import_react6.useCallback)(() => {
866
+ if (!enabled) {
867
+ setPathLength(currentToRef.current);
868
+ setIsComplete(true);
869
+ return;
870
+ }
871
+ if (prefersReducedMotion2) {
872
+ setPathLength(currentToRef.current);
873
+ setIsComplete(true);
874
+ onComplete?.();
875
+ return;
876
+ }
877
+ cancelAnimation();
878
+ setIsComplete(false);
879
+ startTimeRef.current = null;
880
+ pausedTimeRef.current = null;
881
+ const startAnimation = () => {
882
+ setIsAnimating(true);
883
+ animationRef.current = requestAnimationFrame(animate);
884
+ };
885
+ if (delay > 0) {
886
+ setTimeout(startAnimation, delay);
887
+ } else {
888
+ startAnimation();
889
+ }
890
+ }, [enabled, prefersReducedMotion2, cancelAnimation, animate, delay, onComplete]);
891
+ const pause = (0, import_react6.useCallback)(() => {
892
+ if (isAnimating && animationRef.current !== null) {
893
+ pausedTimeRef.current = performance.now();
894
+ cancelAnimation();
895
+ setIsAnimating(false);
896
+ }
897
+ }, [isAnimating, cancelAnimation]);
898
+ const resume = (0, import_react6.useCallback)(() => {
899
+ if (!isAnimating && !isComplete && pausedTimeRef.current !== null && startTimeRef.current !== null) {
900
+ const pausedDuration = performance.now() - pausedTimeRef.current;
901
+ startTimeRef.current += pausedDuration;
902
+ pausedTimeRef.current = null;
903
+ setIsAnimating(true);
904
+ animationRef.current = requestAnimationFrame(animate);
905
+ }
906
+ }, [isAnimating, isComplete, animate]);
907
+ const reset = (0, import_react6.useCallback)(() => {
908
+ cancelAnimation();
909
+ setPathLength(currentFromRef.current);
910
+ setIsAnimating(false);
911
+ setIsComplete(false);
912
+ startTimeRef.current = null;
913
+ pausedTimeRef.current = null;
914
+ }, [cancelAnimation]);
915
+ const update = (0, import_react6.useCallback)(
916
+ (newTo) => {
917
+ currentFromRef.current = pathLength;
918
+ currentToRef.current = newTo;
919
+ start();
920
+ },
921
+ [pathLength, start]
922
+ );
923
+ (0, import_react6.useEffect)(() => {
924
+ if (autoStart) {
925
+ currentFromRef.current = from;
926
+ currentToRef.current = to;
927
+ start();
928
+ }
929
+ return () => {
930
+ cancelAnimation();
931
+ };
932
+ }, []);
933
+ (0, import_react6.useEffect)(() => {
934
+ if (to !== currentToRef.current && isComplete) {
935
+ update(to);
936
+ }
937
+ }, [to, isComplete, update]);
938
+ return {
939
+ pathLength,
940
+ isAnimating,
941
+ isComplete,
942
+ start,
943
+ pause,
944
+ resume,
945
+ reset,
946
+ update,
947
+ prefersReducedMotion: prefersReducedMotion2
948
+ };
949
+ }
950
+
951
+ // src/hooks/use-motion-preset.ts
952
+ var import_react7 = require("react");
953
+
34
954
  // src/presets/motion-presets.ts
35
955
  var ambientPaths = {
36
956
  slow: {
@@ -83,29 +1003,27 @@ function applyMotionPreset(preset, baseConfig) {
83
1003
  }
84
1004
 
85
1005
  // src/hooks/use-motion-preset.ts
86
- var DEFAULT_CSS_VARS = {
87
- durationMultiplier: 1,
88
- opacityMin: 0.35,
89
- opacityMax: 0.6
90
- };
91
1006
  function readCSSVariables() {
92
1007
  if (typeof window === "undefined") {
93
- return DEFAULT_CSS_VARS;
1008
+ throw new Error("useMotionPreset/readCSSVariables requires a browser environment");
94
1009
  }
95
1010
  const root = document.documentElement;
96
1011
  const styles = getComputedStyle(root);
97
- const parseFloat_ = (value, fallback) => {
1012
+ const parseMotionVar = (value) => {
98
1013
  const parsed = parseFloat(value);
99
- return Number.isNaN(parsed) ? fallback : parsed;
1014
+ if (Number.isNaN(parsed)) {
1015
+ throw new Error("Motion CSS variable could not be parsed as a number");
1016
+ }
1017
+ return parsed;
100
1018
  };
101
1019
  return {
102
- durationMultiplier: parseFloat_(styles.getPropertyValue("--motion-duration-multiplier"), DEFAULT_CSS_VARS.durationMultiplier),
103
- opacityMin: parseFloat_(styles.getPropertyValue("--motion-opacity-min"), DEFAULT_CSS_VARS.opacityMin),
104
- opacityMax: parseFloat_(styles.getPropertyValue("--motion-opacity-max"), DEFAULT_CSS_VARS.opacityMax)
1020
+ durationMultiplier: parseMotionVar(styles.getPropertyValue("--motion-duration-multiplier")),
1021
+ opacityMin: parseMotionVar(styles.getPropertyValue("--motion-opacity-min")),
1022
+ opacityMax: parseMotionVar(styles.getPropertyValue("--motion-opacity-max"))
105
1023
  };
106
1024
  }
107
- function computePathsMotion(preset, cssVars, prefersReducedMotion) {
108
- if (prefersReducedMotion) {
1025
+ function computePathsMotion(preset, cssVars, prefersReducedMotion2) {
1026
+ if (prefersReducedMotion2) {
109
1027
  return {
110
1028
  baseDuration: 0,
111
1029
  opacity: [cssVars.opacityMin, cssVars.opacityMin, cssVars.opacityMin],
@@ -128,8 +1046,8 @@ function computePathsMotion(preset, cssVars, prefersReducedMotion) {
128
1046
  prefersReducedMotion: false
129
1047
  };
130
1048
  }
131
- function computeRaysMotion(preset, cssVars, prefersReducedMotion) {
132
- if (prefersReducedMotion) {
1049
+ function computeRaysMotion(preset, cssVars, prefersReducedMotion2) {
1050
+ if (prefersReducedMotion2) {
133
1051
  return {
134
1052
  cycleDuration: 0,
135
1053
  intensity: 0,
@@ -145,19 +1063,24 @@ function computeRaysMotion(preset, cssVars, prefersReducedMotion) {
145
1063
  };
146
1064
  }
147
1065
  function useMotionPreset(component, preset) {
148
- const [prefersReducedMotion, setPrefersReducedMotion] = (0, import_react.useState)(() => {
1066
+ const [prefersReducedMotion2, setPrefersReducedMotion] = (0, import_react7.useState)(() => {
149
1067
  if (typeof window === "undefined") return false;
150
1068
  return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
151
1069
  });
152
- const [cssVars, setCssVars] = (0, import_react.useState)(DEFAULT_CSS_VARS);
153
- (0, import_react.useEffect)(() => {
1070
+ const [cssVars, setCssVars] = (0, import_react7.useState)(() => {
1071
+ if (typeof window === "undefined") {
1072
+ throw new Error("useMotionPreset requires a browser environment");
1073
+ }
1074
+ return readCSSVariables();
1075
+ });
1076
+ (0, import_react7.useEffect)(() => {
154
1077
  const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
155
1078
  setPrefersReducedMotion(mediaQuery.matches);
156
1079
  const handler = (e) => setPrefersReducedMotion(e.matches);
157
1080
  mediaQuery.addEventListener("change", handler);
158
1081
  return () => mediaQuery.removeEventListener("change", handler);
159
1082
  }, []);
160
- (0, import_react.useEffect)(() => {
1083
+ (0, import_react7.useEffect)(() => {
161
1084
  setCssVars(readCSSVariables());
162
1085
  const observer = new MutationObserver(() => {
163
1086
  setCssVars(readCSSVariables());
@@ -168,21 +1091,1514 @@ function useMotionPreset(component, preset) {
168
1091
  });
169
1092
  return () => observer.disconnect();
170
1093
  }, []);
171
- return (0, import_react.useMemo)(() => {
1094
+ return (0, import_react7.useMemo)(() => {
172
1095
  if (component === "paths") {
173
1096
  const presetConfig2 = getPreset(preset, "paths");
174
- return computePathsMotion(presetConfig2, cssVars, prefersReducedMotion);
1097
+ return computePathsMotion(presetConfig2, cssVars, prefersReducedMotion2);
175
1098
  }
176
1099
  const presetConfig = getPreset(preset, "rays");
177
- return computeRaysMotion(presetConfig, cssVars, prefersReducedMotion);
178
- }, [component, preset, cssVars, prefersReducedMotion]);
1100
+ return computeRaysMotion(presetConfig, cssVars, prefersReducedMotion2);
1101
+ }, [component, preset, cssVars, prefersReducedMotion2]);
1102
+ }
1103
+
1104
+ // src/presets/component-presets.ts
1105
+ function createTweenTransition(style, options) {
1106
+ const duration = options?.duration ?? getDuration(style, "normal");
1107
+ return {
1108
+ type: "tween",
1109
+ duration: msToSeconds(duration),
1110
+ ease: [0.25, 0.1, 0.25, 1],
1111
+ // cubic-bezier ease-out
1112
+ delay: options?.delay ? msToSeconds(options.delay) : 0
1113
+ };
1114
+ }
1115
+ function createSpringTransition(style, options) {
1116
+ const spring = getSpringConfig(style);
1117
+ return {
1118
+ type: "spring",
1119
+ stiffness: spring.stiffness,
1120
+ damping: spring.damping,
1121
+ mass: spring.mass,
1122
+ delay: options?.delay ? msToSeconds(options.delay) : 0
1123
+ };
179
1124
  }
1125
+ function getTransition(style, preferSpring, options) {
1126
+ const useSpring = options?.useSpring ?? preferSpring;
1127
+ return useSpring ? createSpringTransition(style, options) : createTweenTransition(style, options);
1128
+ }
1129
+ var fadeIn = {
1130
+ metadata: {
1131
+ id: "fadeIn",
1132
+ name: "Fade In",
1133
+ description: "Smooth opacity transition from invisible to visible",
1134
+ useCase: ["entrance", "reveal"],
1135
+ context: ["tooltip", "dropdown", "modal", "notification"],
1136
+ intensity: 2,
1137
+ hasMovement: false
1138
+ },
1139
+ getProps: (style, options) => ({
1140
+ initial: { opacity: 0 },
1141
+ animate: { opacity: 1 },
1142
+ exit: { opacity: 0 },
1143
+ transition: createTweenTransition(style, options)
1144
+ })
1145
+ };
1146
+ var fadeOut = {
1147
+ metadata: {
1148
+ id: "fadeOut",
1149
+ name: "Fade Out",
1150
+ description: "Smooth opacity transition from visible to invisible",
1151
+ useCase: ["exit"],
1152
+ context: ["tooltip", "dropdown", "modal", "notification"],
1153
+ intensity: 2,
1154
+ hasMovement: false
1155
+ },
1156
+ getProps: (style, options) => ({
1157
+ initial: { opacity: 1 },
1158
+ animate: { opacity: 0 },
1159
+ transition: createTweenTransition(style, options)
1160
+ })
1161
+ };
1162
+ var DEFAULT_SLIDE_DISTANCE = 20;
1163
+ var slideUp = {
1164
+ metadata: {
1165
+ id: "slideUp",
1166
+ name: "Slide Up",
1167
+ description: "Element slides upward while fading in",
1168
+ useCase: ["entrance", "reveal"],
1169
+ context: ["modal", "card", "list-item", "notification"],
1170
+ intensity: 3,
1171
+ hasMovement: true,
1172
+ direction: "up"
1173
+ },
1174
+ getProps: (style, options) => {
1175
+ const distance = options?.distance ?? DEFAULT_SLIDE_DISTANCE;
1176
+ return {
1177
+ initial: { opacity: 0, y: distance },
1178
+ animate: { opacity: 1, y: 0 },
1179
+ exit: { opacity: 0, y: distance },
1180
+ transition: getTransition(style, true, options)
1181
+ };
1182
+ }
1183
+ };
1184
+ var slideDown = {
1185
+ metadata: {
1186
+ id: "slideDown",
1187
+ name: "Slide Down",
1188
+ description: "Element slides downward while fading in",
1189
+ useCase: ["entrance", "reveal"],
1190
+ context: ["dropdown", "tooltip", "notification"],
1191
+ intensity: 3,
1192
+ hasMovement: true,
1193
+ direction: "down"
1194
+ },
1195
+ getProps: (style, options) => {
1196
+ const distance = options?.distance ?? DEFAULT_SLIDE_DISTANCE;
1197
+ return {
1198
+ initial: { opacity: 0, y: -distance },
1199
+ animate: { opacity: 1, y: 0 },
1200
+ exit: { opacity: 0, y: -distance },
1201
+ transition: getTransition(style, true, options)
1202
+ };
1203
+ }
1204
+ };
1205
+ var slideLeft = {
1206
+ metadata: {
1207
+ id: "slideLeft",
1208
+ name: "Slide Left",
1209
+ description: "Element slides leftward while fading in",
1210
+ useCase: ["entrance", "transition"],
1211
+ context: ["drawer", "page", "section"],
1212
+ intensity: 3,
1213
+ hasMovement: true,
1214
+ direction: "left"
1215
+ },
1216
+ getProps: (style, options) => {
1217
+ const distance = options?.distance ?? DEFAULT_SLIDE_DISTANCE;
1218
+ return {
1219
+ initial: { opacity: 0, x: distance },
1220
+ animate: { opacity: 1, x: 0 },
1221
+ exit: { opacity: 0, x: -distance },
1222
+ transition: getTransition(style, true, options)
1223
+ };
1224
+ }
1225
+ };
1226
+ var slideRight = {
1227
+ metadata: {
1228
+ id: "slideRight",
1229
+ name: "Slide Right",
1230
+ description: "Element slides rightward while fading in",
1231
+ useCase: ["entrance", "transition"],
1232
+ context: ["drawer", "page", "section"],
1233
+ intensity: 3,
1234
+ hasMovement: true,
1235
+ direction: "right"
1236
+ },
1237
+ getProps: (style, options) => {
1238
+ const distance = options?.distance ?? DEFAULT_SLIDE_DISTANCE;
1239
+ return {
1240
+ initial: { opacity: 0, x: -distance },
1241
+ animate: { opacity: 1, x: 0 },
1242
+ exit: { opacity: 0, x: distance },
1243
+ transition: getTransition(style, true, options)
1244
+ };
1245
+ }
1246
+ };
1247
+ var DEFAULT_SCALE_FROM = 0.95;
1248
+ var DEFAULT_ZOOM_SCALE = 0.5;
1249
+ var scale = {
1250
+ metadata: {
1251
+ id: "scale",
1252
+ name: "Scale",
1253
+ description: "Subtle scale transition with fade",
1254
+ useCase: ["entrance", "emphasis"],
1255
+ context: ["modal", "card", "notification"],
1256
+ intensity: 3,
1257
+ hasMovement: true,
1258
+ direction: "in"
1259
+ },
1260
+ getProps: (style, options) => {
1261
+ const scaleFrom = options?.scale ?? DEFAULT_SCALE_FROM;
1262
+ return {
1263
+ initial: { opacity: 0, scale: scaleFrom },
1264
+ animate: { opacity: 1, scale: 1 },
1265
+ exit: { opacity: 0, scale: scaleFrom },
1266
+ transition: getTransition(style, true, options)
1267
+ };
1268
+ }
1269
+ };
1270
+ var zoomIn = {
1271
+ metadata: {
1272
+ id: "zoomIn",
1273
+ name: "Zoom In",
1274
+ description: "Dramatic zoom from small to full size",
1275
+ useCase: ["entrance", "emphasis"],
1276
+ context: ["hero", "modal", "card"],
1277
+ intensity: 4,
1278
+ hasMovement: true,
1279
+ direction: "in"
1280
+ },
1281
+ getProps: (style, options) => {
1282
+ const scaleFrom = options?.scale ?? DEFAULT_ZOOM_SCALE;
1283
+ return {
1284
+ initial: { opacity: 0, scale: scaleFrom },
1285
+ animate: { opacity: 1, scale: 1 },
1286
+ exit: { opacity: 0, scale: scaleFrom },
1287
+ transition: getTransition(style, true, options)
1288
+ };
1289
+ }
1290
+ };
1291
+ var zoomOut = {
1292
+ metadata: {
1293
+ id: "zoomOut",
1294
+ name: "Zoom Out",
1295
+ description: "Scale from larger to normal size",
1296
+ useCase: ["entrance", "emphasis"],
1297
+ context: ["hero", "modal"],
1298
+ intensity: 4,
1299
+ hasMovement: true,
1300
+ direction: "out"
1301
+ },
1302
+ getProps: (style, options) => {
1303
+ const scaleTo = options?.scale ?? 1.1;
1304
+ return {
1305
+ initial: { opacity: 0, scale: scaleTo },
1306
+ animate: { opacity: 1, scale: 1 },
1307
+ exit: { opacity: 0, scale: scaleTo },
1308
+ transition: getTransition(style, true, options)
1309
+ };
1310
+ }
1311
+ };
1312
+ var DEFAULT_ROTATION = 10;
1313
+ var rotate = {
1314
+ metadata: {
1315
+ id: "rotate",
1316
+ name: "Rotate",
1317
+ description: "Subtle rotation animation with fade",
1318
+ useCase: ["entrance", "emphasis"],
1319
+ context: ["card", "notification"],
1320
+ intensity: 4,
1321
+ hasMovement: true
1322
+ },
1323
+ getProps: (style, options) => {
1324
+ const rotation = options?.rotation ?? DEFAULT_ROTATION;
1325
+ return {
1326
+ initial: { opacity: 0, rotate: -rotation },
1327
+ animate: { opacity: 1, rotate: 0 },
1328
+ exit: { opacity: 0, rotate: rotation },
1329
+ transition: getTransition(style, true, options)
1330
+ };
1331
+ }
1332
+ };
1333
+ var slideUpScale = {
1334
+ metadata: {
1335
+ id: "slideUpScale",
1336
+ name: "Slide Up & Scale",
1337
+ description: "Combines upward slide with subtle scale",
1338
+ useCase: ["entrance", "emphasis"],
1339
+ context: ["hero", "card", "section"],
1340
+ intensity: 4,
1341
+ hasMovement: true,
1342
+ direction: "up"
1343
+ },
1344
+ getProps: (style, options) => {
1345
+ const distance = options?.distance ?? DEFAULT_SLIDE_DISTANCE;
1346
+ const scaleFrom = options?.scale ?? 0.98;
1347
+ return {
1348
+ initial: { opacity: 0, y: distance, scale: scaleFrom },
1349
+ animate: { opacity: 1, y: 0, scale: 1 },
1350
+ exit: { opacity: 0, y: distance, scale: scaleFrom },
1351
+ transition: getTransition(style, true, options)
1352
+ };
1353
+ }
1354
+ };
1355
+ var flip = {
1356
+ metadata: {
1357
+ id: "flip",
1358
+ name: "Flip",
1359
+ description: "3D flip animation on the X axis",
1360
+ useCase: ["entrance", "transition"],
1361
+ context: ["card"],
1362
+ intensity: 5,
1363
+ hasMovement: true
1364
+ },
1365
+ getProps: (style, options) => {
1366
+ const rotation = options?.rotation ?? 90;
1367
+ return {
1368
+ initial: { opacity: 0, rotateX: rotation },
1369
+ animate: { opacity: 1, rotateX: 0 },
1370
+ exit: { opacity: 0, rotateX: -rotation },
1371
+ transition: getTransition(style, true, options)
1372
+ };
1373
+ }
1374
+ };
1375
+ var expand = {
1376
+ metadata: {
1377
+ id: "expand",
1378
+ name: "Expand",
1379
+ description: "Height expansion animation",
1380
+ useCase: ["entrance", "reveal"],
1381
+ context: ["section"],
1382
+ intensity: 2,
1383
+ hasMovement: true,
1384
+ direction: "down"
1385
+ },
1386
+ getProps: (style, options) => ({
1387
+ initial: { opacity: 0, height: 0 },
1388
+ animate: { opacity: 1, height: "auto" },
1389
+ exit: { opacity: 0, height: 0 },
1390
+ transition: createTweenTransition(style, options)
1391
+ })
1392
+ };
1393
+ var componentPresets = {
1394
+ fadeIn,
1395
+ fadeOut,
1396
+ slideUp,
1397
+ slideDown,
1398
+ slideLeft,
1399
+ slideRight,
1400
+ scale,
1401
+ zoomIn,
1402
+ zoomOut,
1403
+ rotate,
1404
+ slideUpScale,
1405
+ flip,
1406
+ expand
1407
+ };
1408
+ function getComponentPreset(name) {
1409
+ return componentPresets[name];
1410
+ }
1411
+ function getPresetsByUseCase(useCase) {
1412
+ return Object.values(componentPresets).filter((preset) => preset.metadata.useCase.includes(useCase));
1413
+ }
1414
+ function getPresetsByContext(context) {
1415
+ return Object.values(componentPresets).filter((preset) => preset.metadata.context.includes(context));
1416
+ }
1417
+
1418
+ // src/presets/micro-interactions.ts
1419
+ function prefersReducedMotion() {
1420
+ if (typeof window === "undefined") return false;
1421
+ return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
1422
+ }
1423
+ function getReducedMotionProps() {
1424
+ return {};
1425
+ }
1426
+ var buttonPress = {
1427
+ name: "buttonPress",
1428
+ description: "Scale down slightly on press, spring back on release",
1429
+ useCase: ["buttons", "clickable cards", "list items", "interactive elements", "call-to-action"],
1430
+ getProps: (style) => {
1431
+ if (prefersReducedMotion()) return getReducedMotionProps();
1432
+ const config = getMotionStyle(style);
1433
+ const scaleAmount = style === "subtle" ? 0.98 : style === "playful" ? 0.92 : 0.95;
1434
+ return {
1435
+ whileTap: {
1436
+ scale: scaleAmount
1437
+ },
1438
+ whileHover: {
1439
+ scale: style === "subtle" ? 1.01 : 1.02
1440
+ },
1441
+ transition: {
1442
+ type: "spring",
1443
+ stiffness: config.spring.stiffness,
1444
+ damping: config.spring.damping,
1445
+ mass: config.spring.mass
1446
+ }
1447
+ };
1448
+ }
1449
+ };
1450
+ var cardHover = {
1451
+ name: "cardHover",
1452
+ description: "Subtle lift with shadow enhancement on hover",
1453
+ useCase: ["cards", "tiles", "panels", "content blocks", "media items", "product listings"],
1454
+ getProps: (style) => {
1455
+ if (prefersReducedMotion()) return getReducedMotionProps();
1456
+ const config = getMotionStyle(style);
1457
+ const liftAmount = style === "subtle" ? -2 : style === "playful" ? -8 : -4;
1458
+ const shadowIntensity = style === "subtle" ? 0.08 : style === "playful" ? 0.2 : 0.12;
1459
+ return {
1460
+ whileHover: {
1461
+ y: liftAmount,
1462
+ boxShadow: `0 ${Math.abs(liftAmount) * 2}px ${Math.abs(liftAmount) * 4}px rgba(0, 0, 0, ${shadowIntensity})`
1463
+ },
1464
+ transition: {
1465
+ type: "spring",
1466
+ stiffness: config.spring.stiffness,
1467
+ damping: config.spring.damping,
1468
+ mass: config.spring.mass
1469
+ }
1470
+ };
1471
+ }
1472
+ };
1473
+ var iconSpin = {
1474
+ name: "iconSpin",
1475
+ description: "360 degree rotation animation",
1476
+ useCase: ["refresh buttons", "sync icons", "loading indicators", "settings icons", "interactive icons"],
1477
+ getProps: (style) => {
1478
+ if (prefersReducedMotion()) return getReducedMotionProps();
1479
+ const config = getMotionStyle(style);
1480
+ return {
1481
+ whileTap: {
1482
+ rotate: 360
1483
+ },
1484
+ whileHover: {
1485
+ rotate: style === "playful" ? 15 : 5
1486
+ },
1487
+ transition: {
1488
+ type: "spring",
1489
+ stiffness: config.spring.stiffness * 0.8,
1490
+ damping: config.spring.damping,
1491
+ mass: config.spring.mass
1492
+ }
1493
+ };
1494
+ }
1495
+ };
1496
+ var pulse = {
1497
+ name: "pulse",
1498
+ description: "Scale pulse animation with breathing effect",
1499
+ useCase: ["notifications", "live indicators", "attention grabbers", "status badges", "loading states"],
1500
+ getProps: (style) => {
1501
+ if (prefersReducedMotion()) return getReducedMotionProps();
1502
+ const config = getMotionStyle(style);
1503
+ const scaleRange = style === "subtle" ? 1.03 : style === "playful" ? 1.12 : 1.06;
1504
+ return {
1505
+ initial: {
1506
+ scale: 1
1507
+ },
1508
+ animate: {
1509
+ scale: [1, scaleRange, 1]
1510
+ },
1511
+ transition: {
1512
+ duration: msToSeconds(config.duration.slow),
1513
+ repeat: Infinity,
1514
+ ease: config.easing.interactive
1515
+ }
1516
+ };
1517
+ }
1518
+ };
1519
+ var shake = {
1520
+ name: "shake",
1521
+ description: "Horizontal shake animation for error states",
1522
+ useCase: ["error states", "invalid inputs", "denied actions", "form validation", "authentication failures"],
1523
+ getProps: (style) => {
1524
+ if (prefersReducedMotion()) return getReducedMotionProps();
1525
+ const config = getMotionStyle(style);
1526
+ const shakeDistance = style === "subtle" ? 4 : style === "playful" ? 12 : 8;
1527
+ return {
1528
+ initial: {
1529
+ x: 0
1530
+ },
1531
+ animate: {
1532
+ x: [0, -shakeDistance, shakeDistance, -shakeDistance, shakeDistance, 0]
1533
+ },
1534
+ transition: {
1535
+ duration: msToSeconds(config.duration.fast),
1536
+ ease: config.easing.interactive
1537
+ }
1538
+ };
1539
+ }
1540
+ };
1541
+ var wiggle = {
1542
+ name: "wiggle",
1543
+ description: "Playful rotation wiggle animation",
1544
+ useCase: ["playful interfaces", "gamification", "attention indicators", "celebration elements", "decorative icons"],
1545
+ getProps: (style) => {
1546
+ if (prefersReducedMotion()) return getReducedMotionProps();
1547
+ const config = getMotionStyle(style);
1548
+ const wiggleAngle = style === "subtle" ? 3 : style === "playful" ? 12 : 6;
1549
+ return {
1550
+ whileHover: {
1551
+ rotate: [0, -wiggleAngle, wiggleAngle, -wiggleAngle, wiggleAngle, 0]
1552
+ },
1553
+ transition: {
1554
+ duration: msToSeconds(config.duration.normal),
1555
+ ease: config.easing.interactive
1556
+ }
1557
+ };
1558
+ }
1559
+ };
1560
+ var heartbeat = {
1561
+ name: "heartbeat",
1562
+ description: "Double-pulse heartbeat pattern animation",
1563
+ useCase: ["like buttons", "health apps", "love reactions", "favorite indicators", "activity monitors"],
1564
+ getProps: (style) => {
1565
+ if (prefersReducedMotion()) return getReducedMotionProps();
1566
+ const config = getMotionStyle(style);
1567
+ const pulseScale = style === "subtle" ? 1.1 : style === "playful" ? 1.3 : 1.2;
1568
+ return {
1569
+ initial: {
1570
+ scale: 1
1571
+ },
1572
+ animate: {
1573
+ scale: [1, pulseScale, 1, pulseScale * 0.95, 1]
1574
+ },
1575
+ transition: {
1576
+ duration: msToSeconds(config.duration.slow * 1.5),
1577
+ repeat: Infinity,
1578
+ repeatDelay: msToSeconds(config.duration.normal),
1579
+ ease: config.easing.interactive
1580
+ }
1581
+ };
1582
+ }
1583
+ };
1584
+ var rubberBand = {
1585
+ name: "rubberBand",
1586
+ description: "Elastic stretch and snap back animation",
1587
+ useCase: ["emphasis animations", "attention grabbers", "playful buttons", "celebration effects", "interactive feedback"],
1588
+ getProps: (style) => {
1589
+ if (prefersReducedMotion()) return getReducedMotionProps();
1590
+ const config = getMotionStyle(style);
1591
+ const stretchX = style === "subtle" ? 1.05 : style === "playful" ? 1.25 : 1.15;
1592
+ const stretchY = style === "subtle" ? 0.95 : style === "playful" ? 0.75 : 0.85;
1593
+ return {
1594
+ whileTap: {
1595
+ scaleX: [1, stretchX, 0.95, 1.05, 1],
1596
+ scaleY: [1, stretchY, 1.05, 0.95, 1]
1597
+ },
1598
+ whileHover: {
1599
+ scaleX: 1.02,
1600
+ scaleY: 0.98
1601
+ },
1602
+ transition: {
1603
+ type: "spring",
1604
+ stiffness: config.spring.stiffness * 0.6,
1605
+ damping: config.spring.damping * 0.5,
1606
+ mass: config.spring.mass
1607
+ }
1608
+ };
1609
+ }
1610
+ };
1611
+ var scale2 = {
1612
+ name: "scale",
1613
+ description: "Scale up animation for selection feedback",
1614
+ useCase: ["checkboxes", "toggles", "radio buttons", "selection states", "activation feedback"],
1615
+ getProps: (style) => {
1616
+ if (prefersReducedMotion()) return getReducedMotionProps();
1617
+ const config = getMotionStyle(style);
1618
+ const scaleAmount = style === "subtle" ? 1.05 : style === "playful" ? 1.2 : 1.1;
1619
+ return {
1620
+ initial: {
1621
+ scale: 0.8,
1622
+ opacity: 0
1623
+ },
1624
+ animate: {
1625
+ scale: [0.8, scaleAmount, 1],
1626
+ opacity: 1
1627
+ },
1628
+ transition: {
1629
+ type: "spring",
1630
+ stiffness: config.spring.stiffness,
1631
+ damping: config.spring.damping,
1632
+ mass: config.spring.mass
1633
+ }
1634
+ };
1635
+ }
1636
+ };
1637
+ var shimmer = {
1638
+ name: "shimmer",
1639
+ description: "Gradient shimmer effect that slides across the element",
1640
+ useCase: ["skeleton loading", "placeholder content", "progress indicators", "loading states", "content placeholders"],
1641
+ getProps: (style) => {
1642
+ if (prefersReducedMotion()) return getReducedMotionProps();
1643
+ const config = getMotionStyle(style);
1644
+ const duration = style === "subtle" ? 2 : style === "playful" ? 1.2 : 1.5;
1645
+ return {
1646
+ initial: {
1647
+ backgroundPosition: "200% 0"
1648
+ },
1649
+ animate: {
1650
+ backgroundPosition: ["-200% 0", "200% 0"]
1651
+ },
1652
+ transition: {
1653
+ duration,
1654
+ repeat: Infinity,
1655
+ ease: config.easing.exit,
1656
+ repeatDelay: 0.5
1657
+ }
1658
+ };
1659
+ }
1660
+ };
1661
+ var glowPulse = {
1662
+ name: "glowPulse",
1663
+ description: "Glowing pulse effect for emphasis and AI indicators",
1664
+ useCase: ["AI content indicators", "featured items", "premium elements", "special badges", "magical effects"],
1665
+ getProps: (style) => {
1666
+ if (prefersReducedMotion()) return getReducedMotionProps();
1667
+ const config = getMotionStyle(style);
1668
+ const glowIntensity = style === "subtle" ? 8 : style === "playful" ? 20 : 12;
1669
+ const glowColor = "rgba(99, 102, 241, 0.6)";
1670
+ return {
1671
+ initial: {
1672
+ boxShadow: `0 0 0 rgba(99, 102, 241, 0)`
1673
+ },
1674
+ animate: {
1675
+ boxShadow: [`0 0 0 rgba(99, 102, 241, 0)`, `0 0 ${glowIntensity}px ${glowColor}`, `0 0 0 rgba(99, 102, 241, 0)`]
1676
+ },
1677
+ transition: {
1678
+ duration: msToSeconds(config.duration.slow * 1.5),
1679
+ repeat: Infinity,
1680
+ ease: config.easing.interactive
1681
+ }
1682
+ };
1683
+ }
1684
+ };
1685
+ var progressFill = {
1686
+ name: "progressFill",
1687
+ description: "Animated fill from 0% to target width for progress bars",
1688
+ useCase: ["progress bars", "completion indicators", "skill bars", "loading progress", "data visualization"],
1689
+ getProps: (style) => {
1690
+ if (prefersReducedMotion()) return getReducedMotionProps();
1691
+ const config = getMotionStyle(style);
1692
+ const duration = style === "subtle" ? 0.6 : style === "playful" ? 1.2 : 0.8;
1693
+ return {
1694
+ initial: {
1695
+ scaleX: 0
1696
+ },
1697
+ animate: {
1698
+ scaleX: 1
1699
+ },
1700
+ transition: {
1701
+ duration,
1702
+ ease: config.easing.exit
1703
+ }
1704
+ };
1705
+ }
1706
+ };
1707
+ var checkmarkDraw = {
1708
+ name: "checkmarkDraw",
1709
+ description: "Animated checkmark draw effect for success states",
1710
+ useCase: ["success confirmations", "completed tasks", "checkboxes", "form submissions", "achievement unlocks"],
1711
+ getProps: (style) => {
1712
+ if (prefersReducedMotion()) return getReducedMotionProps();
1713
+ const config = getMotionStyle(style);
1714
+ const duration = style === "subtle" ? config.duration.fast : style === "playful" ? config.duration.slow : config.duration.normal;
1715
+ return {
1716
+ initial: {
1717
+ pathLength: 0,
1718
+ opacity: 0
1719
+ },
1720
+ animate: {
1721
+ pathLength: 1,
1722
+ opacity: 1
1723
+ },
1724
+ transition: {
1725
+ duration: msToSeconds(duration),
1726
+ ease: config.easing.interactive
1727
+ }
1728
+ };
1729
+ }
1730
+ };
1731
+ var successFlash = {
1732
+ name: "successFlash",
1733
+ description: "Brief success highlight flash animation",
1734
+ useCase: ["success toasts", "inline confirmations", "save indicators", "completion feedback", "achievement notifications"],
1735
+ getProps: (style) => {
1736
+ if (prefersReducedMotion()) return getReducedMotionProps();
1737
+ const config = getMotionStyle(style);
1738
+ const scale3 = style === "subtle" ? 1.02 : style === "playful" ? 1.08 : 1.05;
1739
+ return {
1740
+ initial: {
1741
+ scale: 1,
1742
+ backgroundColor: "transparent"
1743
+ },
1744
+ animate: {
1745
+ scale: [1, scale3, 1],
1746
+ backgroundColor: ["transparent", "var(--color-surface-success-subtle)", "transparent"]
1747
+ },
1748
+ transition: {
1749
+ duration: msToSeconds(config.duration.fast),
1750
+ ease: config.easing.interactive
1751
+ }
1752
+ };
1753
+ }
1754
+ };
1755
+ var badgePop = {
1756
+ name: "badgePop",
1757
+ description: "Pop animation for badge count changes",
1758
+ useCase: ["notification badges", "count indicators", "numeric updates", "inventory changes", "score updates"],
1759
+ getProps: (style) => {
1760
+ if (prefersReducedMotion()) return getReducedMotionProps();
1761
+ const config = getMotionStyle(style);
1762
+ const scale3 = style === "subtle" ? 1.15 : style === "playful" ? 1.4 : 1.25;
1763
+ return {
1764
+ initial: {
1765
+ scale: 0,
1766
+ opacity: 0
1767
+ },
1768
+ animate: {
1769
+ scale: [0, scale3, 1],
1770
+ opacity: [0, 1, 1]
1771
+ },
1772
+ transition: {
1773
+ duration: msToSeconds(config.duration.fast),
1774
+ ease: config.easing.interactive
1775
+ }
1776
+ };
1777
+ }
1778
+ };
1779
+ var microInteractions = {
1780
+ buttonPress,
1781
+ cardHover,
1782
+ iconSpin,
1783
+ pulse,
1784
+ scale: scale2,
1785
+ shake,
1786
+ wiggle,
1787
+ heartbeat,
1788
+ rubberBand,
1789
+ shimmer,
1790
+ glowPulse,
1791
+ progressFill,
1792
+ checkmarkDraw,
1793
+ successFlash,
1794
+ badgePop
1795
+ };
1796
+ function getMicroInteraction(name) {
1797
+ return microInteractions[name];
1798
+ }
1799
+ function getMicroInteractionNames() {
1800
+ return Object.keys(microInteractions);
1801
+ }
1802
+ function findPresetsForUseCase(useCase) {
1803
+ const searchTerm = useCase.toLowerCase();
1804
+ return Object.values(microInteractions).filter((preset) => preset.useCase.some((uc) => uc.toLowerCase().includes(searchTerm)));
1805
+ }
1806
+
1807
+ // src/presets/stagger-presets.ts
1808
+ function createBaseItemVariants(style) {
1809
+ const config = getMotionStyle(style);
1810
+ return {
1811
+ hidden: {
1812
+ opacity: 0,
1813
+ y: 20
1814
+ },
1815
+ visible: {
1816
+ opacity: 1,
1817
+ y: 0,
1818
+ transition: {
1819
+ type: "spring",
1820
+ stiffness: config.spring.stiffness,
1821
+ damping: config.spring.damping,
1822
+ mass: config.spring.mass
1823
+ }
1824
+ }
1825
+ };
1826
+ }
1827
+ var staggerSequential = {
1828
+ name: "Sequential",
1829
+ description: "Items animate one after another from top to bottom",
1830
+ useCase: ["Navigation menus", "Vertical lists", "Table rows", "Form fields", "Sidebar items"],
1831
+ getDelay(index, _total, style) {
1832
+ const config = getMotionStyle(style);
1833
+ return msToSeconds(config.staggerDelay * index);
1834
+ },
1835
+ getContainerVariants(style) {
1836
+ const config = getMotionStyle(style);
1837
+ return {
1838
+ hidden: { opacity: 0 },
1839
+ visible: {
1840
+ opacity: 1,
1841
+ transition: {
1842
+ staggerChildren: msToSeconds(config.staggerDelay),
1843
+ delayChildren: msToSeconds(config.duration.fast * 0.5)
1844
+ }
1845
+ }
1846
+ };
1847
+ },
1848
+ getItemVariants: createBaseItemVariants
1849
+ };
1850
+ var staggerReverse = {
1851
+ name: "Reverse",
1852
+ description: "Items animate from bottom to top",
1853
+ useCase: ["Toast notifications", "Chat messages (newest first)", "Bottom-anchored content", "Rising effect animations", "Upward reveals"],
1854
+ getDelay(index, total, style) {
1855
+ const config = getMotionStyle(style);
1856
+ const reverseIndex = total - 1 - index;
1857
+ return msToSeconds(config.staggerDelay * reverseIndex);
1858
+ },
1859
+ getContainerVariants(style) {
1860
+ const config = getMotionStyle(style);
1861
+ return {
1862
+ hidden: { opacity: 0 },
1863
+ visible: {
1864
+ opacity: 1,
1865
+ transition: {
1866
+ staggerChildren: msToSeconds(config.staggerDelay),
1867
+ staggerDirection: -1,
1868
+ delayChildren: msToSeconds(config.duration.fast * 0.5)
1869
+ }
1870
+ }
1871
+ };
1872
+ },
1873
+ getItemVariants(style) {
1874
+ const config = getMotionStyle(style);
1875
+ return {
1876
+ hidden: {
1877
+ opacity: 0,
1878
+ y: -20
1879
+ },
1880
+ visible: {
1881
+ opacity: 1,
1882
+ y: 0,
1883
+ transition: {
1884
+ type: "spring",
1885
+ stiffness: config.spring.stiffness,
1886
+ damping: config.spring.damping,
1887
+ mass: config.spring.mass
1888
+ }
1889
+ }
1890
+ };
1891
+ }
1892
+ };
1893
+ var staggerCenter = {
1894
+ name: "Center",
1895
+ description: "Items animate from center outward",
1896
+ useCase: ["Hero sections", "Featured content", "Pricing cards", "Centered navigation", "Focus-based reveals"],
1897
+ getDelay(index, total, style) {
1898
+ const config = getMotionStyle(style);
1899
+ const centerIndex = (total - 1) / 2;
1900
+ const distanceFromCenter = Math.abs(index - centerIndex);
1901
+ return msToSeconds(config.staggerDelay * distanceFromCenter);
1902
+ },
1903
+ getContainerVariants(style) {
1904
+ const config = getMotionStyle(style);
1905
+ return {
1906
+ hidden: { opacity: 0 },
1907
+ visible: {
1908
+ opacity: 1,
1909
+ transition: {
1910
+ staggerChildren: msToSeconds(config.staggerDelay),
1911
+ delayChildren: msToSeconds(config.duration.fast * 0.5)
1912
+ }
1913
+ }
1914
+ };
1915
+ },
1916
+ getItemVariants(style) {
1917
+ const config = getMotionStyle(style);
1918
+ return {
1919
+ hidden: {
1920
+ opacity: 0,
1921
+ scale: 0.8
1922
+ },
1923
+ visible: {
1924
+ opacity: 1,
1925
+ scale: 1,
1926
+ transition: {
1927
+ type: "spring",
1928
+ stiffness: config.spring.stiffness,
1929
+ damping: config.spring.damping,
1930
+ mass: config.spring.mass
1931
+ }
1932
+ }
1933
+ };
1934
+ }
1935
+ };
1936
+ var staggerRandom = {
1937
+ name: "Random",
1938
+ description: "Items animate in random order",
1939
+ useCase: ["Photo galleries", "Tag clouds", "Creative portfolios", "Playful interfaces", "Organic reveals"],
1940
+ getDelay(index, total, style) {
1941
+ const config = getMotionStyle(style);
1942
+ const seed = index * 7919 % total / total;
1943
+ const maxDelay = config.staggerDelay * total;
1944
+ return msToSeconds(seed * maxDelay);
1945
+ },
1946
+ getContainerVariants(style) {
1947
+ const config = getMotionStyle(style);
1948
+ return {
1949
+ hidden: { opacity: 0 },
1950
+ visible: {
1951
+ opacity: 1,
1952
+ transition: {
1953
+ staggerChildren: msToSeconds(config.staggerDelay * 0.3),
1954
+ delayChildren: msToSeconds(config.duration.fast * 0.5)
1955
+ }
1956
+ }
1957
+ };
1958
+ },
1959
+ getItemVariants(style) {
1960
+ const config = getMotionStyle(style);
1961
+ return {
1962
+ hidden: {
1963
+ opacity: 0,
1964
+ scale: 0.9,
1965
+ rotate: -5
1966
+ },
1967
+ visible: {
1968
+ opacity: 1,
1969
+ scale: 1,
1970
+ rotate: 0,
1971
+ transition: {
1972
+ type: "spring",
1973
+ stiffness: config.spring.stiffness,
1974
+ damping: config.spring.damping,
1975
+ mass: config.spring.mass
1976
+ }
1977
+ }
1978
+ };
1979
+ }
1980
+ };
1981
+ var staggerGrid = {
1982
+ name: "Grid",
1983
+ description: "2D diagonal wave pattern for grid layouts",
1984
+ useCase: ["Image galleries", "Card grids", "Dashboard widgets", "Product catalogs", "Portfolio items"],
1985
+ getDelay(index, _total, style, columns = 4) {
1986
+ const config = getMotionStyle(style);
1987
+ const row = Math.floor(index / columns);
1988
+ const col = index % columns;
1989
+ const diagonalIndex = row + col;
1990
+ return msToSeconds(config.staggerDelay * diagonalIndex);
1991
+ },
1992
+ getContainerVariants(style) {
1993
+ const config = getMotionStyle(style);
1994
+ return {
1995
+ hidden: { opacity: 0 },
1996
+ visible: {
1997
+ opacity: 1,
1998
+ transition: {
1999
+ staggerChildren: msToSeconds(config.staggerDelay * 0.8),
2000
+ delayChildren: msToSeconds(config.duration.fast * 0.5)
2001
+ }
2002
+ }
2003
+ };
2004
+ },
2005
+ getItemVariants(style) {
2006
+ const config = getMotionStyle(style);
2007
+ return {
2008
+ hidden: {
2009
+ opacity: 0,
2010
+ scale: 0.9,
2011
+ y: 10
2012
+ },
2013
+ visible: {
2014
+ opacity: 1,
2015
+ scale: 1,
2016
+ y: 0,
2017
+ transition: {
2018
+ type: "spring",
2019
+ stiffness: config.spring.stiffness,
2020
+ damping: config.spring.damping,
2021
+ mass: config.spring.mass
2022
+ }
2023
+ }
2024
+ };
2025
+ }
2026
+ };
2027
+ var staggerWave = {
2028
+ name: "Wave",
2029
+ description: "Sine-wave based stagger pattern for organic motion",
2030
+ useCase: ["Audio visualizers", "Timeline animations", "Organic reveals", "Music interfaces", "Flowing sequences"],
2031
+ getDelay(index, total, style) {
2032
+ const config = getMotionStyle(style);
2033
+ const wavePosition = index / total * Math.PI * 2;
2034
+ const waveOffset = (Math.sin(wavePosition) + 1) / 2;
2035
+ const baseDelay = config.staggerDelay * index;
2036
+ const waveDelay = config.staggerDelay * waveOffset * 2;
2037
+ return msToSeconds(baseDelay + waveDelay);
2038
+ },
2039
+ getContainerVariants(style) {
2040
+ const config = getMotionStyle(style);
2041
+ return {
2042
+ hidden: { opacity: 0 },
2043
+ visible: {
2044
+ opacity: 1,
2045
+ transition: {
2046
+ staggerChildren: msToSeconds(config.staggerDelay * 0.6),
2047
+ delayChildren: msToSeconds(config.duration.fast * 0.5)
2048
+ }
2049
+ }
2050
+ };
2051
+ },
2052
+ getItemVariants(style) {
2053
+ const config = getMotionStyle(style);
2054
+ return {
2055
+ hidden: {
2056
+ opacity: 0,
2057
+ y: 15,
2058
+ x: -5
2059
+ },
2060
+ visible: {
2061
+ opacity: 1,
2062
+ y: 0,
2063
+ x: 0,
2064
+ transition: {
2065
+ type: "spring",
2066
+ stiffness: config.spring.stiffness,
2067
+ damping: config.spring.damping,
2068
+ mass: config.spring.mass
2069
+ }
2070
+ }
2071
+ };
2072
+ }
2073
+ };
2074
+ var staggerCascade = {
2075
+ name: "Cascade",
2076
+ description: "Fast initial items, progressively slower later ones",
2077
+ useCase: ["Long lists", "Data tables", "Search results", "Infinite scroll content", "Progressive reveals"],
2078
+ getDelay(index, total, style) {
2079
+ const config = getMotionStyle(style);
2080
+ const normalizedIndex = index / Math.max(total - 1, 1);
2081
+ const cascadeFactor = Math.sqrt(normalizedIndex);
2082
+ const maxDuration = config.staggerDelay * total;
2083
+ return msToSeconds(cascadeFactor * maxDuration);
2084
+ },
2085
+ getContainerVariants(style) {
2086
+ const config = getMotionStyle(style);
2087
+ return {
2088
+ hidden: { opacity: 0 },
2089
+ visible: {
2090
+ opacity: 1,
2091
+ transition: {
2092
+ staggerChildren: msToSeconds(config.staggerDelay * 0.4),
2093
+ delayChildren: msToSeconds(config.duration.fast * 0.3)
2094
+ }
2095
+ }
2096
+ };
2097
+ },
2098
+ getItemVariants(style) {
2099
+ const config = getMotionStyle(style);
2100
+ return {
2101
+ hidden: {
2102
+ opacity: 0,
2103
+ x: -10
2104
+ },
2105
+ visible: {
2106
+ opacity: 1,
2107
+ x: 0,
2108
+ transition: {
2109
+ type: "spring",
2110
+ stiffness: config.spring.stiffness + 50,
2111
+ // Slightly snappier
2112
+ damping: config.spring.damping + 5,
2113
+ mass: config.spring.mass * 0.9
2114
+ }
2115
+ }
2116
+ };
2117
+ }
2118
+ };
2119
+ var staggerPresets = {
2120
+ sequential: staggerSequential,
2121
+ reverse: staggerReverse,
2122
+ center: staggerCenter,
2123
+ random: staggerRandom,
2124
+ grid: staggerGrid,
2125
+ wave: staggerWave,
2126
+ cascade: staggerCascade
2127
+ };
2128
+ function getStaggerPreset(name) {
2129
+ const preset = staggerPresets[name];
2130
+ if (!preset) {
2131
+ throw new Error(`Unknown stagger preset: ${name}. Available: ${Object.keys(staggerPresets).join(", ")}`);
2132
+ }
2133
+ return preset;
2134
+ }
2135
+ function calculateStaggerDelays(preset, total, style) {
2136
+ const staggerPreset = getStaggerPreset(preset);
2137
+ return Array.from({ length: total }, (_, index) => staggerPreset.getDelay(index, total, style));
2138
+ }
2139
+
2140
+ // src/utils/easing.ts
2141
+ var linear = [0, 0, 1, 1];
2142
+ var easeIn = [0.4, 0, 1, 1];
2143
+ var easeOut = [0, 0, 0.2, 1];
2144
+ var easeInOut = [0.4, 0, 0.2, 1];
2145
+ var easeOutQuart = [0.25, 1, 0.5, 1];
2146
+ var easeInOutCubic = [0.65, 0, 0.35, 1];
2147
+ var easeOutBack = [0.34, 1.56, 0.64, 1];
2148
+ var easeOutExpo = [0.16, 1, 0.3, 1];
2149
+ var easeInOutQuint = [0.83, 0, 0.17, 1];
2150
+ function createTween(duration, ease) {
2151
+ return {
2152
+ type: "tween",
2153
+ duration,
2154
+ ease: ease ?? easeOut
2155
+ };
2156
+ }
2157
+ function createTweenFromParams(params) {
2158
+ const result = {
2159
+ type: "tween",
2160
+ duration: params.duration
2161
+ };
2162
+ if (params.ease !== void 0) {
2163
+ return { ...result, ease: params.ease };
2164
+ }
2165
+ return result;
2166
+ }
2167
+ var durations = {
2168
+ /** Micro-interactions: hover states, small toggles (100ms) */
2169
+ instant: 0.1,
2170
+ /** Quick feedback: button clicks, checkboxes (200ms) */
2171
+ fast: 0.2,
2172
+ /** Standard transitions: most UI elements (300ms) */
2173
+ normal: 0.3,
2174
+ /** Emphasized transitions: modals, drawers (400ms) */
2175
+ slow: 0.4,
2176
+ /** Dramatic transitions: page changes, reveals (600ms) */
2177
+ slower: 0.6
2178
+ };
2179
+ var easingPresets = {
2180
+ linear,
2181
+ easeIn,
2182
+ easeOut,
2183
+ easeInOut,
2184
+ easeOutQuart,
2185
+ easeInOutCubic,
2186
+ easeOutBack,
2187
+ easeOutExpo,
2188
+ easeInOutQuint
2189
+ };
2190
+ var tweenPresets = {
2191
+ /** Quick fade for hover states and micro-interactions */
2192
+ instant: createTween(durations.instant, easeOut),
2193
+ /** Snappy transition for interactive elements */
2194
+ fast: createTween(durations.fast, easeOut),
2195
+ /** Balanced transition for most UI elements */
2196
+ normal: createTween(durations.normal, easeOutQuart),
2197
+ /** Smooth transition for modals and overlays */
2198
+ slow: createTween(durations.slow, easeOutQuart),
2199
+ /** Dramatic transition for page-level changes */
2200
+ slower: createTween(durations.slower, easeInOutCubic)
2201
+ };
2202
+
2203
+ // src/utils/reduced-motion.ts
2204
+ var import_react8 = require("react");
2205
+ var REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
2206
+ var INSTANT_TRANSITION = {
2207
+ duration: 0,
2208
+ delay: 0
2209
+ };
2210
+ function getReducedMotionVariant(normalVariant, reducedVariant, prefersReducedMotion2) {
2211
+ return prefersReducedMotion2 ? reducedVariant : normalVariant;
2212
+ }
2213
+ function filterVariantForReducedMotion(variant, options) {
2214
+ const { preserveOpacity = true, preserveColors = true } = options;
2215
+ const filtered = {};
2216
+ for (const [key, value] of Object.entries(variant)) {
2217
+ const isOpacityProperty = key === "opacity";
2218
+ const isColorProperty = key === "color" || key === "backgroundColor" || key === "borderColor" || key === "fill" || key === "stroke";
2219
+ if (preserveOpacity && isOpacityProperty || preserveColors && isColorProperty) {
2220
+ filtered[key] = value;
2221
+ }
2222
+ }
2223
+ return filtered;
2224
+ }
2225
+ function createReducedMotionProps(props, prefersReducedMotion2, options = {}) {
2226
+ if (!prefersReducedMotion2) {
2227
+ return props;
2228
+ }
2229
+ const { preserveOpacity = true, preserveColors = true, reducedTransition } = options;
2230
+ const transition = reducedTransition ?? INSTANT_TRANSITION;
2231
+ const processVariant = (variant) => {
2232
+ if (variant === void 0 || typeof variant === "string" || typeof variant === "boolean") {
2233
+ return variant;
2234
+ }
2235
+ return filterVariantForReducedMotion(variant, { preserveOpacity, preserveColors });
2236
+ };
2237
+ const processVariants = (variants) => {
2238
+ if (!variants) {
2239
+ return void 0;
2240
+ }
2241
+ const processed = {};
2242
+ for (const [key, variant] of Object.entries(variants)) {
2243
+ processed[key] = filterVariantForReducedMotion(variant, { preserveOpacity, preserveColors });
2244
+ }
2245
+ return processed;
2246
+ };
2247
+ const processNonBooleanVariant = (variant) => {
2248
+ if (variant === void 0 || typeof variant === "string") {
2249
+ return variant;
2250
+ }
2251
+ return filterVariantForReducedMotion(variant, { preserveOpacity, preserveColors });
2252
+ };
2253
+ return {
2254
+ ...props,
2255
+ initial: processVariant(props.initial),
2256
+ animate: processNonBooleanVariant(props.animate),
2257
+ exit: processNonBooleanVariant(props.exit),
2258
+ variants: processVariants(props.variants),
2259
+ transition,
2260
+ // Disable hover/tap/focus animations in reduced motion mode
2261
+ // as they often involve movement
2262
+ whileHover: void 0,
2263
+ whileTap: void 0,
2264
+ whileFocus: void 0,
2265
+ whileDrag: void 0,
2266
+ whileInView: processNonBooleanVariant(props.whileInView)
2267
+ };
2268
+ }
2269
+ function checkReducedMotion() {
2270
+ if (typeof window === "undefined") {
2271
+ return false;
2272
+ }
2273
+ return window.matchMedia(REDUCED_MOTION_QUERY).matches;
2274
+ }
2275
+
2276
+ // src/utils/select-preset.ts
2277
+ function calculateMatchScore(preset, criteria) {
2278
+ let score = 0;
2279
+ let factors = 0;
2280
+ if (criteria.useCase) {
2281
+ factors++;
2282
+ if (preset.metadata.useCase.includes(criteria.useCase)) {
2283
+ score += 1;
2284
+ }
2285
+ }
2286
+ if (criteria.context) {
2287
+ factors++;
2288
+ if (preset.metadata.context.includes(criteria.context)) {
2289
+ score += 1;
2290
+ }
2291
+ }
2292
+ if (criteria.maxIntensity !== void 0) {
2293
+ factors++;
2294
+ if (preset.metadata.intensity <= criteria.maxIntensity) {
2295
+ score += 1;
2296
+ }
2297
+ }
2298
+ if (criteria.minIntensity !== void 0) {
2299
+ factors++;
2300
+ if (preset.metadata.intensity >= criteria.minIntensity) {
2301
+ score += 1;
2302
+ }
2303
+ }
2304
+ if (criteria.preferMovement !== void 0) {
2305
+ factors++;
2306
+ if (preset.metadata.hasMovement === criteria.preferMovement) {
2307
+ score += 1;
2308
+ }
2309
+ }
2310
+ if (criteria.direction && preset.metadata.direction) {
2311
+ factors++;
2312
+ if (preset.metadata.direction === criteria.direction) {
2313
+ score += 1;
2314
+ }
2315
+ }
2316
+ if (criteria.prioritizeAccessibility) {
2317
+ factors++;
2318
+ score += (5 - preset.metadata.intensity) / 5;
2319
+ }
2320
+ return factors > 0 ? score / factors : 0;
2321
+ }
2322
+ function determineStyle(criteria) {
2323
+ if (criteria.style) {
2324
+ return criteria.style;
2325
+ }
2326
+ if (criteria.prioritizeAccessibility) {
2327
+ return "subtle";
2328
+ }
2329
+ if (criteria.context === "hero" || criteria.context === "page") {
2330
+ return "bold";
2331
+ }
2332
+ if (criteria.context === "tooltip" || criteria.context === "dropdown") {
2333
+ return "subtle";
2334
+ }
2335
+ return "standard";
2336
+ }
2337
+ function generateReasoning(preset, criteria, score) {
2338
+ const reasons = [];
2339
+ if (criteria.useCase && preset.metadata.useCase.includes(criteria.useCase)) {
2340
+ reasons.push(`matches use case "${criteria.useCase}"`);
2341
+ }
2342
+ if (criteria.context && preset.metadata.context.includes(criteria.context)) {
2343
+ reasons.push(`suitable for "${criteria.context}" context`);
2344
+ }
2345
+ if (criteria.direction && preset.metadata.direction === criteria.direction) {
2346
+ reasons.push(`provides "${criteria.direction}" movement`);
2347
+ }
2348
+ if (criteria.prioritizeAccessibility && preset.metadata.intensity <= 2) {
2349
+ reasons.push("has low intensity for accessibility");
2350
+ }
2351
+ if (reasons.length === 0) {
2352
+ reasons.push("general-purpose animation");
2353
+ }
2354
+ return `Selected "${preset.metadata.name}" (${Math.round(score * 100)}% match): ${reasons.join(", ")}.`;
2355
+ }
2356
+ function selectPreset(criteria) {
2357
+ const allPresets = Object.entries(componentPresets);
2358
+ const scoredPresets = allPresets.map(([name, preset]) => ({
2359
+ name,
2360
+ preset,
2361
+ score: calculateMatchScore(preset, criteria)
2362
+ }));
2363
+ scoredPresets.sort((a, b) => b.score - a.score);
2364
+ const best = scoredPresets[0];
2365
+ const style = determineStyle(criteria);
2366
+ if (!best) {
2367
+ throw new Error("selectPreset: no presets available; cannot select a preset.");
2368
+ }
2369
+ const alternatives = scoredPresets.slice(1, 4).filter((p) => p.score > 0.3).map((p) => p.name);
2370
+ return {
2371
+ preset: best.preset,
2372
+ presetName: best.name,
2373
+ style,
2374
+ confidence: best.score,
2375
+ reasoning: generateReasoning(best.preset, criteria, best.score),
2376
+ alternatives
2377
+ };
2378
+ }
2379
+ function getRecommendations(context, options = {}) {
2380
+ const { maxResults = 5, minScore = 0.3 } = options;
2381
+ const contextPresets = getPresetsByContext(context);
2382
+ const recommendations = contextPresets.map((preset) => {
2383
+ const name = Object.entries(componentPresets).find(([_, p]) => p === preset)?.[0];
2384
+ const contextFit = preset.metadata.context.indexOf(context) === 0 ? 1 : 0.7;
2385
+ const intensityFit = 1 - Math.abs(preset.metadata.intensity - 3) / 4;
2386
+ const score = (contextFit + intensityFit) / 2;
2387
+ return {
2388
+ preset,
2389
+ name,
2390
+ reason: `${preset.metadata.description}. Ideal for ${preset.metadata.context.slice(0, 2).join(", ")}.`,
2391
+ score
2392
+ };
2393
+ });
2394
+ return recommendations.filter((r) => r.score >= minScore).sort((a, b) => b.score - a.score).slice(0, maxResults);
2395
+ }
2396
+ function getDefaultPreset(context) {
2397
+ const defaults = {
2398
+ modal: "scale",
2399
+ dropdown: "slideDown",
2400
+ tooltip: "fadeIn",
2401
+ drawer: "slideRight",
2402
+ card: "fadeIn",
2403
+ "list-item": "slideUp",
2404
+ notification: "slideRight",
2405
+ page: "fadeIn",
2406
+ section: "slideUp",
2407
+ hero: "slideUpScale"
2408
+ };
2409
+ return componentPresets[defaults[context]];
2410
+ }
2411
+ function suggestAnimations(context, style = "standard") {
2412
+ const entranceResult = selectPreset({
2413
+ useCase: "entrance",
2414
+ context,
2415
+ style
2416
+ });
2417
+ const exitResult = selectPreset({
2418
+ useCase: "exit",
2419
+ context,
2420
+ style
2421
+ });
2422
+ return {
2423
+ entrance: entranceResult.preset,
2424
+ entranceName: entranceResult.presetName,
2425
+ exit: exitResult.preset,
2426
+ exitName: exitResult.presetName,
2427
+ style
2428
+ };
2429
+ }
2430
+ function getAllPresetNames() {
2431
+ return Object.keys(componentPresets);
2432
+ }
2433
+ function getAllContexts() {
2434
+ return ["modal", "dropdown", "tooltip", "drawer", "card", "list-item", "notification", "page", "section", "hero"];
2435
+ }
2436
+ function getAllUseCases() {
2437
+ return ["entrance", "exit", "transition", "emphasis", "reveal"];
2438
+ }
2439
+ function getPresetMetadata(name) {
2440
+ return componentPresets[name].metadata;
2441
+ }
2442
+
2443
+ // src/utils/spring-configs.ts
2444
+ var springGentle = {
2445
+ type: "spring",
2446
+ stiffness: 200,
2447
+ damping: 30,
2448
+ mass: 1
2449
+ };
2450
+ var springSnappy = {
2451
+ type: "spring",
2452
+ stiffness: 400,
2453
+ damping: 30,
2454
+ mass: 0.8
2455
+ };
2456
+ var springBouncy = {
2457
+ type: "spring",
2458
+ stiffness: 300,
2459
+ damping: 15,
2460
+ mass: 1
2461
+ };
2462
+ var springStiff = {
2463
+ type: "spring",
2464
+ stiffness: 500,
2465
+ damping: 35,
2466
+ mass: 0.6
2467
+ };
2468
+ function createSpring(stiffness, damping, mass) {
2469
+ return {
2470
+ type: "spring",
2471
+ stiffness,
2472
+ damping,
2473
+ mass
2474
+ };
2475
+ }
2476
+ function createSpringFromParams(params) {
2477
+ return {
2478
+ type: "spring",
2479
+ stiffness: params.stiffness,
2480
+ damping: params.damping,
2481
+ mass: params.mass
2482
+ };
2483
+ }
2484
+ var springPresets = {
2485
+ gentle: springGentle,
2486
+ snappy: springSnappy,
2487
+ bouncy: springBouncy,
2488
+ stiff: springStiff
2489
+ };
180
2490
  // Annotate the CommonJS export names for ESM import in node:
181
2491
  0 && (module.exports = {
2492
+ CountUp,
2493
+ INSTANT_TRANSITION,
2494
+ MotionDiv,
2495
+ REDUCED_MOTION_QUERY,
2496
+ StaggerContainer,
182
2497
  ambientPaths,
183
2498
  applyMotionPreset,
2499
+ badgePop,
2500
+ boldStyle,
2501
+ buttonPress,
2502
+ calculateStaggerDelays,
2503
+ cardHover,
2504
+ cascadeStagger,
2505
+ checkReducedMotion,
2506
+ checkmarkDraw,
2507
+ componentPresets,
2508
+ createAccessibleMotionProps,
2509
+ createMotionProps,
2510
+ createReducedMotionProps,
2511
+ createSpring,
2512
+ createSpringFromParams,
2513
+ createTween,
2514
+ createTweenFromParams,
2515
+ durations,
2516
+ easeIn,
2517
+ easeInOut,
2518
+ easeInOutCubic,
2519
+ easeInOutQuint,
2520
+ easeOut,
2521
+ easeOutBack,
2522
+ easeOutExpo,
2523
+ easeOutQuart,
2524
+ easingPresets,
2525
+ expand,
2526
+ explodeStagger,
2527
+ fadeIn,
2528
+ fadeOut,
2529
+ findPresetsForUseCase,
2530
+ flip,
2531
+ getAllContexts,
2532
+ getAllPresetNames,
2533
+ getAllUseCases,
2534
+ getComponentPreset,
2535
+ getDefaultPreset,
2536
+ getDuration,
2537
+ getMicroInteraction,
2538
+ getMicroInteractionNames,
2539
+ getMotionStyle,
184
2540
  getPreset,
2541
+ getPresetMetadata,
2542
+ getPresetsByContext,
2543
+ getPresetsByUseCase,
2544
+ getRecommendations,
2545
+ getReducedMotionVariant,
2546
+ getSpringConfig,
2547
+ getStaggerPreset,
2548
+ glowPulse,
2549
+ gridStagger,
2550
+ heartbeat,
2551
+ iconSpin,
185
2552
  lightRays,
186
- useMotionPreset
2553
+ linear,
2554
+ microInteractions,
2555
+ motionStyles,
2556
+ msToSeconds,
2557
+ playfulStyle,
2558
+ progressFill,
2559
+ pulse,
2560
+ rotate,
2561
+ rubberBand,
2562
+ scale,
2563
+ scaleMicro,
2564
+ selectPreset,
2565
+ shake,
2566
+ shimmer,
2567
+ slideDown,
2568
+ slideLeft,
2569
+ slideRight,
2570
+ slideUp,
2571
+ slideUpScale,
2572
+ springBouncy,
2573
+ springGentle,
2574
+ springPresets,
2575
+ springSnappy,
2576
+ springStiff,
2577
+ staggerCascade,
2578
+ staggerCenter,
2579
+ staggerGrid,
2580
+ staggerPresets,
2581
+ staggerRandom,
2582
+ staggerReverse,
2583
+ staggerSequential,
2584
+ staggerWave,
2585
+ standardStyle,
2586
+ subtleStyle,
2587
+ successFlash,
2588
+ suggestAnimations,
2589
+ tweenPresets,
2590
+ useAnimationVariants,
2591
+ useComponentAnimation,
2592
+ useCountUp,
2593
+ useDelayedAnimation,
2594
+ useDrawPath,
2595
+ useMotionPreset,
2596
+ useReducedMotion,
2597
+ useStagger,
2598
+ waveStagger,
2599
+ wiggle,
2600
+ withStagger,
2601
+ zoomIn,
2602
+ zoomOut
187
2603
  });
188
2604
  //# sourceMappingURL=index.js.map