@mks2508/mks-ui 0.2.1 → 0.3.1

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 (155) hide show
  1. package/dist/react-ui/hooks/Animation/UseAutoHeight.js +7 -7
  2. package/dist/react-ui/hooks/DOM/UseIsInView.js +3 -3
  3. package/dist/react-ui/hooks/Formatting/UseListFormat.d.ts +49 -0
  4. package/dist/react-ui/hooks/Formatting/UseListFormat.d.ts.map +1 -0
  5. package/dist/react-ui/hooks/Formatting/UseListFormat.js +105 -0
  6. package/dist/react-ui/hooks/State/UseControlledState.js +4 -4
  7. package/dist/react-ui/hooks/State/UseDataState.js +5 -5
  8. package/dist/react-ui/hooks/index.d.ts +2 -0
  9. package/dist/react-ui/hooks/index.d.ts.map +1 -1
  10. package/dist/react-ui/hooks/index.js +1 -0
  11. package/dist/react-ui/index.js +22 -2
  12. package/dist/react-ui/lib/get-strict-context.js +3 -3
  13. package/dist/react-ui/primitives/CountingNumber/index.js +3 -3
  14. package/dist/react-ui/primitives/Highlight/index.js +26 -26
  15. package/dist/react-ui/primitives/Slot/index.js +3 -3
  16. package/dist/react-ui/primitives/index.d.ts +1 -0
  17. package/dist/react-ui/primitives/index.d.ts.map +1 -1
  18. package/dist/react-ui/primitives/index.js +18 -0
  19. package/dist/react-ui/primitives/waapi/Morph/Morph.types.d.ts +76 -0
  20. package/dist/react-ui/primitives/waapi/Morph/Morph.types.d.ts.map +1 -0
  21. package/dist/react-ui/primitives/waapi/Morph/MorphContext.d.ts +11 -0
  22. package/dist/react-ui/primitives/waapi/Morph/MorphContext.d.ts.map +1 -0
  23. package/dist/react-ui/primitives/waapi/Morph/MorphContext.js +19 -0
  24. package/dist/react-ui/primitives/waapi/Morph/index.d.ts +23 -0
  25. package/dist/react-ui/primitives/waapi/Morph/index.d.ts.map +1 -0
  26. package/dist/react-ui/primitives/waapi/Morph/index.js +45 -0
  27. package/dist/react-ui/primitives/waapi/Morph/techniques/index.d.ts +12 -0
  28. package/dist/react-ui/primitives/waapi/Morph/techniques/index.d.ts.map +1 -0
  29. package/dist/react-ui/primitives/waapi/Morph/techniques/useCSSGridMorph.d.ts +38 -0
  30. package/dist/react-ui/primitives/waapi/Morph/techniques/useCSSGridMorph.d.ts.map +1 -0
  31. package/dist/react-ui/primitives/waapi/Morph/techniques/useCSSGridMorph.js +78 -0
  32. package/dist/react-ui/primitives/waapi/Morph/techniques/useFLIPClipPath.d.ts +23 -0
  33. package/dist/react-ui/primitives/waapi/Morph/techniques/useFLIPClipPath.d.ts.map +1 -0
  34. package/dist/react-ui/primitives/waapi/Morph/techniques/useFLIPClipPath.js +140 -0
  35. package/dist/react-ui/primitives/waapi/Morph/techniques/useViewTransitions.d.ts +28 -0
  36. package/dist/react-ui/primitives/waapi/Morph/techniques/useViewTransitions.d.ts.map +1 -0
  37. package/dist/react-ui/primitives/waapi/Morph/techniques/useViewTransitions.js +77 -0
  38. package/dist/react-ui/primitives/waapi/Morph/useMorph.d.ts +27 -0
  39. package/dist/react-ui/primitives/waapi/Morph/useMorph.d.ts.map +1 -0
  40. package/dist/react-ui/primitives/waapi/Morph/useMorph.js +86 -0
  41. package/dist/react-ui/primitives/waapi/Reorder/Reorder.types.d.ts +168 -0
  42. package/dist/react-ui/primitives/waapi/Reorder/Reorder.types.d.ts.map +1 -0
  43. package/dist/react-ui/primitives/waapi/Reorder/index.d.ts +25 -0
  44. package/dist/react-ui/primitives/waapi/Reorder/index.d.ts.map +1 -0
  45. package/dist/react-ui/primitives/waapi/Reorder/index.js +186 -0
  46. package/dist/react-ui/primitives/waapi/Reorder/useReorder.d.ts +26 -0
  47. package/dist/react-ui/primitives/waapi/Reorder/useReorder.d.ts.map +1 -0
  48. package/dist/react-ui/primitives/waapi/Reorder/useReorder.js +48 -0
  49. package/dist/react-ui/primitives/waapi/Reorder/useReorderPresence.d.ts +33 -0
  50. package/dist/react-ui/primitives/waapi/Reorder/useReorderPresence.d.ts.map +1 -0
  51. package/dist/react-ui/primitives/waapi/Reorder/useReorderPresence.js +137 -0
  52. package/dist/react-ui/primitives/waapi/Reorder/utils/separatorCoordination.d.ts +47 -0
  53. package/dist/react-ui/primitives/waapi/Reorder/utils/separatorCoordination.d.ts.map +1 -0
  54. package/dist/react-ui/primitives/waapi/Reorder/utils/separatorCoordination.js +72 -0
  55. package/dist/react-ui/primitives/waapi/SlidingNumber/SlidingNumber.styles.d.ts +10 -0
  56. package/dist/react-ui/primitives/waapi/SlidingNumber/SlidingNumber.styles.d.ts.map +1 -0
  57. package/dist/react-ui/primitives/waapi/SlidingNumber/SlidingNumber.types.d.ts +74 -0
  58. package/dist/react-ui/primitives/waapi/SlidingNumber/SlidingNumber.types.d.ts.map +1 -0
  59. package/dist/react-ui/primitives/waapi/SlidingNumber/index.d.ts +33 -0
  60. package/dist/react-ui/primitives/waapi/SlidingNumber/index.d.ts.map +1 -0
  61. package/dist/react-ui/primitives/waapi/SlidingNumber/index.js +354 -0
  62. package/dist/react-ui/primitives/waapi/SlidingText/SlidingText.styles.d.ts +25 -0
  63. package/dist/react-ui/primitives/waapi/SlidingText/SlidingText.styles.d.ts.map +1 -0
  64. package/dist/react-ui/primitives/waapi/SlidingText/SlidingText.types.d.ts +57 -0
  65. package/dist/react-ui/primitives/waapi/SlidingText/SlidingText.types.d.ts.map +1 -0
  66. package/dist/react-ui/primitives/waapi/SlidingText/index.d.ts +26 -0
  67. package/dist/react-ui/primitives/waapi/SlidingText/index.d.ts.map +1 -0
  68. package/dist/react-ui/primitives/waapi/SlidingText/index.js +105 -0
  69. package/dist/react-ui/primitives/waapi/core/animationConstants.d.ts +156 -0
  70. package/dist/react-ui/primitives/waapi/core/animationConstants.d.ts.map +1 -0
  71. package/dist/react-ui/primitives/waapi/core/animationConstants.js +180 -0
  72. package/dist/react-ui/primitives/waapi/core/index.d.ts +16 -0
  73. package/dist/react-ui/primitives/waapi/core/index.d.ts.map +1 -0
  74. package/dist/react-ui/primitives/waapi/core/index.js +5 -0
  75. package/dist/react-ui/primitives/waapi/core/types.d.ts +143 -0
  76. package/dist/react-ui/primitives/waapi/core/types.d.ts.map +1 -0
  77. package/dist/react-ui/primitives/waapi/core/useAnimationOrchestrator.d.ts +32 -0
  78. package/dist/react-ui/primitives/waapi/core/useAnimationOrchestrator.d.ts.map +1 -0
  79. package/dist/react-ui/primitives/waapi/core/useAnimationOrchestrator.js +322 -0
  80. package/dist/react-ui/primitives/waapi/core/useElementRegistry.d.ts +21 -0
  81. package/dist/react-ui/primitives/waapi/core/useElementRegistry.d.ts.map +1 -0
  82. package/dist/react-ui/primitives/waapi/core/useElementRegistry.js +65 -0
  83. package/dist/react-ui/primitives/waapi/core/useFLIPAnimation.d.ts +20 -0
  84. package/dist/react-ui/primitives/waapi/core/useFLIPAnimation.d.ts.map +1 -0
  85. package/dist/react-ui/primitives/waapi/core/useFLIPAnimation.js +99 -0
  86. package/dist/react-ui/primitives/waapi/core/usePositionCapture.d.ts +24 -0
  87. package/dist/react-ui/primitives/waapi/core/usePositionCapture.d.ts.map +1 -0
  88. package/dist/react-ui/primitives/waapi/core/usePositionCapture.js +75 -0
  89. package/dist/react-ui/primitives/waapi/index.d.ts +33 -0
  90. package/dist/react-ui/primitives/waapi/index.d.ts.map +1 -0
  91. package/dist/react-ui/primitives/waapi/index.js +18 -0
  92. package/dist/react-ui/ui/Accordion/index.js +3 -3
  93. package/dist/react-ui/ui/Button/index.js +8 -8
  94. package/dist/react-ui/ui/Combobox/index.js +2 -2
  95. package/dist/react-ui/ui/DataCard/DataCard.styles.d.ts +35 -0
  96. package/dist/react-ui/ui/DataCard/DataCard.styles.d.ts.map +1 -0
  97. package/dist/react-ui/ui/DataCard/DataCard.styles.js +114 -0
  98. package/dist/react-ui/ui/DataCard/DataCard.types.d.ts +135 -0
  99. package/dist/react-ui/ui/DataCard/DataCard.types.d.ts.map +1 -0
  100. package/dist/react-ui/ui/DataCard/index.d.ts +129 -0
  101. package/dist/react-ui/ui/DataCard/index.d.ts.map +1 -0
  102. package/dist/react-ui/ui/DataCard/index.js +276 -0
  103. package/dist/react-ui/ui/Menu/index.js +2 -2
  104. package/dist/react-ui/ui/Switch/index.js +3 -3
  105. package/dist/react-ui/ui/Tabs/index.js +3 -3
  106. package/dist/react-ui/ui/TextFlow/TextFlow.styles.d.ts +16 -0
  107. package/dist/react-ui/ui/TextFlow/TextFlow.styles.d.ts.map +1 -0
  108. package/dist/react-ui/ui/TextFlow/TextFlow.types.d.ts +101 -0
  109. package/dist/react-ui/ui/TextFlow/TextFlow.types.d.ts.map +1 -0
  110. package/dist/react-ui/ui/TextFlow/index.d.ts +26 -0
  111. package/dist/react-ui/ui/TextFlow/index.d.ts.map +1 -0
  112. package/dist/react-ui/ui/TextFlow/index.js +187 -0
  113. package/dist/react-ui/ui/index.d.ts +2 -1
  114. package/dist/react-ui/ui/index.d.ts.map +1 -1
  115. package/dist/react-ui/ui/index.js +3 -1
  116. package/package.json +6 -2
  117. package/src/react-ui/hooks/Formatting/UseListFormat.ts +134 -0
  118. package/src/react-ui/hooks/index.ts +3 -0
  119. package/src/react-ui/primitives/index.ts +3 -0
  120. package/src/react-ui/primitives/waapi/Morph/Morph.types.ts +106 -0
  121. package/src/react-ui/primitives/waapi/Morph/MorphContext.tsx +21 -0
  122. package/src/react-ui/primitives/waapi/Morph/index.tsx +56 -0
  123. package/src/react-ui/primitives/waapi/Morph/techniques/index.ts +12 -0
  124. package/src/react-ui/primitives/waapi/Morph/techniques/useCSSGridMorph.ts +88 -0
  125. package/src/react-ui/primitives/waapi/Morph/techniques/useFLIPClipPath.ts +175 -0
  126. package/src/react-ui/primitives/waapi/Morph/techniques/useViewTransitions.ts +86 -0
  127. package/src/react-ui/primitives/waapi/Morph/useMorph.ts +100 -0
  128. package/src/react-ui/primitives/waapi/Reorder/Reorder.types.ts +177 -0
  129. package/src/react-ui/primitives/waapi/Reorder/index.tsx +260 -0
  130. package/src/react-ui/primitives/waapi/Reorder/useReorder.ts +46 -0
  131. package/src/react-ui/primitives/waapi/Reorder/useReorderPresence.ts +208 -0
  132. package/src/react-ui/primitives/waapi/Reorder/utils/separatorCoordination.ts +104 -0
  133. package/src/react-ui/primitives/waapi/SlidingNumber/SlidingNumber.styles.ts +14 -0
  134. package/src/react-ui/primitives/waapi/SlidingNumber/SlidingNumber.types.ts +84 -0
  135. package/src/react-ui/primitives/waapi/SlidingNumber/index.tsx +474 -0
  136. package/src/react-ui/primitives/waapi/SlidingText/SlidingText.styles.ts +32 -0
  137. package/src/react-ui/primitives/waapi/SlidingText/SlidingText.types.ts +69 -0
  138. package/src/react-ui/primitives/waapi/SlidingText/index.tsx +140 -0
  139. package/src/react-ui/primitives/waapi/core/animationConstants.ts +215 -0
  140. package/src/react-ui/primitives/waapi/core/index.ts +53 -0
  141. package/src/react-ui/primitives/waapi/core/types.ts +200 -0
  142. package/src/react-ui/primitives/waapi/core/useAnimationOrchestrator.ts +429 -0
  143. package/src/react-ui/primitives/waapi/core/useElementRegistry.ts +80 -0
  144. package/src/react-ui/primitives/waapi/core/useFLIPAnimation.ts +137 -0
  145. package/src/react-ui/primitives/waapi/core/usePositionCapture.ts +105 -0
  146. package/src/react-ui/primitives/waapi/index.ts +116 -0
  147. package/src/react-ui/styles/animations.css +369 -0
  148. package/src/react-ui/ui/DataCard/DataCard.styles.ts +150 -0
  149. package/src/react-ui/ui/DataCard/DataCard.types.ts +146 -0
  150. package/src/react-ui/ui/DataCard/index.tsx +406 -0
  151. package/src/react-ui/ui/TextFlow/TextFlow.styles.ts +36 -0
  152. package/src/react-ui/ui/TextFlow/TextFlow.types.ts +118 -0
  153. package/src/react-ui/ui/TextFlow/index.tsx +276 -0
  154. package/src/react-ui/ui/index.ts +4 -1
  155. /package/dist/react-ui/components/MorphingPopover/{morphing-popover.module-CgbYV_HS.css → morphing-popover.module-BycNI8nU.css} +0 -0
@@ -0,0 +1,354 @@
1
+ "use client";
2
+
3
+ import { cn } from "../../../lib/utils.js";
4
+ import React, { useEffect, useLayoutEffect, useMemo, useRef } from "react";
5
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
+
7
+ //#region src/react-ui/primitives/waapi/SlidingNumber/index.tsx
8
+ /**
9
+ * SlidingNumber - Animated number transitions with format preservation
10
+ *
11
+ * Uses WAAPI slot-machine-style animation with optional motion blur.
12
+ * Supports Intl.NumberFormat for currency, percentage, and decimal formatting.
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * // Basic counter
17
+ * <SlidingNumber value={1234} />
18
+ *
19
+ * // Currency with animation
20
+ * <SlidingNumber
21
+ * value={99.99}
22
+ * format={{ style: 'currency', currency: 'USD' }}
23
+ * duration={700}
24
+ * />
25
+ *
26
+ * // Percentage
27
+ * <SlidingNumber
28
+ * value={75.5}
29
+ * format={{ style: 'percent' }}
30
+ * />
31
+ * ```
32
+ */
33
+ const SlidingNumber = ({ value, duration = 700, fontSize = "3rem", fontWeight = "700", color = "#000", digitHeight = 60, stagger = 30, motionBlur = true, format, trend = 0, animationConfig }) => {
34
+ const computedEasing = useMemo(() => {
35
+ if (animationConfig) {
36
+ const { overshoot = 1, stiffness = 1, mass = 1 } = animationConfig;
37
+ const p1 = .34 * stiffness;
38
+ const p2 = 1 + .56 * overshoot;
39
+ const p3 = .64 / mass;
40
+ return `cubic-bezier(${Math.min(p1, 1).toFixed(2)}, ${Math.min(p2, 2).toFixed(2)}, ${Math.min(p3, 1).toFixed(2)}, 1)`;
41
+ }
42
+ return "cubic-bezier(0.34, 1.56, 0.64, 1)";
43
+ }, [animationConfig]);
44
+ const currentChars = useMemo(() => parseNumberToChars(value, format), [value, format]);
45
+ const prevKeysRef = useRef(/* @__PURE__ */ new Set());
46
+ const isFirstRenderRef = useRef(true);
47
+ const enteringKeys = useMemo(() => {
48
+ if (isFirstRenderRef.current) return /* @__PURE__ */ new Set();
49
+ const entering = /* @__PURE__ */ new Set();
50
+ currentChars.forEach((c) => {
51
+ if (!prevKeysRef.current.has(c.key)) entering.add(c.key);
52
+ });
53
+ return entering;
54
+ }, [currentChars]);
55
+ useEffect(() => {
56
+ isFirstRenderRef.current = false;
57
+ prevKeysRef.current = new Set(currentChars.map((c) => c.key));
58
+ }, [currentChars]);
59
+ const getDelay = (position) => {
60
+ return (Math.abs(position) - 1) * stagger;
61
+ };
62
+ return /* @__PURE__ */ jsx("div", {
63
+ className: cn("waapi-sliding-number"),
64
+ style: {
65
+ display: "inline-flex",
66
+ alignItems: "center",
67
+ fontSize,
68
+ fontWeight,
69
+ color,
70
+ fontVariantNumeric: "tabular-nums",
71
+ fontFamily: "system-ui, -apple-system, sans-serif",
72
+ overflow: "hidden"
73
+ },
74
+ children: currentChars.map((item) => {
75
+ const isEntering = enteringKeys.has(item.key);
76
+ if (item.isDigit) return /* @__PURE__ */ jsx(Digit, {
77
+ digit: Number.parseInt(item.char),
78
+ duration,
79
+ digitHeight,
80
+ delay: getDelay(item.position),
81
+ motionBlur,
82
+ easing: computedEasing,
83
+ isEntering,
84
+ trend
85
+ }, item.key);
86
+ return /* @__PURE__ */ jsx(Symbol, {
87
+ char: item.char,
88
+ isEntering,
89
+ duration,
90
+ easing: computedEasing
91
+ }, item.key);
92
+ })
93
+ });
94
+ };
95
+ SlidingNumber.displayName = "SlidingNumber";
96
+ function parseNumberToChars(value, format) {
97
+ const locale = format?.locale || "en-US";
98
+ const options = {
99
+ style: format?.style || "decimal",
100
+ minimumFractionDigits: format?.minimumFractionDigits,
101
+ maximumFractionDigits: format?.maximumFractionDigits,
102
+ useGrouping: format?.useGrouping ?? true
103
+ };
104
+ if (format?.style === "currency" && format?.currency) options.currency = format.currency;
105
+ const parts = new Intl.NumberFormat(locale, options).formatToParts(value);
106
+ const result = [];
107
+ let integerDigitCount = 0;
108
+ parts.forEach((part) => {
109
+ if (part.type === "integer") integerDigitCount += part.value.length;
110
+ });
111
+ let integerIndex = integerDigitCount;
112
+ let fractionIndex = 0;
113
+ let groupCount = 0;
114
+ parts.forEach((part, partIdx) => {
115
+ if (part.type === "integer") for (const char of part.value) {
116
+ result.push({
117
+ char,
118
+ key: `int-${integerIndex}`,
119
+ isDigit: true,
120
+ position: integerIndex
121
+ });
122
+ integerIndex--;
123
+ }
124
+ else if (part.type === "fraction") for (const char of part.value) {
125
+ fractionIndex++;
126
+ result.push({
127
+ char,
128
+ key: `frac-${fractionIndex}`,
129
+ isDigit: true,
130
+ position: -fractionIndex
131
+ });
132
+ }
133
+ else if (part.type === "decimal") result.push({
134
+ char: part.value,
135
+ key: "decimal",
136
+ isDigit: false,
137
+ position: 0
138
+ });
139
+ else if (part.type === "group") {
140
+ groupCount++;
141
+ result.push({
142
+ char: part.value,
143
+ key: `group-${groupCount}`,
144
+ isDigit: false,
145
+ position: 0
146
+ });
147
+ } else if (part.type === "currency") result.push({
148
+ char: part.value,
149
+ key: `currency-${partIdx}`,
150
+ isDigit: false,
151
+ position: 0
152
+ });
153
+ else if (part.type === "percentSign") result.push({
154
+ char: part.value,
155
+ key: "percent",
156
+ isDigit: false,
157
+ position: 0
158
+ });
159
+ else result.push({
160
+ char: part.value,
161
+ key: `symbol-${partIdx}`,
162
+ isDigit: false,
163
+ position: 0
164
+ });
165
+ });
166
+ return result;
167
+ }
168
+ function Symbol({ char, isEntering, duration, easing }) {
169
+ const ref = useRef(null);
170
+ const hasAnimatedRef = useRef(false);
171
+ useLayoutEffect(() => {
172
+ if (!ref.current || !isEntering || hasAnimatedRef.current) return;
173
+ hasAnimatedRef.current = true;
174
+ ref.current.animate([{
175
+ opacity: 0,
176
+ transform: "scale(0.8)"
177
+ }, {
178
+ opacity: 1,
179
+ transform: "scale(1)"
180
+ }], {
181
+ duration: duration * .3,
182
+ easing,
183
+ fill: "forwards"
184
+ });
185
+ }, [
186
+ isEntering,
187
+ duration,
188
+ easing
189
+ ]);
190
+ return /* @__PURE__ */ jsx("span", {
191
+ ref,
192
+ style: {
193
+ display: "inline-block",
194
+ whiteSpace: "pre",
195
+ opacity: isEntering ? 0 : 1
196
+ },
197
+ children: char
198
+ });
199
+ }
200
+ function Digit({ digit, duration, digitHeight, delay, motionBlur, easing, isEntering, trend }) {
201
+ const columnRef = useRef(null);
202
+ const containerRef = useRef(null);
203
+ const animationRef = useRef(null);
204
+ const filterId = useRef(`blur-${Math.random().toString(36).slice(2, 9)}`).current;
205
+ const currentOffsetRef = useRef(null);
206
+ const targetDigitRef = useRef(digit);
207
+ const hasInitializedRef = useRef(false);
208
+ const sequence = useMemo(() => {
209
+ const seq = [];
210
+ for (let cycle = -1; cycle <= 1; cycle++) for (let d = 0; d <= 9; d++) seq.push(d);
211
+ return seq;
212
+ }, []);
213
+ useLayoutEffect(() => {
214
+ if (!hasInitializedRef.current) {
215
+ hasInitializedRef.current = true;
216
+ const offset = -(digit + 10) * digitHeight;
217
+ currentOffsetRef.current = offset;
218
+ targetDigitRef.current = digit;
219
+ if (columnRef.current) columnRef.current.style.transform = `translateY(${offset}px)`;
220
+ }
221
+ }, [digit, digitHeight]);
222
+ useLayoutEffect(() => {
223
+ if (!containerRef.current || !isEntering) return;
224
+ containerRef.current.animate([{
225
+ opacity: 0,
226
+ transform: "scale(0.5) translateY(-20px)"
227
+ }, {
228
+ opacity: 1,
229
+ transform: "scale(1) translateY(0)"
230
+ }], {
231
+ duration: duration * .4,
232
+ easing,
233
+ fill: "forwards"
234
+ });
235
+ }, [
236
+ isEntering,
237
+ duration,
238
+ easing
239
+ ]);
240
+ useEffect(() => {
241
+ targetDigitRef.current = digit;
242
+ if (!hasInitializedRef.current) return;
243
+ if (digit === (currentOffsetRef.current !== null ? ((Math.round(-currentOffsetRef.current / digitHeight) - 10) % 10 + 10) % 10 : digit) && currentOffsetRef.current !== null) return;
244
+ animateToDigit(digit);
245
+ }, [digit, digitHeight]);
246
+ const animateToDigit = (target) => {
247
+ if (!columnRef.current || !containerRef.current) return;
248
+ if (animationRef.current) {
249
+ const computedStyle = getComputedStyle(columnRef.current);
250
+ currentOffsetRef.current = new DOMMatrix(computedStyle.transform).m42;
251
+ animationRef.current.cancel();
252
+ animationRef.current = null;
253
+ columnRef.current.style.transform = `translateY(${currentOffsetRef.current}px)`;
254
+ }
255
+ const rawIndex = currentOffsetRef.current !== null ? -currentOffsetRef.current / digitHeight : target + 10;
256
+ const from = ((Math.round(rawIndex) - 10) % 10 + 10) % 10;
257
+ if (target === from && currentOffsetRef.current !== null) {
258
+ const normalizedOffset = -(target + 10) * digitHeight;
259
+ if (columnRef.current) {
260
+ const currentAnim = animationRef.current;
261
+ if (currentAnim) currentAnim.cancel();
262
+ columnRef.current.style.transform = `translateY(${normalizedOffset}px)`;
263
+ }
264
+ currentOffsetRef.current = normalizedOffset;
265
+ return;
266
+ }
267
+ let diff;
268
+ if (trend === 1) diff = target >= from ? target - from : 10 - from + target;
269
+ else if (trend === -1) diff = target <= from ? target - from : target - from - 10;
270
+ else {
271
+ diff = target - from;
272
+ if (diff > 5) diff -= 10;
273
+ else if (diff < -5) diff += 10;
274
+ }
275
+ const startOffset = currentOffsetRef.current ?? -(from + 10) * digitHeight;
276
+ const endOffset = startOffset - diff * digitHeight;
277
+ const blurEl = document.getElementById(filterId)?.querySelector("feGaussianBlur");
278
+ if (motionBlur && blurEl) {
279
+ const intensity = Math.min(Math.abs(diff) * 1.2, 6);
280
+ blurEl.setAttribute("stdDeviation", `0,${intensity}`);
281
+ containerRef.current.style.filter = `url(#${filterId})`;
282
+ }
283
+ const anim = columnRef.current.animate([{ transform: `translateY(${startOffset}px)` }, { transform: `translateY(${endOffset}px)` }], {
284
+ duration,
285
+ delay,
286
+ easing,
287
+ fill: "forwards"
288
+ });
289
+ animationRef.current = anim;
290
+ anim.onfinish = () => {
291
+ const normalizedOffset = -(target + 10) * digitHeight;
292
+ if (columnRef.current) {
293
+ anim.cancel();
294
+ columnRef.current.style.transform = `translateY(${normalizedOffset}px)`;
295
+ }
296
+ currentOffsetRef.current = normalizedOffset;
297
+ if (containerRef.current) containerRef.current.style.filter = "none";
298
+ if (blurEl) blurEl.setAttribute("stdDeviation", "0,0");
299
+ animationRef.current = null;
300
+ if (targetDigitRef.current !== target) requestAnimationFrame(() => {
301
+ animateToDigit(targetDigitRef.current);
302
+ });
303
+ };
304
+ anim.oncancel = () => {
305
+ animationRef.current = null;
306
+ };
307
+ };
308
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("svg", {
309
+ style: {
310
+ position: "absolute",
311
+ width: 0,
312
+ height: 0
313
+ },
314
+ "aria-hidden": "true",
315
+ children: /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("filter", {
316
+ id: filterId,
317
+ children: /* @__PURE__ */ jsx("feGaussianBlur", {
318
+ in: "SourceGraphic",
319
+ stdDeviation: "0,0"
320
+ })
321
+ }) })
322
+ }), /* @__PURE__ */ jsx("div", {
323
+ ref: containerRef,
324
+ style: {
325
+ position: "relative",
326
+ height: `${digitHeight}px`,
327
+ overflow: "hidden",
328
+ width: "0.65em",
329
+ textAlign: "center",
330
+ opacity: isEntering ? 0 : 1
331
+ },
332
+ children: /* @__PURE__ */ jsx("div", {
333
+ ref: columnRef,
334
+ style: {
335
+ position: "absolute",
336
+ left: 0,
337
+ right: 0,
338
+ willChange: "transform"
339
+ },
340
+ children: sequence.map((d, i) => /* @__PURE__ */ jsx("div", {
341
+ style: {
342
+ height: `${digitHeight}px`,
343
+ display: "flex",
344
+ alignItems: "center",
345
+ justifyContent: "center"
346
+ },
347
+ children: d
348
+ }, i))
349
+ })
350
+ })] });
351
+ }
352
+
353
+ //#endregion
354
+ export { SlidingNumber };
@@ -0,0 +1,25 @@
1
+ import type { StyleSlots } from '../../../../core/types';
2
+ /**
3
+ * Style slots for SlidingText component
4
+ */
5
+ export type SlidingTextSlot = 'root' | 'content' | 'token';
6
+ /**
7
+ * Base styles for SlidingText component
8
+ */
9
+ export declare const slidingTextBaseStyles: StyleSlots<SlidingTextSlot>;
10
+ /**
11
+ * CSS classes for animation states
12
+ */
13
+ export declare const slidingTextAnimationClasses: {
14
+ readonly enterFrom: "enter-from";
15
+ readonly enterTo: "enter-to";
16
+ readonly exitActive: "exit-active";
17
+ };
18
+ /**
19
+ * CSS classes for direction variants
20
+ */
21
+ export declare const slidingTextDirectionClasses: {
22
+ readonly vertical: "waapi-direction-vertical";
23
+ readonly horizontal: "waapi-direction-horizontal";
24
+ };
25
+ //# sourceMappingURL=SlidingText.styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SlidingText.styles.d.ts","sourceRoot":"","sources":["../../../../../src/react-ui/primitives/waapi/SlidingText/SlidingText.styles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;AAE3D;;GAEG;AACH,eAAO,MAAM,qBAAqB,EAAE,UAAU,CAAC,eAAe,CAI7D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,2BAA2B;;;;CAI9B,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,2BAA2B;;;CAG9B,CAAC"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Props for SlidingText component
3
+ *
4
+ * Character or word-by-word text animations with entrance/exit transitions and blur effects.
5
+ *
6
+ * @example
7
+ * ```tsx
8
+ * // Character animation (default)
9
+ * <SlidingText text="Hello World" mode="character" />
10
+ *
11
+ * // Word animation
12
+ * <SlidingText text="React Components" mode="word" />
13
+ *
14
+ * // Horizontal direction
15
+ * <SlidingText
16
+ * text="Slide In"
17
+ * direction="horizontal"
18
+ * blur={false}
19
+ * />
20
+ * ```
21
+ */
22
+ export interface ISlidingTextProps {
23
+ /** The text content to animate */
24
+ text: string;
25
+ /**
26
+ * Animation mode
27
+ * - 'character': Each character animates individually
28
+ * - 'word': The text animates as a unit
29
+ * - 'none': No animation
30
+ */
31
+ mode?: 'word' | 'character' | 'none';
32
+ /** Animation direction */
33
+ direction?: 'vertical' | 'horizontal';
34
+ /** Delay between each character/word in milliseconds */
35
+ staggerDelay?: number;
36
+ /** Animation duration in milliseconds */
37
+ duration?: number;
38
+ /** CSS easing function */
39
+ easing?: string;
40
+ /** Enable blur effect during animation */
41
+ blur?: boolean;
42
+ /** Animate width changes during animation */
43
+ widthAnimation?: boolean;
44
+ /** Initial animation state */
45
+ initial?: 'initial' | false;
46
+ /** Trigger animation state */
47
+ animate?: 'animate';
48
+ /** Exit animation state */
49
+ exit?: 'exit';
50
+ /** Callback when animation completes */
51
+ onAnimationComplete?: () => void;
52
+ /** Additional CSS class name */
53
+ className?: string;
54
+ /** Additional inline styles */
55
+ style?: React.CSSProperties;
56
+ }
57
+ //# sourceMappingURL=SlidingText.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SlidingText.types.d.ts","sourceRoot":"","sources":["../../../../../src/react-ui/primitives/waapi/SlidingText/SlidingText.types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,iBAAiB;IAChC,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;IAEb;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;IAErC,0BAA0B;IAC1B,SAAS,CAAC,EAAE,UAAU,GAAG,YAAY,CAAC;IAEtC,wDAAwD;IACxD,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,0BAA0B;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,0CAA0C;IAC1C,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf,6CAA6C;IAC7C,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB,8BAA8B;IAC9B,OAAO,CAAC,EAAE,SAAS,GAAG,KAAK,CAAC;IAE5B,8BAA8B;IAC9B,OAAO,CAAC,EAAE,SAAS,CAAC;IAEpB,2BAA2B;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,wCAAwC;IACxC,mBAAmB,CAAC,EAAE,MAAM,IAAI,CAAC;IAEjC,gCAAgC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,+BAA+B;IAC/B,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B"}
@@ -0,0 +1,26 @@
1
+ import React from 'react';
2
+ import type { ISlidingTextProps } from './SlidingText.types';
3
+ /**
4
+ * SlidingText - Character or word-by-word text animations
5
+ *
6
+ * Animated text component with entrance/exit transitions and blur effects.
7
+ * Supports character-level or word-level animation modes.
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * // Character animation (default)
12
+ * <SlidingText text="Hello World" mode="character" />
13
+ *
14
+ * // Word animation
15
+ * <SlidingText text="React Components" mode="word" />
16
+ *
17
+ * // Exit animation
18
+ * <SlidingText text="Goodbye" exit="exit" />
19
+ * ```
20
+ */
21
+ export declare const SlidingText: {
22
+ ({ text, mode, direction, staggerDelay, duration, easing, blur, widthAnimation, initial, exit, className, style, }: ISlidingTextProps): React.ReactElement;
23
+ displayName: string;
24
+ };
25
+ export type { ISlidingTextProps };
26
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/react-ui/primitives/waapi/SlidingText/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAuD,MAAM,OAAO,CAAC;AAC5E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAG7D;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,WAAW;wHAarB,iBAAiB,GAAG,KAAK,CAAC,YAAY;;CAkGxC,CAAC;AAIF,YAAY,EAAE,iBAAiB,EAAE,CAAC"}
@@ -0,0 +1,105 @@
1
+ "use client";
2
+
3
+ import { cn } from "../../../lib/utils.js";
4
+ import React, { useEffect, useLayoutEffect, useRef, useState } from "react";
5
+ import { jsx } from "react/jsx-runtime";
6
+
7
+ //#region src/react-ui/primitives/waapi/SlidingText/index.tsx
8
+ /**
9
+ * SlidingText - Character or word-by-word text animations
10
+ *
11
+ * Animated text component with entrance/exit transitions and blur effects.
12
+ * Supports character-level or word-level animation modes.
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * // Character animation (default)
17
+ * <SlidingText text="Hello World" mode="character" />
18
+ *
19
+ * // Word animation
20
+ * <SlidingText text="React Components" mode="word" />
21
+ *
22
+ * // Exit animation
23
+ * <SlidingText text="Goodbye" exit="exit" />
24
+ * ```
25
+ */
26
+ const SlidingText = ({ text, mode = "word", direction = "vertical", staggerDelay = 15, duration = 200, easing = "cubic-bezier(0.33, 1, 0.68, 1)", blur = true, widthAnimation = false, initial = "initial", exit, className = "", style }) => {
27
+ const containerRef = useRef(null);
28
+ const contentRef = useRef(null);
29
+ const hasTriggeredEnterRef = useRef(false);
30
+ const [showAnimate, setShowAnimate] = useState(initial !== "initial");
31
+ useEffect(() => {
32
+ if (initial === "initial" && !hasTriggeredEnterRef.current) {
33
+ hasTriggeredEnterRef.current = true;
34
+ requestAnimationFrame(() => {
35
+ setShowAnimate(true);
36
+ });
37
+ }
38
+ }, [initial]);
39
+ const visualState = exit === "exit" ? "exit" : showAnimate ? "animate" : "initial";
40
+ const elements = mode === "character" ? text.split("") : [text];
41
+ useLayoutEffect(() => {
42
+ if (!widthAnimation || !containerRef.current || !contentRef.current) return;
43
+ const container = containerRef.current;
44
+ const content = contentRef.current;
45
+ if (visualState === "initial") container.style.width = "0px";
46
+ else if (visualState === "animate") if (CSS.supports("interpolate-size", "allow-keywords")) {
47
+ container.style.width = "auto";
48
+ container.style.transition = `width ${duration}ms ${easing}`;
49
+ } else {
50
+ const targetWidth = content.scrollWidth;
51
+ container.style.width = `${targetWidth}px`;
52
+ container.style.transition = `width ${duration}ms ${easing}`;
53
+ const timer = setTimeout(() => {
54
+ container.style.width = "auto";
55
+ }, duration);
56
+ return () => clearTimeout(timer);
57
+ }
58
+ else if (visualState === "exit") {
59
+ const currentWidth = container.getBoundingClientRect().width;
60
+ container.style.width = `${currentWidth}px`;
61
+ container.getBoundingClientRect();
62
+ container.style.width = "0px";
63
+ container.style.transition = `width 180ms cubic-bezier(0.32, 0, 0.67, 0)`;
64
+ }
65
+ }, [
66
+ visualState,
67
+ widthAnimation,
68
+ duration,
69
+ easing,
70
+ text
71
+ ]);
72
+ const getTransitionStyle = (index) => {
73
+ const delay = index * staggerDelay;
74
+ const isExit = visualState === "exit";
75
+ const currentDuration = isExit ? 180 : duration;
76
+ const currentEasing = isExit ? "cubic-bezier(0.32, 0, 0.67, 0)" : easing;
77
+ return {
78
+ transition: `
79
+ opacity ${currentDuration}ms ${currentEasing} ${delay}ms,
80
+ transform ${currentDuration}ms ${currentEasing} ${delay}ms,
81
+ filter ${currentDuration}ms ${currentEasing} ${delay}ms
82
+ `,
83
+ "--blur-amount": blur ? "4px" : "0px",
84
+ "--offset": direction === "vertical" ? "8px" : "16px"
85
+ };
86
+ };
87
+ return /* @__PURE__ */ jsx("div", {
88
+ ref: containerRef,
89
+ className: cn("waapi-sliding-text-container", className),
90
+ style,
91
+ children: /* @__PURE__ */ jsx("div", {
92
+ ref: contentRef,
93
+ className: cn("waapi-sliding-text-content", `waapi-direction-${direction}`),
94
+ children: elements.map((char, index) => /* @__PURE__ */ jsx("span", {
95
+ className: cn("waapi-sliding-text-token", visualState === "initial" && "enter-from", visualState === "animate" && "enter-to", visualState === "exit" && "exit-active"),
96
+ style: getTransitionStyle(index),
97
+ children: char
98
+ }, index))
99
+ })
100
+ });
101
+ };
102
+ SlidingText.displayName = "SlidingText";
103
+
104
+ //#endregion
105
+ export { SlidingText };