@ansh-ui/react 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 (111) hide show
  1. package/LICENSE +21 -0
  2. package/dist/chunk-5CFQFMP5.js +178 -0
  3. package/dist/chunk-5CFQFMP5.js.map +1 -0
  4. package/dist/chunk-6VRF7X5C.cjs +164 -0
  5. package/dist/chunk-6VRF7X5C.cjs.map +1 -0
  6. package/dist/chunk-AVPEA5PB.cjs +718 -0
  7. package/dist/chunk-AVPEA5PB.cjs.map +1 -0
  8. package/dist/chunk-C32LKF23.cjs +198 -0
  9. package/dist/chunk-C32LKF23.cjs.map +1 -0
  10. package/dist/chunk-C5JG6TMM.cjs +1200 -0
  11. package/dist/chunk-C5JG6TMM.cjs.map +1 -0
  12. package/dist/chunk-DATBU46V.cjs +614 -0
  13. package/dist/chunk-DATBU46V.cjs.map +1 -0
  14. package/dist/chunk-EGG4CP7C.js +320 -0
  15. package/dist/chunk-EGG4CP7C.js.map +1 -0
  16. package/dist/chunk-H34OXXJU.js +55 -0
  17. package/dist/chunk-H34OXXJU.js.map +1 -0
  18. package/dist/chunk-HO2YSF5O.js +187 -0
  19. package/dist/chunk-HO2YSF5O.js.map +1 -0
  20. package/dist/chunk-HPGCILO4.js +760 -0
  21. package/dist/chunk-HPGCILO4.js.map +1 -0
  22. package/dist/chunk-IBXLC5IE.js +154 -0
  23. package/dist/chunk-IBXLC5IE.js.map +1 -0
  24. package/dist/chunk-LDCZQP3R.js +1185 -0
  25. package/dist/chunk-LDCZQP3R.js.map +1 -0
  26. package/dist/chunk-LXCIXR5T.js +27 -0
  27. package/dist/chunk-LXCIXR5T.js.map +1 -0
  28. package/dist/chunk-O2PX54KX.js +94 -0
  29. package/dist/chunk-O2PX54KX.js.map +1 -0
  30. package/dist/chunk-OHBWBXLO.cjs +101 -0
  31. package/dist/chunk-OHBWBXLO.cjs.map +1 -0
  32. package/dist/chunk-OJN5JBNP.cjs +776 -0
  33. package/dist/chunk-OJN5JBNP.cjs.map +1 -0
  34. package/dist/chunk-OLTS6G5M.js +606 -0
  35. package/dist/chunk-OLTS6G5M.js.map +1 -0
  36. package/dist/chunk-PO5DU3FU.cjs +29 -0
  37. package/dist/chunk-PO5DU3FU.cjs.map +1 -0
  38. package/dist/chunk-QO3E7TJS.js +2940 -0
  39. package/dist/chunk-QO3E7TJS.js.map +1 -0
  40. package/dist/chunk-RHTLNSVW.cjs +2976 -0
  41. package/dist/chunk-RHTLNSVW.cjs.map +1 -0
  42. package/dist/chunk-SFU5EPSN.cjs +61 -0
  43. package/dist/chunk-SFU5EPSN.cjs.map +1 -0
  44. package/dist/chunk-T4AK2KLM.js +699 -0
  45. package/dist/chunk-T4AK2KLM.js.map +1 -0
  46. package/dist/chunk-WGYNCSTP.cjs +333 -0
  47. package/dist/chunk-WGYNCSTP.cjs.map +1 -0
  48. package/dist/chunk-XEP6P7E6.js +279 -0
  49. package/dist/chunk-XEP6P7E6.js.map +1 -0
  50. package/dist/chunk-XMXECSQO.cjs +286 -0
  51. package/dist/chunk-XMXECSQO.cjs.map +1 -0
  52. package/dist/chunk-ZWAFLHC2.cjs +181 -0
  53. package/dist/chunk-ZWAFLHC2.cjs.map +1 -0
  54. package/dist/data.cjs +71 -0
  55. package/dist/data.cjs.map +1 -0
  56. package/dist/data.d.cts +316 -0
  57. package/dist/data.d.ts +316 -0
  58. package/dist/data.js +6 -0
  59. package/dist/data.js.map +1 -0
  60. package/dist/form.cjs +153 -0
  61. package/dist/form.cjs.map +1 -0
  62. package/dist/form.d.cts +660 -0
  63. package/dist/form.d.ts +660 -0
  64. package/dist/form.js +8 -0
  65. package/dist/form.js.map +1 -0
  66. package/dist/index.cjs +1641 -0
  67. package/dist/index.cjs.map +1 -0
  68. package/dist/index.d.cts +552 -0
  69. package/dist/index.d.ts +552 -0
  70. package/dist/index.js +956 -0
  71. package/dist/index.js.map +1 -0
  72. package/dist/layout.cjs +68 -0
  73. package/dist/layout.cjs.map +1 -0
  74. package/dist/layout.d.cts +169 -0
  75. package/dist/layout.d.ts +169 -0
  76. package/dist/layout.js +7 -0
  77. package/dist/layout.js.map +1 -0
  78. package/dist/motion-CQmCq6_k.d.ts +395 -0
  79. package/dist/motion-CSX4g2N8.d.cts +395 -0
  80. package/dist/motion.cjs +79 -0
  81. package/dist/motion.cjs.map +1 -0
  82. package/dist/motion.d.cts +4 -0
  83. package/dist/motion.d.ts +4 -0
  84. package/dist/motion.js +6 -0
  85. package/dist/motion.js.map +1 -0
  86. package/dist/navigation.cjs +48 -0
  87. package/dist/navigation.cjs.map +1 -0
  88. package/dist/navigation.d.cts +210 -0
  89. package/dist/navigation.d.ts +210 -0
  90. package/dist/navigation.js +7 -0
  91. package/dist/navigation.js.map +1 -0
  92. package/dist/overlay.cjs +69 -0
  93. package/dist/overlay.cjs.map +1 -0
  94. package/dist/overlay.d.cts +330 -0
  95. package/dist/overlay.d.ts +330 -0
  96. package/dist/overlay.js +8 -0
  97. package/dist/overlay.js.map +1 -0
  98. package/dist/position-DVScKcaa.d.cts +66 -0
  99. package/dist/position-DVScKcaa.d.ts +66 -0
  100. package/dist/primitives.cjs +162 -0
  101. package/dist/primitives.cjs.map +1 -0
  102. package/dist/primitives.d.cts +294 -0
  103. package/dist/primitives.d.ts +294 -0
  104. package/dist/primitives.js +9 -0
  105. package/dist/primitives.js.map +1 -0
  106. package/dist/sidebar-D-PafAXw.d.cts +71 -0
  107. package/dist/sidebar-D-PafAXw.d.ts +71 -0
  108. package/dist/styles.css +5575 -0
  109. package/dist/use-observers-B9qtimrk.d.cts +99 -0
  110. package/dist/use-observers-B9qtimrk.d.ts +99 -0
  111. package/package.json +92 -0
@@ -0,0 +1,699 @@
1
+ import { useMergedRef } from './chunk-IBXLC5IE.js';
2
+ import { cx } from './chunk-H34OXXJU.js';
3
+ import { createContext, forwardRef, useRef, useEffect, useMemo, useContext, useState, useLayoutEffect, useCallback, Children, isValidElement, cloneElement } from 'react';
4
+ import { mountBehaviour, magnetic, tilt, ripple, marquee, scrollReveal, parallax, resolvePalette, createGradient, prefersReducedMotion, resolveEasing, stagger, getTicker, observeIntersection, setReducedMotionMode, attachLifecycle, springs, animate } from '@ansh-ui/core';
5
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
+ import { applyTheme, resolveTheme } from '@ansh-ui/tokens';
7
+
8
+ function createBehaviourComponent(definition, displayName, defaultElement = "div") {
9
+ const optionKeys = new Set(Object.keys(definition.defaults));
10
+ function Render(props, forwardedRef) {
11
+ const { as: Component2 = defaultElement, className, style, children, ...rest } = props;
12
+ const hostRef = useRef(null);
13
+ const handleRef = useRef(null);
14
+ const mergedRef = useMergedRef(hostRef, forwardedRef);
15
+ const options = {};
16
+ const domProps = {};
17
+ for (const [key, value] of Object.entries(rest)) {
18
+ if (optionKeys.has(key)) options[key] = value;
19
+ else domProps[key] = value;
20
+ }
21
+ const optionsKey = stableKey(options);
22
+ const optionsRef = useRef(options);
23
+ optionsRef.current = options;
24
+ useEffect(() => {
25
+ const host = hostRef.current;
26
+ if (!host) return;
27
+ const handle = mountBehaviour(definition, host, optionsRef.current);
28
+ handleRef.current = handle;
29
+ return () => {
30
+ handle.destroy();
31
+ handleRef.current = null;
32
+ };
33
+ }, []);
34
+ useEffect(() => {
35
+ handleRef.current?.update(optionsRef.current);
36
+ }, [optionsKey]);
37
+ return /* @__PURE__ */ jsx(Component2, { ref: mergedRef, className, style, ...domProps, children });
38
+ }
39
+ const Component = forwardRef(Render);
40
+ Component.displayName = displayName ?? `Ansh(${definition.name})`;
41
+ return Component;
42
+ }
43
+ function stableKey(options) {
44
+ const keys = Object.keys(options).sort();
45
+ const parts = [];
46
+ for (const key of keys) {
47
+ const value = options[key];
48
+ if (typeof value === "function") parts.push(`${key}:fn`);
49
+ else if (value === void 0) continue;
50
+ else parts.push(`${key}:${JSON.stringify(value)}`);
51
+ }
52
+ return parts.join("|");
53
+ }
54
+ function useBehaviour(ref, definition, options) {
55
+ const handleRef = useRef(null);
56
+ const optionsRef = useRef(options ?? {});
57
+ optionsRef.current = options ?? {};
58
+ const optionsKey = stableKey(optionsRef.current);
59
+ useEffect(() => {
60
+ const element = ref.current;
61
+ if (!element) return;
62
+ const handle = mountBehaviour(definition, element, optionsRef.current);
63
+ handleRef.current = handle;
64
+ return () => {
65
+ handle.destroy();
66
+ handleRef.current = null;
67
+ };
68
+ }, [definition, ref]);
69
+ useEffect(() => {
70
+ handleRef.current?.update(optionsRef.current);
71
+ }, [optionsKey]);
72
+ }
73
+ var MagneticButton = createBehaviourComponent(magnetic, "MagneticButton", "button");
74
+ var TiltCard = createBehaviourComponent(tilt, "TiltCard", "div");
75
+ var Ripple = createBehaviourComponent(ripple, "Ripple", "div");
76
+ var Marquee = createBehaviourComponent(marquee, "Marquee", "div");
77
+ var ScrollReveal = createBehaviourComponent(scrollReveal, "ScrollReveal", "div");
78
+ var Parallax = createBehaviourComponent(parallax, "Parallax", "div");
79
+ var useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect;
80
+ var VISUALLY_HIDDEN = {
81
+ position: "absolute",
82
+ width: 1,
83
+ height: 1,
84
+ padding: 0,
85
+ margin: -1,
86
+ overflow: "hidden",
87
+ clipPath: "inset(50%)",
88
+ whiteSpace: "nowrap",
89
+ borderWidth: 0
90
+ };
91
+ function GradientText({
92
+ children,
93
+ colors,
94
+ angle = 100,
95
+ duration = 0,
96
+ stops = 16,
97
+ as: Component = "span",
98
+ className,
99
+ style
100
+ }) {
101
+ const gradientCss = useMemo(() => {
102
+ const palette = resolvePalette(colors);
103
+ const looped = duration > 0 ? [...palette, ...palette] : palette;
104
+ return createGradient(looped, { space: "oklab" }).toCss(`${angle}deg`, stops);
105
+ }, [colors, angle, duration, stops]);
106
+ const animated = duration > 0 && !prefersReducedMotion();
107
+ return /* @__PURE__ */ jsxs(
108
+ Component,
109
+ {
110
+ className,
111
+ style: {
112
+ backgroundImage: gradientCss,
113
+ backgroundSize: animated ? "200% 100%" : "100% 100%",
114
+ backgroundClip: "text",
115
+ WebkitBackgroundClip: "text",
116
+ color: "transparent",
117
+ // A fallback for the rare engine without background-clip support: the first colour still
118
+ // renders as solid text rather than the content vanishing entirely.
119
+ WebkitTextFillColor: "transparent",
120
+ display: "inline-block",
121
+ ...animated ? {
122
+ animation: `ansh-gradient-shift ${duration}s linear infinite`
123
+ } : {},
124
+ ...style
125
+ },
126
+ children: [
127
+ children,
128
+ animated ? /* @__PURE__ */ jsx(GradientKeyframes, {}) : null
129
+ ]
130
+ }
131
+ );
132
+ }
133
+ function GradientKeyframes() {
134
+ return /* @__PURE__ */ jsx(
135
+ "style",
136
+ {
137
+ dangerouslySetInnerHTML: {
138
+ __html: "@keyframes ansh-gradient-shift{from{background-position:0% 50%}to{background-position:200% 50%}}"
139
+ }
140
+ }
141
+ );
142
+ }
143
+ function AnimatedText({
144
+ children,
145
+ by = "chars",
146
+ duration = 0.6,
147
+ each = 0.03,
148
+ from = "first",
149
+ easing = "cinematic",
150
+ distance = 18,
151
+ blur = 0,
152
+ rotate = 0,
153
+ mask = false,
154
+ whenInView = true,
155
+ repeat = false,
156
+ delay = 0,
157
+ as: Component = "span",
158
+ className,
159
+ style,
160
+ onComplete
161
+ }) {
162
+ const hostRef = useRef(null);
163
+ const unitRefs = useRef([]);
164
+ const onCompleteRef = useRef(onComplete);
165
+ onCompleteRef.current = onComplete;
166
+ const units = useMemo(() => {
167
+ if (by === "words") {
168
+ return children.split(/(\s+)/).filter((token) => token.length > 0).map((token) => ({ text: token, space: /^\s+$/.test(token) }));
169
+ }
170
+ const graphemes = typeof Intl !== "undefined" && "Segmenter" in Intl ? Array.from(
171
+ new Intl.Segmenter(void 0, { granularity: "grapheme" }).segment(children),
172
+ (s) => s.segment
173
+ ) : Array.from(children);
174
+ return graphemes.map((character) => ({ text: character, space: /^\s$/.test(character) }));
175
+ }, [children, by]);
176
+ const animatedCount = useMemo(() => units.filter((u) => !u.space).length, [units]);
177
+ useIsomorphicLayoutEffect(() => {
178
+ const host = hostRef.current;
179
+ if (!host) return;
180
+ if (prefersReducedMotion()) {
181
+ onCompleteRef.current?.();
182
+ return;
183
+ }
184
+ const ease = resolveEasing(easing);
185
+ const delayFor = stagger(animatedCount, { each, from });
186
+ const ticker = getTicker();
187
+ const targets = [];
188
+ let animationIndex = 0;
189
+ units.forEach((unit, i) => {
190
+ if (unit.space) return;
191
+ const node = unitRefs.current[i];
192
+ if (node) targets.push({ node, delay: delay + delayFor(animationIndex) });
193
+ animationIndex++;
194
+ });
195
+ const apply = (node, progress) => {
196
+ const eased = ease(progress);
197
+ const inverse = 1 - eased;
198
+ node.style.opacity = String(eased);
199
+ const parts = [`translate3d(0, ${(distance * inverse).toFixed(2)}px, 0)`];
200
+ if (rotate !== 0) parts.push(`rotate(${(rotate * inverse).toFixed(2)}deg)`);
201
+ node.style.transform = parts.join(" ");
202
+ if (blur > 0) {
203
+ const amount = blur * inverse;
204
+ node.style.filter = amount > 0.05 ? `blur(${amount.toFixed(2)}px)` : "";
205
+ }
206
+ };
207
+ const reset = () => {
208
+ for (const { node } of targets) apply(node, 0);
209
+ };
210
+ const settle = (node) => {
211
+ node.style.opacity = "";
212
+ node.style.transform = "";
213
+ node.style.filter = "";
214
+ node.style.willChange = "";
215
+ };
216
+ let elapsed = 0;
217
+ let running = false;
218
+ let stopTicker = null;
219
+ const start = () => {
220
+ if (running) return;
221
+ running = true;
222
+ elapsed = 0;
223
+ for (const { node } of targets) node.style.willChange = "opacity, transform";
224
+ reset();
225
+ stopTicker = ticker.add(
226
+ ({ delta }) => {
227
+ elapsed += delta;
228
+ let allDone = true;
229
+ for (const target of targets) {
230
+ const local = elapsed - target.delay;
231
+ if (local < 0) {
232
+ allDone = false;
233
+ continue;
234
+ }
235
+ const progress = duration <= 0 ? 1 : local / duration;
236
+ if (progress >= 1) {
237
+ settle(target.node);
238
+ continue;
239
+ }
240
+ apply(target.node, progress);
241
+ allDone = false;
242
+ }
243
+ if (allDone) {
244
+ stopTicker?.();
245
+ stopTicker = null;
246
+ running = false;
247
+ onCompleteRef.current?.();
248
+ }
249
+ },
250
+ { phase: "write", name: "AnimatedText" }
251
+ );
252
+ };
253
+ if (!whenInView) {
254
+ reset();
255
+ start();
256
+ return () => {
257
+ stopTicker?.();
258
+ for (const { node } of targets) settle(node);
259
+ };
260
+ }
261
+ reset();
262
+ const stopObserver = observeIntersection(
263
+ host,
264
+ (entry) => {
265
+ if (entry.isIntersecting) {
266
+ start();
267
+ } else if (repeat) {
268
+ stopTicker?.();
269
+ stopTicker = null;
270
+ running = false;
271
+ reset();
272
+ }
273
+ },
274
+ { threshold: 0.2, rootMargin: "0px 0px -8% 0px" }
275
+ );
276
+ return () => {
277
+ stopObserver();
278
+ stopTicker?.();
279
+ for (const { node } of targets) settle(node);
280
+ };
281
+ }, [
282
+ units,
283
+ animatedCount,
284
+ duration,
285
+ each,
286
+ from,
287
+ easing,
288
+ distance,
289
+ blur,
290
+ rotate,
291
+ whenInView,
292
+ repeat,
293
+ delay
294
+ ]);
295
+ return /* @__PURE__ */ jsxs(Component, { ref: hostRef, className, style: { display: "inline-block", ...style }, children: [
296
+ /* @__PURE__ */ jsx("span", { style: VISUALLY_HIDDEN, children }),
297
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: units.map(
298
+ (unit, i) => unit.space ? (
299
+ // Whitespace as a plain text node so it collapses and wraps like real text.
300
+ /* @__PURE__ */ jsx("span", { children: unit.text }, i)
301
+ ) : mask ? /* @__PURE__ */ jsx(
302
+ "span",
303
+ {
304
+ style: { display: "inline-block", overflow: "hidden", verticalAlign: "top" },
305
+ children: /* @__PURE__ */ jsx(
306
+ "span",
307
+ {
308
+ ref: (node) => {
309
+ unitRefs.current[i] = node;
310
+ },
311
+ style: { display: "inline-block" },
312
+ children: unit.text
313
+ }
314
+ )
315
+ },
316
+ i
317
+ ) : /* @__PURE__ */ jsx(
318
+ "span",
319
+ {
320
+ ref: (node) => {
321
+ unitRefs.current[i] = node;
322
+ },
323
+ style: { display: "inline-block" },
324
+ children: unit.text
325
+ },
326
+ i
327
+ )
328
+ ) })
329
+ ] });
330
+ }
331
+ var MotionConfigContext = createContext({
332
+ reducedMotion: "auto",
333
+ timeScale: 1,
334
+ quality: null
335
+ });
336
+ function MotionConfig({
337
+ reducedMotion = "auto",
338
+ timeScale = 1,
339
+ quality = null,
340
+ pauseWhenHidden = true,
341
+ pauseWhenBlurred = false,
342
+ respectBattery = true,
343
+ children
344
+ }) {
345
+ useEffect(() => {
346
+ setReducedMotionMode(reducedMotion);
347
+ }, [reducedMotion]);
348
+ useEffect(() => {
349
+ getTicker().timeScale = timeScale;
350
+ }, [timeScale]);
351
+ useEffect(() => {
352
+ if (quality !== null) getTicker().lockQuality(quality);
353
+ }, [quality]);
354
+ useEffect(
355
+ () => attachLifecycle(getTicker(), {
356
+ pauseWhenHidden,
357
+ pauseWhenBlurred,
358
+ respectBattery
359
+ }),
360
+ [pauseWhenHidden, pauseWhenBlurred, respectBattery]
361
+ );
362
+ const value = useMemo(
363
+ () => ({ reducedMotion, timeScale, quality }),
364
+ [reducedMotion, timeScale, quality]
365
+ );
366
+ return /* @__PURE__ */ jsx(MotionConfigContext.Provider, { value, children });
367
+ }
368
+ function useMotionConfig() {
369
+ return useContext(MotionConfigContext);
370
+ }
371
+ var ThemeContext = createContext({
372
+ theme: "system",
373
+ resolved: "light",
374
+ setTheme: () => {
375
+ }
376
+ });
377
+ function ThemeProvider({
378
+ defaultTheme = "system",
379
+ storageKey = "ansh-theme",
380
+ children
381
+ }) {
382
+ const [theme, setThemeState] = useState(defaultTheme);
383
+ const [resolved, setResolved] = useState("light");
384
+ useEffect(() => {
385
+ if (!storageKey) return;
386
+ try {
387
+ const stored = localStorage.getItem(storageKey);
388
+ if (stored === "light" || stored === "dark" || stored === "system") {
389
+ setThemeState(stored);
390
+ }
391
+ } catch {
392
+ }
393
+ }, [storageKey]);
394
+ useEffect(() => {
395
+ applyTheme(theme);
396
+ setResolved(resolveTheme());
397
+ if (storageKey) {
398
+ try {
399
+ localStorage.setItem(storageKey, theme);
400
+ } catch {
401
+ }
402
+ }
403
+ }, [theme, storageKey]);
404
+ useEffect(() => {
405
+ if (theme !== "system" || typeof matchMedia !== "function") return;
406
+ const query = matchMedia("(prefers-color-scheme: dark)");
407
+ const onChange = () => setResolved(query.matches ? "dark" : "light");
408
+ query.addEventListener("change", onChange);
409
+ return () => query.removeEventListener("change", onChange);
410
+ }, [theme]);
411
+ const value = useMemo(() => ({ theme, resolved, setTheme: setThemeState }), [theme, resolved]);
412
+ return /* @__PURE__ */ jsx(ThemeContext.Provider, { value, children });
413
+ }
414
+ function useTheme() {
415
+ return useContext(ThemeContext);
416
+ }
417
+ function themeScript(storageKey = "ansh-theme") {
418
+ return `(function(){try{var t=localStorage.getItem(${JSON.stringify(storageKey)});if(t==='light'||t==='dark'){document.documentElement.setAttribute('data-theme',t)}}catch(e){}})()`;
419
+ }
420
+ var DEFAULTS = {
421
+ opacity: 1,
422
+ x: 0,
423
+ y: 0,
424
+ scale: 1,
425
+ scaleX: 1,
426
+ scaleY: 1,
427
+ rotate: 0,
428
+ blur: 0
429
+ };
430
+ function applyValues(node, values) {
431
+ const transform = `translate3d(${values.x}px, ${values.y}px, 0) scale(${values.scale * values.scaleX}, ${values.scale * values.scaleY}) rotate(${values.rotate}deg)`;
432
+ node.style.transform = transform;
433
+ node.style.opacity = String(values.opacity);
434
+ node.style.filter = values.blur > 0 ? `blur(${values.blur}px)` : "";
435
+ }
436
+ function resolve(values, base) {
437
+ return { ...base, ...values };
438
+ }
439
+ function Motion({
440
+ as: Component = "div",
441
+ initial,
442
+ animate: target,
443
+ // Destructured but unused here: `AnimatePresence` reads `exit` off the element's props when the
444
+ // child is removed and swaps it into `animate`. Pulling it out of `rest` stops it reaching the
445
+ // DOM as an unknown attribute.
446
+ exit: _exit,
447
+ transition,
448
+ whileHover,
449
+ whileTap,
450
+ whileInView = false,
451
+ inViewAmount = 0.2,
452
+ className,
453
+ style,
454
+ children,
455
+ ...rest
456
+ }) {
457
+ const nodeRef = useRef(null);
458
+ const currentRef = useRef(resolve(initial, DEFAULTS));
459
+ const controlsRef = useRef(null);
460
+ const [inView, setInView] = useState(!whileInView);
461
+ useLayoutEffect(() => {
462
+ if (nodeRef.current) applyValues(nodeRef.current, currentRef.current);
463
+ }, []);
464
+ const runTo = useCallback(
465
+ (next, options) => {
466
+ const node = nodeRef.current;
467
+ if (!node) return;
468
+ controlsRef.current?.stop();
469
+ const from = { ...currentRef.current };
470
+ const springOption = options?.spring ?? transition?.spring;
471
+ const animationOptions = {
472
+ ...options?.delay ?? transition?.delay !== void 0 ? { delay: options?.delay ?? transition?.delay ?? 0 } : null,
473
+ ...springOption ? {
474
+ spring: springOption === true ? springs.default : typeof springOption === "string" ? springs[springOption] : springOption
475
+ } : {
476
+ duration: options?.duration ?? transition?.duration ?? 0.4,
477
+ ...options?.easing ?? transition?.easing ? { easing: options?.easing ?? transition?.easing } : null
478
+ },
479
+ onUpdate: (t) => {
480
+ const frame = {};
481
+ for (const key of Object.keys(DEFAULTS)) {
482
+ frame[key] = from[key] + (next[key] - from[key]) * t;
483
+ }
484
+ currentRef.current = frame;
485
+ applyValues(node, frame);
486
+ },
487
+ onComplete: () => {
488
+ currentRef.current = next;
489
+ applyValues(node, next);
490
+ }
491
+ };
492
+ controlsRef.current = animate(0, 1, animationOptions);
493
+ },
494
+ [transition]
495
+ );
496
+ const targetKey = JSON.stringify(target ?? null);
497
+ useEffect(() => {
498
+ if (!inView) return;
499
+ runTo(resolve(target, DEFAULTS));
500
+ }, [targetKey, inView, runTo]);
501
+ useEffect(() => {
502
+ if (!whileInView) return;
503
+ const node = nodeRef.current;
504
+ if (!node || typeof IntersectionObserver === "undefined") {
505
+ setInView(true);
506
+ return;
507
+ }
508
+ const observer = new IntersectionObserver(
509
+ ([entry]) => {
510
+ if (entry?.isIntersecting) {
511
+ setInView(true);
512
+ observer.disconnect();
513
+ }
514
+ },
515
+ { threshold: inViewAmount }
516
+ );
517
+ observer.observe(node);
518
+ return () => observer.disconnect();
519
+ }, [whileInView, inViewAmount]);
520
+ useEffect(() => () => controlsRef.current?.stop(), []);
521
+ const interaction = {};
522
+ if (whileHover) {
523
+ interaction.onMouseEnter = () => runTo(resolve({ ...target, ...whileHover }, DEFAULTS));
524
+ interaction.onMouseLeave = () => runTo(resolve(target, DEFAULTS));
525
+ }
526
+ if (whileTap) {
527
+ interaction.onPointerDown = () => runTo(resolve({ ...target, ...whileTap }, DEFAULTS), { duration: 0.12 });
528
+ interaction.onPointerUp = () => runTo(resolve({ ...target, ...whileHover }, DEFAULTS));
529
+ }
530
+ return /* @__PURE__ */ jsx(
531
+ Component,
532
+ {
533
+ ref: nodeRef,
534
+ className,
535
+ style: { willChange: "transform, opacity", ...style },
536
+ ...interaction,
537
+ ...rest,
538
+ children
539
+ }
540
+ );
541
+ }
542
+ function AnimatePresence({ children, exitDuration = 0.35 }) {
543
+ const currentChildren = Children.toArray(children).filter(isValidElement);
544
+ const [rendered, setRendered] = useState(currentChildren);
545
+ const timersRef = useRef(/* @__PURE__ */ new Map());
546
+ const keys = currentChildren.map((child) => String(child.key));
547
+ const keysSignature = keys.join("|");
548
+ useEffect(() => {
549
+ const currentKeys2 = new Set(keys);
550
+ const departing = rendered.filter((child) => !currentKeys2.has(String(child.key)));
551
+ if (departing.length === 0) {
552
+ setRendered(currentChildren);
553
+ return;
554
+ }
555
+ setRendered([...currentChildren, ...departing]);
556
+ const delay = prefersReducedMotion() ? 0 : exitDuration * 1e3;
557
+ for (const child of departing) {
558
+ const key = String(child.key);
559
+ clearTimeout(timersRef.current.get(key));
560
+ timersRef.current.set(
561
+ key,
562
+ setTimeout(() => {
563
+ setRendered((previous) => previous.filter((entry) => String(entry.key) !== key));
564
+ timersRef.current.delete(key);
565
+ }, delay)
566
+ );
567
+ }
568
+ }, [keysSignature, exitDuration]);
569
+ useEffect(() => {
570
+ const timers = timersRef.current;
571
+ return () => {
572
+ for (const timer of timers.values()) clearTimeout(timer);
573
+ timers.clear();
574
+ };
575
+ }, []);
576
+ const currentKeys = new Set(keys);
577
+ return /* @__PURE__ */ jsx(Fragment, { children: rendered.map((child) => {
578
+ const leaving = !currentKeys.has(String(child.key));
579
+ if (!leaving) return child;
580
+ const props = child.props;
581
+ return cloneElement(child, {
582
+ animate: props.exit ?? { opacity: 0, scale: 0.96 },
583
+ transition: { duration: exitDuration, ...props.transition }
584
+ });
585
+ }) });
586
+ }
587
+ function Draggable({
588
+ axis = "both",
589
+ bounds,
590
+ snapBack = false,
591
+ momentum,
592
+ onDragStart,
593
+ onDragEnd,
594
+ className,
595
+ style,
596
+ children
597
+ }) {
598
+ const nodeRef = useRef(null);
599
+ const offsetRef = useRef({ x: 0, y: 0 });
600
+ const [dragging, setDragging] = useState(false);
601
+ const useMomentum = momentum ?? !snapBack;
602
+ const clamp = useCallback(
603
+ (value) => ({
604
+ x: Math.min(Math.max(value.x, bounds?.left ?? -Infinity), bounds?.right ?? Infinity),
605
+ y: Math.min(Math.max(value.y, bounds?.top ?? -Infinity), bounds?.bottom ?? Infinity)
606
+ }),
607
+ [bounds]
608
+ );
609
+ const write = (value) => {
610
+ if (nodeRef.current) {
611
+ nodeRef.current.style.transform = `translate3d(${value.x}px, ${value.y}px, 0)`;
612
+ }
613
+ };
614
+ const onPointerDown = (event) => {
615
+ event.currentTarget.setPointerCapture(event.pointerId);
616
+ setDragging(true);
617
+ onDragStart?.();
618
+ const start = { x: event.clientX, y: event.clientY };
619
+ const origin = { ...offsetRef.current };
620
+ const samples = [];
621
+ const onMove = (moveEvent) => {
622
+ const next = clamp({
623
+ x: axis === "y" ? origin.x : origin.x + (moveEvent.clientX - start.x),
624
+ y: axis === "x" ? origin.y : origin.y + (moveEvent.clientY - start.y)
625
+ });
626
+ offsetRef.current = next;
627
+ write(next);
628
+ samples.push({ x: next.x, y: next.y, t: performance.now() });
629
+ if (samples.length > 5) samples.shift();
630
+ };
631
+ const onUp = () => {
632
+ setDragging(false);
633
+ window.removeEventListener("pointermove", onMove);
634
+ window.removeEventListener("pointerup", onUp);
635
+ window.removeEventListener("pointercancel", onUp);
636
+ if (snapBack) {
637
+ animate(0, 1, {
638
+ spring: springs.subtle,
639
+ onUpdate: (t) => {
640
+ const value = { x: offsetRef.current.x * (1 - t), y: offsetRef.current.y * (1 - t) };
641
+ write(value);
642
+ },
643
+ onComplete: () => {
644
+ offsetRef.current = { x: 0, y: 0 };
645
+ write(offsetRef.current);
646
+ onDragEnd?.(offsetRef.current);
647
+ }
648
+ });
649
+ return;
650
+ }
651
+ if (useMomentum && samples.length >= 2) {
652
+ const first = samples[0];
653
+ const last = samples[samples.length - 1];
654
+ const elapsed = Math.max(1, last.t - first.t);
655
+ let velocity = {
656
+ x: (last.x - first.x) / elapsed * 1e3,
657
+ y: (last.y - first.y) / elapsed * 1e3
658
+ };
659
+ const decay = 0.95;
660
+ const stop = getTicker().add(
661
+ ({ delta }) => {
662
+ const factor = Math.pow(decay, delta * 60);
663
+ velocity = { x: velocity.x * factor, y: velocity.y * factor };
664
+ const next = clamp({
665
+ x: offsetRef.current.x + velocity.x * delta,
666
+ y: offsetRef.current.y + velocity.y * delta
667
+ });
668
+ offsetRef.current = next;
669
+ write(next);
670
+ if (Math.hypot(velocity.x, velocity.y) < 8) {
671
+ stop();
672
+ onDragEnd?.(offsetRef.current);
673
+ }
674
+ },
675
+ { phase: "write", name: "Draggable" }
676
+ );
677
+ return;
678
+ }
679
+ onDragEnd?.(offsetRef.current);
680
+ };
681
+ window.addEventListener("pointermove", onMove);
682
+ window.addEventListener("pointerup", onUp);
683
+ window.addEventListener("pointercancel", onUp);
684
+ };
685
+ return /* @__PURE__ */ jsx(
686
+ "div",
687
+ {
688
+ ref: nodeRef,
689
+ className: cx("ansh-draggable", dragging && "ansh-draggable--active", className),
690
+ style: { touchAction: axis === "x" ? "pan-y" : axis === "y" ? "pan-x" : "none", ...style },
691
+ onPointerDown,
692
+ children
693
+ }
694
+ );
695
+ }
696
+
697
+ export { AnimatePresence, AnimatedText, Draggable, GradientText, MagneticButton, Marquee, Motion, MotionConfig, Parallax, Ripple, ScrollReveal, ThemeProvider, TiltCard, createBehaviourComponent, themeScript, useBehaviour, useMotionConfig, useTheme };
698
+ //# sourceMappingURL=chunk-T4AK2KLM.js.map
699
+ //# sourceMappingURL=chunk-T4AK2KLM.js.map