@ansh-ui/vue 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 (109) hide show
  1. package/LICENSE +21 -0
  2. package/dist/chunk-2VSROZ2N.js +1281 -0
  3. package/dist/chunk-2VSROZ2N.js.map +1 -0
  4. package/dist/chunk-5BQEZYG6.cjs +1294 -0
  5. package/dist/chunk-5BQEZYG6.cjs.map +1 -0
  6. package/dist/chunk-6732H4BQ.cjs +28 -0
  7. package/dist/chunk-6732H4BQ.cjs.map +1 -0
  8. package/dist/chunk-6ABPGOJP.js +722 -0
  9. package/dist/chunk-6ABPGOJP.js.map +1 -0
  10. package/dist/chunk-6XJOB6LE.js +62 -0
  11. package/dist/chunk-6XJOB6LE.js.map +1 -0
  12. package/dist/chunk-774WBLDR.cjs +24 -0
  13. package/dist/chunk-774WBLDR.cjs.map +1 -0
  14. package/dist/chunk-B6OXKW5Q.js +567 -0
  15. package/dist/chunk-B6OXKW5Q.js.map +1 -0
  16. package/dist/chunk-DMPNT3MY.cjs +64 -0
  17. package/dist/chunk-DMPNT3MY.cjs.map +1 -0
  18. package/dist/chunk-EISHOEB6.cjs +158 -0
  19. package/dist/chunk-EISHOEB6.cjs.map +1 -0
  20. package/dist/chunk-EVO23GUS.js +223 -0
  21. package/dist/chunk-EVO23GUS.js.map +1 -0
  22. package/dist/chunk-FVKLCGA4.js +1035 -0
  23. package/dist/chunk-FVKLCGA4.js.map +1 -0
  24. package/dist/chunk-IOXGBPOV.cjs +3681 -0
  25. package/dist/chunk-IOXGBPOV.cjs.map +1 -0
  26. package/dist/chunk-J2LA4GRP.cjs +1051 -0
  27. package/dist/chunk-J2LA4GRP.cjs.map +1 -0
  28. package/dist/chunk-JQ4YLXXM.cjs +580 -0
  29. package/dist/chunk-JQ4YLXXM.cjs.map +1 -0
  30. package/dist/chunk-KCA7RNJ4.cjs +781 -0
  31. package/dist/chunk-KCA7RNJ4.cjs.map +1 -0
  32. package/dist/chunk-NJDDNO4C.js +23 -0
  33. package/dist/chunk-NJDDNO4C.js.map +1 -0
  34. package/dist/chunk-OAQ7MDYX.js +22 -0
  35. package/dist/chunk-OAQ7MDYX.js.map +1 -0
  36. package/dist/chunk-PP6OYURM.cjs +238 -0
  37. package/dist/chunk-PP6OYURM.cjs.map +1 -0
  38. package/dist/chunk-SHX2JGID.cjs +269 -0
  39. package/dist/chunk-SHX2JGID.cjs.map +1 -0
  40. package/dist/chunk-SOYRICHU.js +3645 -0
  41. package/dist/chunk-SOYRICHU.js.map +1 -0
  42. package/dist/chunk-T425FIC7.js +773 -0
  43. package/dist/chunk-T425FIC7.js.map +1 -0
  44. package/dist/chunk-TMG3M6TK.js +152 -0
  45. package/dist/chunk-TMG3M6TK.js.map +1 -0
  46. package/dist/chunk-XLLSS464.cjs +286 -0
  47. package/dist/chunk-XLLSS464.cjs.map +1 -0
  48. package/dist/chunk-XZ5ZFLZM.js +280 -0
  49. package/dist/chunk-XZ5ZFLZM.js.map +1 -0
  50. package/dist/chunk-Z7XOFKM4.cjs +733 -0
  51. package/dist/chunk-Z7XOFKM4.cjs.map +1 -0
  52. package/dist/chunk-ZGMXOMCB.js +266 -0
  53. package/dist/chunk-ZGMXOMCB.js.map +1 -0
  54. package/dist/data.cjs +70 -0
  55. package/dist/data.cjs.map +1 -0
  56. package/dist/data.d.cts +963 -0
  57. package/dist/data.d.ts +963 -0
  58. package/dist/data.js +5 -0
  59. package/dist/data.js.map +1 -0
  60. package/dist/form.cjs +151 -0
  61. package/dist/form.cjs.map +1 -0
  62. package/dist/form.d.cts +2639 -0
  63. package/dist/form.d.ts +2639 -0
  64. package/dist/form.js +6 -0
  65. package/dist/form.js.map +1 -0
  66. package/dist/index.cjs +1158 -0
  67. package/dist/index.cjs.map +1 -0
  68. package/dist/index.d.cts +439 -0
  69. package/dist/index.d.ts +439 -0
  70. package/dist/index.js +547 -0
  71. package/dist/index.js.map +1 -0
  72. package/dist/layout.cjs +67 -0
  73. package/dist/layout.cjs.map +1 -0
  74. package/dist/layout.d.cts +729 -0
  75. package/dist/layout.d.ts +729 -0
  76. package/dist/layout.js +6 -0
  77. package/dist/layout.js.map +1 -0
  78. package/dist/motion.cjs +50 -0
  79. package/dist/motion.cjs.map +1 -0
  80. package/dist/motion.d.cts +681 -0
  81. package/dist/motion.d.ts +681 -0
  82. package/dist/motion.js +5 -0
  83. package/dist/motion.js.map +1 -0
  84. package/dist/navigation.cjs +48 -0
  85. package/dist/navigation.cjs.map +1 -0
  86. package/dist/navigation.d.cts +515 -0
  87. package/dist/navigation.d.ts +515 -0
  88. package/dist/navigation.js +7 -0
  89. package/dist/navigation.js.map +1 -0
  90. package/dist/overlay.cjs +61 -0
  91. package/dist/overlay.cjs.map +1 -0
  92. package/dist/overlay.d.cts +772 -0
  93. package/dist/overlay.d.ts +772 -0
  94. package/dist/overlay.js +8 -0
  95. package/dist/overlay.js.map +1 -0
  96. package/dist/position-Cn7qP1pn.d.cts +50 -0
  97. package/dist/position-Cn7qP1pn.d.ts +50 -0
  98. package/dist/primitives.cjs +129 -0
  99. package/dist/primitives.cjs.map +1 -0
  100. package/dist/primitives.d.cts +300 -0
  101. package/dist/primitives.d.ts +300 -0
  102. package/dist/primitives.js +8 -0
  103. package/dist/primitives.js.map +1 -0
  104. package/dist/sidebar-CQqEmpid.d.cts +124 -0
  105. package/dist/sidebar-CTZ-Ckko.d.ts +124 -0
  106. package/dist/styles.css +5593 -0
  107. package/dist/utils-IKPG3zcC.d.cts +46 -0
  108. package/dist/utils-IKPG3zcC.d.ts +46 -0
  109. package/package.json +91 -0
@@ -0,0 +1,733 @@
1
+ 'use strict';
2
+
3
+ var chunkPP6OYURM_cjs = require('./chunk-PP6OYURM.cjs');
4
+ var chunk6732H4BQ_cjs = require('./chunk-6732H4BQ.cjs');
5
+ var vue = require('vue');
6
+ var core = require('@ansh-ui/core');
7
+ var tokens = require('@ansh-ui/tokens');
8
+
9
+ var VISUALLY_HIDDEN = {
10
+ position: "absolute",
11
+ width: "1px",
12
+ height: "1px",
13
+ padding: "0",
14
+ margin: "-1px",
15
+ overflow: "hidden",
16
+ clipPath: "inset(50%)",
17
+ whiteSpace: "nowrap",
18
+ borderWidth: "0"
19
+ };
20
+ var GradientText = vue.defineComponent({
21
+ name: "AnshGradientText",
22
+ props: {
23
+ text: { type: String, default: "" },
24
+ colors: {
25
+ type: [Array, String],
26
+ default: void 0
27
+ },
28
+ /** Gradient angle in degrees. */
29
+ angle: { type: Number, default: 100 },
30
+ /** Seconds per cycle. `0` holds a static gradient. */
31
+ duration: { type: Number, default: 0 },
32
+ /** Interpolated stops handed to CSS. More is smoother. */
33
+ stops: { type: Number, default: 16 },
34
+ as: { type: String, default: "span" }
35
+ },
36
+ setup(props, { slots }) {
37
+ const gradient = vue.computed(() => {
38
+ const palette = core.resolvePalette(props.colors);
39
+ const looped = props.duration > 0 ? [...palette, ...palette] : palette;
40
+ return core.createGradient(looped, { space: "oklab" }).toCss(`${props.angle}deg`, props.stops);
41
+ });
42
+ const animated = vue.computed(() => props.duration > 0 && !core.prefersReducedMotion());
43
+ return () => vue.h(
44
+ props.as,
45
+ {
46
+ style: {
47
+ backgroundImage: gradient.value,
48
+ backgroundSize: animated.value ? "200% 100%" : "100% 100%",
49
+ backgroundClip: "text",
50
+ WebkitBackgroundClip: "text",
51
+ color: "transparent",
52
+ WebkitTextFillColor: "transparent",
53
+ display: "inline-block",
54
+ ...animated.value ? { animation: `ansh-gradient-shift ${props.duration}s linear infinite` } : {}
55
+ }
56
+ },
57
+ [
58
+ slots.default?.() ?? props.text,
59
+ // The keyframes are injected inline so `<GradientText :duration="6" />` works with no
60
+ // stylesheet import. Identical rules from multiple instances are deduplicated by the
61
+ // browser, so this costs nothing at scale.
62
+ animated.value ? vue.h("style", {
63
+ innerHTML: "@keyframes ansh-gradient-shift{from{background-position:0% 50%}to{background-position:200% 50%}}"
64
+ }) : null
65
+ ]
66
+ );
67
+ }
68
+ });
69
+ var AnimatedText = vue.defineComponent({
70
+ name: "AnshAnimatedText",
71
+ props: {
72
+ text: { type: String, required: true },
73
+ /** Split granularity. */
74
+ by: { type: String, default: "chars" },
75
+ /** Seconds per unit. */
76
+ duration: { type: Number, default: 0.6 },
77
+ /** Seconds between units. */
78
+ each: { type: Number, default: 0.03 },
79
+ /** Where the reveal wave begins. */
80
+ from: { type: [String, Number], default: "first" },
81
+ easing: { type: [String, Function, Array], default: "cinematic" },
82
+ /** Distance each unit travels into place, in pixels. */
83
+ distance: { type: Number, default: 18 },
84
+ /** Starting blur in pixels — the "focus in" look. */
85
+ blur: { type: Number, default: 0 },
86
+ /** Starting rotation in degrees. */
87
+ rotate: { type: Number, default: 0 },
88
+ /** Clip each unit so it rises from behind a mask. */
89
+ mask: { type: Boolean, default: false },
90
+ /** Wait until scrolled into view. */
91
+ whenInView: { type: Boolean, default: true },
92
+ /** Replay every time it re-enters the viewport. */
93
+ repeat: { type: Boolean, default: false },
94
+ /** Seconds to wait before starting. */
95
+ delay: { type: Number, default: 0 },
96
+ as: { type: String, default: "span" }
97
+ },
98
+ emits: ["complete"],
99
+ setup(props, { emit }) {
100
+ const host = vue.ref(null);
101
+ const unitNodes = vue.ref([]);
102
+ const units = vue.computed(() => {
103
+ if (props.by === "words") {
104
+ return props.text.split(/(\s+)/).filter((token) => token.length > 0).map((token) => ({ text: token, space: /^\s+$/.test(token) }));
105
+ }
106
+ const graphemes = typeof Intl !== "undefined" && "Segmenter" in Intl ? Array.from(
107
+ new Intl.Segmenter(void 0, { granularity: "grapheme" }).segment(props.text),
108
+ (s) => s.segment
109
+ ) : Array.from(props.text);
110
+ return graphemes.map((character) => ({ text: character, space: /^\s$/.test(character) }));
111
+ });
112
+ let stopTicker = null;
113
+ let stopObserver = null;
114
+ vue.onMounted(() => {
115
+ const element = host.value;
116
+ if (!element) return;
117
+ if (core.prefersReducedMotion()) {
118
+ emit("complete");
119
+ return;
120
+ }
121
+ const ease = core.resolveEasing(props.easing);
122
+ const animatedUnits = units.value.filter((u) => !u.space);
123
+ const delayFor = core.stagger(animatedUnits.length, { each: props.each, from: props.from });
124
+ const targets = [];
125
+ let animationIndex = 0;
126
+ units.value.forEach((unit, i) => {
127
+ if (unit.space) return;
128
+ const node = unitNodes.value[i];
129
+ if (node) targets.push({ node, delay: props.delay + delayFor(animationIndex) });
130
+ animationIndex++;
131
+ });
132
+ const apply = (node, progress) => {
133
+ const eased = ease(progress);
134
+ const inverse = 1 - eased;
135
+ node.style.opacity = String(eased);
136
+ const parts = [`translate3d(0, ${(props.distance * inverse).toFixed(2)}px, 0)`];
137
+ if (props.rotate !== 0) parts.push(`rotate(${(props.rotate * inverse).toFixed(2)}deg)`);
138
+ node.style.transform = parts.join(" ");
139
+ if (props.blur > 0) {
140
+ const amount = props.blur * inverse;
141
+ node.style.filter = amount > 0.05 ? `blur(${amount.toFixed(2)}px)` : "";
142
+ }
143
+ };
144
+ const settle = (node) => {
145
+ node.style.opacity = "";
146
+ node.style.transform = "";
147
+ node.style.filter = "";
148
+ node.style.willChange = "";
149
+ };
150
+ const reset = () => {
151
+ for (const { node } of targets) apply(node, 0);
152
+ };
153
+ let elapsed = 0;
154
+ let running = false;
155
+ const start = () => {
156
+ if (running) return;
157
+ running = true;
158
+ elapsed = 0;
159
+ for (const { node } of targets) node.style.willChange = "opacity, transform";
160
+ reset();
161
+ stopTicker = core.getTicker().add(
162
+ ({ delta }) => {
163
+ elapsed += delta;
164
+ let allDone = true;
165
+ for (const target of targets) {
166
+ const local = elapsed - target.delay;
167
+ if (local < 0) {
168
+ allDone = false;
169
+ continue;
170
+ }
171
+ const progress = props.duration <= 0 ? 1 : local / props.duration;
172
+ if (progress >= 1) {
173
+ settle(target.node);
174
+ continue;
175
+ }
176
+ apply(target.node, progress);
177
+ allDone = false;
178
+ }
179
+ if (allDone) {
180
+ stopTicker?.();
181
+ stopTicker = null;
182
+ running = false;
183
+ emit("complete");
184
+ }
185
+ },
186
+ { phase: "write", name: "AnimatedText" }
187
+ );
188
+ };
189
+ reset();
190
+ if (!props.whenInView) {
191
+ start();
192
+ return;
193
+ }
194
+ stopObserver = core.observeIntersection(
195
+ element,
196
+ (entry) => {
197
+ if (entry.isIntersecting) {
198
+ start();
199
+ } else if (props.repeat) {
200
+ stopTicker?.();
201
+ stopTicker = null;
202
+ running = false;
203
+ reset();
204
+ }
205
+ },
206
+ { threshold: 0.2, rootMargin: "0px 0px -8% 0px" }
207
+ );
208
+ });
209
+ vue.onBeforeUnmount(() => {
210
+ stopObserver?.();
211
+ stopTicker?.();
212
+ stopObserver = null;
213
+ stopTicker = null;
214
+ });
215
+ return () => vue.h(props.as, { ref: host, style: { display: "inline-block" } }, [
216
+ // The accessible representation: the real string, unfragmented.
217
+ vue.h("span", { style: VISUALLY_HIDDEN }, props.text),
218
+ vue.h(
219
+ "span",
220
+ { "aria-hidden": "true" },
221
+ units.value.map((unit, i) => {
222
+ if (unit.space) return vue.h("span", {}, unit.text);
223
+ const inner = vue.h(
224
+ "span",
225
+ {
226
+ ref: (node) => {
227
+ unitNodes.value[i] = node ?? null;
228
+ },
229
+ style: { display: "inline-block" }
230
+ },
231
+ unit.text
232
+ );
233
+ return props.mask ? vue.h(
234
+ "span",
235
+ {
236
+ style: {
237
+ display: "inline-block",
238
+ overflow: "hidden",
239
+ // Without this, descenders (g, y, p) are clipped by the mask box.
240
+ verticalAlign: "top"
241
+ }
242
+ },
243
+ [inner]
244
+ ) : inner;
245
+ })
246
+ )
247
+ ]);
248
+ }
249
+ });
250
+ var DEFAULT_MOTION_CONFIG = {
251
+ reducedMotion: "auto",
252
+ timeScale: 1,
253
+ quality: null
254
+ };
255
+ var MotionConfigKey = /* @__PURE__ */ Symbol("ansh-motion-config");
256
+ var MotionConfig = vue.defineComponent({
257
+ name: "AnshMotionConfig",
258
+ props: {
259
+ reducedMotion: { type: String, default: "auto" },
260
+ timeScale: { type: Number, default: 1 },
261
+ quality: { type: Number, default: null },
262
+ /**
263
+ * Pause every animation while the document is hidden. Default `true`.
264
+ *
265
+ * Leave this on. Animating a background tab burns battery and spins fans for output nobody can
266
+ * see, and it is the most common performance complaint about animation-heavy sites.
267
+ */
268
+ pauseWhenHidden: { type: Boolean, default: true },
269
+ pauseWhenBlurred: { type: Boolean, default: false },
270
+ respectBattery: { type: Boolean, default: true }
271
+ },
272
+ setup(props, { slots }) {
273
+ vue.watch(
274
+ () => props.reducedMotion,
275
+ (mode) => core.setReducedMotionMode(mode),
276
+ { immediate: true }
277
+ );
278
+ vue.watch(
279
+ () => props.timeScale,
280
+ (scale) => {
281
+ core.getTicker().timeScale = scale;
282
+ },
283
+ { immediate: true }
284
+ );
285
+ vue.watch(
286
+ () => props.quality,
287
+ (quality) => {
288
+ if (quality !== null) core.getTicker().lockQuality(quality);
289
+ },
290
+ { immediate: true }
291
+ );
292
+ let detach = null;
293
+ vue.watch(
294
+ () => [props.pauseWhenHidden, props.pauseWhenBlurred, props.respectBattery],
295
+ ([pauseWhenHidden, pauseWhenBlurred, respectBattery]) => {
296
+ detach?.();
297
+ detach = core.attachLifecycle(core.getTicker(), { pauseWhenHidden, pauseWhenBlurred, respectBattery });
298
+ },
299
+ { immediate: true }
300
+ );
301
+ vue.onBeforeUnmount(() => detach?.());
302
+ vue.provide(
303
+ MotionConfigKey,
304
+ vue.computed(() => ({
305
+ reducedMotion: props.reducedMotion,
306
+ timeScale: props.timeScale,
307
+ quality: props.quality
308
+ }))
309
+ );
310
+ return () => slots.default?.();
311
+ }
312
+ });
313
+ function useMotionConfig() {
314
+ return vue.inject(
315
+ MotionConfigKey,
316
+ vue.computed(() => DEFAULT_MOTION_CONFIG)
317
+ );
318
+ }
319
+ var DEFAULT_THEME = { theme: "system", resolved: "light", setTheme: () => {
320
+ } };
321
+ var ThemeKey = /* @__PURE__ */ Symbol("ansh-theme");
322
+ var ThemeProvider = vue.defineComponent({
323
+ name: "AnshThemeProvider",
324
+ props: {
325
+ /** Initial setting. Default `'system'`. */
326
+ defaultTheme: { type: String, default: "system" },
327
+ /** Persist the choice under this `localStorage` key. Pass `null` to disable. */
328
+ storageKey: { type: String, default: "ansh-theme" }
329
+ },
330
+ setup(props, { slots }) {
331
+ const theme = vue.ref(props.defaultTheme);
332
+ const resolved = vue.ref("light");
333
+ const setTheme = (next) => {
334
+ theme.value = next;
335
+ };
336
+ let mediaQuery = null;
337
+ let onMediaChange = null;
338
+ const syncMedia = () => {
339
+ mediaQuery?.removeEventListener("change", onMediaChange);
340
+ mediaQuery = null;
341
+ onMediaChange = null;
342
+ if (theme.value !== "system" || typeof matchMedia !== "function") return;
343
+ mediaQuery = matchMedia("(prefers-color-scheme: dark)");
344
+ onMediaChange = () => {
345
+ resolved.value = mediaQuery.matches ? "dark" : "light";
346
+ };
347
+ mediaQuery.addEventListener("change", onMediaChange);
348
+ };
349
+ vue.watch(
350
+ theme,
351
+ (next) => {
352
+ tokens.applyTheme(next);
353
+ resolved.value = tokens.resolveTheme();
354
+ syncMedia();
355
+ if (props.storageKey) {
356
+ try {
357
+ localStorage.setItem(props.storageKey, next);
358
+ } catch {
359
+ }
360
+ }
361
+ },
362
+ { flush: "post" }
363
+ );
364
+ if (typeof document !== "undefined") {
365
+ queueMicrotask(() => {
366
+ if (!props.storageKey) return;
367
+ try {
368
+ const stored = localStorage.getItem(props.storageKey);
369
+ if (stored === "light" || stored === "dark" || stored === "system") theme.value = stored;
370
+ } catch {
371
+ }
372
+ });
373
+ tokens.applyTheme(theme.value);
374
+ resolved.value = tokens.resolveTheme();
375
+ syncMedia();
376
+ }
377
+ vue.onBeforeUnmount(() => mediaQuery?.removeEventListener("change", onMediaChange));
378
+ vue.provide(
379
+ ThemeKey,
380
+ vue.computed(() => ({ theme: theme.value, resolved: resolved.value, setTheme }))
381
+ );
382
+ return () => slots.default?.();
383
+ }
384
+ });
385
+ function useTheme() {
386
+ return vue.inject(
387
+ ThemeKey,
388
+ vue.computed(() => DEFAULT_THEME)
389
+ );
390
+ }
391
+ function themeScript(storageKey = "ansh-theme") {
392
+ return `(function(){try{var t=localStorage.getItem(${JSON.stringify(storageKey)});if(t==='light'||t==='dark'){document.documentElement.setAttribute('data-theme',t)}}catch(e){}})()`;
393
+ }
394
+ var DEFAULTS = {
395
+ opacity: 1,
396
+ x: 0,
397
+ y: 0,
398
+ scale: 1,
399
+ scaleX: 1,
400
+ scaleY: 1,
401
+ rotate: 0,
402
+ blur: 0
403
+ };
404
+ function applyValues(node, values) {
405
+ const transform = `translate3d(${values.x}px, ${values.y}px, 0) scale(${values.scale * values.scaleX}, ${values.scale * values.scaleY}) rotate(${values.rotate}deg)`;
406
+ node.style.transform = transform;
407
+ node.style.opacity = String(values.opacity);
408
+ node.style.filter = values.blur > 0 ? `blur(${values.blur}px)` : "";
409
+ }
410
+ function resolve(values, base) {
411
+ return { ...base, ...values };
412
+ }
413
+ function normalizeChildren(nodes) {
414
+ return (nodes ?? []).filter((node) => {
415
+ if (node.type === vue.Comment) return false;
416
+ if (node.type === vue.Text && typeof node.children === "string" && node.children.trim() === "") {
417
+ return false;
418
+ }
419
+ return true;
420
+ });
421
+ }
422
+ var Motion = vue.defineComponent({
423
+ name: "AnshMotion",
424
+ inheritAttrs: false,
425
+ props: {
426
+ as: { type: String, default: "div" },
427
+ /** Starting values. Applied before the first paint. */
428
+ initial: { type: Object, default: void 0 },
429
+ /** Target values. Changing these animates to the new target. */
430
+ animate: { type: Object, default: void 0 },
431
+ // Declared so it lands here rather than in `attrs`: `AnimatePresence` reads it off the vnode's
432
+ // props when the child is removed and swaps it into `animate`. Left undeclared, it would reach
433
+ // the DOM as an unknown `exit` attribute.
434
+ exit: { type: Object, default: void 0 },
435
+ transition: { type: Object, default: void 0 },
436
+ whileHover: { type: Object, default: void 0 },
437
+ whileTap: { type: Object, default: void 0 },
438
+ /** Animate to `animate` only once scrolled into view. */
439
+ whileInView: { type: Boolean, default: false },
440
+ /** Fraction visible before `whileInView` triggers. Default `0.2`. */
441
+ inViewAmount: { type: Number, default: 0.2 }
442
+ },
443
+ setup(props, { attrs, slots, expose }) {
444
+ const node = vue.ref(null);
445
+ let current = resolve(props.initial, DEFAULTS);
446
+ const start = chunkPP6OYURM_cjs.useAnimate();
447
+ expose({
448
+ get element() {
449
+ return node.value;
450
+ }
451
+ });
452
+ vue.onMounted(() => {
453
+ if (!node.value) return;
454
+ applyValues(node.value, current);
455
+ if (inView.value) runTo(resolve(props.animate, DEFAULTS));
456
+ });
457
+ const runTo = (next, options) => {
458
+ const element = node.value;
459
+ if (!element) return;
460
+ const from = { ...current };
461
+ const springOption = options?.spring ?? props.transition?.spring;
462
+ const animationOptions = {
463
+ ...(options?.delay ?? props.transition?.delay) !== void 0 ? { delay: options?.delay ?? props.transition?.delay ?? 0 } : null,
464
+ ...springOption ? {
465
+ spring: springOption === true ? core.springs.default : typeof springOption === "string" ? core.springs[springOption] : springOption
466
+ } : {
467
+ duration: options?.duration ?? props.transition?.duration ?? 0.4,
468
+ ...options?.easing ?? props.transition?.easing ? { easing: options?.easing ?? props.transition?.easing } : null
469
+ },
470
+ onUpdate: (t) => {
471
+ const frame = {};
472
+ for (const key of Object.keys(DEFAULTS)) {
473
+ frame[key] = from[key] + (next[key] - from[key]) * t;
474
+ }
475
+ current = frame;
476
+ applyValues(element, frame);
477
+ },
478
+ onComplete: () => {
479
+ current = next;
480
+ applyValues(element, next);
481
+ }
482
+ };
483
+ start(0, 1, animationOptions);
484
+ };
485
+ const inViewState = chunkPP6OYURM_cjs.useInView(node, { threshold: props.inViewAmount, once: true });
486
+ const inView = vue.computed(() => !props.whileInView || inViewState.value);
487
+ vue.watch(
488
+ [() => JSON.stringify(props.animate ?? null), inView],
489
+ ([, isInView]) => {
490
+ if (!isInView) return;
491
+ runTo(resolve(props.animate, DEFAULTS));
492
+ },
493
+ { flush: "post" }
494
+ );
495
+ return () => {
496
+ const { class: attrClass, style: attrStyle, ...restAttrs } = attrs;
497
+ const interaction = {};
498
+ if (props.whileHover) {
499
+ interaction.onMouseenter = () => runTo(resolve({ ...props.animate, ...props.whileHover }, DEFAULTS));
500
+ interaction.onMouseleave = () => runTo(resolve(props.animate, DEFAULTS));
501
+ }
502
+ if (props.whileTap) {
503
+ interaction.onPointerdown = () => runTo(resolve({ ...props.animate, ...props.whileTap }, DEFAULTS), { duration: 0.12 });
504
+ interaction.onPointerup = () => runTo(resolve({ ...props.animate, ...props.whileHover }, DEFAULTS));
505
+ }
506
+ return vue.h(
507
+ props.as,
508
+ {
509
+ ref: node,
510
+ class: attrClass,
511
+ // `will-change` is set once, statically. Toggling it per animation causes the compositor
512
+ // to create and destroy a layer on every interaction, which is more expensive than the
513
+ // hint saves.
514
+ style: [{ willChange: "transform, opacity" }, attrStyle],
515
+ ...interaction,
516
+ ...restAttrs
517
+ },
518
+ slots.default?.()
519
+ );
520
+ };
521
+ }
522
+ });
523
+ var AnimatePresence = vue.defineComponent({
524
+ name: "AnshAnimatePresence",
525
+ props: {
526
+ exitDuration: { type: Number, default: 0.35 }
527
+ },
528
+ setup(props, { slots }) {
529
+ const currentChildren = vue.computed(() => normalizeChildren(slots.default?.()));
530
+ const keyOf = (node) => String(node.key);
531
+ const keysSignature = vue.computed(() => currentChildren.value.map(keyOf).join("|"));
532
+ const rendered = vue.ref(currentChildren.value);
533
+ const timers = /* @__PURE__ */ new Map();
534
+ vue.watch(
535
+ [keysSignature, () => props.exitDuration],
536
+ () => {
537
+ const next = currentChildren.value;
538
+ const nextKeys = new Set(next.map(keyOf));
539
+ const departing = rendered.value.filter((node) => !nextKeys.has(keyOf(node)));
540
+ if (departing.length === 0) {
541
+ rendered.value = next;
542
+ return;
543
+ }
544
+ rendered.value = [...next, ...departing];
545
+ const delay = core.prefersReducedMotion() ? 0 : props.exitDuration * 1e3;
546
+ for (const node of departing) {
547
+ const key = keyOf(node);
548
+ const existing = timers.get(key);
549
+ if (existing !== void 0) clearTimeout(existing);
550
+ timers.set(
551
+ key,
552
+ setTimeout(() => {
553
+ rendered.value = rendered.value.filter((entry) => keyOf(entry) !== key);
554
+ timers.delete(key);
555
+ }, delay)
556
+ );
557
+ }
558
+ },
559
+ { flush: "post" }
560
+ );
561
+ vue.onScopeDispose(() => {
562
+ for (const timer of timers.values()) clearTimeout(timer);
563
+ timers.clear();
564
+ });
565
+ return () => {
566
+ const nextKeys = new Set(currentChildren.value.map(keyOf));
567
+ return rendered.value.map((node) => {
568
+ const leaving = !nextKeys.has(keyOf(node));
569
+ if (!leaving) return node;
570
+ const nodeProps = node.props ?? {};
571
+ return vue.cloneVNode(node, {
572
+ animate: nodeProps.exit ?? { opacity: 0, scale: 0.96 },
573
+ transition: { duration: props.exitDuration, ...nodeProps.transition }
574
+ });
575
+ });
576
+ };
577
+ }
578
+ });
579
+ var Draggable = vue.defineComponent({
580
+ name: "AnshDraggable",
581
+ inheritAttrs: false,
582
+ props: {
583
+ axis: { type: String, default: "both" },
584
+ bounds: {
585
+ type: Object,
586
+ default: void 0
587
+ },
588
+ snapBack: { type: Boolean, default: false },
589
+ momentum: { type: Boolean, default: void 0 }
590
+ },
591
+ emits: ["dragStart", "dragEnd"],
592
+ setup(props, { attrs, slots, emit, expose }) {
593
+ const node = vue.ref(null);
594
+ let offset = { x: 0, y: 0 };
595
+ const dragging = vue.ref(false);
596
+ const runAnimation = chunkPP6OYURM_cjs.useAnimate();
597
+ let stopMomentum = null;
598
+ vue.onScopeDispose(() => stopMomentum?.());
599
+ expose({
600
+ get element() {
601
+ return node.value;
602
+ },
603
+ get offset() {
604
+ return offset;
605
+ }
606
+ });
607
+ const clamp = (value) => ({
608
+ x: Math.min(
609
+ Math.max(value.x, props.bounds?.left ?? -Infinity),
610
+ props.bounds?.right ?? Infinity
611
+ ),
612
+ y: Math.min(
613
+ Math.max(value.y, props.bounds?.top ?? -Infinity),
614
+ props.bounds?.bottom ?? Infinity
615
+ )
616
+ });
617
+ const write = (value) => {
618
+ if (node.value) node.value.style.transform = `translate3d(${value.x}px, ${value.y}px, 0)`;
619
+ };
620
+ const onPointerdown = (event) => {
621
+ stopMomentum?.();
622
+ stopMomentum = null;
623
+ event.currentTarget.setPointerCapture(event.pointerId);
624
+ dragging.value = true;
625
+ emit("dragStart");
626
+ const useMomentum = props.momentum ?? !props.snapBack;
627
+ const start = { x: event.clientX, y: event.clientY };
628
+ const origin = { ...offset };
629
+ const samples = [];
630
+ const onMove = (moveEvent) => {
631
+ const next = clamp({
632
+ x: props.axis === "y" ? origin.x : origin.x + (moveEvent.clientX - start.x),
633
+ y: props.axis === "x" ? origin.y : origin.y + (moveEvent.clientY - start.y)
634
+ });
635
+ offset = next;
636
+ write(next);
637
+ samples.push({ x: next.x, y: next.y, t: performance.now() });
638
+ if (samples.length > 5) samples.shift();
639
+ };
640
+ const onUp = () => {
641
+ dragging.value = false;
642
+ window.removeEventListener("pointermove", onMove);
643
+ window.removeEventListener("pointerup", onUp);
644
+ window.removeEventListener("pointercancel", onUp);
645
+ if (props.snapBack) {
646
+ runAnimation(0, 1, {
647
+ spring: core.springs.subtle,
648
+ onUpdate: (t) => {
649
+ const value = { x: offset.x * (1 - t), y: offset.y * (1 - t) };
650
+ write(value);
651
+ },
652
+ onComplete: () => {
653
+ offset = { x: 0, y: 0 };
654
+ write(offset);
655
+ emit("dragEnd", offset);
656
+ }
657
+ });
658
+ return;
659
+ }
660
+ if (useMomentum && samples.length >= 2) {
661
+ const first = samples[0];
662
+ const last = samples[samples.length - 1];
663
+ const elapsed = Math.max(1, last.t - first.t);
664
+ let velocity = {
665
+ x: (last.x - first.x) / elapsed * 1e3,
666
+ y: (last.y - first.y) / elapsed * 1e3
667
+ };
668
+ const decay = 0.95;
669
+ const stop = core.getTicker().add(
670
+ ({ delta }) => {
671
+ const factor = Math.pow(decay, delta * 60);
672
+ velocity = { x: velocity.x * factor, y: velocity.y * factor };
673
+ const next = clamp({
674
+ x: offset.x + velocity.x * delta,
675
+ y: offset.y + velocity.y * delta
676
+ });
677
+ offset = next;
678
+ write(next);
679
+ if (Math.hypot(velocity.x, velocity.y) < 8) {
680
+ stop();
681
+ stopMomentum = null;
682
+ emit("dragEnd", offset);
683
+ }
684
+ },
685
+ { phase: "write", name: "Draggable" }
686
+ );
687
+ stopMomentum = stop;
688
+ return;
689
+ }
690
+ emit("dragEnd", offset);
691
+ };
692
+ window.addEventListener("pointermove", onMove);
693
+ window.addEventListener("pointerup", onUp);
694
+ window.addEventListener("pointercancel", onUp);
695
+ };
696
+ return () => {
697
+ const { class: attrClass, style: attrStyle, ...restAttrs } = attrs;
698
+ return vue.h(
699
+ "div",
700
+ {
701
+ ref: node,
702
+ class: chunk6732H4BQ_cjs.cx(
703
+ "ansh-draggable",
704
+ dragging.value && "ansh-draggable--active",
705
+ attrClass
706
+ ),
707
+ style: [
708
+ {
709
+ touchAction: props.axis === "x" ? "pan-y" : props.axis === "y" ? "pan-x" : "none"
710
+ },
711
+ attrStyle
712
+ ],
713
+ onPointerdown,
714
+ ...restAttrs
715
+ },
716
+ slots.default?.()
717
+ );
718
+ };
719
+ }
720
+ });
721
+
722
+ exports.AnimatePresence = AnimatePresence;
723
+ exports.AnimatedText = AnimatedText;
724
+ exports.Draggable = Draggable;
725
+ exports.GradientText = GradientText;
726
+ exports.Motion = Motion;
727
+ exports.MotionConfig = MotionConfig;
728
+ exports.ThemeProvider = ThemeProvider;
729
+ exports.themeScript = themeScript;
730
+ exports.useMotionConfig = useMotionConfig;
731
+ exports.useTheme = useTheme;
732
+ //# sourceMappingURL=chunk-Z7XOFKM4.cjs.map
733
+ //# sourceMappingURL=chunk-Z7XOFKM4.cjs.map