@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.
- package/api-schema.json +206 -0
- package/dist/components/CountUp.d.ts +84 -0
- package/dist/components/CountUp.d.ts.map +1 -0
- package/dist/components/CountUp.js +68 -0
- package/dist/components/CountUp.js.map +1 -0
- package/dist/components/MotionDiv.d.ts +159 -0
- package/dist/components/MotionDiv.d.ts.map +1 -0
- package/dist/components/MotionDiv.js +162 -0
- package/dist/components/MotionDiv.js.map +1 -0
- package/dist/components/StaggerContainer.d.ts +136 -0
- package/dist/components/StaggerContainer.d.ts.map +1 -0
- package/dist/components/StaggerContainer.js +166 -0
- package/dist/components/StaggerContainer.js.map +1 -0
- package/dist/hooks/use-component-animation.d.ts +156 -0
- package/dist/hooks/use-component-animation.d.ts.map +1 -0
- package/dist/hooks/use-component-animation.js +231 -0
- package/dist/hooks/use-component-animation.js.map +1 -0
- package/dist/hooks/use-count-up.d.ts +111 -0
- package/dist/hooks/use-count-up.d.ts.map +1 -0
- package/dist/hooks/use-count-up.js +246 -0
- package/dist/hooks/use-count-up.js.map +1 -0
- package/dist/hooks/use-draw-path.d.ts +96 -0
- package/dist/hooks/use-draw-path.d.ts.map +1 -0
- package/dist/hooks/use-draw-path.js +227 -0
- package/dist/hooks/use-draw-path.js.map +1 -0
- package/dist/hooks/use-motion-preset.d.ts.map +1 -1
- package/dist/hooks/use-motion-preset.js +17 -16
- package/dist/hooks/use-motion-preset.js.map +1 -1
- package/dist/hooks/use-stagger.d.ts +174 -0
- package/dist/hooks/use-stagger.d.ts.map +1 -0
- package/dist/hooks/use-stagger.js +256 -0
- package/dist/hooks/use-stagger.js.map +1 -0
- package/dist/index.d.ts +17 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2442 -26
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2335 -25
- package/dist/index.mjs.map +1 -1
- package/dist/presets/component-presets.d.ts +246 -0
- package/dist/presets/component-presets.d.ts.map +1 -0
- package/dist/presets/component-presets.js +472 -0
- package/dist/presets/component-presets.js.map +1 -0
- package/dist/presets/micro-interactions.d.ts +451 -0
- package/dist/presets/micro-interactions.d.ts.map +1 -0
- package/dist/presets/micro-interactions.js +856 -0
- package/dist/presets/micro-interactions.js.map +1 -0
- package/dist/presets/motion-presets.d.ts.map +1 -1
- package/dist/presets/motion-presets.js +0 -1
- package/dist/presets/motion-presets.js.map +1 -1
- package/dist/presets/motion-styles.d.ts +186 -0
- package/dist/presets/motion-styles.d.ts.map +1 -0
- package/dist/presets/motion-styles.js +204 -0
- package/dist/presets/motion-styles.js.map +1 -0
- package/dist/presets/stagger-presets.d.ts +378 -0
- package/dist/presets/stagger-presets.d.ts.map +1 -0
- package/dist/presets/stagger-presets.js +582 -0
- package/dist/presets/stagger-presets.js.map +1 -0
- package/dist/showcase/motion-presets.demo.d.ts +25 -0
- package/dist/showcase/motion-presets.demo.d.ts.map +1 -0
- package/dist/showcase/motion-presets.demo.js +96 -0
- package/dist/showcase/motion-presets.demo.js.map +1 -0
- package/dist/showcase/motion-presets.story.d.ts +37 -0
- package/dist/showcase/motion-presets.story.d.ts.map +1 -0
- package/dist/showcase/motion-presets.story.js +151 -0
- package/dist/showcase/motion-presets.story.js.map +1 -0
- package/dist/utils/easing.d.ts +294 -0
- package/dist/utils/easing.d.ts.map +1 -0
- package/dist/utils/easing.js +265 -0
- package/dist/utils/easing.js.map +1 -0
- package/dist/utils/reduced-motion.d.ts +322 -0
- package/dist/utils/reduced-motion.d.ts.map +1 -0
- package/dist/utils/reduced-motion.js +362 -0
- package/dist/utils/reduced-motion.js.map +1 -0
- package/dist/utils/select-preset.d.ts +186 -0
- package/dist/utils/select-preset.d.ts.map +1 -0
- package/dist/utils/select-preset.js +320 -0
- package/dist/utils/select-preset.js.map +1 -0
- package/dist/utils/spring-configs.d.ts +187 -0
- package/dist/utils/spring-configs.d.ts.map +1 -0
- package/dist/utils/spring-configs.js +169 -0
- package/dist/utils/spring-configs.js.map +1 -0
- package/package.json +4 -3
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
// Copyright (c) 2026 Amsterdam Data Labs
|
|
2
|
+
"use client";
|
|
3
|
+
/**
|
|
4
|
+
* useComponentAnimation Hook
|
|
5
|
+
*
|
|
6
|
+
* Hook for applying component animation presets with motion style support.
|
|
7
|
+
* Provides a clean API for animating components with Motion library.
|
|
8
|
+
*
|
|
9
|
+
* @packageDocumentation
|
|
10
|
+
*/
|
|
11
|
+
import { useEffect, useMemo, useState } from "react";
|
|
12
|
+
// =============================================================================
|
|
13
|
+
// Reduced Motion Detection
|
|
14
|
+
// =============================================================================
|
|
15
|
+
/**
|
|
16
|
+
* Hook to detect if user prefers reduced motion.
|
|
17
|
+
* Updates reactively when the preference changes.
|
|
18
|
+
*/
|
|
19
|
+
function useReducedMotion() {
|
|
20
|
+
const [prefersReducedMotion, setPrefersReducedMotion] = useState(() => {
|
|
21
|
+
if (typeof window === "undefined")
|
|
22
|
+
return false;
|
|
23
|
+
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
24
|
+
});
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
27
|
+
setPrefersReducedMotion(mediaQuery.matches);
|
|
28
|
+
const handler = (e) => {
|
|
29
|
+
setPrefersReducedMotion(e.matches);
|
|
30
|
+
};
|
|
31
|
+
mediaQuery.addEventListener("change", handler);
|
|
32
|
+
return () => mediaQuery.removeEventListener("change", handler);
|
|
33
|
+
}, []);
|
|
34
|
+
return prefersReducedMotion;
|
|
35
|
+
}
|
|
36
|
+
// =============================================================================
|
|
37
|
+
// Reduced Motion Variants
|
|
38
|
+
// =============================================================================
|
|
39
|
+
/**
|
|
40
|
+
* Creates disabled animation props (no animation).
|
|
41
|
+
*/
|
|
42
|
+
function createDisabledProps(skipInitial) {
|
|
43
|
+
return {
|
|
44
|
+
initial: skipInitial ? false : { opacity: 1 },
|
|
45
|
+
animate: { opacity: 1 },
|
|
46
|
+
exit: { opacity: 1 },
|
|
47
|
+
transition: { type: "tween", duration: 0 },
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
// =============================================================================
|
|
51
|
+
// Main Hook
|
|
52
|
+
// =============================================================================
|
|
53
|
+
/**
|
|
54
|
+
* Hook for applying component animation presets.
|
|
55
|
+
*
|
|
56
|
+
* Provides Motion library compatible animation props that:
|
|
57
|
+
* - Apply the selected motion style (subtle, standard, bold, playful)
|
|
58
|
+
* - Support customization via options
|
|
59
|
+
*
|
|
60
|
+
* @param preset - The component animation preset to use
|
|
61
|
+
* @param style - The motion style to apply (defaults to "standard")
|
|
62
|
+
* @param options - Additional customization options
|
|
63
|
+
* @returns Animation props for Motion library components
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```tsx
|
|
67
|
+
* import { motion } from "motion/react";
|
|
68
|
+
* import { useComponentAnimation, fadeIn } from "@enact-ui/animate";
|
|
69
|
+
*
|
|
70
|
+
* function MyComponent() {
|
|
71
|
+
* const animation = useComponentAnimation(fadeIn, "standard");
|
|
72
|
+
*
|
|
73
|
+
* return (
|
|
74
|
+
* <motion.div {...animation}>
|
|
75
|
+
* Content
|
|
76
|
+
* </motion.div>
|
|
77
|
+
* );
|
|
78
|
+
* }
|
|
79
|
+
* ```
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```tsx
|
|
83
|
+
* // With AnimatePresence for exit animations
|
|
84
|
+
* import { AnimatePresence, motion } from "motion/react";
|
|
85
|
+
* import { useComponentAnimation, slideUp } from "@enact-ui/animate";
|
|
86
|
+
*
|
|
87
|
+
* function Modal({ isOpen, children }) {
|
|
88
|
+
* const animation = useComponentAnimation(slideUp, "bold");
|
|
89
|
+
*
|
|
90
|
+
* return (
|
|
91
|
+
* <AnimatePresence>
|
|
92
|
+
* {isOpen && (
|
|
93
|
+
* <motion.div {...animation}>
|
|
94
|
+
* {children}
|
|
95
|
+
* </motion.div>
|
|
96
|
+
* )}
|
|
97
|
+
* </AnimatePresence>
|
|
98
|
+
* );
|
|
99
|
+
* }
|
|
100
|
+
* ```
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```tsx
|
|
104
|
+
* // With custom options
|
|
105
|
+
* const animation = useComponentAnimation(slideUp, "playful", {
|
|
106
|
+
* distance: 40,
|
|
107
|
+
* delay: 100,
|
|
108
|
+
* useSpring: true,
|
|
109
|
+
* });
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
export function useComponentAnimation(preset, style = "standard", options = {}) {
|
|
113
|
+
const { enabled = true, skipInitial = false, ...presetOptions } = options;
|
|
114
|
+
const prefersReducedMotion = useReducedMotion();
|
|
115
|
+
// Memoize presetOptions to avoid unnecessary re-renders
|
|
116
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: Using JSON.stringify for deep comparison
|
|
117
|
+
const memoizedPresetOptions = useMemo(() => presetOptions, [JSON.stringify(presetOptions)]);
|
|
118
|
+
const animationProps = useMemo(() => {
|
|
119
|
+
if (!enabled) {
|
|
120
|
+
return createDisabledProps(skipInitial);
|
|
121
|
+
}
|
|
122
|
+
const props = preset.getProps(style, memoizedPresetOptions);
|
|
123
|
+
if (skipInitial) {
|
|
124
|
+
return {
|
|
125
|
+
...props,
|
|
126
|
+
initial: false,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
return props;
|
|
130
|
+
}, [preset, style, memoizedPresetOptions, enabled, skipInitial]);
|
|
131
|
+
return {
|
|
132
|
+
...animationProps,
|
|
133
|
+
prefersReducedMotion,
|
|
134
|
+
isEnabled: enabled,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Hook for applying animation props with a delay.
|
|
139
|
+
*
|
|
140
|
+
* Useful for staggering animations without using variants.
|
|
141
|
+
*
|
|
142
|
+
* @param preset - The component animation preset to use
|
|
143
|
+
* @param style - The motion style to apply
|
|
144
|
+
* @param index - The index of this item (for calculating delay)
|
|
145
|
+
* @param options - Additional customization options
|
|
146
|
+
* @returns Animation props with calculated delay
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* ```tsx
|
|
150
|
+
* function ListItem({ index, children }) {
|
|
151
|
+
* const animation = useDelayedAnimation(fadeIn, "standard", index, {
|
|
152
|
+
* delayMultiplier: 50, // 50ms between each item
|
|
153
|
+
* });
|
|
154
|
+
*
|
|
155
|
+
* return (
|
|
156
|
+
* <motion.li {...animation}>
|
|
157
|
+
* {children}
|
|
158
|
+
* </motion.li>
|
|
159
|
+
* );
|
|
160
|
+
* }
|
|
161
|
+
* ```
|
|
162
|
+
*/
|
|
163
|
+
export function useDelayedAnimation(preset, style = "standard", index, options = {}) {
|
|
164
|
+
const { delayMultiplier = 50, maxDelay = 500, ...restOptions } = options;
|
|
165
|
+
const calculatedDelay = Math.min(index * delayMultiplier, maxDelay);
|
|
166
|
+
return useComponentAnimation(preset, style, {
|
|
167
|
+
...restOptions,
|
|
168
|
+
delay: (restOptions.delay ?? 0) + calculatedDelay,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Hook that returns animation props as a function for use with variants.
|
|
173
|
+
*
|
|
174
|
+
* Useful when you need to pass animation config to Motion's variants system.
|
|
175
|
+
*
|
|
176
|
+
* @param preset - The component animation preset to use
|
|
177
|
+
* @param style - The motion style to apply
|
|
178
|
+
* @param options - Additional customization options
|
|
179
|
+
* @returns Object containing variants and transition
|
|
180
|
+
*
|
|
181
|
+
* @example
|
|
182
|
+
* ```tsx
|
|
183
|
+
* function Container({ children }) {
|
|
184
|
+
* const { variants, transition } = useAnimationVariants(fadeIn, "standard");
|
|
185
|
+
*
|
|
186
|
+
* return (
|
|
187
|
+
* <motion.div
|
|
188
|
+
* initial="initial"
|
|
189
|
+
* animate="animate"
|
|
190
|
+
* exit="exit"
|
|
191
|
+
* variants={variants}
|
|
192
|
+
* transition={transition}
|
|
193
|
+
* >
|
|
194
|
+
* {children}
|
|
195
|
+
* </motion.div>
|
|
196
|
+
* );
|
|
197
|
+
* }
|
|
198
|
+
* ```
|
|
199
|
+
*/
|
|
200
|
+
export function useAnimationVariants(preset, style = "standard", options = {}) {
|
|
201
|
+
const { enabled = true, ...presetOptions } = options;
|
|
202
|
+
// Memoize presetOptions to avoid unnecessary re-renders
|
|
203
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: Using JSON.stringify for deep comparison
|
|
204
|
+
const memoizedPresetOptions = useMemo(() => presetOptions, [JSON.stringify(presetOptions)]);
|
|
205
|
+
return useMemo(() => {
|
|
206
|
+
if (!enabled) {
|
|
207
|
+
return {
|
|
208
|
+
variants: {
|
|
209
|
+
initial: { opacity: 0 },
|
|
210
|
+
animate: { opacity: 1 },
|
|
211
|
+
exit: { opacity: 0 },
|
|
212
|
+
},
|
|
213
|
+
transition: { type: "tween", duration: 0.15 },
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
const props = preset.getProps(style, memoizedPresetOptions);
|
|
217
|
+
return {
|
|
218
|
+
variants: {
|
|
219
|
+
initial: props.initial,
|
|
220
|
+
animate: props.animate,
|
|
221
|
+
exit: (props.exit ?? props.initial),
|
|
222
|
+
},
|
|
223
|
+
transition: props.transition,
|
|
224
|
+
};
|
|
225
|
+
}, [preset, style, memoizedPresetOptions, enabled]);
|
|
226
|
+
}
|
|
227
|
+
// =============================================================================
|
|
228
|
+
// Re-exports for convenience
|
|
229
|
+
// =============================================================================
|
|
230
|
+
export { useReducedMotion };
|
|
231
|
+
//# sourceMappingURL=use-component-animation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-component-animation.js","sourceRoot":"","sources":["../../src/hooks/use-component-animation.ts"],"names":[],"mappings":"AAAA,yCAAyC;AAEzC,YAAY,CAAC;AAEb;;;;;;;GAOG;AAEH,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AA4BrD,gFAAgF;AAChF,2BAA2B;AAC3B,gFAAgF;AAEhF;;;GAGG;AACH,SAAS,gBAAgB;IACrB,MAAM,CAAC,oBAAoB,EAAE,uBAAuB,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE;QAClE,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO,KAAK,CAAC;QAChD,OAAO,MAAM,CAAC,UAAU,CAAC,kCAAkC,CAAC,CAAC,OAAO,CAAC;IACzE,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACX,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,kCAAkC,CAAC,CAAC;QACzE,uBAAuB,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAE5C,MAAM,OAAO,GAAG,CAAC,CAAsB,EAAE,EAAE;YACvC,uBAAuB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QACvC,CAAC,CAAC;QAEF,UAAU,CAAC,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC/C,OAAO,GAAG,EAAE,CAAC,UAAU,CAAC,mBAAmB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACnE,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,oBAAoB,CAAC;AAChC,CAAC;AAED,gFAAgF;AAChF,0BAA0B;AAC1B,gFAAgF;AAEhF;;GAEG;AACH,SAAS,mBAAmB,CAAC,WAAoB;IAC7C,OAAO;QACH,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE;QAC7C,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE;QACvB,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE;QACpB,UAAU,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE;KAC7C,CAAC;AACN,CAAC;AAED,gFAAgF;AAChF,YAAY;AACZ,gFAAgF;AAEhF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,MAAM,UAAU,qBAAqB,CACjC,MAAuB,EACvB,QAAqB,UAAU,EAC/B,UAAwC,EAAE;IAE1C,MAAM,EAAE,OAAO,GAAG,IAAI,EAAE,WAAW,GAAG,KAAK,EAAE,GAAG,aAAa,EAAE,GAAG,OAAO,CAAC;IAC1E,MAAM,oBAAoB,GAAG,gBAAgB,EAAE,CAAC;IAEhD,wDAAwD;IACxD,oGAAoG;IACpG,MAAM,qBAAqB,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,aAAa,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAE5F,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,EAAE;QAChC,IAAI,CAAC,OAAO,EAAE,CAAC;YACX,OAAO,mBAAmB,CAAC,WAAW,CAAC,CAAC;QAC5C,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,qBAAqB,CAAC,CAAC;QAE5D,IAAI,WAAW,EAAE,CAAC;YACd,OAAO;gBACH,GAAG,KAAK;gBACR,OAAO,EAAE,KAAK;aACjB,CAAC;QACN,CAAC;QAED,OAAO,KAAK,CAAC;IACjB,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,qBAAqB,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC;IAEjE,OAAO;QACH,GAAG,cAAc;QACjB,oBAAoB;QACpB,SAAS,EAAE,OAAO;KACrB,CAAC;AACN,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,mBAAmB,CAC/B,MAAuB,EACvB,QAAqB,UAAU,EAC/B,KAAa,EACb,UAKI,EAAE;IAEN,MAAM,EAAE,eAAe,GAAG,EAAE,EAAE,QAAQ,GAAG,GAAG,EAAE,GAAG,WAAW,EAAE,GAAG,OAAO,CAAC;IAEzE,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,eAAe,EAAE,QAAQ,CAAC,CAAC;IAEpE,OAAO,qBAAqB,CAAC,MAAM,EAAE,KAAK,EAAE;QACxC,GAAG,WAAW;QACd,KAAK,EAAE,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,eAAe;KACpD,CAAC,CAAC;AACP,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,UAAU,oBAAoB,CAChC,MAAuB,EACvB,QAAqB,UAAU,EAC/B,UAAwC,EAAE;IAS1C,MAAM,EAAE,OAAO,GAAG,IAAI,EAAE,GAAG,aAAa,EAAE,GAAG,OAAO,CAAC;IAErD,wDAAwD;IACxD,oGAAoG;IACpG,MAAM,qBAAqB,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,aAAa,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAE5F,OAAO,OAAO,CAAC,GAAG,EAAE;QAChB,IAAI,CAAC,OAAO,EAAE,CAAC;YACX,OAAO;gBACH,QAAQ,EAAE;oBACN,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE;oBACvB,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE;oBACvB,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE;iBACvB;gBACD,UAAU,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE;aAChD,CAAC;QACN,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,qBAAqB,CAAC,CAAC;QAE5D,OAAO;YACH,QAAQ,EAAE;gBACN,OAAO,EAAE,KAAK,CAAC,OAAkC;gBACjD,OAAO,EAAE,KAAK,CAAC,OAAkC;gBACjD,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,OAAO,CAA4B;aACjE;YACD,UAAU,EAAE,KAAK,CAAC,UAAU;SAC/B,CAAC;IACN,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,qBAAqB,EAAE,OAAO,CAAC,CAAC,CAAC;AACxD,CAAC;AAED,gFAAgF;AAChF,6BAA6B;AAC7B,gFAAgF;AAEhF,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import type { MotionStyle } from "../presets/motion-styles";
|
|
2
|
+
/**
|
|
3
|
+
* Easing function type for count-up animation.
|
|
4
|
+
*/
|
|
5
|
+
export type CountUpEasing = "linear" | "easeOut" | "easeOutExpo" | "easeInOut" | "spring";
|
|
6
|
+
/**
|
|
7
|
+
* Options for the useCountUp hook.
|
|
8
|
+
*/
|
|
9
|
+
export interface UseCountUpOptions {
|
|
10
|
+
/** Starting value. Defaults to 0. */
|
|
11
|
+
from?: number;
|
|
12
|
+
/** Target value to count to. Required. */
|
|
13
|
+
to: number;
|
|
14
|
+
/** Duration in milliseconds. Defaults to motion style duration. */
|
|
15
|
+
duration?: number;
|
|
16
|
+
/** Motion style to use for timing. Defaults to "standard". */
|
|
17
|
+
motionStyle?: MotionStyle;
|
|
18
|
+
/** Easing function. Defaults to "easeOutExpo". */
|
|
19
|
+
easing?: CountUpEasing;
|
|
20
|
+
/** Number of decimal places. Defaults to 0. */
|
|
21
|
+
decimals?: number;
|
|
22
|
+
/** Whether to use locale-specific formatting (e.g., 1,234). Defaults to true. */
|
|
23
|
+
useLocale?: boolean;
|
|
24
|
+
/** Locale for formatting. Defaults to browser locale. */
|
|
25
|
+
locale?: string;
|
|
26
|
+
/** Custom formatter function. Overrides decimals and locale settings. */
|
|
27
|
+
formatter?: (value: number) => string;
|
|
28
|
+
/** Delay before starting animation in ms. Defaults to 0. */
|
|
29
|
+
delay?: number;
|
|
30
|
+
/** Whether to start animation immediately. Defaults to true. */
|
|
31
|
+
autoStart?: boolean;
|
|
32
|
+
/** Callback when animation completes. */
|
|
33
|
+
onComplete?: () => void;
|
|
34
|
+
/** Callback on each value update. */
|
|
35
|
+
onUpdate?: (value: number) => void;
|
|
36
|
+
/** Prefix to add before the number (e.g., "$"). */
|
|
37
|
+
prefix?: string;
|
|
38
|
+
/** Suffix to add after the number (e.g., "%"). */
|
|
39
|
+
suffix?: string;
|
|
40
|
+
/** Whether animation is enabled. Defaults to true. */
|
|
41
|
+
enabled?: boolean;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Return type for the useCountUp hook.
|
|
45
|
+
*/
|
|
46
|
+
export interface UseCountUpResult {
|
|
47
|
+
/** Current animated value (raw number). */
|
|
48
|
+
value: number;
|
|
49
|
+
/** Formatted display string with prefix/suffix. */
|
|
50
|
+
displayValue: string;
|
|
51
|
+
/** Whether animation is currently running. */
|
|
52
|
+
isAnimating: boolean;
|
|
53
|
+
/** Whether animation has completed. */
|
|
54
|
+
isComplete: boolean;
|
|
55
|
+
/** Start or restart the animation. */
|
|
56
|
+
start: () => void;
|
|
57
|
+
/** Pause the animation at current value. */
|
|
58
|
+
pause: () => void;
|
|
59
|
+
/** Resume a paused animation. */
|
|
60
|
+
resume: () => void;
|
|
61
|
+
/** Reset to starting value. */
|
|
62
|
+
reset: () => void;
|
|
63
|
+
/** Update the target value (will animate to new value). */
|
|
64
|
+
update: (newTo: number) => void;
|
|
65
|
+
/** Whether reduced motion is preferred. */
|
|
66
|
+
prefersReducedMotion: boolean;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Hook for animating numbers from one value to another.
|
|
70
|
+
*
|
|
71
|
+
* Features:
|
|
72
|
+
* - Configurable duration and easing
|
|
73
|
+
* - Respects reduced motion preferences
|
|
74
|
+
* - Locale-aware number formatting
|
|
75
|
+
* - Start/pause/resume/reset controls
|
|
76
|
+
* - Prefix and suffix support
|
|
77
|
+
* - Custom formatter support
|
|
78
|
+
*
|
|
79
|
+
* @param options - Configuration options for the animation
|
|
80
|
+
* @returns Object with current value, display string, and control functions
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```tsx
|
|
84
|
+
* // Basic usage
|
|
85
|
+
* const { displayValue } = useCountUp({ to: 1000 });
|
|
86
|
+
* return <span>{displayValue}</span>;
|
|
87
|
+
*
|
|
88
|
+
* // With formatting
|
|
89
|
+
* const { displayValue } = useCountUp({
|
|
90
|
+
* to: 99.5,
|
|
91
|
+
* decimals: 1,
|
|
92
|
+
* suffix: "%",
|
|
93
|
+
* duration: 1500,
|
|
94
|
+
* });
|
|
95
|
+
*
|
|
96
|
+
* // Currency
|
|
97
|
+
* const { displayValue } = useCountUp({
|
|
98
|
+
* to: 1234567,
|
|
99
|
+
* prefix: "$",
|
|
100
|
+
* useLocale: true,
|
|
101
|
+
* });
|
|
102
|
+
*
|
|
103
|
+
* // Manual control
|
|
104
|
+
* const { displayValue, start, reset, isAnimating } = useCountUp({
|
|
105
|
+
* to: 500,
|
|
106
|
+
* autoStart: false,
|
|
107
|
+
* });
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
export declare function useCountUp(options: UseCountUpOptions): UseCountUpResult;
|
|
111
|
+
//# sourceMappingURL=use-count-up.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-count-up.d.ts","sourceRoot":"","sources":["../../src/hooks/use-count-up.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAO5D;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,SAAS,GAAG,aAAa,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE1F;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAC9B,qCAAqC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0CAA0C;IAC1C,EAAE,EAAE,MAAM,CAAC;IACX,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,kDAAkD;IAClD,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iFAAiF;IACjF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACtC,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,yCAAyC;IACzC,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,qCAAqC;IACrC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC7B,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,mDAAmD;IACnD,YAAY,EAAE,MAAM,CAAC;IACrB,8CAA8C;IAC9C,WAAW,EAAE,OAAO,CAAC;IACrB,uCAAuC;IACvC,UAAU,EAAE,OAAO,CAAC;IACpB,sCAAsC;IACtC,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,4CAA4C;IAC5C,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,iCAAiC;IACjC,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,+BAA+B;IAC/B,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,2DAA2D;IAC3D,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,2CAA2C;IAC3C,oBAAoB,EAAE,OAAO,CAAC;CACjC;AA8DD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,gBAAgB,CAyLvE"}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
// Copyright (c) 2026 Amsterdam Data Labs
|
|
2
|
+
"use client";
|
|
3
|
+
/**
|
|
4
|
+
* useCountUp Hook
|
|
5
|
+
*
|
|
6
|
+
* Animates a number from a start value to an end value with configurable
|
|
7
|
+
* duration, easing, and formatting. Respects reduced motion preferences.
|
|
8
|
+
*
|
|
9
|
+
* @packageDocumentation
|
|
10
|
+
*/
|
|
11
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
12
|
+
import { getDuration } from "../presets/motion-styles";
|
|
13
|
+
// =============================================================================
|
|
14
|
+
// Easing Functions
|
|
15
|
+
// =============================================================================
|
|
16
|
+
const easingFunctions = {
|
|
17
|
+
linear: (t) => t,
|
|
18
|
+
easeOut: (t) => 1 - (1 - t) ** 3,
|
|
19
|
+
easeOutExpo: (t) => (t === 1 ? 1 : 1 - 2 ** (-10 * t)),
|
|
20
|
+
easeInOut: (t) => (t < 0.5 ? 4 * t ** 3 : 1 - (-2 * t + 2) ** 3 / 2),
|
|
21
|
+
spring: (t) => {
|
|
22
|
+
const c4 = (2 * Math.PI) / 3;
|
|
23
|
+
return t === 0 ? 0 : t === 1 ? 1 : 2 ** (-10 * t) * Math.sin((t * 10 - 0.75) * c4) + 1;
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
// =============================================================================
|
|
27
|
+
// Reduced Motion Detection
|
|
28
|
+
// =============================================================================
|
|
29
|
+
function useReducedMotion() {
|
|
30
|
+
const [prefersReducedMotion, setPrefersReducedMotion] = useState(() => {
|
|
31
|
+
if (typeof window === "undefined")
|
|
32
|
+
return false;
|
|
33
|
+
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
34
|
+
});
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
37
|
+
setPrefersReducedMotion(mediaQuery.matches);
|
|
38
|
+
const handler = (e) => {
|
|
39
|
+
setPrefersReducedMotion(e.matches);
|
|
40
|
+
};
|
|
41
|
+
mediaQuery.addEventListener("change", handler);
|
|
42
|
+
return () => mediaQuery.removeEventListener("change", handler);
|
|
43
|
+
}, []);
|
|
44
|
+
return prefersReducedMotion;
|
|
45
|
+
}
|
|
46
|
+
// =============================================================================
|
|
47
|
+
// Default Formatter
|
|
48
|
+
// =============================================================================
|
|
49
|
+
function createDefaultFormatter(decimals, useLocale, locale) {
|
|
50
|
+
return (value) => {
|
|
51
|
+
if (useLocale) {
|
|
52
|
+
return value.toLocaleString(locale, {
|
|
53
|
+
minimumFractionDigits: decimals,
|
|
54
|
+
maximumFractionDigits: decimals,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
return value.toFixed(decimals);
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
// =============================================================================
|
|
61
|
+
// useCountUp Hook
|
|
62
|
+
// =============================================================================
|
|
63
|
+
/**
|
|
64
|
+
* Hook for animating numbers from one value to another.
|
|
65
|
+
*
|
|
66
|
+
* Features:
|
|
67
|
+
* - Configurable duration and easing
|
|
68
|
+
* - Respects reduced motion preferences
|
|
69
|
+
* - Locale-aware number formatting
|
|
70
|
+
* - Start/pause/resume/reset controls
|
|
71
|
+
* - Prefix and suffix support
|
|
72
|
+
* - Custom formatter support
|
|
73
|
+
*
|
|
74
|
+
* @param options - Configuration options for the animation
|
|
75
|
+
* @returns Object with current value, display string, and control functions
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```tsx
|
|
79
|
+
* // Basic usage
|
|
80
|
+
* const { displayValue } = useCountUp({ to: 1000 });
|
|
81
|
+
* return <span>{displayValue}</span>;
|
|
82
|
+
*
|
|
83
|
+
* // With formatting
|
|
84
|
+
* const { displayValue } = useCountUp({
|
|
85
|
+
* to: 99.5,
|
|
86
|
+
* decimals: 1,
|
|
87
|
+
* suffix: "%",
|
|
88
|
+
* duration: 1500,
|
|
89
|
+
* });
|
|
90
|
+
*
|
|
91
|
+
* // Currency
|
|
92
|
+
* const { displayValue } = useCountUp({
|
|
93
|
+
* to: 1234567,
|
|
94
|
+
* prefix: "$",
|
|
95
|
+
* useLocale: true,
|
|
96
|
+
* });
|
|
97
|
+
*
|
|
98
|
+
* // Manual control
|
|
99
|
+
* const { displayValue, start, reset, isAnimating } = useCountUp({
|
|
100
|
+
* to: 500,
|
|
101
|
+
* autoStart: false,
|
|
102
|
+
* });
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
export function useCountUp(options) {
|
|
106
|
+
const { from = 0, to, duration: customDuration, motionStyle = "standard", easing = "easeOutExpo", decimals = 0, useLocale = true, locale, formatter: customFormatter, delay = 0, autoStart = true, onComplete, onUpdate, prefix = "", suffix = "", enabled = true, } = options;
|
|
107
|
+
// Get duration from motion style if not custom (use slow for count-up animations)
|
|
108
|
+
const duration = customDuration ?? getDuration(motionStyle, "slow");
|
|
109
|
+
// State
|
|
110
|
+
const [value, setValue] = useState(from);
|
|
111
|
+
const [isAnimating, setIsAnimating] = useState(false);
|
|
112
|
+
const [isComplete, setIsComplete] = useState(false);
|
|
113
|
+
// Refs for animation control
|
|
114
|
+
const animationRef = useRef(null);
|
|
115
|
+
const startTimeRef = useRef(null);
|
|
116
|
+
const pausedTimeRef = useRef(null);
|
|
117
|
+
const currentFromRef = useRef(from);
|
|
118
|
+
const currentToRef = useRef(to);
|
|
119
|
+
// Reduced motion
|
|
120
|
+
const prefersReducedMotion = useReducedMotion();
|
|
121
|
+
// Formatter
|
|
122
|
+
const formatter = customFormatter ?? createDefaultFormatter(decimals, useLocale, locale);
|
|
123
|
+
// Format display value
|
|
124
|
+
const displayValue = `${prefix}${formatter(value)}${suffix}`;
|
|
125
|
+
// Cancel animation
|
|
126
|
+
const cancelAnimation = useCallback(() => {
|
|
127
|
+
if (animationRef.current !== null) {
|
|
128
|
+
cancelAnimationFrame(animationRef.current);
|
|
129
|
+
animationRef.current = null;
|
|
130
|
+
}
|
|
131
|
+
}, []);
|
|
132
|
+
// Animation frame handler
|
|
133
|
+
const animate = useCallback((timestamp) => {
|
|
134
|
+
if (startTimeRef.current === null) {
|
|
135
|
+
startTimeRef.current = timestamp;
|
|
136
|
+
}
|
|
137
|
+
const elapsed = timestamp - startTimeRef.current;
|
|
138
|
+
const progress = Math.min(elapsed / duration, 1);
|
|
139
|
+
const easedProgress = easingFunctions[easing](progress);
|
|
140
|
+
const currentValue = currentFromRef.current + (currentToRef.current - currentFromRef.current) * easedProgress;
|
|
141
|
+
setValue(currentValue);
|
|
142
|
+
onUpdate?.(currentValue);
|
|
143
|
+
if (progress < 1) {
|
|
144
|
+
animationRef.current = requestAnimationFrame(animate);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
setIsAnimating(false);
|
|
148
|
+
setIsComplete(true);
|
|
149
|
+
onComplete?.();
|
|
150
|
+
}
|
|
151
|
+
}, [duration, easing, onComplete, onUpdate]);
|
|
152
|
+
// Start animation
|
|
153
|
+
const start = useCallback(() => {
|
|
154
|
+
if (!enabled) {
|
|
155
|
+
setValue(currentToRef.current);
|
|
156
|
+
setIsComplete(true);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
// Handle reduced motion - jump to end value immediately
|
|
160
|
+
if (prefersReducedMotion) {
|
|
161
|
+
setValue(currentToRef.current);
|
|
162
|
+
setIsComplete(true);
|
|
163
|
+
onComplete?.();
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
cancelAnimation();
|
|
167
|
+
setIsComplete(false);
|
|
168
|
+
startTimeRef.current = null;
|
|
169
|
+
pausedTimeRef.current = null;
|
|
170
|
+
const startAnimation = () => {
|
|
171
|
+
setIsAnimating(true);
|
|
172
|
+
animationRef.current = requestAnimationFrame(animate);
|
|
173
|
+
};
|
|
174
|
+
if (delay > 0) {
|
|
175
|
+
setTimeout(startAnimation, delay);
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
startAnimation();
|
|
179
|
+
}
|
|
180
|
+
}, [enabled, prefersReducedMotion, cancelAnimation, animate, delay, onComplete]);
|
|
181
|
+
// Pause animation
|
|
182
|
+
const pause = useCallback(() => {
|
|
183
|
+
if (isAnimating && animationRef.current !== null) {
|
|
184
|
+
pausedTimeRef.current = performance.now();
|
|
185
|
+
cancelAnimation();
|
|
186
|
+
setIsAnimating(false);
|
|
187
|
+
}
|
|
188
|
+
}, [isAnimating, cancelAnimation]);
|
|
189
|
+
// Resume animation
|
|
190
|
+
const resume = useCallback(() => {
|
|
191
|
+
if (!isAnimating && !isComplete && pausedTimeRef.current !== null && startTimeRef.current !== null) {
|
|
192
|
+
// Adjust start time to account for paused duration
|
|
193
|
+
const pausedDuration = performance.now() - pausedTimeRef.current;
|
|
194
|
+
startTimeRef.current += pausedDuration;
|
|
195
|
+
pausedTimeRef.current = null;
|
|
196
|
+
setIsAnimating(true);
|
|
197
|
+
animationRef.current = requestAnimationFrame(animate);
|
|
198
|
+
}
|
|
199
|
+
}, [isAnimating, isComplete, animate]);
|
|
200
|
+
// Reset to starting value
|
|
201
|
+
const reset = useCallback(() => {
|
|
202
|
+
cancelAnimation();
|
|
203
|
+
setValue(currentFromRef.current);
|
|
204
|
+
setIsAnimating(false);
|
|
205
|
+
setIsComplete(false);
|
|
206
|
+
startTimeRef.current = null;
|
|
207
|
+
pausedTimeRef.current = null;
|
|
208
|
+
}, [cancelAnimation]);
|
|
209
|
+
// Update target value
|
|
210
|
+
const update = useCallback((newTo) => {
|
|
211
|
+
currentFromRef.current = value;
|
|
212
|
+
currentToRef.current = newTo;
|
|
213
|
+
start();
|
|
214
|
+
}, [value, start]);
|
|
215
|
+
// Auto-start on mount - intentionally only runs once
|
|
216
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: We only want to start animation on mount, not on every dependency change
|
|
217
|
+
useEffect(() => {
|
|
218
|
+
if (autoStart) {
|
|
219
|
+
currentFromRef.current = from;
|
|
220
|
+
currentToRef.current = to;
|
|
221
|
+
start();
|
|
222
|
+
}
|
|
223
|
+
return () => {
|
|
224
|
+
cancelAnimation();
|
|
225
|
+
};
|
|
226
|
+
}, []);
|
|
227
|
+
// Update target when `to` prop changes
|
|
228
|
+
useEffect(() => {
|
|
229
|
+
if (to !== currentToRef.current && isComplete) {
|
|
230
|
+
update(to);
|
|
231
|
+
}
|
|
232
|
+
}, [to, isComplete, update]);
|
|
233
|
+
return {
|
|
234
|
+
value,
|
|
235
|
+
displayValue,
|
|
236
|
+
isAnimating,
|
|
237
|
+
isComplete,
|
|
238
|
+
start,
|
|
239
|
+
pause,
|
|
240
|
+
resume,
|
|
241
|
+
reset,
|
|
242
|
+
update,
|
|
243
|
+
prefersReducedMotion,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
//# sourceMappingURL=use-count-up.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-count-up.js","sourceRoot":"","sources":["../../src/hooks/use-count-up.ts"],"names":[],"mappings":"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"}
|