@onlynative/inertia-svg 0.0.1-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +96 -0
- package/dist/index.d.mts +188 -0
- package/dist/index.d.ts +188 -0
- package/dist/index.js +370 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +358 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +83 -0
- package/src/MotionPath.tsx +340 -0
- package/src/index.ts +47 -0
- package/src/path.ts +254 -0
- package/src/types.ts +42 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var react = require('react');
|
|
4
|
+
var reactNativeSvg = require('react-native-svg');
|
|
5
|
+
var Animated = require('react-native-reanimated');
|
|
6
|
+
var inertia = require('@onlynative/inertia');
|
|
7
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
8
|
+
|
|
9
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
|
+
|
|
11
|
+
var Animated__default = /*#__PURE__*/_interopDefault(Animated);
|
|
12
|
+
|
|
13
|
+
// src/MotionPath.tsx
|
|
14
|
+
|
|
15
|
+
// src/path.ts
|
|
16
|
+
var CMD_ARGS = {
|
|
17
|
+
M: 2,
|
|
18
|
+
m: 2,
|
|
19
|
+
L: 2,
|
|
20
|
+
l: 2,
|
|
21
|
+
H: 1,
|
|
22
|
+
h: 1,
|
|
23
|
+
V: 1,
|
|
24
|
+
v: 1,
|
|
25
|
+
C: 6,
|
|
26
|
+
c: 6,
|
|
27
|
+
S: 4,
|
|
28
|
+
s: 4,
|
|
29
|
+
Q: 4,
|
|
30
|
+
q: 4,
|
|
31
|
+
T: 2,
|
|
32
|
+
t: 2,
|
|
33
|
+
A: 7,
|
|
34
|
+
a: 7,
|
|
35
|
+
Z: 0,
|
|
36
|
+
z: 0
|
|
37
|
+
};
|
|
38
|
+
var CMD_REPEAT = {
|
|
39
|
+
M: "L",
|
|
40
|
+
m: "l"
|
|
41
|
+
};
|
|
42
|
+
var isDigit = (c) => c >= "0" && c <= "9";
|
|
43
|
+
function tokenize(d) {
|
|
44
|
+
const out = [];
|
|
45
|
+
const len = d.length;
|
|
46
|
+
let i = 0;
|
|
47
|
+
while (i < len) {
|
|
48
|
+
const c = d[i];
|
|
49
|
+
if (c === " " || c === "," || c === " " || c === "\n" || c === "\r") {
|
|
50
|
+
i++;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (c >= "A" && c <= "Z" || c >= "a" && c <= "z") {
|
|
54
|
+
if (!(c in CMD_ARGS)) {
|
|
55
|
+
throw new Error(
|
|
56
|
+
`[inertia-svg] unknown path command '${c}' at position ${i}`
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
out.push(c);
|
|
60
|
+
i++;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
const start = i;
|
|
64
|
+
let hasDigit = false;
|
|
65
|
+
let hasDot = false;
|
|
66
|
+
if (c === "+" || c === "-") i++;
|
|
67
|
+
while (i < len) {
|
|
68
|
+
const ch = d[i];
|
|
69
|
+
if (isDigit(ch)) {
|
|
70
|
+
hasDigit = true;
|
|
71
|
+
i++;
|
|
72
|
+
} else if (ch === "." && !hasDot) {
|
|
73
|
+
hasDot = true;
|
|
74
|
+
i++;
|
|
75
|
+
} else {
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (hasDigit && (d[i] === "e" || d[i] === "E")) {
|
|
80
|
+
i++;
|
|
81
|
+
if (d[i] === "+" || d[i] === "-") i++;
|
|
82
|
+
while (i < len && isDigit(d[i])) i++;
|
|
83
|
+
}
|
|
84
|
+
if (!hasDigit) {
|
|
85
|
+
throw new Error(
|
|
86
|
+
`[inertia-svg] expected number at position ${start} in path '${d}', got '${c}'`
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
out.push(Number(d.substring(start, i)));
|
|
90
|
+
}
|
|
91
|
+
return out;
|
|
92
|
+
}
|
|
93
|
+
function parsePathD(d) {
|
|
94
|
+
const tokens = tokenize(d);
|
|
95
|
+
const segments = [];
|
|
96
|
+
let i = 0;
|
|
97
|
+
while (i < tokens.length) {
|
|
98
|
+
const t = tokens[i];
|
|
99
|
+
if (typeof t !== "string") {
|
|
100
|
+
throw new Error(
|
|
101
|
+
`[inertia-svg] expected command letter at token ${i}, got number ${t} \u2014 paths must start with a command`
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
const cmd = t;
|
|
105
|
+
const argCount = CMD_ARGS[cmd];
|
|
106
|
+
i++;
|
|
107
|
+
if (argCount === 0) {
|
|
108
|
+
segments.push({ cmd, args: [] });
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
const first = [];
|
|
112
|
+
for (let j = 0; j < argCount; j++) {
|
|
113
|
+
const v = tokens[i++];
|
|
114
|
+
if (typeof v !== "number") {
|
|
115
|
+
throw new Error(
|
|
116
|
+
`[inertia-svg] command '${cmd}' expected ${argCount} numbers, got '${v}' at token ${i - 1}`
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
first.push(v);
|
|
120
|
+
}
|
|
121
|
+
segments.push({ cmd, args: first });
|
|
122
|
+
const repeatCmd = CMD_REPEAT[cmd] ?? cmd;
|
|
123
|
+
while (i < tokens.length && typeof tokens[i] === "number") {
|
|
124
|
+
const batch = [];
|
|
125
|
+
for (let j = 0; j < argCount; j++) {
|
|
126
|
+
const v = tokens[i++];
|
|
127
|
+
if (typeof v !== "number") {
|
|
128
|
+
throw new Error(
|
|
129
|
+
`[inertia-svg] command '${cmd}' (implicit repeat as '${repeatCmd}') expected ${argCount} numbers`
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
batch.push(v);
|
|
133
|
+
}
|
|
134
|
+
segments.push({ cmd: repeatCmd, args: batch });
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return segments;
|
|
138
|
+
}
|
|
139
|
+
function templateOf(segments) {
|
|
140
|
+
const cmds = segments.map((s) => s.cmd);
|
|
141
|
+
const widths = segments.map((s) => s.args.length);
|
|
142
|
+
let size = 0;
|
|
143
|
+
for (let i = 0; i < widths.length; i++) size += widths[i];
|
|
144
|
+
return { cmds, widths, size };
|
|
145
|
+
}
|
|
146
|
+
function flattenParams(segments) {
|
|
147
|
+
const out = [];
|
|
148
|
+
for (let i = 0; i < segments.length; i++) {
|
|
149
|
+
const args = segments[i].args;
|
|
150
|
+
for (let j = 0; j < args.length; j++) out.push(args[j]);
|
|
151
|
+
}
|
|
152
|
+
return out;
|
|
153
|
+
}
|
|
154
|
+
function diffTemplate(source, target) {
|
|
155
|
+
if (source.cmds.length !== target.cmds.length) {
|
|
156
|
+
return `command count differs: source has ${source.cmds.length} segments, target has ${target.cmds.length}. Paths must produce the same command sequence after implicit-repeat expansion.`;
|
|
157
|
+
}
|
|
158
|
+
for (let i = 0; i < source.cmds.length; i++) {
|
|
159
|
+
if (source.cmds[i] !== target.cmds[i]) {
|
|
160
|
+
return `command at segment ${i} differs: source '${source.cmds[i]}' vs target '${target.cmds[i]}'. Command letters (including case \u2014 absolute vs relative) must match.`;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
function serializePath(template, params) {
|
|
166
|
+
"worklet";
|
|
167
|
+
let out = "";
|
|
168
|
+
let p = 0;
|
|
169
|
+
for (let i = 0; i < template.cmds.length; i++) {
|
|
170
|
+
out += template.cmds[i];
|
|
171
|
+
const w = template.widths[i];
|
|
172
|
+
for (let j = 0; j < w; j++) {
|
|
173
|
+
out += " ";
|
|
174
|
+
out += params[p++];
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return out;
|
|
178
|
+
}
|
|
179
|
+
var AnimatedPath = Animated__default.default.createAnimatedComponent(reactNativeSvg.Path);
|
|
180
|
+
var NO_ANIMATION = { type: "no-animation" };
|
|
181
|
+
function pickTransition(per, key) {
|
|
182
|
+
if (!per) return void 0;
|
|
183
|
+
if ("type" in per) return per;
|
|
184
|
+
return per[key];
|
|
185
|
+
}
|
|
186
|
+
function MotionPath(props) {
|
|
187
|
+
const {
|
|
188
|
+
d,
|
|
189
|
+
fill,
|
|
190
|
+
stroke,
|
|
191
|
+
strokeWidth,
|
|
192
|
+
strokeOpacity,
|
|
193
|
+
fillOpacity,
|
|
194
|
+
opacity,
|
|
195
|
+
strokeDashoffset,
|
|
196
|
+
initial,
|
|
197
|
+
animate,
|
|
198
|
+
transition,
|
|
199
|
+
...rest
|
|
200
|
+
} = props;
|
|
201
|
+
const sourceRef = react.useRef(null);
|
|
202
|
+
if (sourceRef.current === null) {
|
|
203
|
+
const segments = parsePathD(d);
|
|
204
|
+
sourceRef.current = {
|
|
205
|
+
template: templateOf(segments),
|
|
206
|
+
params: flattenParams(segments)
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
const template = sourceRef.current.template;
|
|
210
|
+
if (__DEV__) {
|
|
211
|
+
const segments = parsePathD(d);
|
|
212
|
+
const live = templateOf(segments);
|
|
213
|
+
const err = diffTemplate(template, live);
|
|
214
|
+
if (err) {
|
|
215
|
+
throw new Error(
|
|
216
|
+
`[inertia-svg] d prop template changed after mount: ${err}
|
|
217
|
+
If you need to swap to a structurally different path, remount with key={...}.`
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
const seedSource = initial === false ? animate : initial ?? void 0;
|
|
222
|
+
const seedParams = react.useMemo(() => {
|
|
223
|
+
if (!seedSource?.d) return sourceRef.current.params;
|
|
224
|
+
const segs = parsePathD(seedSource.d);
|
|
225
|
+
const t = templateOf(segs);
|
|
226
|
+
const err = diffTemplate(template, t);
|
|
227
|
+
if (err) {
|
|
228
|
+
if (__DEV__) {
|
|
229
|
+
throw new Error(`[inertia-svg] initial.d template mismatch: ${err}`);
|
|
230
|
+
}
|
|
231
|
+
return sourceRef.current.params;
|
|
232
|
+
}
|
|
233
|
+
return flattenParams(segs);
|
|
234
|
+
}, [seedSource?.d]);
|
|
235
|
+
const paramSvs = [];
|
|
236
|
+
for (let i = 0; i < template.size; i++) {
|
|
237
|
+
paramSvs.push(Animated.useSharedValue(seedParams[i] ?? 0));
|
|
238
|
+
}
|
|
239
|
+
const fillSv = Animated.useSharedValue(
|
|
240
|
+
seedSource?.fill ?? fill ?? "transparent"
|
|
241
|
+
);
|
|
242
|
+
const strokeSv = Animated.useSharedValue(
|
|
243
|
+
seedSource?.stroke ?? stroke ?? "transparent"
|
|
244
|
+
);
|
|
245
|
+
const strokeWidthSv = Animated.useSharedValue(
|
|
246
|
+
seedSource?.strokeWidth ?? strokeWidth ?? 1
|
|
247
|
+
);
|
|
248
|
+
const strokeOpacitySv = Animated.useSharedValue(
|
|
249
|
+
seedSource?.strokeOpacity ?? strokeOpacity ?? 1
|
|
250
|
+
);
|
|
251
|
+
const fillOpacitySv = Animated.useSharedValue(
|
|
252
|
+
seedSource?.fillOpacity ?? fillOpacity ?? 1
|
|
253
|
+
);
|
|
254
|
+
const opacitySv = Animated.useSharedValue(seedSource?.opacity ?? opacity ?? 1);
|
|
255
|
+
const strokeDashoffsetSv = Animated.useSharedValue(
|
|
256
|
+
seedSource?.strokeDashoffset ?? strokeDashoffset ?? 0
|
|
257
|
+
);
|
|
258
|
+
const reduce = inertia.useShouldReduceMotion();
|
|
259
|
+
const animateD = animate?.d;
|
|
260
|
+
const animateFill = animate?.fill;
|
|
261
|
+
const animateStroke = animate?.stroke;
|
|
262
|
+
const animateStrokeWidth = animate?.strokeWidth;
|
|
263
|
+
const animateStrokeOpacity = animate?.strokeOpacity;
|
|
264
|
+
const animateFillOpacity = animate?.fillOpacity;
|
|
265
|
+
const animateOpacity = animate?.opacity;
|
|
266
|
+
const animateStrokeDashoffset = animate?.strokeDashoffset;
|
|
267
|
+
react.useEffect(() => {
|
|
268
|
+
if (animateD === void 0) return;
|
|
269
|
+
const segments = parsePathD(animateD);
|
|
270
|
+
const t = templateOf(segments);
|
|
271
|
+
const err = diffTemplate(template, t);
|
|
272
|
+
if (err) {
|
|
273
|
+
if (__DEV__) {
|
|
274
|
+
throw new Error(`[inertia-svg] animate.d template mismatch: ${err}`);
|
|
275
|
+
}
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
const target = flattenParams(segments);
|
|
279
|
+
const cfg = reduce ? NO_ANIMATION : pickTransition(transition, "d");
|
|
280
|
+
for (let i = 0; i < paramSvs.length; i++) {
|
|
281
|
+
paramSvs[i].value = inertia.resolveTransition(cfg, target[i] ?? 0);
|
|
282
|
+
}
|
|
283
|
+
}, [animateD, reduce, transition]);
|
|
284
|
+
react.useEffect(() => {
|
|
285
|
+
if (animateFill === void 0) return;
|
|
286
|
+
const cfg = reduce ? NO_ANIMATION : pickTransition(transition, "fill");
|
|
287
|
+
fillSv.value = inertia.resolveTransition(cfg, animateFill);
|
|
288
|
+
}, [animateFill, reduce, transition]);
|
|
289
|
+
react.useEffect(() => {
|
|
290
|
+
if (animateStroke === void 0) return;
|
|
291
|
+
const cfg = reduce ? NO_ANIMATION : pickTransition(transition, "stroke");
|
|
292
|
+
strokeSv.value = inertia.resolveTransition(cfg, animateStroke);
|
|
293
|
+
}, [animateStroke, reduce, transition]);
|
|
294
|
+
react.useEffect(() => {
|
|
295
|
+
if (animateStrokeWidth === void 0) return;
|
|
296
|
+
const cfg = reduce ? NO_ANIMATION : pickTransition(transition, "strokeWidth");
|
|
297
|
+
strokeWidthSv.value = inertia.resolveTransition(cfg, animateStrokeWidth);
|
|
298
|
+
}, [animateStrokeWidth, reduce, transition]);
|
|
299
|
+
react.useEffect(() => {
|
|
300
|
+
if (animateStrokeOpacity === void 0) return;
|
|
301
|
+
const cfg = reduce ? NO_ANIMATION : pickTransition(transition, "strokeOpacity");
|
|
302
|
+
strokeOpacitySv.value = inertia.resolveTransition(
|
|
303
|
+
cfg,
|
|
304
|
+
animateStrokeOpacity
|
|
305
|
+
);
|
|
306
|
+
}, [animateStrokeOpacity, reduce, transition]);
|
|
307
|
+
react.useEffect(() => {
|
|
308
|
+
if (animateFillOpacity === void 0) return;
|
|
309
|
+
const cfg = reduce ? NO_ANIMATION : pickTransition(transition, "fillOpacity");
|
|
310
|
+
fillOpacitySv.value = inertia.resolveTransition(cfg, animateFillOpacity);
|
|
311
|
+
}, [animateFillOpacity, reduce, transition]);
|
|
312
|
+
react.useEffect(() => {
|
|
313
|
+
if (animateOpacity === void 0) return;
|
|
314
|
+
const cfg = reduce ? NO_ANIMATION : pickTransition(transition, "opacity");
|
|
315
|
+
opacitySv.value = inertia.resolveTransition(cfg, animateOpacity);
|
|
316
|
+
}, [animateOpacity, reduce, transition]);
|
|
317
|
+
react.useEffect(() => {
|
|
318
|
+
if (animateStrokeDashoffset === void 0) return;
|
|
319
|
+
const cfg = reduce ? NO_ANIMATION : pickTransition(transition, "strokeDashoffset");
|
|
320
|
+
strokeDashoffsetSv.value = inertia.resolveTransition(
|
|
321
|
+
cfg,
|
|
322
|
+
animateStrokeDashoffset
|
|
323
|
+
);
|
|
324
|
+
}, [animateStrokeDashoffset, reduce, transition]);
|
|
325
|
+
const animatedProps = Animated.useAnimatedProps(() => {
|
|
326
|
+
"worklet";
|
|
327
|
+
const params = new Array(paramSvs.length);
|
|
328
|
+
for (let i = 0; i < paramSvs.length; i++) params[i] = paramSvs[i].value;
|
|
329
|
+
return {
|
|
330
|
+
d: serializePath(template, params),
|
|
331
|
+
fill: fillSv.value,
|
|
332
|
+
stroke: strokeSv.value,
|
|
333
|
+
strokeWidth: strokeWidthSv.value,
|
|
334
|
+
strokeOpacity: strokeOpacitySv.value,
|
|
335
|
+
fillOpacity: fillOpacitySv.value,
|
|
336
|
+
opacity: opacitySv.value,
|
|
337
|
+
strokeDashoffset: strokeDashoffsetSv.value
|
|
338
|
+
};
|
|
339
|
+
});
|
|
340
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
341
|
+
AnimatedPath,
|
|
342
|
+
{
|
|
343
|
+
animatedProps,
|
|
344
|
+
d,
|
|
345
|
+
fill,
|
|
346
|
+
stroke,
|
|
347
|
+
strokeWidth,
|
|
348
|
+
strokeOpacity,
|
|
349
|
+
fillOpacity,
|
|
350
|
+
opacity,
|
|
351
|
+
strokeDashoffset,
|
|
352
|
+
...rest
|
|
353
|
+
}
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// src/index.ts
|
|
358
|
+
var MotionSvg = {
|
|
359
|
+
Path: MotionPath
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
exports.MotionPath = MotionPath;
|
|
363
|
+
exports.MotionSvg = MotionSvg;
|
|
364
|
+
exports.diffTemplate = diffTemplate;
|
|
365
|
+
exports.flattenParams = flattenParams;
|
|
366
|
+
exports.parsePathD = parsePathD;
|
|
367
|
+
exports.serializePath = serializePath;
|
|
368
|
+
exports.templateOf = templateOf;
|
|
369
|
+
//# sourceMappingURL=index.js.map
|
|
370
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/path.ts","../src/MotionPath.tsx","../src/index.ts"],"names":["Animated","Path","useRef","useMemo","useSharedValue","useShouldReduceMotion","useEffect","resolveTransition","useAnimatedProps","jsx"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * SVG path-string utilities used by `MotionSvg.Path`. Everything here runs on\n * the JS thread — paths are tokenized into a normalized command list at mount\n * and when `animate.d` changes; the worklet only ever consumes flat number\n * arrays + a frozen command template.\n *\n * Path morphing in v0.2 requires **structural compatibility**: the source and\n * every target `d` must produce the same command sequence (same command\n * letters, in the same order, after implicit-repeat expansion). Element-wise\n * numeric interpolation is the entire morphing model — we do not resample\n * paths or insert/remove commands. Same-shape morphs (e.g. a heart breathing,\n * a chevron flipping, a check mark tracing in) are the supported use case.\n */\n\n/** Arg count per SVG path command. `Z`/`z` close the subpath and take none. */\nconst CMD_ARGS: Readonly<Record<string, number>> = {\n M: 2,\n m: 2,\n L: 2,\n l: 2,\n H: 1,\n h: 1,\n V: 1,\n v: 1,\n C: 6,\n c: 6,\n S: 4,\n s: 4,\n Q: 4,\n q: 4,\n T: 2,\n t: 2,\n A: 7,\n a: 7,\n Z: 0,\n z: 0,\n}\n\n/**\n * After an explicit `M`/`m` the SVG spec says additional coordinate pairs are\n * implicit `L`/`l` commands. Every other command repeats itself.\n */\nconst CMD_REPEAT: Readonly<Record<string, string>> = {\n M: 'L',\n m: 'l',\n}\n\n/**\n * A single normalized path command after implicit-repeat expansion. The cmd\n * letter is preserved (absolute vs relative — case is meaningful to the SVG\n * renderer). `args` always has exactly `CMD_ARGS[cmd]` entries.\n */\nexport interface PathSegment {\n cmd: string\n args: number[]\n}\n\nconst isDigit = (c: string): boolean => c >= '0' && c <= '9'\n\n/**\n * Tokenize a path `d` string into a stream of (command-letter | number)\n * tokens. Handles SVG's \"compact\" number forms — adjacent numbers separated\n * only by sign (`1-2`) or decimal point (`.5.6`) — so author-written paths\n * with mixed spacing all parse to the same tokens.\n */\nfunction tokenize(d: string): Array<string | number> {\n const out: Array<string | number> = []\n const len = d.length\n let i = 0\n while (i < len) {\n const c = d[i]!\n // SVG path whitespace + comma separators.\n if (c === ' ' || c === ',' || c === '\\t' || c === '\\n' || c === '\\r') {\n i++\n continue\n }\n // Command letter — any ASCII letter not adjacent to a number context.\n if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {\n if (!(c in CMD_ARGS)) {\n throw new Error(\n `[inertia-svg] unknown path command '${c}' at position ${i}`,\n )\n }\n out.push(c)\n i++\n continue\n }\n // Number. Reaches here for digits, `.`, `+`, `-`.\n const start = i\n let hasDigit = false\n let hasDot = false\n if (c === '+' || c === '-') i++\n while (i < len) {\n const ch = d[i]!\n if (isDigit(ch)) {\n hasDigit = true\n i++\n } else if (ch === '.' && !hasDot) {\n hasDot = true\n i++\n } else {\n break\n }\n }\n if (hasDigit && (d[i] === 'e' || d[i] === 'E')) {\n i++\n if (d[i] === '+' || d[i] === '-') i++\n while (i < len && isDigit(d[i]!)) i++\n }\n if (!hasDigit) {\n throw new Error(\n `[inertia-svg] expected number at position ${start} in path '${d}', got '${c}'`,\n )\n }\n out.push(Number(d.substring(start, i)))\n }\n return out\n}\n\n/**\n * Parse a path `d` string into a flat list of normalized segments. Implicit\n * repeats are expanded — `M 0 0 10 10 20 20` becomes three segments\n * (`M 0 0`, `L 10 10`, `L 20 20`) so the segment list can be compared and\n * interpolated 1:1 against another path.\n */\nexport function parsePathD(d: string): PathSegment[] {\n const tokens = tokenize(d)\n const segments: PathSegment[] = []\n let i = 0\n while (i < tokens.length) {\n const t = tokens[i]\n if (typeof t !== 'string') {\n throw new Error(\n `[inertia-svg] expected command letter at token ${i}, got number ${t} — paths must start with a command`,\n )\n }\n const cmd = t\n const argCount = CMD_ARGS[cmd]!\n i++\n if (argCount === 0) {\n segments.push({ cmd, args: [] })\n continue\n }\n // First explicit batch for this command.\n const first: number[] = []\n for (let j = 0; j < argCount; j++) {\n const v = tokens[i++]\n if (typeof v !== 'number') {\n throw new Error(\n `[inertia-svg] command '${cmd}' expected ${argCount} numbers, got '${v}' at token ${i - 1}`,\n )\n }\n first.push(v)\n }\n segments.push({ cmd, args: first })\n // Repeated batches consume numbers up to the next command letter, applying\n // the implicit-repeat command (M → L, m → l, everything else → itself).\n // `argCount === 0` is handled above with an early continue, so the loop\n // body here always makes forward progress.\n const repeatCmd = CMD_REPEAT[cmd] ?? cmd\n while (i < tokens.length && typeof tokens[i] === 'number') {\n const batch: number[] = []\n for (let j = 0; j < argCount; j++) {\n const v = tokens[i++]\n if (typeof v !== 'number') {\n throw new Error(\n `[inertia-svg] command '${cmd}' (implicit repeat as '${repeatCmd}') expected ${argCount} numbers`,\n )\n }\n batch.push(v)\n }\n segments.push({ cmd: repeatCmd, args: batch })\n }\n }\n return segments\n}\n\n/**\n * The frozen \"shape\" of a path — just command letters and arg widths. Two\n * paths are morphable iff their templates are equal.\n */\nexport interface PathTemplate {\n cmds: ReadonlyArray<string>\n /** Flat width per segment, indexed parallel to `cmds`. */\n widths: ReadonlyArray<number>\n /** Total scalar count across all segments — `widths.reduce((a,b)=>a+b,0)`. */\n size: number\n}\n\nexport function templateOf(segments: ReadonlyArray<PathSegment>): PathTemplate {\n const cmds = segments.map((s) => s.cmd)\n const widths = segments.map((s) => s.args.length)\n let size = 0\n for (let i = 0; i < widths.length; i++) size += widths[i]!\n return { cmds, widths, size }\n}\n\n/** Flatten a parsed segment list into a single number array (length === size). */\nexport function flattenParams(segments: ReadonlyArray<PathSegment>): number[] {\n const out: number[] = []\n for (let i = 0; i < segments.length; i++) {\n const args = segments[i]!.args\n for (let j = 0; j < args.length; j++) out.push(args[j]!)\n }\n return out\n}\n\n/**\n * Verify a target template matches the source. Returns `null` on match or a\n * descriptive error string on mismatch — callers throw in `__DEV__` and\n * silently snap to the target in production.\n */\nexport function diffTemplate(\n source: PathTemplate,\n target: PathTemplate,\n): string | null {\n if (source.cmds.length !== target.cmds.length) {\n return `command count differs: source has ${source.cmds.length} segments, target has ${target.cmds.length}. Paths must produce the same command sequence after implicit-repeat expansion.`\n }\n for (let i = 0; i < source.cmds.length; i++) {\n if (source.cmds[i] !== target.cmds[i]) {\n return `command at segment ${i} differs: source '${source.cmds[i]}' vs target '${target.cmds[i]}'. Command letters (including case — absolute vs relative) must match.`\n }\n }\n return null\n}\n\n/**\n * Build a path `d` string from a template + flat param array. Runs inside the\n * worklet on the UI thread, so it must not capture any JS-thread closures or\n * use Array.prototype helpers that allocate intermediates the Hermes runtime\n * boxes into JS objects. Manual loops + `+=` string concat keep the worklet\n * cheap.\n *\n * MUST be a worklet — call sites in `MotionPath` wrap it with `'worklet'` via\n * `useAnimatedProps`.\n */\nexport function serializePath(\n template: PathTemplate,\n params: ReadonlyArray<number>,\n): string {\n 'worklet'\n let out = ''\n let p = 0\n for (let i = 0; i < template.cmds.length; i++) {\n out += template.cmds[i]\n const w = template.widths[i]!\n for (let j = 0; j < w; j++) {\n out += ' '\n out += params[p++]\n }\n }\n return out\n}\n","import { useEffect, useMemo, useRef } from 'react'\nimport { Path, type PathProps } from 'react-native-svg'\nimport Animated, {\n useAnimatedProps,\n useSharedValue,\n type SharedValue,\n} from 'react-native-reanimated'\nimport {\n resolveTransition,\n useShouldReduceMotion,\n type TransitionConfig,\n} from '@onlynative/inertia'\nimport {\n diffTemplate,\n flattenParams,\n parsePathD,\n serializePath,\n templateOf,\n type PathTemplate,\n} from './path'\nimport type {\n PathAnimate,\n PathPerPropertyTransition,\n PathTransition,\n} from './types'\n\nconst AnimatedPath = Animated.createAnimatedComponent(Path)\n\nconst NO_ANIMATION: TransitionConfig = { type: 'no-animation' }\n\nfunction pickTransition(\n per: PathTransition | undefined,\n key: keyof PathPerPropertyTransition,\n): TransitionConfig | undefined {\n if (!per) return undefined\n if ('type' in per) return per as TransitionConfig\n return (per as PathPerPropertyTransition)[key]\n}\n\nexport interface MotionPathProps extends Omit<\n PathProps,\n | 'd'\n | 'fill'\n | 'stroke'\n | 'strokeWidth'\n | 'strokeOpacity'\n | 'fillOpacity'\n | 'opacity'\n | 'strokeDashoffset'\n> {\n /**\n * Initial path data. **The command sequence is locked at first render** —\n * every target `d` passed via `animate` / `initial` must produce the same\n * command letters in the same order after implicit-repeat expansion. To\n * morph between structurally different paths, remount with a new `key`.\n */\n d: string\n fill?: string\n stroke?: string\n strokeWidth?: number\n strokeOpacity?: number\n fillOpacity?: number\n opacity?: number\n strokeDashoffset?: number\n /**\n * Initial frame override. When present, the component mounts displaying\n * these values, then animates to `animate` on the next effect. Pass `false`\n * to skip the initial-mount animation entirely.\n */\n initial?: PathAnimate | false\n /** Target animation state. */\n animate?: PathAnimate\n /**\n * Transition config — either a single `TransitionConfig` applied to every\n * animated dimension, or a per-property map. Per-property entries win over\n * the top-level transition.\n */\n transition?: PathTransition\n}\n\n/**\n * Animatable `<Path>` from `react-native-svg`. Wraps `Path` with declarative\n * `initial` / `animate` / `transition` props.\n *\n * Animatable dimensions:\n * - `d` — path morph via element-wise scalar interpolation. Source and target\n * must share the same command sequence (e.g. both `M L L L Z`).\n * - `fill`, `stroke` — color strings, interpolated via Reanimated's native\n * color animation.\n * - `strokeWidth`, `strokeOpacity`, `fillOpacity`, `opacity`,\n * `strokeDashoffset` — numeric, spring or timing-driven.\n *\n * Example:\n * ```tsx\n * <Svg viewBox=\"0 0 100 100\">\n * <MotionPath\n * d=\"M 50 20 L 80 80 L 20 80 Z\"\n * animate={{ d: \"M 50 80 L 80 20 L 20 20 Z\", fill: '#7c3aed' }}\n * transition={{ type: 'spring', tension: 140, friction: 12 }}\n * fill=\"#0ea5e9\"\n * />\n * </Svg>\n * ```\n */\nexport function MotionPath(props: MotionPathProps) {\n const {\n d,\n fill,\n stroke,\n strokeWidth,\n strokeOpacity,\n fillOpacity,\n opacity,\n strokeDashoffset,\n initial,\n animate,\n transition,\n ...rest\n } = props\n\n // Parse + freeze the source template at mount. The number of scalar params\n // is locked here so the shared-value array allocated below has a stable\n // length across renders.\n const sourceRef = useRef<{\n template: PathTemplate\n params: number[]\n } | null>(null)\n if (sourceRef.current === null) {\n const segments = parsePathD(d)\n sourceRef.current = {\n template: templateOf(segments),\n params: flattenParams(segments),\n }\n }\n const template = sourceRef.current.template\n\n if (__DEV__) {\n // Re-parse the current `d` prop and verify the template hasn't shifted.\n // Catches the easy mistake of swapping a star for a hexagon without\n // remounting via `key`.\n const segments = parsePathD(d)\n const live = templateOf(segments)\n const err = diffTemplate(template, live)\n if (err) {\n throw new Error(\n `[inertia-svg] d prop template changed after mount: ${err}\\n` +\n `If you need to swap to a structurally different path, remount with key={...}.`,\n )\n }\n }\n\n // `initial: false` → start at the animate target (no mount animation).\n // `initial: {...}` → explicit seed values.\n // `initial: undefined` → seed from the static props.\n const seedSource = initial === false ? animate : (initial ?? undefined)\n\n // Seed the path params. If `initial.d` is provided, parse it and verify\n // it's template-compatible before seeding.\n const seedParams: number[] = useMemo(() => {\n if (!seedSource?.d) return sourceRef.current!.params\n const segs = parsePathD(seedSource.d)\n const t = templateOf(segs)\n const err = diffTemplate(template, t)\n if (err) {\n if (__DEV__) {\n throw new Error(`[inertia-svg] initial.d template mismatch: ${err}`)\n }\n return sourceRef.current!.params\n }\n return flattenParams(segs)\n // template is stable for the component's lifetime; seedSource is the\n // only meaningful input. We intentionally ignore `template` in deps.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [seedSource?.d])\n\n // Loop-of-hooks per scalar param — safe because `template.size` is locked\n // at mount via the source ref above.\n const paramSvs: SharedValue<number>[] = []\n for (let i = 0; i < template.size; i++) {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n paramSvs.push(useSharedValue<number>(seedParams[i] ?? 0))\n }\n\n // Scalar property SVs. Strings (`fill`, `stroke`) use color seeds so\n // Reanimated recognizes them as colors from frame 1.\n const fillSv = useSharedValue<string>(\n seedSource?.fill ?? fill ?? 'transparent',\n )\n const strokeSv = useSharedValue<string>(\n seedSource?.stroke ?? stroke ?? 'transparent',\n )\n const strokeWidthSv = useSharedValue<number>(\n seedSource?.strokeWidth ?? strokeWidth ?? 1,\n )\n const strokeOpacitySv = useSharedValue<number>(\n seedSource?.strokeOpacity ?? strokeOpacity ?? 1,\n )\n const fillOpacitySv = useSharedValue<number>(\n seedSource?.fillOpacity ?? fillOpacity ?? 1,\n )\n const opacitySv = useSharedValue<number>(seedSource?.opacity ?? opacity ?? 1)\n const strokeDashoffsetSv = useSharedValue<number>(\n seedSource?.strokeDashoffset ?? strokeDashoffset ?? 0,\n )\n\n const reduce = useShouldReduceMotion()\n\n // Serialize scalar targets into stable keys so effects re-run on value\n // change, not on every parent re-render (a fresh `animate` literal each\n // render is the common case).\n const animateD = animate?.d\n const animateFill = animate?.fill\n const animateStroke = animate?.stroke\n const animateStrokeWidth = animate?.strokeWidth\n const animateStrokeOpacity = animate?.strokeOpacity\n const animateFillOpacity = animate?.fillOpacity\n const animateOpacity = animate?.opacity\n const animateStrokeDashoffset = animate?.strokeDashoffset\n\n useEffect(() => {\n if (animateD === undefined) return\n const segments = parsePathD(animateD)\n const t = templateOf(segments)\n const err = diffTemplate(template, t)\n if (err) {\n if (__DEV__) {\n throw new Error(`[inertia-svg] animate.d template mismatch: ${err}`)\n }\n return\n }\n const target = flattenParams(segments)\n const cfg = reduce ? NO_ANIMATION : pickTransition(transition, 'd')\n for (let i = 0; i < paramSvs.length; i++) {\n paramSvs[i]!.value = resolveTransition(cfg, target[i] ?? 0) as number\n }\n // paramSvs / template are stable across renders by the locks above.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [animateD, reduce, transition])\n\n useEffect(() => {\n if (animateFill === undefined) return\n const cfg = reduce ? NO_ANIMATION : pickTransition(transition, 'fill')\n fillSv.value = resolveTransition(cfg, animateFill) as string\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [animateFill, reduce, transition])\n\n useEffect(() => {\n if (animateStroke === undefined) return\n const cfg = reduce ? NO_ANIMATION : pickTransition(transition, 'stroke')\n strokeSv.value = resolveTransition(cfg, animateStroke) as string\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [animateStroke, reduce, transition])\n\n useEffect(() => {\n if (animateStrokeWidth === undefined) return\n const cfg = reduce\n ? NO_ANIMATION\n : pickTransition(transition, 'strokeWidth')\n strokeWidthSv.value = resolveTransition(cfg, animateStrokeWidth) as number\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [animateStrokeWidth, reduce, transition])\n\n useEffect(() => {\n if (animateStrokeOpacity === undefined) return\n const cfg = reduce\n ? NO_ANIMATION\n : pickTransition(transition, 'strokeOpacity')\n strokeOpacitySv.value = resolveTransition(\n cfg,\n animateStrokeOpacity,\n ) as number\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [animateStrokeOpacity, reduce, transition])\n\n useEffect(() => {\n if (animateFillOpacity === undefined) return\n const cfg = reduce\n ? NO_ANIMATION\n : pickTransition(transition, 'fillOpacity')\n fillOpacitySv.value = resolveTransition(cfg, animateFillOpacity) as number\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [animateFillOpacity, reduce, transition])\n\n useEffect(() => {\n if (animateOpacity === undefined) return\n const cfg = reduce ? NO_ANIMATION : pickTransition(transition, 'opacity')\n opacitySv.value = resolveTransition(cfg, animateOpacity) as number\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [animateOpacity, reduce, transition])\n\n useEffect(() => {\n if (animateStrokeDashoffset === undefined) return\n const cfg = reduce\n ? NO_ANIMATION\n : pickTransition(transition, 'strokeDashoffset')\n strokeDashoffsetSv.value = resolveTransition(\n cfg,\n animateStrokeDashoffset,\n ) as number\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [animateStrokeDashoffset, reduce, transition])\n\n const animatedProps = useAnimatedProps(() => {\n 'worklet'\n const params = new Array<number>(paramSvs.length)\n for (let i = 0; i < paramSvs.length; i++) params[i] = paramSvs[i]!.value\n return {\n d: serializePath(template, params),\n fill: fillSv.value,\n stroke: strokeSv.value,\n strokeWidth: strokeWidthSv.value,\n strokeOpacity: strokeOpacitySv.value,\n fillOpacity: fillOpacitySv.value,\n opacity: opacitySv.value,\n strokeDashoffset: strokeDashoffsetSv.value,\n }\n })\n\n return (\n <AnimatedPath\n // `animatedProps` overrides every animated key each frame; the static\n // props below are the first-render seeds so the path renders before the\n // first effect tick. The cast sheds Reanimated's strict-prop constraint\n // that the worklet's return type can't express — the runtime shape is\n // the same.\n animatedProps={animatedProps as never}\n d={d}\n fill={fill}\n stroke={stroke}\n strokeWidth={strokeWidth}\n strokeOpacity={strokeOpacity}\n fillOpacity={fillOpacity}\n opacity={opacity}\n strokeDashoffset={strokeDashoffset}\n {...rest}\n />\n )\n}\n\ndeclare const __DEV__: boolean\n","/**\n * `@onlynative/inertia-svg` — animatable SVG primitives for\n * `@onlynative/inertia`.\n *\n * v0.2 surface:\n * - `MotionPath` / `MotionSvg.Path` — animatable `<Path>` over\n * `react-native-svg`. Supports path morphing on the `d` attribute (source\n * and target must share the same command sequence) plus animatable\n * `fill`, `stroke`, `strokeWidth`, `strokeOpacity`, `fillOpacity`,\n * `opacity`, and `strokeDashoffset` with the same `initial` /\n * `animate` / `transition` shape as the core `Motion.*` primitives.\n *\n * Additional shape primitives (`Circle`, `Rect`, `Line`, `Ellipse`) land in\n * a follow-up once the path morphing API is validated. Path normalization\n * (resampling between structurally different paths) is out of scope for\n * v0.2 — use structurally-compatible source/target paths and remount with\n * `key={...}` to switch shape.\n */\nexport { MotionPath } from './MotionPath'\nexport type { MotionPathProps } from './MotionPath'\nexport type {\n PathAnimate,\n PathPerPropertyTransition,\n PathStateShape,\n PathTransition,\n} from './types'\n\nexport {\n parsePathD,\n templateOf,\n diffTemplate,\n flattenParams,\n serializePath,\n type PathSegment,\n type PathTemplate,\n} from './path'\n\nimport { MotionPath } from './MotionPath'\n\n/**\n * Namespace bundling every animatable SVG primitive. Use `MotionSvg.Path` for\n * autocomplete-friendly grouping or import `MotionPath` directly — both\n * point at the same component.\n */\nexport const MotionSvg = {\n Path: MotionPath,\n} as const\n"]}
|