@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
@@ -0,0 +1,162 @@
1
+ // Copyright (c) 2026 Amsterdam Data Labs
2
+ "use client";
3
+ import { jsx as _jsx } from "react/jsx-runtime";
4
+ /**
5
+ * MotionDiv Component
6
+ *
7
+ * A typed wrapper around motion.div that integrates with the preset system.
8
+ * Provides a convenient way to apply animation presets without manually
9
+ * spreading props.
10
+ *
11
+ * @packageDocumentation
12
+ */
13
+ import { motion } from "motion/react";
14
+ import { useComponentAnimation } from "../hooks/use-component-animation";
15
+ // =============================================================================
16
+ // MotionDiv Component
17
+ // =============================================================================
18
+ /**
19
+ * A motion.div wrapper that integrates with animation presets.
20
+ *
21
+ * This component simplifies the use of animation presets by handling
22
+ * the hook usage internally and providing a clean component API.
23
+ *
24
+ * Note: This component requires motion/react to be installed.
25
+ * It's a convenience wrapper that re-exports motion.div with preset support.
26
+ *
27
+ * @ai-hint Use MotionDiv when you want a simple way to animate a div
28
+ * with a preset. For more control, use useComponentAnimation directly.
29
+ *
30
+ * @example
31
+ * ```tsx
32
+ * import { MotionDiv, fadeIn } from "@enact-ui/animate";
33
+ *
34
+ * function AnimatedCard() {
35
+ * return (
36
+ * <MotionDiv preset={fadeIn} motionStyle="standard">
37
+ * <Card>Content</Card>
38
+ * </MotionDiv>
39
+ * );
40
+ * }
41
+ * ```
42
+ *
43
+ * @example
44
+ * ```tsx
45
+ * // With custom options
46
+ * <MotionDiv
47
+ * preset={slideUp}
48
+ * motionStyle="bold"
49
+ * presetOptions={{ distance: 40, delay: 100 }}
50
+ * className="my-class"
51
+ * >
52
+ * Content
53
+ * </MotionDiv>
54
+ * ```
55
+ *
56
+ * @example
57
+ * ```tsx
58
+ * // With AnimatePresence for exit animations
59
+ * import { AnimatePresence } from "motion/react";
60
+ *
61
+ * function Modal({ isOpen }) {
62
+ * return (
63
+ * <AnimatePresence>
64
+ * {isOpen && (
65
+ * <MotionDiv preset={scale} motionStyle="standard">
66
+ * Modal content
67
+ * </MotionDiv>
68
+ * )}
69
+ * </AnimatePresence>
70
+ * );
71
+ * }
72
+ * ```
73
+ *
74
+ * @example
75
+ * ```tsx
76
+ * // With separate exit animation
77
+ * <MotionDiv preset={slideUp} exit={fadeOut}>
78
+ * Content that slides up on enter, fades out on exit
79
+ * </MotionDiv>
80
+ * ```
81
+ *
82
+ * @example
83
+ * ```tsx
84
+ * // Polymorphic - render as semantic HTML element
85
+ * <MotionDiv preset={fadeIn} as="section" className="my-section">
86
+ * <h2>Section Title</h2>
87
+ * <p>Section content...</p>
88
+ * </MotionDiv>
89
+ * ```
90
+ */
91
+ export function MotionDiv({ preset, exit: exitPreset, as = "div", motionStyle = "standard", presetOptions, enabled = true, skipInitial = false, children, ...motionProps }) {
92
+ const animation = useComponentAnimation(preset, motionStyle, {
93
+ ...presetOptions,
94
+ enabled,
95
+ skipInitial,
96
+ });
97
+ // Get exit animation if a separate exit preset is provided
98
+ // Validate that exitPreset is actually a ComponentPreset with getProps method
99
+ const exitAnimation = exitPreset && typeof exitPreset === "object" && "getProps" in exitPreset && typeof exitPreset.getProps === "function"
100
+ ? exitPreset.getProps(motionStyle, presetOptions)
101
+ : null;
102
+ // Extract animation props without metadata
103
+ const { prefersReducedMotion, isEnabled, ...animationProps } = animation;
104
+ // Build exit props - use separate exit preset's initial state as exit animation
105
+ // (exit animations typically reverse the enter animation)
106
+ const exitValue = exitAnimation ? exitAnimation.initial : undefined;
107
+ // Get the motion component for the specified element
108
+ const MotionComponent = motion[as];
109
+ // Build props object, conditionally including exit.
110
+ // Cast to motion.div props so exit (ExitPropType) is accepted with exactOptionalPropertyTypes.
111
+ const finalProps = {
112
+ ...motionProps,
113
+ ...animationProps,
114
+ ...(exitValue !== undefined && { exit: exitValue }),
115
+ "data-reduced-motion": prefersReducedMotion,
116
+ "data-animation-enabled": isEnabled,
117
+ };
118
+ return _jsx(MotionComponent, { ...finalProps, children: children });
119
+ }
120
+ /**
121
+ * Factory function to create motion props from a preset.
122
+ *
123
+ * Use this when you need the animation props without a component wrapper.
124
+ * This is useful when you want to spread props onto your own motion element.
125
+ *
126
+ * @param preset - The animation preset
127
+ * @param style - Motion style
128
+ * @param options - Preset options
129
+ * @returns Props object to spread on motion.div
130
+ *
131
+ * @example
132
+ * ```tsx
133
+ * import { motion } from "motion/react";
134
+ * import { createMotionProps, fadeIn } from "@enact-ui/animate";
135
+ *
136
+ * function MyComponent() {
137
+ * const props = createMotionProps(fadeIn, "standard");
138
+ *
139
+ * return (
140
+ * <motion.div {...props}>
141
+ * Content
142
+ * </motion.div>
143
+ * );
144
+ * }
145
+ * ```
146
+ */
147
+ export function createMotionProps(preset, style = "standard", options) {
148
+ return preset.getProps(style, options);
149
+ }
150
+ /**
151
+ * Alias for createMotionProps. Use createMotionProps directly.
152
+ *
153
+ * @param preset - The animation preset
154
+ * @param style - Motion style
155
+ * @param options - Preset options
156
+ * @returns Props object to spread on motion.div
157
+ */
158
+ export function createAccessibleMotionProps(preset, style = "standard", options) {
159
+ return preset.getProps(style, options);
160
+ }
161
+ export default MotionDiv;
162
+ //# sourceMappingURL=MotionDiv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MotionDiv.js","sourceRoot":"","sources":["../../src/components/MotionDiv.tsx"],"names":[],"mappings":"AAAA,yCAAyC;AAEzC,YAAY,CAAC;;AAEb;;;;;;;;GAQG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AAkDzE,gFAAgF;AAChF,sBAAsB;AACtB,gFAAgF;AAEhF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwEG;AACH,MAAM,UAAU,SAAS,CAAC,EACtB,MAAM,EACN,IAAI,EAAE,UAAU,EAChB,EAAE,GAAG,KAAK,EACV,WAAW,GAAG,UAAU,EACxB,aAAa,EACb,OAAO,GAAG,IAAI,EACd,WAAW,GAAG,KAAK,EACnB,QAAQ,EACR,GAAG,WAAW,EACD;IACb,MAAM,SAAS,GAAG,qBAAqB,CAAC,MAAM,EAAE,WAAW,EAAE;QACzD,GAAG,aAAa;QAChB,OAAO;QACP,WAAW;KACd,CAAC,CAAC;IAEH,2DAA2D;IAC3D,8EAA8E;IAC9E,MAAM,aAAa,GACf,UAAU,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,IAAI,UAAU,IAAI,OAAO,UAAU,CAAC,QAAQ,KAAK,UAAU;QACjH,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC;QACjD,CAAC,CAAC,IAAI,CAAC;IAEf,2CAA2C;IAC3C,MAAM,EAAE,oBAAoB,EAAE,SAAS,EAAE,GAAG,cAAc,EAAE,GAAG,SAAS,CAAC;IAEzE,gFAAgF;IAChF,0DAA0D;IAC1D,MAAM,SAAS,GAA6B,aAAa,CAAC,CAAC,CAAE,aAAa,CAAC,OAAwB,CAAC,CAAC,CAAC,SAAS,CAAC;IAEhH,qDAAqD;IACrD,MAAM,eAAe,GAAG,MAAM,CAAC,EAAE,CAAsB,CAAC;IAExD,oDAAoD;IACpD,+FAA+F;IAC/F,MAAM,UAAU,GAAG;QACf,GAAG,WAAW;QACd,GAAI,cAAmD;QACvD,GAAG,CAAC,SAAS,KAAK,SAAS,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QACnD,qBAAqB,EAAE,oBAAoB;QAC3C,wBAAwB,EAAE,SAAS;KACS,CAAC;IAEjD,OAAO,KAAC,eAAe,OAAK,UAAU,YAAG,QAAQ,GAAmB,CAAC;AACzE,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAuB,EAAE,QAAqB,UAAU,EAAE,OAAuB;IAC/G,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;AAC3C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,2BAA2B,CAAC,MAAuB,EAAE,QAAqB,UAAU,EAAE,OAAuB;IACzH,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;AAC3C,CAAC;AAED,eAAe,SAAS,CAAC"}
@@ -0,0 +1,136 @@
1
+ /**
2
+ * StaggerContainer Component
3
+ *
4
+ * A container component that orchestrates staggered animations for its children.
5
+ * Works with Motion library to provide smooth, coordinated entrance animations.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+ import { type ReactElement, type ReactNode } from "react";
10
+ import { type StaggerDirection, type StaggerOptions } from "../hooks/use-stagger";
11
+ import type { MotionStyle } from "../presets/motion-styles";
12
+ /**
13
+ * Props for the StaggerContainer component.
14
+ */
15
+ export interface StaggerContainerProps {
16
+ /** The child elements to animate */
17
+ children: ReactNode;
18
+ /** Motion style to apply */
19
+ style?: MotionStyle;
20
+ /** Stagger direction pattern */
21
+ direction?: StaggerDirection;
22
+ /** Custom delay between items in ms */
23
+ delay?: number;
24
+ /** Maximum total delay in ms */
25
+ maxDelay?: number;
26
+ /** Use spring physics for item animations */
27
+ useSpring?: boolean;
28
+ /** Custom delay function */
29
+ getDelay?: (index: number, total: number) => number;
30
+ /** Additional class name for the container */
31
+ className?: string;
32
+ /** HTML element to render as (default: div) */
33
+ as?: "div" | "ul" | "ol" | "section" | "article" | "nav";
34
+ /** Whether to animate (useful for conditional rendering) */
35
+ animate?: boolean;
36
+ /** Callback when all animations complete */
37
+ onAnimationComplete?: () => void;
38
+ }
39
+ /**
40
+ * Container component that orchestrates staggered animations.
41
+ *
42
+ * Wraps children in a motion container that coordinates their entrance
43
+ * animations using the Motion library's variants system.
44
+ *
45
+ * @ai-hint Use StaggerContainer when you have a list or grid of items
46
+ * that should animate in sequence. Works with any motion.* children.
47
+ *
48
+ * @example
49
+ * ```tsx
50
+ * import { motion } from "motion/react";
51
+ * import { StaggerContainer } from "@enact-ui/animate";
52
+ *
53
+ * function AnimatedCards({ cards }) {
54
+ * return (
55
+ * <StaggerContainer style="standard" direction="forward">
56
+ * {cards.map((card) => (
57
+ * <motion.div key={card.id}>
58
+ * <Card {...card} />
59
+ * </motion.div>
60
+ * ))}
61
+ * </StaggerContainer>
62
+ * );
63
+ * }
64
+ * ```
65
+ *
66
+ * @example
67
+ * ```tsx
68
+ * // Center-out animation pattern
69
+ * <StaggerContainer
70
+ * style="bold"
71
+ * direction="center"
72
+ * delay={80}
73
+ * >
74
+ * {items.map((item) => (
75
+ * <motion.li key={item.id}>{item.name}</motion.li>
76
+ * ))}
77
+ * </StaggerContainer>
78
+ * ```
79
+ *
80
+ * @example
81
+ * ```tsx
82
+ * // As a navigation menu
83
+ * <StaggerContainer
84
+ * as="nav"
85
+ * style="subtle"
86
+ * direction="forward"
87
+ * delay={30}
88
+ * >
89
+ * {menuItems.map((item) => (
90
+ * <motion.a key={item.href} href={item.href}>
91
+ * {item.label}
92
+ * </motion.a>
93
+ * ))}
94
+ * </StaggerContainer>
95
+ * ```
96
+ */
97
+ export declare function StaggerContainer({ children, style, direction, delay, maxDelay, useSpring, getDelay, className, as: Element, animate, }: StaggerContainerProps): ReactElement;
98
+ /**
99
+ * Props for items in a stagger list.
100
+ */
101
+ export interface StaggerListItemProps {
102
+ /** Index of the item in the list */
103
+ index: number;
104
+ /** Style configuration */
105
+ style: MotionStyle;
106
+ /** Stagger options */
107
+ options: StaggerOptions;
108
+ }
109
+ /**
110
+ * Higher-order component for creating custom stagger containers.
111
+ *
112
+ * @param WrappedComponent - The list container component
113
+ * @returns A stagger-enabled version of the component
114
+ *
115
+ * @example
116
+ * ```tsx
117
+ * const StaggeredGrid = withStagger(Grid);
118
+ *
119
+ * function MyGrid({ items }) {
120
+ * return (
121
+ * <StaggeredGrid style="playful" direction="center">
122
+ * {items.map((item, index) => (
123
+ * <GridItem key={item.id} index={index}>
124
+ * {item.content}
125
+ * </GridItem>
126
+ * ))}
127
+ * </StaggeredGrid>
128
+ * );
129
+ * }
130
+ * ```
131
+ */
132
+ export declare function withStagger<P extends {
133
+ children?: ReactNode;
134
+ }>(WrappedComponent: React.ComponentType<P>): React.FC<P & Pick<StaggerContainerProps, "style" | "direction" | "delay" | "maxDelay" | "useSpring" | "getDelay">>;
135
+ export default StaggerContainer;
136
+ //# sourceMappingURL=StaggerContainer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StaggerContainer.d.ts","sourceRoot":"","sources":["../../src/components/StaggerContainer.tsx"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AAEH,OAAO,EAA0C,KAAK,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAClG,OAAO,EAAqB,KAAK,gBAAgB,EAAE,KAAK,cAAc,EAAc,MAAM,sBAAsB,CAAC;AACjH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAM5D;;GAEG;AACH,MAAM,WAAW,qBAAqB;IAClC,oCAAoC;IACpC,QAAQ,EAAE,SAAS,CAAC;IACpB,4BAA4B;IAC5B,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,gCAAgC;IAChC,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,uCAAuC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6CAA6C;IAC7C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACpD,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,EAAE,CAAC,EAAE,KAAK,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,GAAG,SAAS,GAAG,KAAK,CAAC;IACzD,4DAA4D;IAC5D,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,4CAA4C;IAC5C,mBAAmB,CAAC,EAAE,MAAM,IAAI,CAAC;CACpC;AA8CD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AACH,wBAAgB,gBAAgB,CAAC,EAC7B,QAAQ,EACR,KAAkB,EAClB,SAAqB,EACrB,KAAK,EACL,QAAe,EACf,SAAgB,EAChB,QAAQ,EACR,SAAS,EACT,EAAE,EAAE,OAAe,EACnB,OAAc,GACjB,EAAE,qBAAqB,GAAG,YAAY,CAwCtC;AAMD;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACjC,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,0BAA0B;IAC1B,KAAK,EAAE,WAAW,CAAC;IACnB,sBAAsB;IACtB,OAAO,EAAE,cAAc,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS;IAAE,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,EAC1D,gBAAgB,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,GACzC,KAAK,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,qBAAqB,EAAE,OAAO,GAAG,WAAW,GAAG,OAAO,GAAG,UAAU,GAAG,WAAW,GAAG,UAAU,CAAC,CAAC,CAwBpH;AAED,eAAe,gBAAgB,CAAC"}
@@ -0,0 +1,166 @@
1
+ // Copyright (c) 2026 Amsterdam Data Labs
2
+ "use client";
3
+ import { jsx as _jsx } from "react/jsx-runtime";
4
+ /**
5
+ * StaggerContainer Component
6
+ *
7
+ * A container component that orchestrates staggered animations for its children.
8
+ * Works with Motion library to provide smooth, coordinated entrance animations.
9
+ *
10
+ * @packageDocumentation
11
+ */
12
+ import { Children, cloneElement, isValidElement } from "react";
13
+ import { useStagger } from "../hooks/use-stagger";
14
+ // =============================================================================
15
+ // StaggerItem Component
16
+ // =============================================================================
17
+ /**
18
+ * Internal component that wraps each child with animation props.
19
+ * This is used to inject the stagger animation without requiring
20
+ * motion.* wrapper elements in the child components.
21
+ */
22
+ function StaggerItem({ children, index, variants }) {
23
+ // Clone the child element and add motion props
24
+ // The child must be a motion.* element for this to work
25
+ if (!isValidElement(children)) {
26
+ return children;
27
+ }
28
+ // Cast to any because motion props aren't in standard React element types
29
+ const motionProps = {
30
+ variants,
31
+ custom: index,
32
+ initial: "hidden",
33
+ animate: "visible",
34
+ exit: "hidden",
35
+ };
36
+ return cloneElement(children, motionProps);
37
+ }
38
+ // =============================================================================
39
+ // StaggerContainer Component
40
+ // =============================================================================
41
+ /**
42
+ * Container component that orchestrates staggered animations.
43
+ *
44
+ * Wraps children in a motion container that coordinates their entrance
45
+ * animations using the Motion library's variants system.
46
+ *
47
+ * @ai-hint Use StaggerContainer when you have a list or grid of items
48
+ * that should animate in sequence. Works with any motion.* children.
49
+ *
50
+ * @example
51
+ * ```tsx
52
+ * import { motion } from "motion/react";
53
+ * import { StaggerContainer } from "@enact-ui/animate";
54
+ *
55
+ * function AnimatedCards({ cards }) {
56
+ * return (
57
+ * <StaggerContainer style="standard" direction="forward">
58
+ * {cards.map((card) => (
59
+ * <motion.div key={card.id}>
60
+ * <Card {...card} />
61
+ * </motion.div>
62
+ * ))}
63
+ * </StaggerContainer>
64
+ * );
65
+ * }
66
+ * ```
67
+ *
68
+ * @example
69
+ * ```tsx
70
+ * // Center-out animation pattern
71
+ * <StaggerContainer
72
+ * style="bold"
73
+ * direction="center"
74
+ * delay={80}
75
+ * >
76
+ * {items.map((item) => (
77
+ * <motion.li key={item.id}>{item.name}</motion.li>
78
+ * ))}
79
+ * </StaggerContainer>
80
+ * ```
81
+ *
82
+ * @example
83
+ * ```tsx
84
+ * // As a navigation menu
85
+ * <StaggerContainer
86
+ * as="nav"
87
+ * style="subtle"
88
+ * direction="forward"
89
+ * delay={30}
90
+ * >
91
+ * {menuItems.map((item) => (
92
+ * <motion.a key={item.href} href={item.href}>
93
+ * {item.label}
94
+ * </motion.a>
95
+ * ))}
96
+ * </StaggerContainer>
97
+ * ```
98
+ */
99
+ export function StaggerContainer({ children, style = "standard", direction = "forward", delay, maxDelay = 1000, useSpring = true, getDelay, className, as: Element = "div", animate = true, }) {
100
+ // Count children for stagger calculations
101
+ const childArray = Children.toArray(children);
102
+ const totalItems = childArray.length;
103
+ // Configure stagger options - filter out undefined values
104
+ const staggerOptions = {
105
+ direction,
106
+ totalItems,
107
+ ...(delay !== undefined && { delayMultiplier: delay }),
108
+ maxDelay,
109
+ useSpring,
110
+ ...(getDelay !== undefined && { getDelay }),
111
+ };
112
+ // Get stagger configuration
113
+ const { itemVariants } = useStagger(style, staggerOptions);
114
+ // If animation is disabled, render without motion
115
+ if (!animate) {
116
+ return _jsx(Element, { className: className, children: children });
117
+ }
118
+ // We need to import motion dynamically or expect it to be used with motion elements
119
+ // For now, we'll render a regular element and expect children to be motion elements
120
+ return (_jsx(Element, { className: className, children: childArray.map((child, index) => {
121
+ if (!isValidElement(child)) {
122
+ return child;
123
+ }
124
+ return (_jsx(StaggerItem, { index: index, variants: itemVariants, children: child }, child.key ?? index));
125
+ }) }));
126
+ }
127
+ /**
128
+ * Higher-order component for creating custom stagger containers.
129
+ *
130
+ * @param WrappedComponent - The list container component
131
+ * @returns A stagger-enabled version of the component
132
+ *
133
+ * @example
134
+ * ```tsx
135
+ * const StaggeredGrid = withStagger(Grid);
136
+ *
137
+ * function MyGrid({ items }) {
138
+ * return (
139
+ * <StaggeredGrid style="playful" direction="center">
140
+ * {items.map((item, index) => (
141
+ * <GridItem key={item.id} index={index}>
142
+ * {item.content}
143
+ * </GridItem>
144
+ * ))}
145
+ * </StaggeredGrid>
146
+ * );
147
+ * }
148
+ * ```
149
+ */
150
+ export function withStagger(WrappedComponent) {
151
+ return function StaggerWrapper({ style = "standard", direction = "forward", delay, maxDelay, useSpring, getDelay, children, ...props }) {
152
+ // Build props object with only defined values
153
+ const staggerProps = {
154
+ children: _jsx(WrappedComponent, { ...props, children: children }),
155
+ style,
156
+ direction,
157
+ ...(delay !== undefined && { delay }),
158
+ ...(maxDelay !== undefined && { maxDelay }),
159
+ ...(useSpring !== undefined && { useSpring }),
160
+ ...(getDelay !== undefined && { getDelay }),
161
+ };
162
+ return _jsx(StaggerContainer, { ...staggerProps });
163
+ };
164
+ }
165
+ export default StaggerContainer;
166
+ //# sourceMappingURL=StaggerContainer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StaggerContainer.js","sourceRoot":"","sources":["../../src/components/StaggerContainer.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,156 @@
1
+ import type { ComponentAnimationProps, ComponentPreset, PresetOptions } from "../presets/component-presets";
2
+ import type { MotionStyle } from "../presets/motion-styles";
3
+ /**
4
+ * Options for the useComponentAnimation hook.
5
+ */
6
+ export interface UseComponentAnimationOptions extends PresetOptions {
7
+ /** Whether the animation is enabled. Defaults to true. */
8
+ enabled?: boolean;
9
+ /** Whether to skip the initial animation. Useful for SSR. */
10
+ skipInitial?: boolean;
11
+ }
12
+ /**
13
+ * Return type for the useComponentAnimation hook.
14
+ */
15
+ export interface ComponentAnimationResult extends ComponentAnimationProps {
16
+ /** Whether reduced motion is preferred by the user */
17
+ prefersReducedMotion: boolean;
18
+ /** Whether the animation is enabled */
19
+ isEnabled: boolean;
20
+ }
21
+ /**
22
+ * Hook to detect if user prefers reduced motion.
23
+ * Updates reactively when the preference changes.
24
+ */
25
+ declare function useReducedMotion(): boolean;
26
+ /**
27
+ * Hook for applying component animation presets.
28
+ *
29
+ * Provides Motion library compatible animation props that:
30
+ * - Apply the selected motion style (subtle, standard, bold, playful)
31
+ * - Support customization via options
32
+ *
33
+ * @param preset - The component animation preset to use
34
+ * @param style - The motion style to apply (defaults to "standard")
35
+ * @param options - Additional customization options
36
+ * @returns Animation props for Motion library components
37
+ *
38
+ * @example
39
+ * ```tsx
40
+ * import { motion } from "motion/react";
41
+ * import { useComponentAnimation, fadeIn } from "@enact-ui/animate";
42
+ *
43
+ * function MyComponent() {
44
+ * const animation = useComponentAnimation(fadeIn, "standard");
45
+ *
46
+ * return (
47
+ * <motion.div {...animation}>
48
+ * Content
49
+ * </motion.div>
50
+ * );
51
+ * }
52
+ * ```
53
+ *
54
+ * @example
55
+ * ```tsx
56
+ * // With AnimatePresence for exit animations
57
+ * import { AnimatePresence, motion } from "motion/react";
58
+ * import { useComponentAnimation, slideUp } from "@enact-ui/animate";
59
+ *
60
+ * function Modal({ isOpen, children }) {
61
+ * const animation = useComponentAnimation(slideUp, "bold");
62
+ *
63
+ * return (
64
+ * <AnimatePresence>
65
+ * {isOpen && (
66
+ * <motion.div {...animation}>
67
+ * {children}
68
+ * </motion.div>
69
+ * )}
70
+ * </AnimatePresence>
71
+ * );
72
+ * }
73
+ * ```
74
+ *
75
+ * @example
76
+ * ```tsx
77
+ * // With custom options
78
+ * const animation = useComponentAnimation(slideUp, "playful", {
79
+ * distance: 40,
80
+ * delay: 100,
81
+ * useSpring: true,
82
+ * });
83
+ * ```
84
+ */
85
+ export declare function useComponentAnimation(preset: ComponentPreset, style?: MotionStyle, options?: UseComponentAnimationOptions): ComponentAnimationResult;
86
+ /**
87
+ * Hook for applying animation props with a delay.
88
+ *
89
+ * Useful for staggering animations without using variants.
90
+ *
91
+ * @param preset - The component animation preset to use
92
+ * @param style - The motion style to apply
93
+ * @param index - The index of this item (for calculating delay)
94
+ * @param options - Additional customization options
95
+ * @returns Animation props with calculated delay
96
+ *
97
+ * @example
98
+ * ```tsx
99
+ * function ListItem({ index, children }) {
100
+ * const animation = useDelayedAnimation(fadeIn, "standard", index, {
101
+ * delayMultiplier: 50, // 50ms between each item
102
+ * });
103
+ *
104
+ * return (
105
+ * <motion.li {...animation}>
106
+ * {children}
107
+ * </motion.li>
108
+ * );
109
+ * }
110
+ * ```
111
+ */
112
+ export declare function useDelayedAnimation(preset: ComponentPreset, style: MotionStyle | undefined, index: number, options?: UseComponentAnimationOptions & {
113
+ /** Delay multiplier per item in ms. Defaults to 50. */
114
+ delayMultiplier?: number;
115
+ /** Maximum delay in ms. Defaults to 500. */
116
+ maxDelay?: number;
117
+ }): ComponentAnimationResult;
118
+ /**
119
+ * Hook that returns animation props as a function for use with variants.
120
+ *
121
+ * Useful when you need to pass animation config to Motion's variants system.
122
+ *
123
+ * @param preset - The component animation preset to use
124
+ * @param style - The motion style to apply
125
+ * @param options - Additional customization options
126
+ * @returns Object containing variants and transition
127
+ *
128
+ * @example
129
+ * ```tsx
130
+ * function Container({ children }) {
131
+ * const { variants, transition } = useAnimationVariants(fadeIn, "standard");
132
+ *
133
+ * return (
134
+ * <motion.div
135
+ * initial="initial"
136
+ * animate="animate"
137
+ * exit="exit"
138
+ * variants={variants}
139
+ * transition={transition}
140
+ * >
141
+ * {children}
142
+ * </motion.div>
143
+ * );
144
+ * }
145
+ * ```
146
+ */
147
+ export declare function useAnimationVariants(preset: ComponentPreset, style?: MotionStyle, options?: UseComponentAnimationOptions): {
148
+ variants: {
149
+ initial: Record<string, unknown>;
150
+ animate: Record<string, unknown>;
151
+ exit: Record<string, unknown>;
152
+ };
153
+ transition: Record<string, unknown>;
154
+ };
155
+ export { useReducedMotion };
156
+ //# sourceMappingURL=use-component-animation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-component-animation.d.ts","sourceRoot":"","sources":["../../src/hooks/use-component-animation.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,uBAAuB,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC5G,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAM5D;;GAEG;AACH,MAAM,WAAW,4BAA6B,SAAQ,aAAa;IAC/D,0DAA0D;IAC1D,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,6DAA6D;IAC7D,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,wBAAyB,SAAQ,uBAAuB;IACrE,sDAAsD;IACtD,oBAAoB,EAAE,OAAO,CAAC;IAC9B,uCAAuC;IACvC,SAAS,EAAE,OAAO,CAAC;CACtB;AAMD;;;GAGG;AACH,iBAAS,gBAAgB,IAAI,OAAO,CAmBnC;AAsBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,wBAAgB,qBAAqB,CACjC,MAAM,EAAE,eAAe,EACvB,KAAK,GAAE,WAAwB,EAC/B,OAAO,GAAE,4BAAiC,GAC3C,wBAAwB,CA8B1B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,mBAAmB,CAC/B,MAAM,EAAE,eAAe,EACvB,KAAK,EAAE,WAAW,YAAa,EAC/B,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,4BAA4B,GAAG;IACpC,uDAAuD;IACvD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;CAChB,GACP,wBAAwB,CAS1B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,oBAAoB,CAChC,MAAM,EAAE,eAAe,EACvB,KAAK,GAAE,WAAwB,EAC/B,OAAO,GAAE,4BAAiC,GAC3C;IACC,QAAQ,EAAE;QACN,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACjC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACjC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACjC,CAAC;IACF,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC,CA8BA;AAMD,OAAO,EAAE,gBAAgB,EAAE,CAAC"}