@tombcato/smart-ticker 1.0.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.
@@ -0,0 +1,243 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
+ const EMPTY_CHAR = "\0";
6
+ const TickerUtils = {
7
+ provideNumberList: () => "0123456789",
8
+ provideAlphabeticalList: () => "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
9
+ };
10
+ class TickerCharacterList {
11
+ constructor(characterList) {
12
+ __publicField(this, "numOriginalCharacters");
13
+ __publicField(this, "characterList");
14
+ __publicField(this, "characterIndicesMap");
15
+ const charsArray = characterList.split("");
16
+ const length = charsArray.length;
17
+ this.numOriginalCharacters = length;
18
+ this.characterIndicesMap = /* @__PURE__ */ new Map();
19
+ for (let i = 0; i < length; i++) {
20
+ this.characterIndicesMap.set(charsArray[i], i);
21
+ }
22
+ this.characterList = new Array(length * 2 + 1);
23
+ this.characterList[0] = EMPTY_CHAR;
24
+ for (let i = 0; i < length; i++) {
25
+ this.characterList[1 + i] = charsArray[i];
26
+ this.characterList[1 + length + i] = charsArray[i];
27
+ }
28
+ }
29
+ getCharacterIndices(start, end, direction) {
30
+ let startIndex = this.getIndexOfChar(start);
31
+ let endIndex = this.getIndexOfChar(end);
32
+ if (startIndex < 0 || endIndex < 0) return null;
33
+ switch (direction) {
34
+ case "DOWN":
35
+ if (end === EMPTY_CHAR) {
36
+ endIndex = this.characterList.length;
37
+ } else if (endIndex < startIndex) {
38
+ endIndex += this.numOriginalCharacters;
39
+ }
40
+ break;
41
+ case "UP":
42
+ if (startIndex < endIndex) {
43
+ startIndex += this.numOriginalCharacters;
44
+ }
45
+ break;
46
+ case "ANY":
47
+ if (start !== EMPTY_CHAR && end !== EMPTY_CHAR) {
48
+ if (endIndex < startIndex) {
49
+ const nonWrap = startIndex - endIndex;
50
+ const wrap = this.numOriginalCharacters - startIndex + endIndex;
51
+ if (wrap < nonWrap) endIndex += this.numOriginalCharacters;
52
+ } else if (startIndex < endIndex) {
53
+ const nonWrap = endIndex - startIndex;
54
+ const wrap = this.numOriginalCharacters - endIndex + startIndex;
55
+ if (wrap < nonWrap) startIndex += this.numOriginalCharacters;
56
+ }
57
+ }
58
+ break;
59
+ }
60
+ return { startIndex, endIndex };
61
+ }
62
+ getSupportedCharacters() {
63
+ return new Set(this.characterIndicesMap.keys());
64
+ }
65
+ getCharacterList() {
66
+ return this.characterList;
67
+ }
68
+ getIndexOfChar(c) {
69
+ if (c === EMPTY_CHAR) return 0;
70
+ if (this.characterIndicesMap.has(c)) return this.characterIndicesMap.get(c) + 1;
71
+ return -1;
72
+ }
73
+ }
74
+ const ACTION_SAME = 0;
75
+ const ACTION_INSERT = 1;
76
+ const ACTION_DELETE = 2;
77
+ function computeColumnActions(source, target, supported) {
78
+ let si = 0, ti = 0;
79
+ const actions = [];
80
+ while (true) {
81
+ const endS = si === source.length;
82
+ const endT = ti === target.length;
83
+ if (endS && endT) break;
84
+ if (endS) {
85
+ for (; ti < target.length; ti++) actions.push(ACTION_INSERT);
86
+ break;
87
+ }
88
+ if (endT) {
89
+ for (; si < source.length; si++) actions.push(ACTION_DELETE);
90
+ break;
91
+ }
92
+ const sSupp = supported.has(source[si]);
93
+ const tSupp = supported.has(target[ti]);
94
+ if (sSupp && tSupp) {
95
+ let se = si + 1, te = ti + 1;
96
+ while (se < source.length && supported.has(source[se])) se++;
97
+ while (te < target.length && supported.has(target[te])) te++;
98
+ const sLen = se - si, tLen = te - ti;
99
+ if (sLen === tLen) {
100
+ for (let i = 0; i < sLen; i++) actions.push(ACTION_SAME);
101
+ } else {
102
+ const matrix = Array(sLen + 1).fill(null).map(() => Array(tLen + 1).fill(0));
103
+ for (let i = 0; i <= sLen; i++) matrix[i][0] = i;
104
+ for (let j = 0; j <= tLen; j++) matrix[0][j] = j;
105
+ for (let r2 = 1; r2 <= sLen; r2++) {
106
+ for (let c2 = 1; c2 <= tLen; c2++) {
107
+ const cost = source[si + r2 - 1] === target[ti + c2 - 1] ? 0 : 1;
108
+ matrix[r2][c2] = Math.min(matrix[r2 - 1][c2] + 1, matrix[r2][c2 - 1] + 1, matrix[r2 - 1][c2 - 1] + cost);
109
+ }
110
+ }
111
+ const result = [];
112
+ let r = sLen, c = tLen;
113
+ while (r > 0 || c > 0) {
114
+ if (r === 0) {
115
+ result.push(ACTION_INSERT);
116
+ c--;
117
+ } else if (c === 0) {
118
+ result.push(ACTION_DELETE);
119
+ r--;
120
+ } else {
121
+ const ins = matrix[r][c - 1], del = matrix[r - 1][c], rep = matrix[r - 1][c - 1];
122
+ if (ins < del && ins < rep) {
123
+ result.push(ACTION_INSERT);
124
+ c--;
125
+ } else if (del < rep) {
126
+ result.push(ACTION_DELETE);
127
+ r--;
128
+ } else {
129
+ result.push(ACTION_SAME);
130
+ r--;
131
+ c--;
132
+ }
133
+ }
134
+ }
135
+ for (let i = result.length - 1; i >= 0; i--) actions.push(result[i]);
136
+ }
137
+ si = se;
138
+ ti = te;
139
+ } else if (sSupp) {
140
+ actions.push(ACTION_INSERT);
141
+ ti++;
142
+ } else if (tSupp) {
143
+ actions.push(ACTION_DELETE);
144
+ si++;
145
+ } else {
146
+ actions.push(ACTION_SAME);
147
+ si++;
148
+ ti++;
149
+ }
150
+ }
151
+ return actions;
152
+ }
153
+ function createColumn() {
154
+ return {
155
+ currentChar: EMPTY_CHAR,
156
+ targetChar: EMPTY_CHAR,
157
+ charList: null,
158
+ startIndex: 0,
159
+ endIndex: 0,
160
+ sourceWidth: 0,
161
+ currentWidth: 0,
162
+ targetWidth: 0,
163
+ directionAdj: 1,
164
+ prevDelta: 0,
165
+ currDelta: 0
166
+ };
167
+ }
168
+ function setTarget(col, target, lists, dir) {
169
+ const c = { ...col };
170
+ c.targetChar = target;
171
+ c.sourceWidth = c.currentWidth;
172
+ c.targetWidth = target === EMPTY_CHAR ? 0 : 1;
173
+ let found = false;
174
+ for (const list of lists) {
175
+ const indices = list.getCharacterIndices(c.currentChar, target, dir);
176
+ if (indices) {
177
+ c.charList = list.getCharacterList();
178
+ c.startIndex = indices.startIndex;
179
+ c.endIndex = indices.endIndex;
180
+ found = true;
181
+ break;
182
+ }
183
+ }
184
+ if (!found) {
185
+ c.charList = c.currentChar === target ? [c.currentChar] : [c.currentChar, target];
186
+ c.startIndex = 0;
187
+ c.endIndex = c.currentChar === target ? 0 : 1;
188
+ }
189
+ c.directionAdj = c.endIndex >= c.startIndex ? 1 : -1;
190
+ c.prevDelta = c.currDelta;
191
+ c.currDelta = 0;
192
+ return c;
193
+ }
194
+ function applyProgress(col, progress, forceUpdate = false) {
195
+ const c = { ...col };
196
+ const total = Math.abs(c.endIndex - c.startIndex);
197
+ const pos = progress * total;
198
+ const offset = pos - Math.floor(pos);
199
+ const additional = c.prevDelta * (1 - progress);
200
+ const delta = offset * c.directionAdj + additional;
201
+ const charIdx = c.startIndex + Math.floor(pos) * c.directionAdj;
202
+ if (progress >= 1) {
203
+ c.currentChar = c.targetChar;
204
+ c.currDelta = 0;
205
+ c.prevDelta = 0;
206
+ } else if (forceUpdate && c.charList && charIdx >= 0 && charIdx < c.charList.length) {
207
+ c.currentChar = c.charList[charIdx];
208
+ c.currDelta = delta;
209
+ }
210
+ c.currentWidth = c.sourceWidth + (c.targetWidth - c.sourceWidth) * progress;
211
+ return { col: c, charIdx, delta };
212
+ }
213
+ const easingFunctions = {
214
+ linear: (t) => t,
215
+ easeIn: (t) => t * t,
216
+ easeOut: (t) => 1 - (1 - t) * (1 - t),
217
+ easeInOut: (t) => t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2,
218
+ bounce: (t) => {
219
+ const n1 = 7.5625;
220
+ const d1 = 2.75;
221
+ if (t < 1 / d1) {
222
+ return n1 * t * t;
223
+ } else if (t < 2 / d1) {
224
+ return n1 * (t -= 1.5 / d1) * t + 0.75;
225
+ } else if (t < 2.5 / d1) {
226
+ return n1 * (t -= 2.25 / d1) * t + 0.9375;
227
+ } else {
228
+ return n1 * (t -= 2.625 / d1) * t + 0.984375;
229
+ }
230
+ }
231
+ };
232
+ exports.ACTION_DELETE = ACTION_DELETE;
233
+ exports.ACTION_INSERT = ACTION_INSERT;
234
+ exports.ACTION_SAME = ACTION_SAME;
235
+ exports.EMPTY_CHAR = EMPTY_CHAR;
236
+ exports.TickerCharacterList = TickerCharacterList;
237
+ exports.TickerUtils = TickerUtils;
238
+ exports.applyProgress = applyProgress;
239
+ exports.computeColumnActions = computeColumnActions;
240
+ exports.createColumn = createColumn;
241
+ exports.easingFunctions = easingFunctions;
242
+ exports.setTarget = setTarget;
243
+ //# sourceMappingURL=TickerCore-DSrG8V7Z.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TickerCore-DSrG8V7Z.cjs","sources":["../src/core/TickerCore.ts"],"sourcesContent":["// ============================================================================\r\n// Constants\r\n// ============================================================================\r\nexport const EMPTY_CHAR = '\\0';\r\n\r\nexport const TickerUtils = {\r\n provideNumberList: () => '0123456789',\r\n provideAlphabeticalList: () => 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',\r\n};\r\n\r\nexport type ScrollingDirection = 'ANY' | 'UP' | 'DOWN';\r\n\r\n// ============================================================================\r\n// TickerCharacterList\r\n// ============================================================================\r\nexport class TickerCharacterList {\r\n private numOriginalCharacters: number;\r\n private characterList: string[];\r\n private characterIndicesMap: Map<string, number>;\r\n\r\n constructor(characterList: string) {\r\n const charsArray = characterList.split('');\r\n const length = charsArray.length;\r\n this.numOriginalCharacters = length;\r\n this.characterIndicesMap = new Map();\r\n\r\n for (let i = 0; i < length; i++) {\r\n this.characterIndicesMap.set(charsArray[i], i);\r\n }\r\n\r\n this.characterList = new Array(length * 2 + 1);\r\n this.characterList[0] = EMPTY_CHAR;\r\n for (let i = 0; i < length; i++) {\r\n this.characterList[1 + i] = charsArray[i];\r\n this.characterList[1 + length + i] = charsArray[i];\r\n }\r\n }\r\n\r\n getCharacterIndices(\r\n start: string,\r\n end: string,\r\n direction: ScrollingDirection\r\n ): { startIndex: number; endIndex: number } | null {\r\n let startIndex = this.getIndexOfChar(start);\r\n let endIndex = this.getIndexOfChar(end);\r\n\r\n if (startIndex < 0 || endIndex < 0) return null;\r\n\r\n switch (direction) {\r\n case 'DOWN':\r\n if (end === EMPTY_CHAR) {\r\n endIndex = this.characterList.length;\r\n } else if (endIndex < startIndex) {\r\n endIndex += this.numOriginalCharacters;\r\n }\r\n break;\r\n case 'UP':\r\n if (startIndex < endIndex) {\r\n startIndex += this.numOriginalCharacters;\r\n }\r\n break;\r\n case 'ANY':\r\n if (start !== EMPTY_CHAR && end !== EMPTY_CHAR) {\r\n if (endIndex < startIndex) {\r\n const nonWrap = startIndex - endIndex;\r\n const wrap = this.numOriginalCharacters - startIndex + endIndex;\r\n if (wrap < nonWrap) endIndex += this.numOriginalCharacters;\r\n } else if (startIndex < endIndex) {\r\n const nonWrap = endIndex - startIndex;\r\n const wrap = this.numOriginalCharacters - endIndex + startIndex;\r\n if (wrap < nonWrap) startIndex += this.numOriginalCharacters;\r\n }\r\n }\r\n break;\r\n }\r\n return { startIndex, endIndex };\r\n }\r\n\r\n getSupportedCharacters(): Set<string> {\r\n return new Set(this.characterIndicesMap.keys());\r\n }\r\n\r\n getCharacterList(): string[] {\r\n return this.characterList;\r\n }\r\n\r\n private getIndexOfChar(c: string): number {\r\n if (c === EMPTY_CHAR) return 0;\r\n if (this.characterIndicesMap.has(c)) return this.characterIndicesMap.get(c)! + 1;\r\n return -1;\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Levenshtein\r\n// ============================================================================\r\nexport const ACTION_SAME = 0;\r\nexport const ACTION_INSERT = 1;\r\nexport const ACTION_DELETE = 2;\r\n\r\nexport function computeColumnActions(source: string[], target: string[], supported: Set<string>): number[] {\r\n let si = 0, ti = 0;\r\n const actions: number[] = [];\r\n\r\n while (true) {\r\n const endS = si === source.length;\r\n const endT = ti === target.length;\r\n if (endS && endT) break;\r\n if (endS) { for (; ti < target.length; ti++) actions.push(ACTION_INSERT); break; }\r\n if (endT) { for (; si < source.length; si++) actions.push(ACTION_DELETE); break; }\r\n\r\n const sSupp = supported.has(source[si]);\r\n const tSupp = supported.has(target[ti]);\r\n\r\n if (sSupp && tSupp) {\r\n let se = si + 1, te = ti + 1;\r\n while (se < source.length && supported.has(source[se])) se++;\r\n while (te < target.length && supported.has(target[te])) te++;\r\n\r\n const sLen = se - si, tLen = te - ti;\r\n if (sLen === tLen) {\r\n for (let i = 0; i < sLen; i++) actions.push(ACTION_SAME);\r\n } else {\r\n const matrix: number[][] = Array(sLen + 1).fill(null).map(() => Array(tLen + 1).fill(0));\r\n for (let i = 0; i <= sLen; i++) matrix[i][0] = i;\r\n for (let j = 0; j <= tLen; j++) matrix[0][j] = j;\r\n for (let r = 1; r <= sLen; r++) {\r\n for (let c = 1; c <= tLen; c++) {\r\n const cost = source[si + r - 1] === target[ti + c - 1] ? 0 : 1;\r\n matrix[r][c] = Math.min(matrix[r - 1][c] + 1, matrix[r][c - 1] + 1, matrix[r - 1][c - 1] + cost);\r\n }\r\n }\r\n const result: number[] = [];\r\n let r = sLen, c = tLen;\r\n while (r > 0 || c > 0) {\r\n if (r === 0) { result.push(ACTION_INSERT); c--; }\r\n else if (c === 0) { result.push(ACTION_DELETE); r--; }\r\n else {\r\n const ins = matrix[r][c - 1], del = matrix[r - 1][c], rep = matrix[r - 1][c - 1];\r\n if (ins < del && ins < rep) { result.push(ACTION_INSERT); c--; }\r\n else if (del < rep) { result.push(ACTION_DELETE); r--; }\r\n else { result.push(ACTION_SAME); r--; c--; }\r\n }\r\n }\r\n for (let i = result.length - 1; i >= 0; i--) actions.push(result[i]);\r\n }\r\n si = se; ti = te;\r\n } else if (sSupp) { actions.push(ACTION_INSERT); ti++; }\r\n else if (tSupp) { actions.push(ACTION_DELETE); si++; }\r\n else { actions.push(ACTION_SAME); si++; ti++; }\r\n }\r\n return actions;\r\n}\r\n\r\n// ============================================================================\r\n// Column State\r\n// ============================================================================\r\nexport interface ColumnState {\r\n currentChar: string;\r\n targetChar: string;\r\n charList: string[] | null;\r\n startIndex: number;\r\n endIndex: number;\r\n sourceWidth: number;\r\n currentWidth: number;\r\n targetWidth: number;\r\n directionAdj: number;\r\n prevDelta: number;\r\n currDelta: number;\r\n}\r\n\r\nexport function createColumn(): ColumnState {\r\n return {\r\n currentChar: EMPTY_CHAR, targetChar: EMPTY_CHAR, charList: null,\r\n startIndex: 0, endIndex: 0, sourceWidth: 0, currentWidth: 0, targetWidth: 0,\r\n directionAdj: 1, prevDelta: 0, currDelta: 0,\r\n };\r\n}\r\n\r\nexport function setTarget(col: ColumnState, target: string, lists: TickerCharacterList[], dir: ScrollingDirection): ColumnState {\r\n const c = { ...col };\r\n c.targetChar = target;\r\n c.sourceWidth = c.currentWidth;\r\n c.targetWidth = target === EMPTY_CHAR ? 0 : 1;\r\n\r\n let found = false;\r\n for (const list of lists) {\r\n const indices = list.getCharacterIndices(c.currentChar, target, dir);\r\n if (indices) {\r\n c.charList = list.getCharacterList();\r\n c.startIndex = indices.startIndex;\r\n c.endIndex = indices.endIndex;\r\n found = true;\r\n break;\r\n }\r\n }\r\n if (!found) {\r\n c.charList = c.currentChar === target ? [c.currentChar] : [c.currentChar, target];\r\n c.startIndex = 0;\r\n c.endIndex = c.currentChar === target ? 0 : 1;\r\n }\r\n\r\n c.directionAdj = c.endIndex >= c.startIndex ? 1 : -1;\r\n c.prevDelta = c.currDelta;\r\n c.currDelta = 0;\r\n return c;\r\n}\r\n\r\nexport function applyProgress(col: ColumnState, progress: number, forceUpdate = false): { col: ColumnState; charIdx: number; delta: number } {\r\n const c = { ...col };\r\n const total = Math.abs(c.endIndex - c.startIndex);\r\n const pos = progress * total;\r\n const offset = pos - Math.floor(pos);\r\n const additional = c.prevDelta * (1 - progress);\r\n const delta = offset * c.directionAdj + additional;\r\n const charIdx = c.startIndex + Math.floor(pos) * c.directionAdj;\r\n\r\n if (progress >= 1) {\r\n c.currentChar = c.targetChar;\r\n c.currDelta = 0;\r\n c.prevDelta = 0;\r\n } else if (forceUpdate && c.charList && charIdx >= 0 && charIdx < c.charList.length) {\r\n c.currentChar = c.charList[charIdx];\r\n c.currDelta = delta;\r\n }\r\n\r\n c.currentWidth = c.sourceWidth + (c.targetWidth - c.sourceWidth) * progress;\r\n return { col: c, charIdx, delta };\r\n}\r\n\r\n// ============================================================================\r\n// Easing Functions\r\n// ============================================================================\r\nexport const easingFunctions: Record<string, (t: number) => number> = {\r\n linear: (t) => t,\r\n easeIn: (t) => t * t,\r\n easeOut: (t) => 1 - (1 - t) * (1 - t),\r\n easeInOut: (t) => t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2,\r\n bounce: (t) => {\r\n const n1 = 7.5625;\r\n const d1 = 2.75;\r\n if (t < 1 / d1) {\r\n return n1 * t * t;\r\n } else if (t < 2 / d1) {\r\n return n1 * (t -= 1.5 / d1) * t + 0.75;\r\n } else if (t < 2.5 / d1) {\r\n return n1 * (t -= 2.25 / d1) * t + 0.9375;\r\n } else {\r\n return n1 * (t -= 2.625 / d1) * t + 0.984375;\r\n }\r\n },\r\n};\r\n"],"names":["r","c"],"mappings":"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"}
package/dist/index.cjs ADDED
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const React = require("react");
5
+ const TickerCore = require("./TickerCore-DSrG8V7Z.cjs");
6
+ const Ticker = ({
7
+ value,
8
+ characterLists: charListStrings = [TickerCore.TickerUtils.provideNumberList()],
9
+ duration = 500,
10
+ direction = "ANY",
11
+ easing = "easeInOut",
12
+ // Robinhood 默认: AccelerateDecelerateInterpolator
13
+ className = "",
14
+ charWidth = 1
15
+ }) => {
16
+ const [columns, setColumns] = React.useState([]);
17
+ const [progress, setProgress] = React.useState(1);
18
+ const animRef = React.useRef();
19
+ const colsRef = React.useRef([]);
20
+ const progressRef = React.useRef(1);
21
+ const isFirstRef = React.useRef(true);
22
+ const prevValueRef = React.useRef("");
23
+ const lists = React.useMemo(() => charListStrings.map((s) => new TickerCore.TickerCharacterList(s)), [charListStrings]);
24
+ const supported = React.useMemo(() => {
25
+ const set = /* @__PURE__ */ new Set();
26
+ lists.forEach((l) => l.getSupportedCharacters().forEach((c) => set.add(c)));
27
+ return set;
28
+ }, [lists]);
29
+ const listsRef = React.useRef(lists);
30
+ const supportedRef = React.useRef(supported);
31
+ const directionRef = React.useRef(direction);
32
+ const durationRef = React.useRef(duration);
33
+ const easingRef = React.useRef(easing);
34
+ listsRef.current = lists;
35
+ supportedRef.current = supported;
36
+ directionRef.current = direction;
37
+ durationRef.current = duration;
38
+ easingRef.current = easing;
39
+ React.useEffect(() => {
40
+ if (value === prevValueRef.current) {
41
+ return;
42
+ }
43
+ prevValueRef.current = value;
44
+ if (animRef.current) {
45
+ cancelAnimationFrame(animRef.current);
46
+ animRef.current = void 0;
47
+ }
48
+ let currentCols = colsRef.current;
49
+ if (progressRef.current < 1 && progressRef.current > 0) {
50
+ currentCols = currentCols.map((c) => TickerCore.applyProgress(c, progressRef.current, true).col);
51
+ colsRef.current = currentCols;
52
+ }
53
+ const targetChars = value.split("");
54
+ const sourceChars = currentCols.map((c) => c.currentChar);
55
+ const actions = TickerCore.computeColumnActions(sourceChars, targetChars, supportedRef.current);
56
+ let ci = 0, ti = 0;
57
+ const result = [];
58
+ const validCols = currentCols.filter((c) => c.currentWidth > 0);
59
+ for (const action of actions) {
60
+ if (action === TickerCore.ACTION_INSERT) {
61
+ result.push(TickerCore.setTarget(TickerCore.createColumn(), targetChars[ti++], listsRef.current, directionRef.current));
62
+ } else if (action === TickerCore.ACTION_SAME) {
63
+ const existing = validCols[ci++] || TickerCore.createColumn();
64
+ result.push(TickerCore.setTarget(existing, targetChars[ti++], listsRef.current, directionRef.current));
65
+ } else {
66
+ const existing = validCols[ci++] || TickerCore.createColumn();
67
+ result.push(TickerCore.setTarget(existing, TickerCore.EMPTY_CHAR, listsRef.current, directionRef.current));
68
+ }
69
+ }
70
+ colsRef.current = result;
71
+ setColumns(result);
72
+ if (!isFirstRef.current && result.length > 0) {
73
+ progressRef.current = 0;
74
+ setProgress(0);
75
+ const start = performance.now();
76
+ const dur = durationRef.current;
77
+ const easeFn = TickerCore.easingFunctions[easingRef.current] || TickerCore.easingFunctions.linear;
78
+ let lastUpdate = 0;
79
+ const animate = (now) => {
80
+ const linearP = Math.min((now - start) / dur, 1);
81
+ const p = easeFn(linearP);
82
+ progressRef.current = p;
83
+ if (now - lastUpdate >= 16 || linearP >= 1) {
84
+ lastUpdate = now;
85
+ setProgress(p);
86
+ }
87
+ if (linearP < 1) {
88
+ animRef.current = requestAnimationFrame(animate);
89
+ } else {
90
+ const final = colsRef.current.map((c) => TickerCore.applyProgress(c, 1).col).filter((c) => c.currentWidth > 0);
91
+ colsRef.current = final;
92
+ setColumns(final);
93
+ animRef.current = void 0;
94
+ }
95
+ };
96
+ animRef.current = requestAnimationFrame(animate);
97
+ } else {
98
+ isFirstRef.current = false;
99
+ progressRef.current = 1;
100
+ setProgress(1);
101
+ const final = result.map((c) => TickerCore.applyProgress(c, 1).col).filter((c) => c.currentWidth > 0);
102
+ colsRef.current = final;
103
+ setColumns(final);
104
+ }
105
+ return () => {
106
+ if (animRef.current) cancelAnimationFrame(animRef.current);
107
+ };
108
+ }, [value]);
109
+ const charHeight = 1.2;
110
+ const rendered = React.useMemo(() => {
111
+ return columns.map((col, i) => {
112
+ const { charIdx, delta } = TickerCore.applyProgress(col, progress);
113
+ const width = col.sourceWidth + (col.targetWidth - col.sourceWidth) * progress;
114
+ if (width <= 0) return null;
115
+ const chars = [];
116
+ const list = col.charList || [];
117
+ const deltaEm = delta * charHeight;
118
+ if (charIdx >= 0 && charIdx < list.length) {
119
+ chars.push(
120
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ticker-char", style: { transform: `translateY(${deltaEm}em)` }, children: list[charIdx] === TickerCore.EMPTY_CHAR ? " " : list[charIdx] }, `c-${charIdx}`)
121
+ );
122
+ }
123
+ const nextIdx = charIdx + 1;
124
+ if (nextIdx >= 0 && nextIdx < list.length) {
125
+ chars.push(
126
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ticker-char", style: { transform: `translateY(${deltaEm - charHeight}em)` }, children: list[nextIdx] === TickerCore.EMPTY_CHAR ? " " : list[nextIdx] }, `n-${nextIdx}`)
127
+ );
128
+ }
129
+ const prevIdx = charIdx - 1;
130
+ if (prevIdx >= 0 && prevIdx < list.length) {
131
+ chars.push(
132
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ticker-char", style: { transform: `translateY(${deltaEm + charHeight}em)` }, children: list[prevIdx] === TickerCore.EMPTY_CHAR ? " " : list[prevIdx] }, `p-${prevIdx}`)
133
+ );
134
+ }
135
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ticker-column", style: { width: `${width * 0.8 * charWidth}em` }, children: chars }, i);
136
+ });
137
+ }, [columns, progress, charWidth]);
138
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `ticker ${className}`.trim(), children: rendered });
139
+ };
140
+ React.memo(Ticker);
141
+ exports.ACTION_DELETE = TickerCore.ACTION_DELETE;
142
+ exports.ACTION_INSERT = TickerCore.ACTION_INSERT;
143
+ exports.ACTION_SAME = TickerCore.ACTION_SAME;
144
+ exports.EMPTY_CHAR = TickerCore.EMPTY_CHAR;
145
+ exports.TickerCharacterList = TickerCore.TickerCharacterList;
146
+ exports.TickerUtils = TickerCore.TickerUtils;
147
+ exports.applyProgress = TickerCore.applyProgress;
148
+ exports.computeColumnActions = TickerCore.computeColumnActions;
149
+ exports.createColumn = TickerCore.createColumn;
150
+ exports.easingFunctions = TickerCore.easingFunctions;
151
+ exports.setTarget = TickerCore.setTarget;
152
+ exports.Ticker = Ticker;
153
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../src/components/Ticker.tsx"],"sourcesContent":["/**\r\n * Ticker - 直接翻译自 Robinhood Android Ticker\r\n * https://github.com/robinhood/ticker\r\n */\r\nimport React, { useEffect, useRef, useState, useMemo } from 'react';\r\nimport './Ticker.css';\r\nimport {\r\n TickerUtils,\r\n TickerCharacterList,\r\n ScrollingDirection,\r\n ColumnState,\r\n EMPTY_CHAR,\r\n computeColumnActions,\r\n createColumn,\r\n setTarget,\r\n applyProgress,\r\n easingFunctions,\r\n ACTION_INSERT,\r\n ACTION_SAME,\r\n} from '../core/TickerCore';\r\n\r\n// 导出 Utils 供外部使用\r\nexport { TickerUtils };\r\n\r\n// ============================================================================\r\n// Ticker Component\r\n// ============================================================================\r\nexport interface TickerProps {\r\n value: string;\r\n characterLists?: string[];\r\n duration?: number;\r\n direction?: ScrollingDirection;\r\n easing?: string;\r\n className?: string;\r\n charWidth?: number;\r\n}\r\n\r\nexport const Ticker: React.FC<TickerProps> = ({\r\n value,\r\n characterLists: charListStrings = [TickerUtils.provideNumberList()],\r\n duration = 500,\r\n direction = 'ANY',\r\n easing = 'easeInOut', // Robinhood 默认: AccelerateDecelerateInterpolator\r\n className = '',\r\n charWidth = 1,\r\n}) => {\r\n const [columns, setColumns] = useState<ColumnState[]>([]);\r\n const [progress, setProgress] = useState(1);\r\n const animRef = useRef<number>();\r\n const colsRef = useRef<ColumnState[]>([]);\r\n const progressRef = useRef(1);\r\n const isFirstRef = useRef(true);\r\n const prevValueRef = useRef('');\r\n\r\n const lists = useMemo(() => charListStrings.map(s => new TickerCharacterList(s)), [charListStrings]);\r\n const supported = useMemo(() => {\r\n const set = new Set<string>();\r\n lists.forEach(l => l.getSupportedCharacters().forEach(c => set.add(c)));\r\n return set;\r\n }, [lists]);\r\n\r\n // 用 ref 存储依赖项,避免 useEffect 因为这些依赖重复触发\r\n const listsRef = useRef(lists);\r\n const supportedRef = useRef(supported);\r\n const directionRef = useRef(direction);\r\n const durationRef = useRef(duration);\r\n const easingRef = useRef(easing);\r\n listsRef.current = lists;\r\n supportedRef.current = supported;\r\n directionRef.current = direction;\r\n durationRef.current = duration;\r\n easingRef.current = easing;\r\n\r\n // 主要逻辑:value 变化时处理\r\n useEffect(() => {\r\n // 防止相同 value 重复触发(React StrictMode)\r\n if (value === prevValueRef.current) {\r\n return;\r\n }\r\n prevValueRef.current = value;\r\n\r\n // 取消正在进行的动画\r\n if (animRef.current) {\r\n cancelAnimationFrame(animRef.current);\r\n animRef.current = undefined;\r\n }\r\n\r\n // 如果动画进行中,先用当前进度更新列状态\r\n let currentCols = colsRef.current;\r\n if (progressRef.current < 1 && progressRef.current > 0) {\r\n currentCols = currentCols.map(c => applyProgress(c, progressRef.current, true).col);\r\n colsRef.current = currentCols;\r\n }\r\n\r\n const targetChars = value.split('');\r\n const sourceChars = currentCols.map(c => c.currentChar);\r\n const actions = computeColumnActions(sourceChars, targetChars, supportedRef.current);\r\n\r\n let ci = 0, ti = 0;\r\n const result: ColumnState[] = [];\r\n const validCols = currentCols.filter(c => c.currentWidth > 0);\r\n\r\n for (const action of actions) {\r\n if (action === ACTION_INSERT) {\r\n result.push(setTarget(createColumn(), targetChars[ti++], listsRef.current, directionRef.current));\r\n } else if (action === ACTION_SAME) {\r\n const existing = validCols[ci++] || createColumn();\r\n result.push(setTarget(existing, targetChars[ti++], listsRef.current, directionRef.current));\r\n } else {\r\n const existing = validCols[ci++] || createColumn();\r\n result.push(setTarget(existing, EMPTY_CHAR, listsRef.current, directionRef.current));\r\n }\r\n }\r\n\r\n colsRef.current = result;\r\n setColumns(result);\r\n\r\n // 动画\r\n if (!isFirstRef.current && result.length > 0) {\r\n progressRef.current = 0;\r\n setProgress(0);\r\n const start = performance.now();\r\n const dur = durationRef.current;\r\n const easeFn = easingFunctions[easingRef.current] || easingFunctions.linear;\r\n let lastUpdate = 0;\r\n\r\n const animate = (now: number) => {\r\n const linearP = Math.min((now - start) / dur, 1);\r\n const p = easeFn(linearP); // 应用 easing 函数\r\n progressRef.current = p;\r\n\r\n // 节流:每 16ms 最多更新一次视图 (约 60fps)\r\n if (now - lastUpdate >= 16 || linearP >= 1) {\r\n lastUpdate = now;\r\n setProgress(p);\r\n }\r\n\r\n if (linearP < 1) {\r\n animRef.current = requestAnimationFrame(animate);\r\n } else {\r\n // 动画结束\r\n const final = colsRef.current\r\n .map(c => applyProgress(c, 1).col)\r\n .filter(c => c.currentWidth > 0);\r\n colsRef.current = final;\r\n setColumns(final);\r\n animRef.current = undefined;\r\n }\r\n };\r\n animRef.current = requestAnimationFrame(animate);\r\n } else {\r\n // 首次渲染,直接显示\r\n isFirstRef.current = false;\r\n progressRef.current = 1;\r\n setProgress(1);\r\n const final = result.map(c => applyProgress(c, 1).col).filter(c => c.currentWidth > 0);\r\n colsRef.current = final;\r\n setColumns(final);\r\n }\r\n\r\n return () => {\r\n if (animRef.current) cancelAnimationFrame(animRef.current);\r\n };\r\n }, [value]); // 只依赖 value\r\n\r\n // 渲染\r\n const charHeight = 1.2; // 与 CSS line-height 匹配\r\n\r\n const rendered = useMemo(() => {\r\n return columns.map((col, i) => {\r\n const { charIdx, delta } = applyProgress(col, progress);\r\n const width = col.sourceWidth + (col.targetWidth - col.sourceWidth) * progress;\r\n if (width <= 0) return null;\r\n\r\n const chars: React.ReactNode[] = [];\r\n const list = col.charList || [];\r\n const deltaEm = delta * charHeight;\r\n\r\n // 当前字符\r\n if (charIdx >= 0 && charIdx < list.length) {\r\n chars.push(\r\n <div key={`c-${charIdx}`} className=\"ticker-char\" style={{ transform: `translateY(${deltaEm}em)` }}>\r\n {list[charIdx] === EMPTY_CHAR ? '\\u00A0' : list[charIdx]}\r\n </div>\r\n );\r\n }\r\n // 下一个字符\r\n const nextIdx = charIdx + 1;\r\n if (nextIdx >= 0 && nextIdx < list.length) {\r\n chars.push(\r\n <div key={`n-${nextIdx}`} className=\"ticker-char\" style={{ transform: `translateY(${deltaEm - charHeight}em)` }}>\r\n {list[nextIdx] === EMPTY_CHAR ? '\\u00A0' : list[nextIdx]}\r\n </div>\r\n );\r\n }\r\n // 上一个字符(处理中断)\r\n const prevIdx = charIdx - 1;\r\n if (prevIdx >= 0 && prevIdx < list.length) {\r\n chars.push(\r\n <div key={`p-${prevIdx}`} className=\"ticker-char\" style={{ transform: `translateY(${deltaEm + charHeight}em)` }}>\r\n {list[prevIdx] === EMPTY_CHAR ? '\\u00A0' : list[prevIdx]}\r\n </div>\r\n );\r\n }\r\n\r\n // 基准宽度 0.8em * 倍率\r\n return (\r\n <div key={i} className=\"ticker-column\" style={{ width: `${width * 0.8 * charWidth}em` }}>\r\n {chars}\r\n </div>\r\n );\r\n });\r\n }, [columns, progress, charWidth]);\r\n\r\n return <div className={`ticker ${className}`.trim()}>{rendered}</div>;\r\n};\r\n\r\nexport default React.memo(Ticker);\r\n"],"names":["TickerUtils","useState","useRef","useMemo","TickerCharacterList","useEffect","applyProgress","computeColumnActions","ACTION_INSERT","setTarget","createColumn","ACTION_SAME","EMPTY_CHAR","easingFunctions","jsx"],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ import { default as default_2 } from 'react';
2
+
3
+ export declare const ACTION_DELETE = 2;
4
+
5
+ export declare const ACTION_INSERT = 1;
6
+
7
+ export declare const ACTION_SAME = 0;
8
+
9
+ export declare function applyProgress(col: ColumnState, progress: number, forceUpdate?: boolean): {
10
+ col: ColumnState;
11
+ charIdx: number;
12
+ delta: number;
13
+ };
14
+
15
+ export declare interface ColumnState {
16
+ currentChar: string;
17
+ targetChar: string;
18
+ charList: string[] | null;
19
+ startIndex: number;
20
+ endIndex: number;
21
+ sourceWidth: number;
22
+ currentWidth: number;
23
+ targetWidth: number;
24
+ directionAdj: number;
25
+ prevDelta: number;
26
+ currDelta: number;
27
+ }
28
+
29
+ export declare function computeColumnActions(source: string[], target: string[], supported: Set<string>): number[];
30
+
31
+ export declare function createColumn(): ColumnState;
32
+
33
+ export declare const easingFunctions: Record<string, (t: number) => number>;
34
+
35
+ export declare const EMPTY_CHAR = "\0";
36
+
37
+ export declare type ScrollingDirection = 'ANY' | 'UP' | 'DOWN';
38
+
39
+ export declare function setTarget(col: ColumnState, target: string, lists: TickerCharacterList[], dir: ScrollingDirection): ColumnState;
40
+
41
+ export declare const Ticker: default_2.FC<TickerProps>;
42
+
43
+ export declare class TickerCharacterList {
44
+ private numOriginalCharacters;
45
+ private characterList;
46
+ private characterIndicesMap;
47
+ constructor(characterList: string);
48
+ getCharacterIndices(start: string, end: string, direction: ScrollingDirection): {
49
+ startIndex: number;
50
+ endIndex: number;
51
+ } | null;
52
+ getSupportedCharacters(): Set<string>;
53
+ getCharacterList(): string[];
54
+ private getIndexOfChar;
55
+ }
56
+
57
+ export declare interface TickerProps {
58
+ value: string;
59
+ characterLists?: string[];
60
+ duration?: number;
61
+ direction?: ScrollingDirection;
62
+ easing?: string;
63
+ className?: string;
64
+ charWidth?: number;
65
+ }
66
+
67
+ export declare const TickerUtils: {
68
+ provideNumberList: () => string;
69
+ provideAlphabeticalList: () => string;
70
+ };
71
+
72
+ export { }