@pixodesk/svg-animator-rn 1.0.21
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/LICENSE +21 -0
- package/dist/index.cjs +459 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +158 -0
- package/dist/index.d.ts +158 -0
- package/dist/index.js +470 -0
- package/dist/index.js.map +1 -0
- package/package.json +59 -0
- package/src/PixodeskSvgAnimator.tsx +386 -0
- package/src/PxRnPropNames.ts +55 -0
- package/src/PxRnRender.tsx +94 -0
- package/src/PxRnTracks.test.ts +185 -0
- package/src/PxRnTracks.ts +150 -0
- package/src/PxRnTypeMap.ts +64 -0
- package/src/index.ts +15 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 pixodesk
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,459 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __defProps = Object.defineProperties;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
7
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
8
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
9
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
10
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
11
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
12
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
13
|
+
var __spreadValues = (a, b) => {
|
|
14
|
+
for (var prop in b || (b = {}))
|
|
15
|
+
if (__hasOwnProp.call(b, prop))
|
|
16
|
+
__defNormalProp(a, prop, b[prop]);
|
|
17
|
+
if (__getOwnPropSymbols)
|
|
18
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
19
|
+
if (__propIsEnum.call(b, prop))
|
|
20
|
+
__defNormalProp(a, prop, b[prop]);
|
|
21
|
+
}
|
|
22
|
+
return a;
|
|
23
|
+
};
|
|
24
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
25
|
+
var __objRest = (source, exclude) => {
|
|
26
|
+
var target = {};
|
|
27
|
+
for (var prop in source)
|
|
28
|
+
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
29
|
+
target[prop] = source[prop];
|
|
30
|
+
if (source != null && __getOwnPropSymbols)
|
|
31
|
+
for (var prop of __getOwnPropSymbols(source)) {
|
|
32
|
+
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
33
|
+
target[prop] = source[prop];
|
|
34
|
+
}
|
|
35
|
+
return target;
|
|
36
|
+
};
|
|
37
|
+
var __export = (target, all) => {
|
|
38
|
+
for (var name in all)
|
|
39
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
40
|
+
};
|
|
41
|
+
var __copyProps = (to, from, except, desc) => {
|
|
42
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
43
|
+
for (let key of __getOwnPropNames(from))
|
|
44
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
45
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
46
|
+
}
|
|
47
|
+
return to;
|
|
48
|
+
};
|
|
49
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
50
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
51
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
52
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
53
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
54
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
55
|
+
mod
|
|
56
|
+
));
|
|
57
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
58
|
+
|
|
59
|
+
// src/index.ts
|
|
60
|
+
var index_exports = {};
|
|
61
|
+
__export(index_exports, {
|
|
62
|
+
PixodeskSvgAnimator: () => PixodeskSvgAnimator,
|
|
63
|
+
RN_SVG_COMPONENTS: () => RN_SVG_COMPONENTS,
|
|
64
|
+
compileTracks: () => compileTracks,
|
|
65
|
+
default: () => PixodeskSvgAnimator_default,
|
|
66
|
+
renderRnNode: () => renderRnNode,
|
|
67
|
+
sampleProps: () => sampleProps,
|
|
68
|
+
toRnPropName: () => toRnPropName,
|
|
69
|
+
toRnProps: () => toRnProps
|
|
70
|
+
});
|
|
71
|
+
module.exports = __toCommonJS(index_exports);
|
|
72
|
+
|
|
73
|
+
// src/PixodeskSvgAnimator.tsx
|
|
74
|
+
var import_svg_animator_core4 = require("@pixodesk/svg-animator-core");
|
|
75
|
+
var import_react2 = require("react");
|
|
76
|
+
var import_react_native_reanimated = __toESM(require("react-native-reanimated"), 1);
|
|
77
|
+
|
|
78
|
+
// src/PxRnTracks.ts
|
|
79
|
+
var import_svg_animator_core2 = require("@pixodesk/svg-animator-core");
|
|
80
|
+
|
|
81
|
+
// src/PxRnPropNames.ts
|
|
82
|
+
var import_svg_animator_core = require("@pixodesk/svg-animator-core");
|
|
83
|
+
var ATTR_NAME_OVERRIDES = {
|
|
84
|
+
"xlink:href": "href"
|
|
85
|
+
};
|
|
86
|
+
var DROPPED_ATTRS = /* @__PURE__ */ new Set(["class", "className", "style", "xmlns", "xmlns:xlink", "data-px-meta"]);
|
|
87
|
+
function toRnPropName(attrName) {
|
|
88
|
+
if (DROPPED_ATTRS.has(attrName)) return void 0;
|
|
89
|
+
const override = ATTR_NAME_OVERRIDES[attrName];
|
|
90
|
+
if (override) return override;
|
|
91
|
+
return (0, import_svg_animator_core.kebabToCamelCaseWord)(attrName);
|
|
92
|
+
}
|
|
93
|
+
var LENGTH_LIST_PROPS = /* @__PURE__ */ new Set(["strokeDasharray"]);
|
|
94
|
+
function toRnPropValue(rnPropName, value) {
|
|
95
|
+
if (LENGTH_LIST_PROPS.has(rnPropName)) {
|
|
96
|
+
const parts = String(value).trim().replace(/,/g, " ").split(/\s+/).map(Number).filter((n) => Number.isFinite(n));
|
|
97
|
+
return parts.length % 2 === 1 ? parts.concat(parts) : parts;
|
|
98
|
+
}
|
|
99
|
+
if (typeof value === "number") return value;
|
|
100
|
+
const num = +value;
|
|
101
|
+
return Number.isFinite(num) && String(num) === value ? num : value;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// src/PxRnTracks.ts
|
|
105
|
+
function compileTracks(doc, opts) {
|
|
106
|
+
var _a, _b, _c;
|
|
107
|
+
const config = (0, import_svg_animator_core2.getAnimatorConfig)(doc) || {};
|
|
108
|
+
const duration = +(config.duration || import_svg_animator_core2.DEFAULT_DURATION_MS);
|
|
109
|
+
const _iterations = config.iterations;
|
|
110
|
+
let iterations = 1;
|
|
111
|
+
if (typeof _iterations === "number") iterations = _iterations || 1;
|
|
112
|
+
if (_iterations === "infinite") iterations = Infinity;
|
|
113
|
+
if (iterations < 1) iterations = 1;
|
|
114
|
+
const sampleRate = (_a = opts == null ? void 0 : opts.sampleRate) != null ? _a : 60;
|
|
115
|
+
const maxSamples = (_b = opts == null ? void 0 : opts.maxSamples) != null ? _b : 600;
|
|
116
|
+
let sampleCount = Math.max(2, Math.round(duration / 1e3 * sampleRate) + 1);
|
|
117
|
+
if (sampleCount > maxSamples) sampleCount = maxSamples;
|
|
118
|
+
const stepMs = duration / (sampleCount - 1);
|
|
119
|
+
const bindings = (0, import_svg_animator_core2.getNormalisedBindings)(doc, import_svg_animator_core2.PxAnimatorEngine.frames) || [];
|
|
120
|
+
const elements = [];
|
|
121
|
+
for (const binding of bindings) {
|
|
122
|
+
const animDef = binding.animate;
|
|
123
|
+
if (!animDef || typeof animDef !== "object" || Array.isArray(animDef)) continue;
|
|
124
|
+
const props = {};
|
|
125
|
+
for (let i = 0; i < sampleCount; i++) {
|
|
126
|
+
const t = i === sampleCount - 1 ? duration : i * stepMs;
|
|
127
|
+
const values = (0, import_svg_animator_core2.calcAnimationValues)(animDef, t);
|
|
128
|
+
for (const [attr, value] of Object.entries(values)) {
|
|
129
|
+
const rnProp = toRnPropName(attr);
|
|
130
|
+
if (!rnProp) continue;
|
|
131
|
+
let arr = props[rnProp];
|
|
132
|
+
if (!arr) {
|
|
133
|
+
arr = props[rnProp] = new Array(sampleCount);
|
|
134
|
+
for (let j = 0; j < i; j++) arr[j] = toRnPropValue(rnProp, value);
|
|
135
|
+
}
|
|
136
|
+
arr[i] = toRnPropValue(rnProp, value);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
for (const arr of Object.values(props)) {
|
|
140
|
+
for (let i = 1; i < sampleCount; i++) {
|
|
141
|
+
if (arr[i] === void 0) arr[i] = arr[i - 1];
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (Object.keys(props).length > 0) {
|
|
145
|
+
elements.push({ id: binding.id, props });
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
duration,
|
|
150
|
+
iterations,
|
|
151
|
+
direction: config.direction || "normal",
|
|
152
|
+
delay: config.delay || 0,
|
|
153
|
+
fill: (_c = config.fill) != null ? _c : "forwards",
|
|
154
|
+
stepMs,
|
|
155
|
+
sampleCount,
|
|
156
|
+
elements
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function sampleProps(tracks, tMs, stepMs, sampleCount) {
|
|
160
|
+
"worklet";
|
|
161
|
+
let idx = Math.round(tMs / stepMs);
|
|
162
|
+
if (idx < 0) idx = 0;
|
|
163
|
+
if (idx >= sampleCount) idx = sampleCount - 1;
|
|
164
|
+
const out = {};
|
|
165
|
+
for (const key in tracks.props) {
|
|
166
|
+
out[key] = tracks.props[key][idx];
|
|
167
|
+
}
|
|
168
|
+
return out;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// src/PxRnRender.tsx
|
|
172
|
+
var import_svg_animator_core3 = require("@pixodesk/svg-animator-core");
|
|
173
|
+
var import_react = require("react");
|
|
174
|
+
|
|
175
|
+
// src/PxRnTypeMap.ts
|
|
176
|
+
var import_react_native_svg = require("react-native-svg");
|
|
177
|
+
var RN_SVG_COMPONENTS = {
|
|
178
|
+
svg: import_react_native_svg.Svg,
|
|
179
|
+
g: import_react_native_svg.G,
|
|
180
|
+
rect: import_react_native_svg.Rect,
|
|
181
|
+
circle: import_react_native_svg.Circle,
|
|
182
|
+
ellipse: import_react_native_svg.Ellipse,
|
|
183
|
+
line: import_react_native_svg.Line,
|
|
184
|
+
path: import_react_native_svg.Path,
|
|
185
|
+
polygon: import_react_native_svg.Polygon,
|
|
186
|
+
polyline: import_react_native_svg.Polyline,
|
|
187
|
+
text: import_react_native_svg.Text,
|
|
188
|
+
tspan: import_react_native_svg.TSpan,
|
|
189
|
+
textPath: import_react_native_svg.TextPath,
|
|
190
|
+
defs: import_react_native_svg.Defs,
|
|
191
|
+
linearGradient: import_react_native_svg.LinearGradient,
|
|
192
|
+
radialGradient: import_react_native_svg.RadialGradient,
|
|
193
|
+
stop: import_react_native_svg.Stop,
|
|
194
|
+
use: import_react_native_svg.Use,
|
|
195
|
+
symbol: import_react_native_svg.Symbol,
|
|
196
|
+
mask: import_react_native_svg.Mask,
|
|
197
|
+
clipPath: import_react_native_svg.ClipPath,
|
|
198
|
+
pattern: import_react_native_svg.Pattern,
|
|
199
|
+
marker: import_react_native_svg.Marker,
|
|
200
|
+
image: import_react_native_svg.Image
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
// src/PxRnRender.tsx
|
|
204
|
+
function toRnProps(props, warnings) {
|
|
205
|
+
const normalised = (0, import_svg_animator_core3.getNormalizedProps)(props);
|
|
206
|
+
const out = {};
|
|
207
|
+
for (const key of Object.keys(normalised)) {
|
|
208
|
+
const sanitised = (0, import_svg_animator_core3.sanitiseAttributeValue)(key, normalised[key]);
|
|
209
|
+
if (sanitised === void 0) continue;
|
|
210
|
+
const rnKey = toRnPropName(key);
|
|
211
|
+
if (!rnKey) continue;
|
|
212
|
+
out[rnKey] = toRnPropValue(rnKey, String(sanitised));
|
|
213
|
+
}
|
|
214
|
+
return out;
|
|
215
|
+
}
|
|
216
|
+
function renderRnNode(node, opts = {}, key) {
|
|
217
|
+
var _b, _c, _d;
|
|
218
|
+
if (!node) return null;
|
|
219
|
+
const _a = node, { type, children, style, animate, meta, effects } = _a, props = __objRest(_a, ["type", "children", "style", "animate", "meta", "effects"]);
|
|
220
|
+
const tag = String(type || "g");
|
|
221
|
+
if (import_svg_animator_core3.DISALLOWED_SVG_TAGS_LOWER.has(tag.toLowerCase())) {
|
|
222
|
+
(_b = opts.warnings) == null ? void 0 : _b.push("tag blocked (dangerous): " + tag);
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
const Component = RN_SVG_COMPONENTS[tag];
|
|
226
|
+
if (!Component) {
|
|
227
|
+
(_c = opts.warnings) == null ? void 0 : _c.push("tag not supported in react-native-svg mapping: " + tag);
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
const rnProps = toRnProps(props, opts.warnings);
|
|
231
|
+
if (key !== void 0) rnProps.key = key;
|
|
232
|
+
const textContent = props[import_svg_animator_core3.TEXT_ATTR] || props[import_svg_animator_core3.TEXT_CONTENT_ATTR];
|
|
233
|
+
let childElements = void 0;
|
|
234
|
+
if (Array.isArray(children) && children.length > 0) {
|
|
235
|
+
childElements = children.map((ch, i) => renderRnNode(ch, opts, i)).filter(Boolean);
|
|
236
|
+
} else if (textContent !== void 0) {
|
|
237
|
+
childElements = String(textContent);
|
|
238
|
+
}
|
|
239
|
+
const decorated = (_d = opts.decorate) == null ? void 0 : _d.call(opts, node, Component, rnProps, childElements);
|
|
240
|
+
if (decorated !== void 0) return decorated;
|
|
241
|
+
return (0, import_react.createElement)(Component, rnProps, childElements);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// src/PixodeskSvgAnimator.tsx
|
|
245
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
246
|
+
var animatedComponentCache = /* @__PURE__ */ new Map();
|
|
247
|
+
function getAnimatedComponent(Component) {
|
|
248
|
+
let cached = animatedComponentCache.get(Component);
|
|
249
|
+
if (!cached) {
|
|
250
|
+
cached = import_react_native_reanimated.default.createAnimatedComponent(Component);
|
|
251
|
+
animatedComponentCache.set(Component, cached);
|
|
252
|
+
}
|
|
253
|
+
return cached;
|
|
254
|
+
}
|
|
255
|
+
function AnimatedPxElement({
|
|
256
|
+
Component,
|
|
257
|
+
staticProps,
|
|
258
|
+
children,
|
|
259
|
+
tracks,
|
|
260
|
+
progress,
|
|
261
|
+
stepMs,
|
|
262
|
+
sampleCount
|
|
263
|
+
}) {
|
|
264
|
+
const AnimatedComponent = (0, import_react2.useMemo)(() => getAnimatedComponent(Component), [Component]);
|
|
265
|
+
const animatedProps = (0, import_react_native_reanimated.useAnimatedProps)(() => {
|
|
266
|
+
return sampleProps(tracks, progress.value, stepMs, sampleCount);
|
|
267
|
+
}, [tracks, stepMs, sampleCount]);
|
|
268
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AnimatedComponent, __spreadProps(__spreadValues({}, staticProps), { animatedProps, children }));
|
|
269
|
+
}
|
|
270
|
+
function PixodeskSvgAnimator({
|
|
271
|
+
doc,
|
|
272
|
+
duration,
|
|
273
|
+
delay,
|
|
274
|
+
iterations,
|
|
275
|
+
fill,
|
|
276
|
+
direction,
|
|
277
|
+
autoplay,
|
|
278
|
+
play,
|
|
279
|
+
pause,
|
|
280
|
+
apiRef,
|
|
281
|
+
time,
|
|
282
|
+
timeMs,
|
|
283
|
+
onPlay,
|
|
284
|
+
onStop,
|
|
285
|
+
onPause,
|
|
286
|
+
onCancel,
|
|
287
|
+
onFinish
|
|
288
|
+
}) {
|
|
289
|
+
var _a, _b, _c;
|
|
290
|
+
const compiled = (0, import_react2.useMemo)(() => {
|
|
291
|
+
const warnings = (0, import_svg_animator_core4.validateNodeEffects)(doc);
|
|
292
|
+
for (const w of warnings) console.warn("[PixodeskSvgAnimator] effects shape warning:", w);
|
|
293
|
+
let prepared = (0, import_svg_animator_core4.materialiseAllInTree)(doc, import_svg_animator_core4.PxAnimatorEngine.webapi);
|
|
294
|
+
const animator = (0, import_svg_animator_core4.getAnimatorConfig)(prepared) || {};
|
|
295
|
+
prepared = __spreadProps(__spreadValues({}, prepared), {
|
|
296
|
+
animator: __spreadProps(__spreadValues({}, animator), {
|
|
297
|
+
duration: duration !== void 0 ? duration : animator.duration,
|
|
298
|
+
delay: delay !== void 0 ? delay : animator.delay,
|
|
299
|
+
iterations: iterations !== void 0 ? iterations : animator.iterations,
|
|
300
|
+
fill: fill !== void 0 ? fill : animator.fill,
|
|
301
|
+
direction: direction !== void 0 ? direction : animator.direction
|
|
302
|
+
})
|
|
303
|
+
});
|
|
304
|
+
prepared = (0, import_svg_animator_core4.generateNewIds)(prepared);
|
|
305
|
+
const tracks2 = compileTracks(prepared);
|
|
306
|
+
return { doc: prepared, tracks: tracks2 };
|
|
307
|
+
}, [doc, duration, delay, iterations, fill, direction]);
|
|
308
|
+
const tracks = compiled.tracks;
|
|
309
|
+
const totalDuration = tracks.duration * (tracks.iterations === Infinity ? 1 : tracks.iterations);
|
|
310
|
+
const progress = (0, import_react_native_reanimated.useSharedValue)(0);
|
|
311
|
+
const playingRef = (0, import_react2.useRef)(false);
|
|
312
|
+
const rateRef = (0, import_react2.useRef)(1);
|
|
313
|
+
const notifyFinish = () => {
|
|
314
|
+
playingRef.current = false;
|
|
315
|
+
if (tracks.fill === "none" || tracks.fill === "backwards") progress.value = 0;
|
|
316
|
+
onFinish == null ? void 0 : onFinish();
|
|
317
|
+
onStop == null ? void 0 : onStop();
|
|
318
|
+
};
|
|
319
|
+
const startFrom = (fromMs) => {
|
|
320
|
+
const dur = tracks.duration;
|
|
321
|
+
const rate = rateRef.current || 1;
|
|
322
|
+
const reversedStart = tracks.direction === "reverse" || tracks.direction === "alternate-reverse";
|
|
323
|
+
const alternates = tracks.direction === "alternate" || tracks.direction === "alternate-reverse";
|
|
324
|
+
const from = Math.max(0, Math.min(fromMs, dur));
|
|
325
|
+
const legTarget = reversedStart ? 0 : dur;
|
|
326
|
+
const legRemaining = Math.abs(legTarget - from) / rate;
|
|
327
|
+
const repeats = tracks.iterations === Infinity ? -1 : tracks.iterations;
|
|
328
|
+
(0, import_react_native_reanimated.cancelAnimation)(progress);
|
|
329
|
+
progress.value = reversedStart ? from === 0 ? dur : from : from;
|
|
330
|
+
const animation = repeats === 1 ? (0, import_react_native_reanimated.withTiming)(legTarget, { duration: legRemaining, easing: import_react_native_reanimated.Easing.linear }, (finished) => {
|
|
331
|
+
"worklet";
|
|
332
|
+
if (finished) (0, import_react_native_reanimated.runOnJS)(notifyFinish)();
|
|
333
|
+
}) : (0, import_react_native_reanimated.withRepeat)(
|
|
334
|
+
(0, import_react_native_reanimated.withTiming)(legTarget, { duration: legRemaining, easing: import_react_native_reanimated.Easing.linear }),
|
|
335
|
+
repeats,
|
|
336
|
+
alternates,
|
|
337
|
+
(finished) => {
|
|
338
|
+
"worklet";
|
|
339
|
+
if (finished) (0, import_react_native_reanimated.runOnJS)(notifyFinish)();
|
|
340
|
+
}
|
|
341
|
+
);
|
|
342
|
+
progress.value = tracks.delay > 0 && from === 0 ? (0, import_react_native_reanimated.withDelay)(tracks.delay / rate, animation) : animation;
|
|
343
|
+
playingRef.current = true;
|
|
344
|
+
};
|
|
345
|
+
const api = {
|
|
346
|
+
isPlaying: () => playingRef.current,
|
|
347
|
+
play: () => {
|
|
348
|
+
const from = playingRef.current ? progress.value : progress.value >= tracks.duration ? 0 : progress.value;
|
|
349
|
+
startFrom(from);
|
|
350
|
+
onPlay == null ? void 0 : onPlay();
|
|
351
|
+
},
|
|
352
|
+
pause: () => {
|
|
353
|
+
(0, import_react_native_reanimated.cancelAnimation)(progress);
|
|
354
|
+
playingRef.current = false;
|
|
355
|
+
onPause == null ? void 0 : onPause();
|
|
356
|
+
onStop == null ? void 0 : onStop();
|
|
357
|
+
},
|
|
358
|
+
cancel: () => {
|
|
359
|
+
(0, import_react_native_reanimated.cancelAnimation)(progress);
|
|
360
|
+
progress.value = 0;
|
|
361
|
+
playingRef.current = false;
|
|
362
|
+
onCancel == null ? void 0 : onCancel();
|
|
363
|
+
onStop == null ? void 0 : onStop();
|
|
364
|
+
},
|
|
365
|
+
finish: () => {
|
|
366
|
+
(0, import_react_native_reanimated.cancelAnimation)(progress);
|
|
367
|
+
progress.value = tracks.fill === "none" || tracks.fill === "backwards" ? 0 : tracks.duration;
|
|
368
|
+
playingRef.current = false;
|
|
369
|
+
onFinish == null ? void 0 : onFinish();
|
|
370
|
+
onStop == null ? void 0 : onStop();
|
|
371
|
+
},
|
|
372
|
+
setPlaybackRate: (rate) => {
|
|
373
|
+
if (!isFinite(rate) || rate <= 0) {
|
|
374
|
+
console.warn("setPlaybackRate: only finite positive rates are supported in the RN player (reverse is on the feature-gap list)");
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
rateRef.current = rate;
|
|
378
|
+
if (playingRef.current) startFrom(progress.value);
|
|
379
|
+
},
|
|
380
|
+
getCurrentTime: () => progress.value,
|
|
381
|
+
setCurrentTime: (t) => {
|
|
382
|
+
(0, import_react_native_reanimated.cancelAnimation)(progress);
|
|
383
|
+
playingRef.current = false;
|
|
384
|
+
const clamped = Math.max(0, Math.min(t, totalDuration));
|
|
385
|
+
progress.value = tracks.duration > 0 ? clamped % tracks.duration || (clamped === 0 ? 0 : tracks.duration) : 0;
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
(0, import_react2.useImperativeHandle)(apiRef, () => api, [compiled]);
|
|
389
|
+
const startOn = (_c = (_b = (_a = (0, import_svg_animator_core4.getAnimatorConfig)(compiled.doc)) == null ? void 0 : _a.trigger) == null ? void 0 : _b.startOn) != null ? _c : "load";
|
|
390
|
+
(0, import_react2.useEffect)(() => {
|
|
391
|
+
if (time !== void 0 || timeMs !== void 0) {
|
|
392
|
+
const seekMs = timeMs !== void 0 ? timeMs : (time != null ? time : 0) * totalDuration;
|
|
393
|
+
api.setCurrentTime(seekMs);
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
if (play !== void 0 || pause !== void 0) {
|
|
397
|
+
if (play && !pause) api.play();
|
|
398
|
+
else if (pause) api.pause();
|
|
399
|
+
else if (play === false) api.finish();
|
|
400
|
+
else api.play();
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
if (autoplay && startOn === "load") {
|
|
404
|
+
api.play();
|
|
405
|
+
}
|
|
406
|
+
}, [compiled, autoplay, play, pause, time, timeMs]);
|
|
407
|
+
(0, import_react2.useEffect)(() => {
|
|
408
|
+
return () => {
|
|
409
|
+
(0, import_react_native_reanimated.cancelAnimation)(progress);
|
|
410
|
+
playingRef.current = false;
|
|
411
|
+
};
|
|
412
|
+
}, [compiled]);
|
|
413
|
+
const trackById = (0, import_react2.useMemo)(() => {
|
|
414
|
+
const map = /* @__PURE__ */ new Map();
|
|
415
|
+
for (const el of tracks.elements) map.set(el.id, el);
|
|
416
|
+
return map;
|
|
417
|
+
}, [tracks]);
|
|
418
|
+
const warningsRef = (0, import_react2.useRef)([]);
|
|
419
|
+
const root = (0, import_react2.useMemo)(() => {
|
|
420
|
+
warningsRef.current = [];
|
|
421
|
+
return renderRnNode(compiled.doc, {
|
|
422
|
+
warnings: warningsRef.current,
|
|
423
|
+
decorate: (node, Component, staticProps, children) => {
|
|
424
|
+
const id = node.id;
|
|
425
|
+
const elTracks = id ? trackById.get(id) : void 0;
|
|
426
|
+
if (!elTracks) return void 0;
|
|
427
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
428
|
+
AnimatedPxElement,
|
|
429
|
+
{
|
|
430
|
+
Component,
|
|
431
|
+
staticProps,
|
|
432
|
+
tracks: elTracks,
|
|
433
|
+
progress,
|
|
434
|
+
stepMs: tracks.stepMs,
|
|
435
|
+
sampleCount: tracks.sampleCount,
|
|
436
|
+
children
|
|
437
|
+
},
|
|
438
|
+
staticProps.key
|
|
439
|
+
);
|
|
440
|
+
}
|
|
441
|
+
});
|
|
442
|
+
}, [compiled, trackById]);
|
|
443
|
+
(0, import_react2.useEffect)(() => {
|
|
444
|
+
for (const w of warningsRef.current) console.warn("[PixodeskSvgAnimator]", w);
|
|
445
|
+
}, [root]);
|
|
446
|
+
return root;
|
|
447
|
+
}
|
|
448
|
+
var PixodeskSvgAnimator_default = PixodeskSvgAnimator;
|
|
449
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
450
|
+
0 && (module.exports = {
|
|
451
|
+
PixodeskSvgAnimator,
|
|
452
|
+
RN_SVG_COMPONENTS,
|
|
453
|
+
compileTracks,
|
|
454
|
+
renderRnNode,
|
|
455
|
+
sampleProps,
|
|
456
|
+
toRnPropName,
|
|
457
|
+
toRnProps
|
|
458
|
+
});
|
|
459
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/PixodeskSvgAnimator.tsx","../src/PxRnTracks.ts","../src/PxRnPropNames.ts","../src/PxRnRender.tsx","../src/PxRnTypeMap.ts"],"sourcesContent":["/*---------------------------------------------------------------------------------------\n * Copyright (c) Pixodesk LTD.\n * Licensed under the MIT License. See the LICENSE file in the project root for details.\n *---------------------------------------------------------------------------------------*/\n\nexport { PixodeskSvgAnimator, default } from './PixodeskSvgAnimator';\nexport type { PixodeskSvgAnimatorProps, RnAnimatorApi } from './PixodeskSvgAnimator';\n\nexport { renderRnNode, toRnProps } from './PxRnRender';\nexport type { RenderRnNodeOptions } from './PxRnRender';\n\nexport { compileTracks, sampleProps } from './PxRnTracks';\nexport type { CompileTracksOptions, PxCompiledTracks, PxElementTracks } from './PxRnTracks';\n\nexport { RN_SVG_COMPONENTS, toRnPropName } from './PxRnTypeMap';\n","/*---------------------------------------------------------------------------------------\n * Copyright (c) Pixodesk LTD.\n * Licensed under the MIT License. See the LICENSE file in the project root for details.\n *---------------------------------------------------------------------------------------*/\n\nimport {\n generateNewIds,\n getAnimatorConfig,\n materialiseAllInTree,\n validateNodeEffects,\n PxAnimatorEngine,\n type FillMode,\n type PlaybackDirection,\n type PxAnimatedSvgDocument,\n type PxNode,\n} from '@pixodesk/svg-animator-core';\nimport React, { useEffect, useImperativeHandle, useMemo, useRef, type ComponentType, type ReactElement, type ReactNode } from 'react';\nimport Animated, {\n cancelAnimation,\n Easing,\n runOnJS,\n useAnimatedProps,\n useSharedValue,\n withDelay,\n withRepeat,\n withTiming,\n type SharedValue,\n} from 'react-native-reanimated';\nimport { compileTracks, sampleProps, type PxCompiledTracks, type PxElementTracks } from './PxRnTracks';\nimport { renderRnNode } from './PxRnRender';\n\n\n// -- Public types -----------------------------------------------------------\n\n/** Imperative playback API — mirrors ReactAnimatorApi from svg-animator-react. */\nexport interface RnAnimatorApi {\n /** Returns true if the animation is currently running. */\n isPlaying(): boolean;\n\n /** Starts or resumes the animation. */\n play(): void;\n\n /** Pauses the animation at its current state. */\n pause(): void;\n\n /** Stops the animation and resets it to its initial state. */\n cancel(): void;\n\n /** Jumps to the end of the animation and holds the final state. */\n finish(): void;\n\n /** Changes the speed of the animation. 1 is normal, 2 is double. */\n setPlaybackRate(rate: number): void;\n\n /** Returns the current playback time in milliseconds. */\n getCurrentTime(): number | null;\n\n /** Jumps to a specific time (in milliseconds) in the animation. */\n setCurrentTime(time: number): void;\n}\n\nexport interface PixodeskSvgAnimatorProps {\n\n // -- Source ---------------------------------------------------------------\n\n /** The animation document to render. */\n doc: PxAnimatedSvgDocument;\n\n // -- Timing overrides -----------------------------------------------------\n\n /** Duration of a single iteration in milliseconds. */\n duration?: number;\n\n /** Delay before the animation starts, in milliseconds. */\n delay?: number;\n\n /** Number of iterations, or 'infinite' for endless looping. */\n iterations?: number | 'infinite';\n\n /** Defines the element's state when the animation is not active. */\n fill?: FillMode;\n\n /** Playback direction. */\n direction?: PlaybackDirection;\n\n // -- Declarative control --------------------------------------------------\n\n /** When true, honours the document trigger (`startOn: 'load'` plays on mount). */\n autoplay?: boolean;\n\n /** Starts playback unconditionally. */\n play?: boolean;\n\n /** Pauses current playback. */\n pause?: boolean;\n\n // -- Imperative control ---------------------------------------------------\n\n /** Ref populated with the imperative playback API. */\n apiRef?: React.RefObject<RnAnimatorApi | null>;\n\n // -- Controlled (external) time -------------------------------------------\n\n /** Seek to a fraction (0–1) of the whole timeline (duration × iterations). */\n time?: number;\n\n /** Seek to a specific time in milliseconds. */\n timeMs?: number;\n\n // -- Callbacks ------------------------------------------------------------\n\n onPlay?: () => void;\n onStop?: () => void;\n onPause?: () => void;\n onCancel?: () => void;\n onFinish?: () => void;\n}\n\n\n// -- Animated element wrapper ------------------------------------------------\n\nconst animatedComponentCache = new Map<ComponentType<any>, ComponentType<any>>();\n\nfunction getAnimatedComponent(Component: ComponentType<any>): ComponentType<any> {\n let cached = animatedComponentCache.get(Component);\n if (!cached) {\n cached = Animated.createAnimatedComponent(Component as any);\n animatedComponentCache.set(Component, cached);\n }\n return cached;\n}\n\n/** One animated element: static props + UI-thread sampled animated props. */\nfunction AnimatedPxElement({\n Component, staticProps, children, tracks, progress, stepMs, sampleCount,\n}: {\n Component: ComponentType<any>;\n staticProps: Record<string, any>;\n children: ReactNode;\n tracks: PxElementTracks;\n progress: SharedValue<number>;\n stepMs: number;\n sampleCount: number;\n}) {\n const AnimatedComponent = useMemo(() => getAnimatedComponent(Component), [Component]);\n\n // Runs on the UI thread every frame; `sampleProps` is a trivial indexed\n // lookup into the precompiled tracks — no interpolation logic on the hot path.\n const animatedProps = useAnimatedProps(() => {\n return sampleProps(tracks, progress.value, stepMs, sampleCount);\n }, [tracks, stepMs, sampleCount]);\n\n return (\n <AnimatedComponent {...staticProps} animatedProps={animatedProps}>\n {children}\n </AnimatedComponent>\n );\n}\n\n\n// -- Main component ----------------------------------------------------------\n\n/**\n * React Native component for rendering and controlling Pixodesk SVG animations.\n *\n * The document is materialised once through the shared core pipeline (effects,\n * loops, motion-path sampling, animated-`<use>` inlining — identical to the\n * web frames engine), compiled into densely sampled per-element tracks, and\n * played back natively: a single reanimated progress value driven by\n * `withTiming`/`withRepeat` on the UI thread, with per-element worklets\n * indexing the precompiled tracks. No JS-thread frame loop.\n */\nexport function PixodeskSvgAnimator({\n doc, duration, delay, iterations, fill, direction,\n autoplay, play, pause, apiRef, time, timeMs,\n onPlay, onStop, onPause, onCancel, onFinish,\n}: PixodeskSvgAnimatorProps): ReactElement | null {\n\n // -- Compile the document (once per doc/override change) ------------------\n\n const compiled = useMemo(() => {\n const warnings = validateNodeEffects(doc as PxNode);\n for (const w of warnings) console.warn('[PixodeskSvgAnimator] effects shape warning:', w);\n\n // `webapi` = the FULLY-FLATTENED materialisation: effects + loops +\n // sampled motion paths + animated `<use>` inlined into real `<g>`\n // clones + orphaned defs pruned. That last part is why RN must not use\n // the `frames` flavour: frames keeps `<use href=\"#animatedTarget\">`\n // live references, which only work because the DOM propagates\n // attribute writes through `<use>` shadow trees. react-native-svg has\n // no such live propagation, so an animated `<use>` would render frozen.\n let prepared = materialiseAllInTree(doc, PxAnimatorEngine.webapi);\n\n // Apply prop overrides onto the animator config (mirrors the react wrapper).\n const animator = getAnimatorConfig(prepared) || {};\n prepared = {\n ...prepared,\n animator: {\n ...animator,\n duration: duration !== undefined ? duration : animator.duration,\n delay: delay !== undefined ? delay : animator.delay,\n iterations: iterations !== undefined ? iterations : animator.iterations,\n fill: fill !== undefined ? fill : animator.fill,\n direction: direction !== undefined ? direction : animator.direction,\n },\n };\n\n prepared = generateNewIds(prepared);\n const tracks = compileTracks(prepared);\n return { doc: prepared, tracks };\n }, [doc, duration, delay, iterations, fill, direction]);\n\n const tracks: PxCompiledTracks = compiled.tracks;\n const totalDuration = tracks.duration * (tracks.iterations === Infinity ? 1 : tracks.iterations);\n\n // -- Playback state -------------------------------------------------------\n\n // Progress in ms within ONE iteration; iteration repetition/alternation is\n // expressed through withRepeat, so worklets only ever see [0, duration].\n const progress = useSharedValue(0);\n const playingRef = useRef(false);\n const rateRef = useRef(1);\n\n const notifyFinish = () => {\n playingRef.current = false;\n if (tracks.fill === 'none' || tracks.fill === 'backwards') progress.value = 0;\n onFinish?.();\n onStop?.();\n };\n\n const startFrom = (fromMs: number) => {\n const dur = tracks.duration;\n const rate = rateRef.current || 1;\n const reversedStart = tracks.direction === 'reverse' || tracks.direction === 'alternate-reverse';\n const alternates = tracks.direction === 'alternate' || tracks.direction === 'alternate-reverse';\n const from = Math.max(0, Math.min(fromMs, dur));\n\n const legTarget = reversedStart ? 0 : dur;\n const legRemaining = Math.abs(legTarget - from) / rate;\n const repeats = tracks.iterations === Infinity ? -1 : tracks.iterations;\n\n cancelAnimation(progress);\n progress.value = reversedStart ? (from === 0 ? dur : from) : from;\n\n const animation = repeats === 1\n ? withTiming(legTarget, { duration: legRemaining, easing: Easing.linear }, (finished) => {\n 'worklet';\n if (finished) runOnJS(notifyFinish)();\n })\n : withRepeat(\n withTiming(legTarget, { duration: legRemaining, easing: Easing.linear }),\n repeats, alternates,\n (finished) => {\n 'worklet';\n if (finished) runOnJS(notifyFinish)();\n }\n );\n\n progress.value = tracks.delay > 0 && from === 0\n ? withDelay(tracks.delay / rate, animation)\n : animation;\n\n playingRef.current = true;\n };\n\n const api: RnAnimatorApi = {\n isPlaying: () => playingRef.current,\n play: () => {\n const from = playingRef.current ? progress.value : progress.value >= tracks.duration ? 0 : progress.value;\n startFrom(from);\n onPlay?.();\n },\n pause: () => {\n cancelAnimation(progress);\n playingRef.current = false;\n onPause?.();\n onStop?.();\n },\n cancel: () => {\n cancelAnimation(progress);\n progress.value = 0;\n playingRef.current = false;\n onCancel?.();\n onStop?.();\n },\n finish: () => {\n cancelAnimation(progress);\n progress.value = tracks.fill === 'none' || tracks.fill === 'backwards' ? 0 : tracks.duration;\n playingRef.current = false;\n onFinish?.();\n onStop?.();\n },\n setPlaybackRate: (rate: number) => {\n if (!isFinite(rate) || rate <= 0) {\n console.warn('setPlaybackRate: only finite positive rates are supported in the RN player (reverse is on the feature-gap list)');\n return;\n }\n rateRef.current = rate;\n if (playingRef.current) startFrom(progress.value);\n },\n getCurrentTime: () => progress.value,\n setCurrentTime: (t: number) => {\n cancelAnimation(progress);\n playingRef.current = false;\n const clamped = Math.max(0, Math.min(t, totalDuration));\n progress.value = tracks.duration > 0 ? clamped % tracks.duration || (clamped === 0 ? 0 : tracks.duration) : 0;\n },\n };\n\n useImperativeHandle(apiRef, () => api, [compiled]);\n\n // -- Declarative control --------------------------------------------------\n\n const startOn = getAnimatorConfig(compiled.doc)?.trigger?.startOn ?? 'load';\n\n useEffect(() => {\n if (time !== undefined || timeMs !== undefined) {\n const seekMs = timeMs !== undefined ? timeMs : (time ?? 0) * totalDuration;\n api.setCurrentTime(seekMs);\n return;\n }\n if (play !== undefined || pause !== undefined) {\n if (play && !pause) api.play();\n else if (pause) api.pause();\n else if (play === false) api.finish();\n else api.play();\n return;\n }\n if (autoplay && startOn === 'load') {\n api.play();\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [compiled, autoplay, play, pause, time, timeMs]);\n\n // Stop cleanly on unmount / doc swap.\n useEffect(() => {\n return () => {\n cancelAnimation(progress);\n playingRef.current = false;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [compiled]);\n\n // -- Render ---------------------------------------------------------------\n\n const trackById = useMemo(() => {\n const map = new Map<string, PxElementTracks>();\n for (const el of tracks.elements) map.set(el.id, el);\n return map;\n }, [tracks]);\n\n const warningsRef = useRef<Array<string>>([]);\n const root = useMemo(() => {\n warningsRef.current = [];\n return renderRnNode(compiled.doc as PxNode, {\n warnings: warningsRef.current,\n decorate: (node, Component, staticProps, children) => {\n const id = (node as any).id;\n const elTracks = id ? trackById.get(id) : undefined;\n if (!elTracks) return undefined;\n return (\n <AnimatedPxElement\n key={staticProps.key}\n Component={Component}\n staticProps={staticProps}\n tracks={elTracks}\n progress={progress}\n stepMs={tracks.stepMs}\n sampleCount={tracks.sampleCount}\n >\n {children}\n </AnimatedPxElement>\n );\n },\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [compiled, trackById]);\n\n useEffect(() => {\n for (const w of warningsRef.current) console.warn('[PixodeskSvgAnimator]', w);\n }, [root]);\n\n return root;\n}\n\nexport default PixodeskSvgAnimator;\n","/*---------------------------------------------------------------------------------------\n * Copyright (c) Pixodesk LTD.\n * Licensed under the MIT License. See the LICENSE file in the project root for details.\n *---------------------------------------------------------------------------------------*/\n\nimport {\n calcAnimationValues,\n getAnimatorConfig,\n getNormalisedBindings,\n DEFAULT_DURATION_MS,\n PxAnimatorEngine,\n type PxAnimatedSvgDocument,\n type PxAnimationDefinition,\n} from '@pixodesk/svg-animator-core';\nimport { toRnPropName, toRnPropValue } from './PxRnPropNames';\n\n/**\n * Sampled animation tracks for ONE element: prop name → per-sample values.\n *\n * The compiler densely samples every animated property through core's\n * `calcAnimationValues` — the exact function the web frames engine renders\n * with — so RN playback is value-identical to the web player. Easing, loops,\n * transform composition, colour interpolation and path morphing are all baked\n * into the samples at compile time; the UI-thread worklet only indexes arrays.\n */\nexport interface PxElementTracks {\n /** Element id (after id regeneration). */\n id: string;\n /** react-native-svg prop name → one value per sample. */\n props: Record<string, Array<string | number | Array<number>>>;\n}\n\nexport interface PxCompiledTracks {\n /** Per-iteration duration, ms. */\n duration: number;\n /** Iteration count (Infinity for 'infinite'). */\n iterations: number;\n /** 'normal' | 'reverse' | 'alternate' | 'alternate-reverse' */\n direction: string;\n /** Delay before start, ms (positive = wait). */\n delay: number;\n /** WAAPI-style fill mode (default 'forwards'). */\n fill: string;\n /** Sample step, ms. */\n stepMs: number;\n /** Number of samples per iteration (>= 2; sample i is at time i*stepMs). */\n sampleCount: number;\n /** Tracks for every animated element. */\n elements: Array<PxElementTracks>;\n}\n\nexport interface CompileTracksOptions {\n /** Target sample rate, samples/second. Default 60 (one per frame). */\n sampleRate?: number;\n /** Hard cap on samples per iteration (memory guard). Default 600. */\n maxSamples?: number;\n}\n\n\n\n/**\n * Compiles a MATERIALISED document (run `materialiseAllInTree(doc, 'frames')`\n * + `generateNewIds` first) into densely sampled per-element tracks.\n */\nexport function compileTracks(doc: PxAnimatedSvgDocument, opts?: CompileTracksOptions): PxCompiledTracks {\n const config = getAnimatorConfig(doc) || {};\n\n const duration = +(config.duration || DEFAULT_DURATION_MS);\n const _iterations = config.iterations;\n let iterations = 1;\n if (typeof _iterations === 'number') iterations = _iterations || 1;\n if (_iterations === 'infinite') iterations = Infinity;\n if (iterations < 1) iterations = 1;\n\n const sampleRate = opts?.sampleRate ?? 60;\n const maxSamples = opts?.maxSamples ?? 600;\n let sampleCount = Math.max(2, Math.round((duration / 1000) * sampleRate) + 1);\n if (sampleCount > maxSamples) sampleCount = maxSamples;\n const stepMs = duration / (sampleCount - 1);\n\n const bindings = getNormalisedBindings(doc, PxAnimatorEngine.frames) || [];\n\n const elements: Array<PxElementTracks> = [];\n for (const binding of bindings) {\n const animDef = binding.animate;\n if (!animDef || typeof animDef !== 'object' || Array.isArray(animDef)) continue;\n\n const props: Record<string, Array<string | number | Array<number>>> = {};\n for (let i = 0; i < sampleCount; i++) {\n const t = i === sampleCount - 1 ? duration : i * stepMs;\n const values = calcAnimationValues(animDef as PxAnimationDefinition, t);\n for (const [attr, value] of Object.entries(values)) {\n const rnProp = toRnPropName(attr);\n if (!rnProp) continue;\n let arr = props[rnProp];\n if (!arr) {\n arr = props[rnProp] = new Array(sampleCount);\n // A prop can appear late (e.g. attrs whose first kf is\n // beyond t=0) — backfill earlier samples with the first\n // computed value so the array is always fully populated.\n for (let j = 0; j < i; j++) arr[j] = toRnPropValue(rnProp, value);\n }\n arr[i] = toRnPropValue(rnProp, value);\n }\n }\n // Forward-fill any holes (attr disappeared from a later sample).\n for (const arr of Object.values(props)) {\n for (let i = 1; i < sampleCount; i++) {\n if (arr[i] === undefined) arr[i] = arr[i - 1];\n }\n }\n\n if (Object.keys(props).length > 0) {\n elements.push({ id: binding.id, props });\n }\n }\n\n return {\n duration,\n iterations,\n direction: config.direction || 'normal',\n delay: config.delay || 0,\n fill: config.fill ?? 'forwards',\n stepMs,\n sampleCount,\n elements,\n };\n}\n\n/**\n * Worklet-safe sample lookup: returns the per-prop values at time `tMs`\n * (already mapped into a single iteration by the caller). Kept deliberately\n * trivial — runs on the UI thread every frame.\n */\nexport function sampleProps(\n tracks: PxElementTracks,\n tMs: number,\n stepMs: number,\n sampleCount: number\n): Record<string, string | number | Array<number>> {\n 'worklet';\n let idx = Math.round(tMs / stepMs);\n if (idx < 0) idx = 0;\n if (idx >= sampleCount) idx = sampleCount - 1;\n const out: Record<string, string | number | Array<number>> = {};\n for (const key in tracks.props) {\n out[key] = tracks.props[key][idx];\n }\n return out;\n}\n","/*---------------------------------------------------------------------------------------\n * Copyright (c) Pixodesk LTD.\n * Licensed under the MIT License. See the LICENSE file in the project root for details.\n *---------------------------------------------------------------------------------------*/\n\nimport { kebabToCamelCaseWord } from '@pixodesk/svg-animator-core';\n\n/** Attribute names with a react-native-svg prop equivalent under a\n * different name (not just a casing change). */\nconst ATTR_NAME_OVERRIDES: Record<string, string> = {\n 'xlink:href': 'href',\n};\n\n/** Props react-native-svg does not understand / must not receive. */\nconst DROPPED_ATTRS = new Set(['class', 'className', 'style', 'xmlns', 'xmlns:xlink', 'data-px-meta']);\n\n/**\n * Converts one normalised wire attribute name (camelCase after core's\n * `getNormalizedProps`, or kebab-case raw) to a react-native-svg prop name.\n * Returns undefined for props that must be dropped.\n *\n * Pure (no react-native-svg import) so the track compiler and its tests\n * don't need a React Native environment.\n */\nexport function toRnPropName(attrName: string): string | undefined {\n if (DROPPED_ATTRS.has(attrName)) return undefined;\n const override = ATTR_NAME_OVERRIDES[attrName];\n if (override) return override;\n // react-native-svg uses camelCase props (strokeWidth, fillOpacity, …);\n // core's kebabToCamelCaseWord is a no-op for already-camelCase input.\n return kebabToCamelCaseWord(attrName);\n}\n\n/** Props whose value is a LIST of lengths. react-native-svg's native side\n * expects a number array here (its JS `extractLengthList` splits strings, but\n * values delivered through reanimated's animated-props path bypass that JS\n * extraction and reach the native view directly). */\nconst LENGTH_LIST_PROPS = new Set(['strokeDasharray']);\n\n/**\n * Converts one already-renamed prop value into the shape react-native-svg\n * expects: length-list props become number arrays; numeric strings become\n * numbers; everything else passes through.\n */\nexport function toRnPropValue(rnPropName: string, value: string | number): string | number | Array<number> {\n if (LENGTH_LIST_PROPS.has(rnPropName)) {\n const parts = String(value).trim().replace(/,/g, ' ').split(/\\s+/).map(Number).filter(n => Number.isFinite(n));\n // An odd-length dasharray repeats to become even (SVG spec); rn-svg\n // does this itself for the static path — mirror it so both paths agree.\n return parts.length % 2 === 1 ? parts.concat(parts) : parts;\n }\n if (typeof value === 'number') return value;\n const num = +value;\n return Number.isFinite(num) && String(num) === value ? num : value;\n}\n","/*---------------------------------------------------------------------------------------\n * Copyright (c) Pixodesk LTD.\n * Licensed under the MIT License. See the LICENSE file in the project root for details.\n *---------------------------------------------------------------------------------------*/\n\nimport {\n getNormalizedProps,\n sanitiseAttributeValue,\n DISALLOWED_SVG_TAGS_LOWER,\n TEXT_ATTR,\n TEXT_CONTENT_ATTR,\n type PxNode,\n} from '@pixodesk/svg-animator-core';\nimport { createElement, type ComponentType, type ReactElement, type ReactNode } from 'react';\nimport { RN_SVG_COMPONENTS } from './PxRnTypeMap';\nimport { toRnPropName, toRnPropValue } from './PxRnPropNames';\n\nexport interface RenderRnNodeOptions {\n /** Collects non-fatal issues (unsupported tags, dropped attrs). */\n warnings?: Array<string>;\n /**\n * Wraps the created element for animated nodes: receives the resolved\n * component + static props and returns the element to mount (the animator\n * substitutes an Animated component wired to its tracks). Return undefined\n * to keep the plain static element.\n */\n decorate?: (\n node: PxNode,\n Component: ComponentType<any>,\n props: Record<string, any>,\n children: ReactNode\n ) => ReactElement | undefined;\n}\n\n/**\n * Converts core-normalised wire props into react-native-svg props: RN prop\n * naming, sanitisation (same security rules as the web renderer), numeric\n * coercion where possible.\n */\nexport function toRnProps(props: Record<string, any>, warnings?: Array<string>): Record<string, any> {\n const normalised = getNormalizedProps(props);\n const out: Record<string, any> = {};\n for (const key of Object.keys(normalised)) {\n const sanitised = sanitiseAttributeValue(key, normalised[key]);\n if (sanitised === undefined) continue;\n const rnKey = toRnPropName(key);\n if (!rnKey) continue;\n out[rnKey] = toRnPropValue(rnKey, String(sanitised));\n }\n return out;\n}\n\n/**\n * Renders a (materialised) PxNode tree to react-native-svg elements.\n * Mirrors the web `renderNode` contract: unsupported/dangerous tags are\n * skipped with a warning, never a crash.\n */\nexport function renderRnNode(node: PxNode, opts: RenderRnNodeOptions = {}, key?: string | number): ReactElement | null {\n if (!node) return null;\n\n const { type, children, style, animate, meta, effects, ...props } = node as any;\n const tag = String(type || 'g');\n\n if (DISALLOWED_SVG_TAGS_LOWER.has(tag.toLowerCase())) {\n opts.warnings?.push('tag blocked (dangerous): ' + tag);\n return null;\n }\n\n const Component = RN_SVG_COMPONENTS[tag];\n if (!Component) {\n opts.warnings?.push('tag not supported in react-native-svg mapping: ' + tag);\n return null;\n }\n\n const rnProps = toRnProps(props, opts.warnings);\n if (key !== undefined) rnProps.key = key;\n\n // Text content: wire nodes carry it as `text` / `textContent` attr.\n const textContent: string | undefined = props[TEXT_ATTR] || props[TEXT_CONTENT_ATTR];\n\n let childElements: ReactNode = undefined;\n if (Array.isArray(children) && children.length > 0) {\n childElements = children\n .map((ch: PxNode, i: number) => renderRnNode(ch, opts, i))\n .filter(Boolean);\n } else if (textContent !== undefined) {\n childElements = String(textContent);\n }\n\n const decorated = opts.decorate?.(node, Component, rnProps, childElements);\n if (decorated !== undefined) return decorated;\n\n return createElement(Component, rnProps, childElements);\n}\n","/*---------------------------------------------------------------------------------------\n * Copyright (c) Pixodesk LTD.\n * Licensed under the MIT License. See the LICENSE file in the project root for details.\n *---------------------------------------------------------------------------------------*/\n\nimport {\n Circle,\n ClipPath,\n Defs,\n Ellipse,\n G,\n Image,\n Line,\n LinearGradient,\n Marker,\n Mask,\n Path,\n Pattern,\n Polygon,\n Polyline,\n RadialGradient,\n Rect,\n Stop,\n Svg,\n Symbol as SvgSymbol,\n Text as SvgText,\n TextPath,\n TSpan,\n Use,\n} from 'react-native-svg';\nimport type { ComponentType } from 'react';\n\n/**\n * SVG tag → react-native-svg component. Tags not in this map are skipped at\n * render time (with a warning collected by the renderer) — they go on the\n * feature-gap list rather than crashing the tree.\n */\nexport const RN_SVG_COMPONENTS: Record<string, ComponentType<any>> = {\n svg: Svg,\n g: G,\n rect: Rect,\n circle: Circle,\n ellipse: Ellipse,\n line: Line,\n path: Path,\n polygon: Polygon,\n polyline: Polyline,\n text: SvgText,\n tspan: TSpan,\n textPath: TextPath,\n defs: Defs,\n linearGradient: LinearGradient,\n radialGradient: RadialGradient,\n stop: Stop,\n use: Use,\n symbol: SvgSymbol,\n mask: Mask,\n clipPath: ClipPath,\n pattern: Pattern,\n marker: Marker,\n image: Image,\n};\n\nexport { toRnPropName } from './PxRnPropNames';\n"],"mappings":"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","names":["import_svg_animator_core","import_react","import_svg_animator_core","import_svg_animator_core","SvgText","SvgSymbol","Animated","tracks"]}
|