@pixodesk/svg-animator-rn 1.0.22 → 1.0.26

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 CHANGED
@@ -286,12 +286,12 @@ player sees plain nodes. **All are supported:**
286
286
 
287
287
  | Effect | Status | Notes |
288
288
  |---|---|---|
289
- | `transformation` | ✅ | all parts animatable, including `skew` |
289
+ | `transformBy` | ✅ | all parts animatable, including `skew` |
290
290
  | `repeater` | ✅ | copies materialised as real elements; per-copy params animatable |
291
291
  | `maskedBy` | ✅ | including an animated mask source |
292
292
  | `clipPath` | ✅ | including animated clip geometry |
293
- | `trimPath` | ✅ | incl. `offset` and `trimAllAsOne` |
294
- | `clone` + `retime` | ✅ | each clone keeps its own time shift. `retime.timeCrop` is not implemented (core-wide) |
293
+ | `trimPath` | ✅ | incl. `offset` and `subPaths: 'combined'` |
294
+ | `clone` + `retime` | ✅ | each clone keeps its own time shift, incl. `retime.timeCrop` (a visibility window on the document timeline) |
295
295
  | `fillGradient` / `strokeGradient` | ✅ | animated stops **and animated geometry** (`animate.gradientX1`/`Cx`/`R`, …); `gradientTransform` is static (core-wide) |
296
296
  | `textPath` | ✅ | incl. animated `startOffset` |
297
297
  | `text.useGlyphs` | ✅ | text becomes `<path>` outlines from `definitions.glyphs` — no font needed |
@@ -324,7 +324,7 @@ player sees plain nodes. **All are supported:**
324
324
  | Trigger `scrollIntoView` | ✅ | visibility sampled by measuring against the window (RN has no `IntersectionObserver`); honours `scrollIntoViewThreshold` and `outAction` |
325
325
  | Trigger `mouseOver` | ❌ | no touch equivalent — use `click`, or drive `play` yourself |
326
326
  | `frameRate` | n/a | reanimated runs at the display refresh rate; use `compileTracks({sampleRate})` to trade memory for temporal precision |
327
- | `mode` (`webapi` / `frames`) | n/a | there is no Web Animations API on RN — playback is always native-driven |
327
+ | `mode` (`waapi` / `frames`) | n/a | there is no Web Animations API on RN — playback is always native-driven |
328
328
 
329
329
  ### Known limitations
330
330
 
@@ -333,7 +333,7 @@ player sees plain nodes. **All are supported:**
333
333
  through `react-native-web`; the native reanimated ↔ `react-native-svg` prop
334
334
  bridge (notably filters and `strokeDasharray`) still needs checking on real
335
335
  iOS/Android.
336
- - **`retime.timeCrop`** and **animated `gradientTransform`** are unimplemented
336
+ - **animated `gradientTransform`** is unimplemented (`retime.timeCrop` now works — implemented 2026-08)
337
337
  in the core, so they are unavailable here too.
338
338
  - **`mouseOver`** has no touch analogue and will not be implemented.
339
339
  - **Text on a closed path is worked around, not fixed.** react-native-svg's
package/dist/index.cjs CHANGED
@@ -342,8 +342,8 @@ function renderRnNode(node, opts = {}, key) {
342
342
  if (!node) return null;
343
343
  const _a = node, { type, children, style, animate, meta, effects } = _a, props = __objRest(_a, ["type", "children", "style", "animate", "meta", "effects"]);
344
344
  const tag = String(type || "g");
345
- const feFuncType = props.funcType;
346
- if (feFuncType !== void 0) delete props.funcType;
345
+ const domType = props.domType;
346
+ if (domType !== void 0) delete props.domType;
347
347
  if (import_svg_animator_core3.DISALLOWED_SVG_TAGS_LOWER.has(tag.toLowerCase())) {
348
348
  (_b = opts.warnings) == null ? void 0 : _b.push("tag blocked (dangerous): " + tag);
349
349
  return null;
@@ -354,7 +354,7 @@ function renderRnNode(node, opts = {}, key) {
354
354
  return null;
355
355
  }
356
356
  const rnProps = toRnProps(props, opts.warnings, tag);
357
- if (feFuncType !== void 0) rnProps.type = feFuncType;
357
+ if (domType !== void 0) rnProps.type = domType;
358
358
  const resolved = (0, import_svg_animator_core3.resolveStyle)(style, opts.defs);
359
359
  if (resolved) {
360
360
  for (const [k, v] of Object.entries(resolved)) {
@@ -565,7 +565,7 @@ function compileDocument(doc, overrides) {
565
565
  const { duration, delay, iterations, fill, direction, resetOnFinish } = overrides;
566
566
  const warnings = (0, import_svg_animator_core5.validateNodeEffects)(doc);
567
567
  for (const w of warnings) console.warn("[PixodeskSvgAnimator] effects shape warning:", w);
568
- let prepared = (0, import_svg_animator_core5.materialiseAllInTree)(doc, import_svg_animator_core5.PxAnimatorEngine.webapi);
568
+ let prepared = (0, import_svg_animator_core5.materialiseAllInTree)(doc, import_svg_animator_core5.PxAnimatorEngine.waapi);
569
569
  if (NATIVE_SVG_VIEWS) {
570
570
  prepared = openClosedTextPathTargets(prepared);
571
571
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/PixodeskSvgAnimator.tsx","../src/PxRnTracks.ts","../src/PxRnPropNames.ts","../src/PxRnMatrix.ts","../src/PxRnRender.tsx","../src/PxRnTypeMap.ts","../src/PxRnErrorBoundary.tsx","../src/PxRnSafety.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 { PxRnErrorBoundary, type PxRnErrorBoundaryProps } from './PxRnErrorBoundary';\nexport { openClosedTextPathTargets } from './PxRnSafety';\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 getDefs,\n materialiseAllInTree,\n validateNodeEffects,\n PxAnimatorEngine,\n type FillMode,\n type OutAction,\n type PlaybackDirection,\n type PxAnimatedSvgDocument,\n type PxNode,\n} from '@pixodesk/svg-animator-core';\nimport React, { createElement, useEffect, useImperativeHandle, useMemo, useRef, useState, type ComponentType, type ReactElement, type ReactNode } from 'react';\nimport { Dimensions, Platform, Pressable, View } from 'react-native';\nimport Animated, {\n cancelAnimation,\n useAnimatedReaction,\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, type RenderRnNodeOptions } from './PxRnRender';\nimport { PxRnErrorBoundary } from './PxRnErrorBoundary';\nimport { openClosedTextPathTargets } from './PxRnSafety';\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 /** Snap back to the start state after a natural finish. */\n resetOnFinish?: boolean;\n\n /**\n * What a second tap does when `startOn: 'click'` is active.\n * Defaults to the document's `trigger.outAction`, else `'pause'`.\n */\n outAction?: OutAction;\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 // -- Failure handling -----------------------------------------------------\n\n /**\n * Called when a document cannot be compiled or rendered. The component\n * renders {@link fallback} instead of throwing, so a single broken\n * animation never takes down the screen around it.\n *\n * Only JavaScript failures reach this — a crash inside react-native-svg's\n * native renderer bypasses JavaScript entirely.\n */\n onError?: (error: Error, componentStack?: string) => void;\n\n /** Rendered in place of the animation after a failure. Default: nothing. */\n fallback?: (error: Error) => ReactElement | null;\n}\n\n\n// -- Animated element wrapper ------------------------------------------------\n\n/**\n * Whether react-native-svg is backed by NATIVE views here, rather than by the\n * DOM through react-native-web.\n *\n * The two want different things from an animated `transform`: a native view\n * declares a `matrix` prop taking six numbers, while the DOM wants a\n * `transform` attribute holding an SVG string. Getting it wrong is silent —\n * the value is dropped and the element simply never moves — so this single\n * constant decides it once and feeds both the track compiler (value form) and\n * the sampler (prop name). Everything else in the package defaults to the\n * DOM-compatible form.\n */\nconst NATIVE_SVG_VIEWS = Platform.OS !== 'web';\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 // On iOS/Android these values bypass react-native-svg's JS prop layer\n // and land on the native view, which declares `matrix`, not\n // `transform`. The web build keeps the DOM-facing `transform` name.\n return sampleProps(tracks, progress.value, stepMs, sampleCount, NATIVE_SVG_VIEWS);\n }, [tracks, stepMs, sampleCount]);\n\n return (\n <AnimatedComponent {...staticProps} animatedProps={animatedProps}>\n {children}\n </AnimatedComponent>\n );\n}\n\n\n/**\n * react-native-svg elements whose `render()` returns `null`. They carry data for\n * their PARENT (a `<Stop>` is read by the gradient that owns it) rather than\n * producing a native view, so reanimated has nothing to attach to — wrapping one\n * in `Animated.createAnimatedComponent` throws\n * \"Cannot find host instance for this component\".\n */\nconst NON_HOST_TAGS = new Set(['stop', 'feMergeNode']);\n\n/**\n * Definition elements — they describe paint/geometry for something else rather\n * than drawing themselves. Their animated attributes (a gradient's `y1`, a\n * stop's `stop-color`) do not reliably flow through reanimated's animated-props\n * path, so an animated def is rendered by re-sampling from JS instead. There\n * are only ever a handful per document and they change slowly, so the cost is\n * negligible — visual elements still animate entirely on the UI thread.\n */\nconst SAMPLED_DEF_TAGS = new Set(['linearGradient', 'radialGradient', ...NON_HOST_TAGS]);\n\n/** True when this subtree must be driven from JS rather than the UI thread:\n * either the node itself is an animated def, or it owns an animated non-host\n * child (an animated `<Stop>` only re-renders via its parent gradient). */\nfunction needsJsSampling(node: PxNode, trackById: Map<string, PxElementTracks>): boolean {\n const id = (node as any).id;\n if (SAMPLED_DEF_TAGS.has(String(node.type)) && id && trackById.has(id)) return true;\n return (node.children ?? []).some(c => needsJsSampling(c, trackById));\n}\n\n/**\n * Renders a subtree whose animation cannot run on the UI thread (see\n * {@link NON_HOST_TAGS}) by re-rendering it from JS with sampled values.\n *\n * Changing a `<Stop>`'s props does not re-render its parent gradient, so the\n * whole subtree is rebuilt — which is why this wraps the gradient rather than\n * the stop. The reaction itself runs on the UI thread and only crosses to JS\n * when the QUANTISED sample index changes, capping these few elements at\n * ~30fps instead of a JS call every frame.\n */\nfunction SampledSubtree({\n node, trackById, progress, stepMs, sampleCount, renderOpts,\n}: {\n node: PxNode;\n trackById: Map<string, PxElementTracks>;\n progress: SharedValue<number>;\n stepMs: number;\n sampleCount: number;\n renderOpts: RenderRnNodeOptions;\n}) {\n const [idx, setIdx] = useState(0);\n\n useAnimatedReaction(\n () => Math.floor(Math.round(progress.value / stepMs) / 2) * 2, // half-rate\n (next, prev) => {\n if (next !== prev) runOnJS(setIdx)(next);\n },\n [stepMs]\n );\n\n const tMs = Math.min(Math.max(idx, 0), sampleCount - 1) * stepMs;\n\n return renderRnNode(node, {\n ...renderOpts,\n // Sampled values are baked in as PLAIN props — nothing reanimated-driven.\n decorate: (n, Component, staticProps, children, key) => {\n const id = (n as any).id;\n const tracks = id ? trackById.get(id) : undefined;\n if (!tracks) return undefined;\n // Wire prop names, NOT the native ones: these go back through\n // react-native-svg's JS prop layer, which does the renaming itself.\n const sampled = sampleProps(tracks, tMs, stepMs, sampleCount);\n return createElement(Component, { ...staticProps, ...sampled, key }, children);\n },\n });\n}\n\n\n\n/** Overrides that shadow the document's own `animator` config. */\ninterface ConfigOverrides {\n duration?: number;\n delay?: number;\n iterations?: number | 'infinite';\n fill?: FillMode;\n direction?: PlaybackDirection;\n resetOnFinish?: boolean;\n}\n\ninterface Compiled {\n /** Materialised document, or null when compilation failed. */\n doc: PxAnimatedSvgDocument | null;\n tracks: PxCompiledTracks;\n error: Error | null;\n}\n\n/** Playable-but-empty tracks, so a failed compile still satisfies every hook\n * below it — React forbids skipping hooks on an error path. */\nconst EMPTY_TRACKS: PxCompiledTracks = {\n duration: 1, iterations: 1, direction: 'normal', delay: 0,\n fill: 'forwards', resetOnFinish: false, stepMs: 1, sampleCount: 2, elements: [],\n};\n\n/**\n * Materialises + compiles a document. Extracted from the component so the\n * whole thing sits behind one try/catch, and so it can be tested directly.\n */\nfunction compileDocument(doc: PxAnimatedSvgDocument, overrides: ConfigOverrides): Compiled {\n const { duration, delay, iterations, fill, direction, resetOnFinish } = overrides;\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 // Sidestep a react-native-svg NATIVE crash (see PxRnSafety). Guarded on\n // the platform because the DOM renders this case correctly and the web\n // document must stay exactly as the core pipeline produced it.\n if (NATIVE_SVG_VIEWS) {\n prepared = openClosedTextPathTargets(prepared as PxNode) as PxAnimatedSvgDocument;\n }\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 resetOnFinish: resetOnFinish !== undefined ? resetOnFinish : animator.resetOnFinish,\n },\n };\n\n prepared = generateNewIds(prepared);\n const tracks = compileTracks(prepared, { native: NATIVE_SVG_VIEWS });\n return { doc: prepared, tracks, error: null };\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, resetOnFinish, outAction: outActionProp,\n autoplay, play, pause, apiRef, time, timeMs,\n onPlay, onStop, onPause, onCancel, onFinish, onError, fallback,\n}: PixodeskSvgAnimatorProps): ReactElement | null {\n\n // -- Compile the document (once per doc/override change) ------------------\n\n const compiled = useMemo((): Compiled => {\n try {\n return compileDocument(\n doc,\n { duration, delay, iterations, fill, direction, resetOnFinish }\n );\n } catch (e) {\n // A malformed document must not take the host screen down with it.\n const error = e instanceof Error ? e : new Error(String(e));\n console.warn('[PixodeskSvgAnimator] could not compile the document:', error.message);\n return { doc: null, tracks: EMPTY_TRACKS, error };\n }\n }, [doc, duration, delay, iterations, fill, direction, resetOnFinish]);\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 /** True when the current rate plays the timeline backwards. */\n const reversePlayback = () => rateRef.current < 0;\n\n /** Where the playhead rests once playback ends. `resetOnFinish` snaps back\n * to the start; otherwise `fill` decides whether the final frame is held. */\n const restingPosition = () => {\n if (tracks.resetOnFinish) return 0;\n if (tracks.fill === 'none' || tracks.fill === 'backwards') return 0;\n return reversePlayback() ? 0 : tracks.duration;\n };\n\n const notifyFinish = () => {\n playingRef.current = false;\n progress.value = restingPosition();\n onFinish?.();\n onStop?.();\n };\n\n const startFrom = (fromMs: number) => {\n const dur = tracks.duration;\n const rate = rateRef.current || 1;\n const backwards = rate < 0;\n const speed = Math.abs(rate);\n // `direction` decides which end a leg runs toward; a negative playback\n // rate flips it again (the two compose, as in the Web Animations API).\n const directionReversed = tracks.direction === 'reverse' || tracks.direction === 'alternate-reverse';\n const reversedStart = backwards ? !directionReversed : directionReversed;\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) / speed;\n const repeats = tracks.iterations === Infinity ? -1 : tracks.iterations;\n\n cancelAnimation(progress);\n progress.value = reversedStart ? (from <= 0 ? dur : from) : (from >= dur ? 0 : 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 / speed, animation)\n : animation;\n\n playingRef.current = true;\n };\n\n const api: RnAnimatorApi = {\n isPlaying: () => playingRef.current,\n play: () => {\n // `startFrom` rewinds to the opposite end when the playhead is\n // already resting at a boundary (mirrors WAAPI, where play() on a\n // finished animation auto-rewinds).\n startFrom(progress.value);\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 playingRef.current = false;\n progress.value = restingPosition();\n onFinish?.();\n onStop?.();\n },\n setPlaybackRate: (rate: number) => {\n if (!isFinite(rate) || rate === 0) {\n console.warn('setPlaybackRate: rate must be finite and non-zero');\n return;\n }\n rateRef.current = rate;\n if (playingRef.current) startFrom(progress.value);\n },\n getCurrentTime: () => progress.value,\n setCurrentTime: (t: number) => {\n const wasPlaying = playingRef.current;\n cancelAnimation(progress);\n playingRef.current = false;\n const clamped = Math.max(0, Math.min(t, totalDuration));\n const withinIteration = tracks.duration > 0\n ? (clamped % tracks.duration) || (clamped === 0 ? 0 : tracks.duration)\n : 0;\n progress.value = withinIteration;\n // Seeking mid-playback continues from the new position rather than\n // silently pausing.\n if (wasPlaying) startFrom(withinIteration);\n },\n };\n\n useImperativeHandle(apiRef, () => api, [compiled]);\n\n // -- Declarative control --------------------------------------------------\n\n const trigger = compiled.doc ? getAnimatorConfig(compiled.doc)?.trigger : undefined;\n const startOn = trigger?.startOn ?? 'load';\n const outAction = outActionProp ?? trigger?.outAction ?? 'pause';\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 // 'click' and 'scrollIntoView' start from their own handlers below.\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 // `startOn: 'scrollIntoView'` — react-native has no IntersectionObserver, so\n // visibility is sampled by measuring the view against the window box. The\n // poll is cheap (a native measure every 200ms) and only runs while this\n // trigger is active; `outAction` decides what leaving the viewport does.\n const scrollRef = useRef<View | null>(null);\n const inViewRef = useRef(false);\n useEffect(() => {\n if (!autoplay || startOn !== 'scrollIntoView') return;\n const threshold = trigger?.scrollIntoViewThreshold ?? 0;\n inViewRef.current = false;\n\n const check = () => {\n const node = scrollRef.current;\n if (!node) return;\n node.measureInWindow((_x, y, _w, h) => {\n if (!h) return;\n const screen = Dimensions.get('window').height;\n const visible = Math.max(0, Math.min(y + h, screen) - Math.max(y, 0));\n const ratio = visible / h;\n const isIn = ratio > 0 && ratio >= threshold;\n if (isIn === inViewRef.current) return;\n inViewRef.current = isIn;\n if (isIn) {\n if (rateRef.current < 0) api.setPlaybackRate(Math.abs(rateRef.current));\n api.play();\n } else if (outAction === 'reset') api.cancel();\n else if (outAction === 'reverse') { api.setPlaybackRate(-Math.abs(rateRef.current || 1)); api.play(); }\n else if (outAction !== 'continue') api.pause();\n });\n };\n\n check();\n const id = setInterval(check, 200);\n return () => clearInterval(id);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [compiled, autoplay, startOn, outAction]);\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 renderErrorRef = useRef<Error | null>(null);\n const root = useMemo(() => {\n warningsRef.current = [];\n renderErrorRef.current = null;\n if (!compiled.doc) return null;\n\n const renderOpts: RenderRnNodeOptions = {\n warnings: warningsRef.current,\n defs: getDefs(compiled.doc),\n };\n try {\n return renderRnNode(compiled.doc as PxNode, {\n ...renderOpts,\n decorate: (node, Component, staticProps, children, key) => {\n // An animated definition subtree (gradient / its stops) cannot be\n // driven on the UI thread — hand the WHOLE subtree to the\n // JS-sampled renderer and stop descending here.\n if (needsJsSampling(node, trackById)) {\n return (\n <SampledSubtree\n key={key}\n node={node}\n trackById={trackById}\n progress={progress}\n stepMs={tracks.stepMs}\n sampleCount={tracks.sampleCount}\n renderOpts={renderOpts}\n />\n );\n }\n\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={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 } catch (e) {\n // Building the element tree threw — report it and render nothing\n // rather than propagating and unmounting the host screen.\n const error = e instanceof Error ? e : new Error(String(e));\n renderErrorRef.current = error;\n console.warn('[PixodeskSvgAnimator] could not render the document:', error.message);\n return null;\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 // Surface compile/render failures to the host exactly once per occurrence.\n const failure = compiled.error ?? renderErrorRef.current;\n useEffect(() => {\n if (failure) onError?.(failure);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [failure]);\n\n if (failure) return fallback ? fallback(failure) : null;\n\n // `startOn: 'click'` — the touch analogue of the web player's click trigger:\n // tap to start, tap again to apply `outAction`. Hover (`mouseOver`) has no\n // touch equivalent and `scrollIntoView` needs the surrounding scroll view,\n // so both are left to the host app.\n let content: ReactElement | null = root;\n\n if (autoplay && startOn === 'scrollIntoView' && root) {\n // `collapsable={false}` keeps the view in the native tree so it can be measured.\n content = <View ref={scrollRef} collapsable={false}>{root}</View>;\n } else if (autoplay && startOn === 'click' && root) {\n content = (\n <Pressable\n onPress={() => {\n if (playingRef.current) {\n if (outAction === 'reset') api.cancel();\n else if (outAction === 'reverse') { api.setPlaybackRate(-Math.abs(rateRef.current || 1)); api.play(); }\n else if (outAction !== 'continue') api.pause();\n } else {\n if (rateRef.current < 0) api.setPlaybackRate(Math.abs(rateRef.current));\n api.play();\n }\n }}\n >\n {root}\n </Pressable>\n );\n }\n\n // Catches what the try/catch above cannot: throws during React's own render\n // and commit of the tree — react-native-svg internals, reanimated failing\n // to attach to a component that turns out not to be a host view, and so on.\n return (\n <PxRnErrorBoundary onError={onError} fallback={fallback}>\n {content}\n </PxRnErrorBoundary>\n );\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 /** When true, snap back to the start after a natural finish. */\n resetOnFinish: boolean;\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 * Sample values in the form the NATIVE react-native-svg views expect\n * (currently: `transform` as a 6-number matrix rather than an SVG string).\n *\n * Defaults to `false` — the plain SVG form, which is what react-native-web\n * hands straight to the DOM. Only the component knows the platform, so it\n * decides; every consumer that does not opt in keeps DOM-compatible values.\n */\n native?: boolean;\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 native = opts?.native ?? false;\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 // Element tag per id — `toRnPropValue` needs it to leave the root `<Svg>`'s\n // transform as a string (see its `tag` parameter).\n const tagById = new Map<string, string>();\n const indexTags = (n: any): void => {\n if (n && typeof n.id === 'string') tagById.set(n.id, String(n.type));\n (n?.children ?? []).forEach(indexTags);\n };\n indexTags(doc);\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, tagById.get(binding.id), native);\n }\n arr[i] = toRnPropValue(rnProp, value, tagById.get(binding.id), native);\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 resetOnFinish: !!config.resetOnFinish,\n stepMs,\n sampleCount,\n elements,\n };\n}\n\n/**\n * Wire prop → the prop name the NATIVE view actually declares.\n *\n * react-native-svg's JS layer renames some props on the way down: a\n * `transform` (string or matrix) is parsed by `extractProps` and handed to the\n * native component as `matrix` — the Fabric spec has no `transform` prop at\n * all. Values sent through reanimated's animated-props path skip that JS\n * rename, so they must already use the native name or the native view drops\n * them silently. This is ONLY for the animated path; plain React renders still\n * go through the JS layer and must keep the wire name.\n */\nexport const NATIVE_PROP_NAME: Record<string, string> = {\n transform: 'matrix',\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 *\n * `native = true` applies {@link NATIVE_PROP_NAME} — pass it only on the\n * reanimated animated-props path of a real device. Props that are applied by\n * re-rendering through React (and therefore still pass through react-native-svg's\n * JS layer), and every value on the web, must keep the wire name.\n */\nexport function sampleProps(\n tracks: PxElementTracks,\n tMs: number,\n stepMs: number,\n sampleCount: number,\n native = false\n): Record<string, string | number | Array<number>> {\n 'worklet';\n const out: Record<string, string | number | Array<number>> = {};\n // Defensive: this runs on the UI thread, where a throw is a hard crash\n // with no React boundary to catch it.\n if (!tracks || !tracks.props || !(stepMs > 0)) return out;\n\n let idx = Math.round(tMs / stepMs);\n if (idx < 0) idx = 0;\n if (idx >= sampleCount) idx = sampleCount - 1;\n for (const key in tracks.props) {\n const values = tracks.props[key];\n if (!values) continue;\n const value = values[idx];\n if (value === undefined) continue;\n const name = native && key === 'transform' ? 'matrix' : key;\n out[name] = value;\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';\nimport { svgTransformToMatrix } from './PxRnMatrix';\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(\n rnPropName: string,\n value: string | number,\n /** The owning element's tag. The ROOT `<Svg>` handles `transform` through a\n * different code path (`extractTransformSvgView`, which wants a string or\n * an RN style) — a matrix there would be dropped, so leave it alone. */\n tag?: string,\n /** Opt in to the NATIVE representation of a value (see below). Defaults to\n * off, so web keeps the plain SVG/DOM form it has always been given. */\n native = false,\n): string | number | Array<number> {\n // On a device `transform` must arrive as a matrix, not a string: the\n // string→matrix parse happens in JS during render, which reanimated's\n // animated-props path skips entirely. See PxRnMatrix for the full why.\n // On the web the DOM parses the string itself and an array would serialise\n // to a meaningless `transform=\"1,0,0,1,3,4\"`, so it must stay a string.\n if (native && rnPropName === 'transform' && typeof value === 'string' && tag !== 'svg') {\n const m = svgTransformToMatrix(value);\n if (m) return m;\n }\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\n/**\n * SVG transform string → 2D affine matrix, in the order react-native-svg's\n * native side expects: `[a, b, c, d, e, f]`, i.e. SVG's own `matrix(…)` order\n *\n * ```\n * | a c e |\n * | b d f |\n * | 0 0 1 |\n * ```\n *\n * WHY THIS EXISTS: react-native-svg parses a `transform` STRING into this matrix\n * in JavaScript, inside `extractTransform`, during render. Values delivered\n * through reanimated's `animatedProps` bypass that JS step and reach the native\n * view directly, where a raw string is meaningless — an animated transform\n * simply does nothing. Feeding the matrix instead makes the animated and static\n * paths agree. (On the web the DOM parses the string itself, which is why this\n * only shows up on a device.)\n */\nexport type Mat2D = [number, number, number, number, number, number];\n\nexport const IDENTITY: Mat2D = [1, 0, 0, 1, 0, 0];\n\nconst DEG = Math.PI / 180;\n\n/** `m1 · m2` — apply m2 first, then m1 (same convention as SVG's left-to-right list). */\nfunction multiply(m1: Mat2D, m2: Mat2D): Mat2D {\n const [a1, b1, c1, d1, e1, f1] = m1;\n const [a2, b2, c2, d2, e2, f2] = m2;\n return [\n a1 * a2 + c1 * b2,\n b1 * a2 + d1 * b2,\n a1 * c2 + c1 * d2,\n b1 * c2 + d1 * d2,\n a1 * e2 + c1 * f2 + e1,\n b1 * e2 + d1 * f2 + f1,\n ];\n}\n\n/** Splits `translate(1,2)rotate(45)` into `[['translate',[1,2]], ['rotate',[45]]]`. */\nconst FN_RE = /([a-zA-Z]+)\\s*\\(([^)]*)\\)/g;\n\nfunction numbers(raw: string): Array<number> {\n return raw\n .split(/[\\s,]+/)\n .filter(s => s.length > 0)\n .map(Number)\n .filter(n => Number.isFinite(n));\n}\n\n/**\n * Parses an SVG transform list. Returns `undefined` when the string contains no\n * recognisable function, so callers can leave the original value untouched\n * rather than silently replacing it with an identity matrix.\n */\nexport function svgTransformToMatrix(value: string): Mat2D | undefined {\n let m: Mat2D | undefined;\n FN_RE.lastIndex = 0;\n\n let match: RegExpExecArray | null;\n while ((match = FN_RE.exec(value)) !== null) {\n const fn = match[1].toLowerCase();\n const n = numbers(match[2]);\n let step: Mat2D | undefined;\n\n switch (fn) {\n case 'translate':\n step = [1, 0, 0, 1, n[0] || 0, n[1] || 0];\n break;\n case 'scale': {\n const sx = n[0] ?? 1;\n const sy = n.length > 1 ? n[1] : sx;\n step = [sx, 0, 0, sy, 0, 0];\n break;\n }\n case 'rotate': {\n const rad = (n[0] || 0) * DEG;\n const cos = Math.cos(rad), sin = Math.sin(rad);\n const rot: Mat2D = [cos, sin, -sin, cos, 0, 0];\n if (n.length >= 3) {\n // rotate(a, cx, cy) == translate(cx,cy) rotate(a) translate(-cx,-cy)\n const cx = n[1], cy = n[2];\n step = multiply(multiply([1, 0, 0, 1, cx, cy], rot), [1, 0, 0, 1, -cx, -cy]);\n } else {\n step = rot;\n }\n break;\n }\n case 'skewx':\n step = [1, 0, Math.tan((n[0] || 0) * DEG), 1, 0, 0];\n break;\n case 'skewy':\n step = [1, Math.tan((n[0] || 0) * DEG), 0, 1, 0, 0];\n break;\n case 'matrix':\n if (n.length >= 6) step = [n[0], n[1], n[2], n[3], n[4], n[5]];\n break;\n default:\n step = undefined; // unknown function — ignore it\n }\n\n if (step) m = m ? multiply(m, step) : step;\n }\n\n return m;\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 resolveStyle,\n sanitiseAttributeValue,\n DISALLOWED_SVG_TAGS_LOWER,\n TEXT_ATTR,\n TEXT_CONTENT_ATTR,\n type PxDefs,\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 /** `definitions` from the document, used to resolve named `style` presets. */\n defs?: PxDefs;\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 * `key` is handed over SEPARATELY and is deliberately absent from `props`:\n * React 19 warns when a props object containing `key` is spread into JSX,\n * and implementations of this hook do exactly that.\n */\n decorate?: (\n node: PxNode,\n Component: ComponentType<any>,\n props: Record<string, any>,\n children: ReactNode,\n key: string | number | undefined\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>, tag?: 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), tag);\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 // `feFuncR/G/B/A` carry their SVG `type` attribute (identity/table/…) under\n // `funcType`, because the wire format reserves `type` for the node tag.\n // Restore it as a real prop, mirroring the web renderer.\n const feFuncType: string | undefined = props.funcType;\n if (feFuncType !== undefined) delete props.funcType;\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 // NB: `key` is never written into this object — see `decorate` above.\n const rnProps = toRnProps(props, opts.warnings, tag);\n if (feFuncType !== undefined) rnProps.type = feFuncType;\n\n // `node.style` — a named preset from `definitions.styles`, or an inline\n // record. react-native-svg has no CSS, so the resolved declarations are\n // applied as ordinary props (the same names, e.g. `fill`, `strokeWidth`).\n // Explicit attributes on the node win over the style block.\n const resolved = resolveStyle(style, opts.defs);\n if (resolved) {\n for (const [k, v] of Object.entries(resolved)) {\n const rnKey = toRnPropName(k);\n if (!rnKey || rnKey in rnProps) continue;\n const sanitised = sanitiseAttributeValue(rnKey, v);\n if (sanitised === undefined) continue;\n rnProps[rnKey] = toRnPropValue(rnKey, String(sanitised), tag);\n }\n }\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) => {\n // One malformed child should cost that child, not the whole tree.\n try {\n return renderRnNode(ch, opts, i);\n } catch (e) {\n opts.warnings?.push('child failed to render: ' + (e instanceof Error ? e.message : String(e)));\n return null;\n }\n })\n .filter(Boolean);\n } else if (textContent !== undefined) {\n childElements = String(textContent);\n }\n\n const decorated = opts.decorate?.(node, Component, rnProps, childElements, key);\n if (decorated !== undefined) return decorated;\n\n // `createElement` takes `key` in its config object — that path does NOT\n // trigger React's JSX-spread warning.\n return createElement(\n Component,\n key !== undefined ? { ...rnProps, key } : rnProps,\n childElements\n );\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 FeBlend,\n FeColorMatrix,\n FeComponentTransfer,\n FeComposite,\n FeConvolveMatrix,\n FeDiffuseLighting,\n FeDisplacementMap,\n FeDistantLight,\n FeDropShadow,\n FeFlood,\n FeFuncA,\n FeFuncB,\n FeFuncG,\n FeFuncR,\n FeGaussianBlur,\n FeImage,\n FeMerge,\n FeMergeNode,\n FeMorphology,\n FeOffset,\n FePointLight,\n FeSpecularLighting,\n FeSpotLight,\n FeTile,\n FeTurbulence,\n Filter,\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 *\n * Keys are the wire-format `node.type` values, which follow SVG's own casing\n * (`clipPath`, `feGaussianBlur`, `linearGradient`, …).\n */\nexport const RN_SVG_COMPONENTS: Record<string, ComponentType<any>> = {\n // Root & containers\n svg: Svg,\n g: G,\n defs: Defs,\n symbol: SvgSymbol,\n use: Use,\n\n // Shapes\n rect: Rect,\n circle: Circle,\n ellipse: Ellipse,\n line: Line,\n path: Path,\n polygon: Polygon,\n polyline: Polyline,\n image: Image,\n\n // Text\n text: SvgText,\n tspan: TSpan,\n textPath: TextPath,\n\n // Paint servers & clipping\n linearGradient: LinearGradient,\n radialGradient: RadialGradient,\n stop: Stop,\n pattern: Pattern,\n mask: Mask,\n clipPath: ClipPath,\n marker: Marker,\n\n // Filters — react-native-svg implements the full primitive set.\n // NOTE: filter rendering requires the New Architecture (Fabric) and is\n // newer than the rest of react-native-svg; treat visual parity with the\n // web player as unverified until checked on a device.\n filter: Filter,\n feBlend: FeBlend,\n feColorMatrix: FeColorMatrix,\n feComponentTransfer: FeComponentTransfer,\n feComposite: FeComposite,\n feConvolveMatrix: FeConvolveMatrix,\n feDiffuseLighting: FeDiffuseLighting,\n feDisplacementMap: FeDisplacementMap,\n feDistantLight: FeDistantLight,\n feDropShadow: FeDropShadow,\n feFlood: FeFlood,\n feFuncA: FeFuncA,\n feFuncB: FeFuncB,\n feFuncG: FeFuncG,\n feFuncR: FeFuncR,\n feGaussianBlur: FeGaussianBlur,\n feImage: FeImage,\n feMerge: FeMerge,\n feMergeNode: FeMergeNode,\n feMorphology: FeMorphology,\n feOffset: FeOffset,\n fePointLight: FePointLight,\n feSpecularLighting: FeSpecularLighting,\n feSpotLight: FeSpotLight,\n feTile: FeTile,\n feTurbulence: FeTurbulence,\n};\n\nexport { toRnPropName } from './PxRnPropNames';\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 { Component, type ErrorInfo, type ReactNode } from 'react';\n\nexport interface PxRnErrorBoundaryProps {\n children: ReactNode;\n /** Rendered instead of the children once something has thrown. */\n fallback?: (error: Error) => ReactNode;\n onError?: (error: Error, info?: string) => void;\n}\n\ninterface State {\n error: Error | null;\n}\n\n/**\n * Keeps one bad animation from taking down the screen around it.\n *\n * A throw anywhere in the rendered SVG tree — an unsupported prop shape, a\n * react-native-svg internal, a reanimated attachment failure — otherwise\n * unmounts the whole React tree above it. Here it is contained to this one\n * animation, reported through `onError`, and replaced by `fallback`.\n *\n * NOTE the limit: this catches JavaScript errors only. A crash INSIDE the\n * native renderer (see `openClosedTextPathTargets` for a real example) never\n * reaches JavaScript and cannot be caught here — those have to be avoided\n * rather than handled.\n */\nexport class PxRnErrorBoundary extends Component<PxRnErrorBoundaryProps, State> {\n override state: State = { error: null };\n\n static getDerivedStateFromError(error: Error): State {\n return { error };\n }\n\n override componentDidCatch(error: Error, info: ErrorInfo): void {\n this.props.onError?.(error, info?.componentStack ?? undefined);\n console.warn('[PixodeskSvgAnimator] render failed:', error?.message ?? error);\n }\n\n override componentDidUpdate(prev: PxRnErrorBoundaryProps): void {\n // A new document deserves a fresh attempt — otherwise the boundary\n // would stay latched on the failure for the rest of its life.\n if (this.state.error && prev.children !== this.props.children) {\n this.setState({ error: null });\n }\n }\n\n override render(): ReactNode {\n const { error } = this.state;\n if (error) return this.props.fallback ? this.props.fallback(error) : null;\n return this.props.children;\n }\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 { deepClone, generateUniqueId, type PxNode } from '@pixodesk/svg-animator-core';\n\n/**\n * Workarounds for defects in react-native-svg's NATIVE renderer that would\n * otherwise take the whole app down.\n *\n * These are applied only when the native views are in use — never on the web,\n * where the DOM handles all of this correctly and the document must be left\n * exactly as the core pipeline produced it.\n */\n\n/** True when a path's `d` contains a close-subpath command. */\nfunction isClosedPath(d: unknown): boolean {\n return typeof d === 'string' && /[zZ]/.test(d);\n}\n\n/** Drops close-subpath commands, turning a closed outline into an open one. */\nfunction openPath(d: string): string {\n return d.replace(/[zZ]/g, '').trimEnd();\n}\n\n/** `#foo` → `foo`. Returns undefined for anything that is not a local ref. */\nfunction localRef(value: unknown): string | undefined {\n if (typeof value !== 'string') return undefined;\n const trimmed = value.trim();\n return trimmed.startsWith('#') ? trimmed.slice(1) : undefined;\n}\n\nfunction forEachNode(node: PxNode | undefined, visit: (n: PxNode, parent?: PxNode) => void, parent?: PxNode): void {\n if (!node) return;\n visit(node, parent);\n for (const child of (node.children ?? [])) forEachNode(child, visit, node);\n}\n\n/**\n * Gives every `<textPath>` that follows a CLOSED path its own OPEN copy of it.\n *\n * WHY: react-native-svg's native text-on-path layout crashes the app —\n * an uncatchable `NSRangeException` on iOS — for this combination.\n * `RNSVGTSpan.mm` skips glyphs outside `[startOfRendering, endOfRendering]`,\n * but for a closed path it sets those bounds to `startOffset … startOffset +\n * pathLength` instead of `0 … pathLength`. Any glyph past the end of the path\n * therefore survives the bounds check and reaches `getPosAndTan`, whose\n * `indexOfObjectPassingTest` returns `NSNotFound` — and indexing the lengths\n * array with `NSNotFound` throws. A non-zero `startOffset` on a closed path is\n * all it takes, and animating `startOffset` guarantees hitting it.\n *\n * Opening the path restores the `0 … pathLength` bounds, so out-of-range\n * glyphs are skipped as intended. The copy is private to the `<textPath>`, so\n * anything else drawing the same path still gets the closed original. For a\n * shape whose ends already meet (a circle, the usual case) the removed segment\n * has zero length and nothing changes visually at all.\n *\n * Returns the document unchanged — the same object — when nothing matches.\n */\nexport function openClosedTextPathTargets(doc: PxNode, warnings?: Array<string>): PxNode {\n // Cheap pre-check: the overwhelming majority of documents have no textPath.\n let hasTextPath = false;\n forEachNode(doc, n => { if (String(n.type) === 'textPath') hasTextPath = true; });\n if (!hasTextPath) return doc;\n\n const result = deepClone(doc);\n\n const byId = new Map<string, PxNode>();\n forEachNode(result, n => {\n const id = (n as any).id;\n if (typeof id === 'string') byId.set(id, n);\n });\n\n /** The copy is a geometry reference, never something to draw — so it goes\n * in `<defs>`, alongside the paths textPath targets normally live in. */\n let defs = (result.children ?? []).find(c => String(c.type) === 'defs');\n const ensureDefs = (): PxNode => {\n if (!defs) {\n defs = { type: 'defs', children: [] } as unknown as PxNode;\n (result.children ??= []).unshift(defs);\n }\n return defs;\n };\n\n /** Original path id → id of the open copy, so N textPaths share one copy. */\n const openCopies = new Map<string, string>();\n\n forEachNode(result, node => {\n if (String(node.type) !== 'textPath') return;\n\n const anyNode = node as any;\n const attr = anyNode.href !== undefined ? 'href' : 'xlink:href';\n const targetId = localRef(anyNode[attr]);\n if (!targetId) return;\n\n const target = byId.get(targetId);\n if (!target || !isClosedPath((target as any).d)) return;\n\n let copyId = openCopies.get(targetId);\n if (!copyId) {\n const copy = deepClone(target) as any;\n copyId = 'px_open_' + generateUniqueId();\n copy.id = copyId;\n copy.d = openPath(String(copy.d));\n // A copy that also carried animation would animate twice; the copy\n // exists purely as a geometry reference for the text.\n delete copy.animate;\n delete copy.effects;\n\n (ensureDefs().children ??= []).push(copy);\n openCopies.set(targetId, copyId);\n warnings?.push(\n 'textPath follows a closed path (#' + targetId + '); using an open copy to ' +\n 'avoid a react-native-svg native crash'\n );\n }\n\n anyNode[attr] = '#' + copyId;\n });\n\n return result;\n}\n"],"mappings":"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","names":["import_svg_animator_core","import_react","import_svg_animator_core","_a","import_svg_animator_core","SvgSymbol","SvgText","Component","_a","import_react","import_svg_animator_core","_a","Component","Animated","_a"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/PixodeskSvgAnimator.tsx","../src/PxRnTracks.ts","../src/PxRnPropNames.ts","../src/PxRnMatrix.ts","../src/PxRnRender.tsx","../src/PxRnTypeMap.ts","../src/PxRnErrorBoundary.tsx","../src/PxRnSafety.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 { PxRnErrorBoundary, type PxRnErrorBoundaryProps } from './PxRnErrorBoundary';\nexport { openClosedTextPathTargets } from './PxRnSafety';\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 getDefs,\n materialiseAllInTree,\n validateNodeEffects,\n PxAnimatorEngine,\n type FillMode,\n type OutAction,\n type PlaybackDirection,\n type PxAnimatedSvgDocument,\n type PxNode,\n} from '@pixodesk/svg-animator-core';\nimport React, { createElement, useEffect, useImperativeHandle, useMemo, useRef, useState, type ComponentType, type ReactElement, type ReactNode } from 'react';\nimport { Dimensions, Platform, Pressable, View } from 'react-native';\nimport Animated, {\n cancelAnimation,\n useAnimatedReaction,\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, type RenderRnNodeOptions } from './PxRnRender';\nimport { PxRnErrorBoundary } from './PxRnErrorBoundary';\nimport { openClosedTextPathTargets } from './PxRnSafety';\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 /** Snap back to the start state after a natural finish. */\n resetOnFinish?: boolean;\n\n /**\n * What a second tap does when `startOn: 'click'` is active.\n * Defaults to the document's `trigger.outAction`, else `'pause'`.\n */\n outAction?: OutAction;\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 // -- Failure handling -----------------------------------------------------\n\n /**\n * Called when a document cannot be compiled or rendered. The component\n * renders {@link fallback} instead of throwing, so a single broken\n * animation never takes down the screen around it.\n *\n * Only JavaScript failures reach this — a crash inside react-native-svg's\n * native renderer bypasses JavaScript entirely.\n */\n onError?: (error: Error, componentStack?: string) => void;\n\n /** Rendered in place of the animation after a failure. Default: nothing. */\n fallback?: (error: Error) => ReactElement | null;\n}\n\n\n// -- Animated element wrapper ------------------------------------------------\n\n/**\n * Whether react-native-svg is backed by NATIVE views here, rather than by the\n * DOM through react-native-web.\n *\n * The two want different things from an animated `transform`: a native view\n * declares a `matrix` prop taking six numbers, while the DOM wants a\n * `transform` attribute holding an SVG string. Getting it wrong is silent —\n * the value is dropped and the element simply never moves — so this single\n * constant decides it once and feeds both the track compiler (value form) and\n * the sampler (prop name). Everything else in the package defaults to the\n * DOM-compatible form.\n */\nconst NATIVE_SVG_VIEWS = Platform.OS !== 'web';\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 // On iOS/Android these values bypass react-native-svg's JS prop layer\n // and land on the native view, which declares `matrix`, not\n // `transform`. The web build keeps the DOM-facing `transform` name.\n return sampleProps(tracks, progress.value, stepMs, sampleCount, NATIVE_SVG_VIEWS);\n }, [tracks, stepMs, sampleCount]);\n\n return (\n <AnimatedComponent {...staticProps} animatedProps={animatedProps}>\n {children}\n </AnimatedComponent>\n );\n}\n\n\n/**\n * react-native-svg elements whose `render()` returns `null`. They carry data for\n * their PARENT (a `<Stop>` is read by the gradient that owns it) rather than\n * producing a native view, so reanimated has nothing to attach to — wrapping one\n * in `Animated.createAnimatedComponent` throws\n * \"Cannot find host instance for this component\".\n */\nconst NON_HOST_TAGS = new Set(['stop', 'feMergeNode']);\n\n/**\n * Definition elements — they describe paint/geometry for something else rather\n * than drawing themselves. Their animated attributes (a gradient's `y1`, a\n * stop's `stop-color`) do not reliably flow through reanimated's animated-props\n * path, so an animated def is rendered by re-sampling from JS instead. There\n * are only ever a handful per document and they change slowly, so the cost is\n * negligible — visual elements still animate entirely on the UI thread.\n */\nconst SAMPLED_DEF_TAGS = new Set(['linearGradient', 'radialGradient', ...NON_HOST_TAGS]);\n\n/** True when this subtree must be driven from JS rather than the UI thread:\n * either the node itself is an animated def, or it owns an animated non-host\n * child (an animated `<Stop>` only re-renders via its parent gradient). */\nfunction needsJsSampling(node: PxNode, trackById: Map<string, PxElementTracks>): boolean {\n const id = (node as any).id;\n if (SAMPLED_DEF_TAGS.has(String(node.type)) && id && trackById.has(id)) return true;\n return (node.children ?? []).some(c => needsJsSampling(c, trackById));\n}\n\n/**\n * Renders a subtree whose animation cannot run on the UI thread (see\n * {@link NON_HOST_TAGS}) by re-rendering it from JS with sampled values.\n *\n * Changing a `<Stop>`'s props does not re-render its parent gradient, so the\n * whole subtree is rebuilt — which is why this wraps the gradient rather than\n * the stop. The reaction itself runs on the UI thread and only crosses to JS\n * when the QUANTISED sample index changes, capping these few elements at\n * ~30fps instead of a JS call every frame.\n */\nfunction SampledSubtree({\n node, trackById, progress, stepMs, sampleCount, renderOpts,\n}: {\n node: PxNode;\n trackById: Map<string, PxElementTracks>;\n progress: SharedValue<number>;\n stepMs: number;\n sampleCount: number;\n renderOpts: RenderRnNodeOptions;\n}) {\n const [idx, setIdx] = useState(0);\n\n useAnimatedReaction(\n () => Math.floor(Math.round(progress.value / stepMs) / 2) * 2, // half-rate\n (next, prev) => {\n if (next !== prev) runOnJS(setIdx)(next);\n },\n [stepMs]\n );\n\n const tMs = Math.min(Math.max(idx, 0), sampleCount - 1) * stepMs;\n\n return renderRnNode(node, {\n ...renderOpts,\n // Sampled values are baked in as PLAIN props — nothing reanimated-driven.\n decorate: (n, Component, staticProps, children, key) => {\n const id = (n as any).id;\n const tracks = id ? trackById.get(id) : undefined;\n if (!tracks) return undefined;\n // Wire prop names, NOT the native ones: these go back through\n // react-native-svg's JS prop layer, which does the renaming itself.\n const sampled = sampleProps(tracks, tMs, stepMs, sampleCount);\n return createElement(Component, { ...staticProps, ...sampled, key }, children);\n },\n });\n}\n\n\n\n/** Overrides that shadow the document's own `animator` config. */\ninterface ConfigOverrides {\n duration?: number;\n delay?: number;\n iterations?: number | 'infinite';\n fill?: FillMode;\n direction?: PlaybackDirection;\n resetOnFinish?: boolean;\n}\n\ninterface Compiled {\n /** Materialised document, or null when compilation failed. */\n doc: PxAnimatedSvgDocument | null;\n tracks: PxCompiledTracks;\n error: Error | null;\n}\n\n/** Playable-but-empty tracks, so a failed compile still satisfies every hook\n * below it — React forbids skipping hooks on an error path. */\nconst EMPTY_TRACKS: PxCompiledTracks = {\n duration: 1, iterations: 1, direction: 'normal', delay: 0,\n fill: 'forwards', resetOnFinish: false, stepMs: 1, sampleCount: 2, elements: [],\n};\n\n/**\n * Materialises + compiles a document. Extracted from the component so the\n * whole thing sits behind one try/catch, and so it can be tested directly.\n */\nfunction compileDocument(doc: PxAnimatedSvgDocument, overrides: ConfigOverrides): Compiled {\n const { duration, delay, iterations, fill, direction, resetOnFinish } = overrides;\n const warnings = validateNodeEffects(doc as PxNode);\n for (const w of warnings) console.warn('[PixodeskSvgAnimator] effects shape warning:', w);\n\n // `waapi` = 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.waapi);\n\n // Sidestep a react-native-svg NATIVE crash (see PxRnSafety). Guarded on\n // the platform because the DOM renders this case correctly and the web\n // document must stay exactly as the core pipeline produced it.\n if (NATIVE_SVG_VIEWS) {\n prepared = openClosedTextPathTargets(prepared as PxNode) as PxAnimatedSvgDocument;\n }\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 resetOnFinish: resetOnFinish !== undefined ? resetOnFinish : animator.resetOnFinish,\n },\n };\n\n prepared = generateNewIds(prepared);\n const tracks = compileTracks(prepared, { native: NATIVE_SVG_VIEWS });\n return { doc: prepared, tracks, error: null };\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, resetOnFinish, outAction: outActionProp,\n autoplay, play, pause, apiRef, time, timeMs,\n onPlay, onStop, onPause, onCancel, onFinish, onError, fallback,\n}: PixodeskSvgAnimatorProps): ReactElement | null {\n\n // -- Compile the document (once per doc/override change) ------------------\n\n const compiled = useMemo((): Compiled => {\n try {\n return compileDocument(\n doc,\n { duration, delay, iterations, fill, direction, resetOnFinish }\n );\n } catch (e) {\n // A malformed document must not take the host screen down with it.\n const error = e instanceof Error ? e : new Error(String(e));\n console.warn('[PixodeskSvgAnimator] could not compile the document:', error.message);\n return { doc: null, tracks: EMPTY_TRACKS, error };\n }\n }, [doc, duration, delay, iterations, fill, direction, resetOnFinish]);\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 /** True when the current rate plays the timeline backwards. */\n const reversePlayback = () => rateRef.current < 0;\n\n /** Where the playhead rests once playback ends. `resetOnFinish` snaps back\n * to the start; otherwise `fill` decides whether the final frame is held. */\n const restingPosition = () => {\n if (tracks.resetOnFinish) return 0;\n if (tracks.fill === 'none' || tracks.fill === 'backwards') return 0;\n return reversePlayback() ? 0 : tracks.duration;\n };\n\n const notifyFinish = () => {\n playingRef.current = false;\n progress.value = restingPosition();\n onFinish?.();\n onStop?.();\n };\n\n const startFrom = (fromMs: number) => {\n const dur = tracks.duration;\n const rate = rateRef.current || 1;\n const backwards = rate < 0;\n const speed = Math.abs(rate);\n // `direction` decides which end a leg runs toward; a negative playback\n // rate flips it again (the two compose, as in the Web Animations API).\n const directionReversed = tracks.direction === 'reverse' || tracks.direction === 'alternate-reverse';\n const reversedStart = backwards ? !directionReversed : directionReversed;\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) / speed;\n const repeats = tracks.iterations === Infinity ? -1 : tracks.iterations;\n\n cancelAnimation(progress);\n progress.value = reversedStart ? (from <= 0 ? dur : from) : (from >= dur ? 0 : 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 / speed, animation)\n : animation;\n\n playingRef.current = true;\n };\n\n const api: RnAnimatorApi = {\n isPlaying: () => playingRef.current,\n play: () => {\n // `startFrom` rewinds to the opposite end when the playhead is\n // already resting at a boundary (mirrors WAAPI, where play() on a\n // finished animation auto-rewinds).\n startFrom(progress.value);\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 playingRef.current = false;\n progress.value = restingPosition();\n onFinish?.();\n onStop?.();\n },\n setPlaybackRate: (rate: number) => {\n if (!isFinite(rate) || rate === 0) {\n console.warn('setPlaybackRate: rate must be finite and non-zero');\n return;\n }\n rateRef.current = rate;\n if (playingRef.current) startFrom(progress.value);\n },\n getCurrentTime: () => progress.value,\n setCurrentTime: (t: number) => {\n const wasPlaying = playingRef.current;\n cancelAnimation(progress);\n playingRef.current = false;\n const clamped = Math.max(0, Math.min(t, totalDuration));\n const withinIteration = tracks.duration > 0\n ? (clamped % tracks.duration) || (clamped === 0 ? 0 : tracks.duration)\n : 0;\n progress.value = withinIteration;\n // Seeking mid-playback continues from the new position rather than\n // silently pausing.\n if (wasPlaying) startFrom(withinIteration);\n },\n };\n\n useImperativeHandle(apiRef, () => api, [compiled]);\n\n // -- Declarative control --------------------------------------------------\n\n const trigger = compiled.doc ? getAnimatorConfig(compiled.doc)?.trigger : undefined;\n const startOn = trigger?.startOn ?? 'load';\n const outAction = outActionProp ?? trigger?.outAction ?? 'pause';\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 // 'click' and 'scrollIntoView' start from their own handlers below.\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 // `startOn: 'scrollIntoView'` — react-native has no IntersectionObserver, so\n // visibility is sampled by measuring the view against the window box. The\n // poll is cheap (a native measure every 200ms) and only runs while this\n // trigger is active; `outAction` decides what leaving the viewport does.\n const scrollRef = useRef<View | null>(null);\n const inViewRef = useRef(false);\n useEffect(() => {\n if (!autoplay || startOn !== 'scrollIntoView') return;\n const threshold = trigger?.scrollIntoViewThreshold ?? 0;\n inViewRef.current = false;\n\n const check = () => {\n const node = scrollRef.current;\n if (!node) return;\n node.measureInWindow((_x, y, _w, h) => {\n if (!h) return;\n const screen = Dimensions.get('window').height;\n const visible = Math.max(0, Math.min(y + h, screen) - Math.max(y, 0));\n const ratio = visible / h;\n const isIn = ratio > 0 && ratio >= threshold;\n if (isIn === inViewRef.current) return;\n inViewRef.current = isIn;\n if (isIn) {\n if (rateRef.current < 0) api.setPlaybackRate(Math.abs(rateRef.current));\n api.play();\n } else if (outAction === 'reset') api.cancel();\n else if (outAction === 'reverse') { api.setPlaybackRate(-Math.abs(rateRef.current || 1)); api.play(); }\n else if (outAction !== 'continue') api.pause();\n });\n };\n\n check();\n const id = setInterval(check, 200);\n return () => clearInterval(id);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [compiled, autoplay, startOn, outAction]);\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 renderErrorRef = useRef<Error | null>(null);\n const root = useMemo(() => {\n warningsRef.current = [];\n renderErrorRef.current = null;\n if (!compiled.doc) return null;\n\n const renderOpts: RenderRnNodeOptions = {\n warnings: warningsRef.current,\n defs: getDefs(compiled.doc),\n };\n try {\n return renderRnNode(compiled.doc as PxNode, {\n ...renderOpts,\n decorate: (node, Component, staticProps, children, key) => {\n // An animated definition subtree (gradient / its stops) cannot be\n // driven on the UI thread — hand the WHOLE subtree to the\n // JS-sampled renderer and stop descending here.\n if (needsJsSampling(node, trackById)) {\n return (\n <SampledSubtree\n key={key}\n node={node}\n trackById={trackById}\n progress={progress}\n stepMs={tracks.stepMs}\n sampleCount={tracks.sampleCount}\n renderOpts={renderOpts}\n />\n );\n }\n\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={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 } catch (e) {\n // Building the element tree threw — report it and render nothing\n // rather than propagating and unmounting the host screen.\n const error = e instanceof Error ? e : new Error(String(e));\n renderErrorRef.current = error;\n console.warn('[PixodeskSvgAnimator] could not render the document:', error.message);\n return null;\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 // Surface compile/render failures to the host exactly once per occurrence.\n const failure = compiled.error ?? renderErrorRef.current;\n useEffect(() => {\n if (failure) onError?.(failure);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [failure]);\n\n if (failure) return fallback ? fallback(failure) : null;\n\n // `startOn: 'click'` — the touch analogue of the web player's click trigger:\n // tap to start, tap again to apply `outAction`. Hover (`mouseOver`) has no\n // touch equivalent and `scrollIntoView` needs the surrounding scroll view,\n // so both are left to the host app.\n let content: ReactElement | null = root;\n\n if (autoplay && startOn === 'scrollIntoView' && root) {\n // `collapsable={false}` keeps the view in the native tree so it can be measured.\n content = <View ref={scrollRef} collapsable={false}>{root}</View>;\n } else if (autoplay && startOn === 'click' && root) {\n content = (\n <Pressable\n onPress={() => {\n if (playingRef.current) {\n if (outAction === 'reset') api.cancel();\n else if (outAction === 'reverse') { api.setPlaybackRate(-Math.abs(rateRef.current || 1)); api.play(); }\n else if (outAction !== 'continue') api.pause();\n } else {\n if (rateRef.current < 0) api.setPlaybackRate(Math.abs(rateRef.current));\n api.play();\n }\n }}\n >\n {root}\n </Pressable>\n );\n }\n\n // Catches what the try/catch above cannot: throws during React's own render\n // and commit of the tree — react-native-svg internals, reanimated failing\n // to attach to a component that turns out not to be a host view, and so on.\n return (\n <PxRnErrorBoundary onError={onError} fallback={fallback}>\n {content}\n </PxRnErrorBoundary>\n );\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 /** When true, snap back to the start after a natural finish. */\n resetOnFinish: boolean;\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 * Sample values in the form the NATIVE react-native-svg views expect\n * (currently: `transform` as a 6-number matrix rather than an SVG string).\n *\n * Defaults to `false` — the plain SVG form, which is what react-native-web\n * hands straight to the DOM. Only the component knows the platform, so it\n * decides; every consumer that does not opt in keeps DOM-compatible values.\n */\n native?: boolean;\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 native = opts?.native ?? false;\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 // Element tag per id — `toRnPropValue` needs it to leave the root `<Svg>`'s\n // transform as a string (see its `tag` parameter).\n const tagById = new Map<string, string>();\n const indexTags = (n: any): void => {\n if (n && typeof n.id === 'string') tagById.set(n.id, String(n.type));\n (n?.children ?? []).forEach(indexTags);\n };\n indexTags(doc);\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, tagById.get(binding.id), native);\n }\n arr[i] = toRnPropValue(rnProp, value, tagById.get(binding.id), native);\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 resetOnFinish: !!config.resetOnFinish,\n stepMs,\n sampleCount,\n elements,\n };\n}\n\n/**\n * Wire prop → the prop name the NATIVE view actually declares.\n *\n * react-native-svg's JS layer renames some props on the way down: a\n * `transform` (string or matrix) is parsed by `extractProps` and handed to the\n * native component as `matrix` — the Fabric spec has no `transform` prop at\n * all. Values sent through reanimated's animated-props path skip that JS\n * rename, so they must already use the native name or the native view drops\n * them silently. This is ONLY for the animated path; plain React renders still\n * go through the JS layer and must keep the wire name.\n */\nexport const NATIVE_PROP_NAME: Record<string, string> = {\n transform: 'matrix',\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 *\n * `native = true` applies {@link NATIVE_PROP_NAME} — pass it only on the\n * reanimated animated-props path of a real device. Props that are applied by\n * re-rendering through React (and therefore still pass through react-native-svg's\n * JS layer), and every value on the web, must keep the wire name.\n */\nexport function sampleProps(\n tracks: PxElementTracks,\n tMs: number,\n stepMs: number,\n sampleCount: number,\n native = false\n): Record<string, string | number | Array<number>> {\n 'worklet';\n const out: Record<string, string | number | Array<number>> = {};\n // Defensive: this runs on the UI thread, where a throw is a hard crash\n // with no React boundary to catch it.\n if (!tracks || !tracks.props || !(stepMs > 0)) return out;\n\n let idx = Math.round(tMs / stepMs);\n if (idx < 0) idx = 0;\n if (idx >= sampleCount) idx = sampleCount - 1;\n for (const key in tracks.props) {\n const values = tracks.props[key];\n if (!values) continue;\n const value = values[idx];\n if (value === undefined) continue;\n const name = native && key === 'transform' ? 'matrix' : key;\n out[name] = value;\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';\nimport { svgTransformToMatrix } from './PxRnMatrix';\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(\n rnPropName: string,\n value: string | number,\n /** The owning element's tag. The ROOT `<Svg>` handles `transform` through a\n * different code path (`extractTransformSvgView`, which wants a string or\n * an RN style) — a matrix there would be dropped, so leave it alone. */\n tag?: string,\n /** Opt in to the NATIVE representation of a value (see below). Defaults to\n * off, so web keeps the plain SVG/DOM form it has always been given. */\n native = false,\n): string | number | Array<number> {\n // On a device `transform` must arrive as a matrix, not a string: the\n // string→matrix parse happens in JS during render, which reanimated's\n // animated-props path skips entirely. See PxRnMatrix for the full why.\n // On the web the DOM parses the string itself and an array would serialise\n // to a meaningless `transform=\"1,0,0,1,3,4\"`, so it must stay a string.\n if (native && rnPropName === 'transform' && typeof value === 'string' && tag !== 'svg') {\n const m = svgTransformToMatrix(value);\n if (m) return m;\n }\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\n/**\n * SVG transform string → 2D affine matrix, in the order react-native-svg's\n * native side expects: `[a, b, c, d, e, f]`, i.e. SVG's own `matrix(…)` order\n *\n * ```\n * | a c e |\n * | b d f |\n * | 0 0 1 |\n * ```\n *\n * WHY THIS EXISTS: react-native-svg parses a `transform` STRING into this matrix\n * in JavaScript, inside `extractTransform`, during render. Values delivered\n * through reanimated's `animatedProps` bypass that JS step and reach the native\n * view directly, where a raw string is meaningless — an animated transform\n * simply does nothing. Feeding the matrix instead makes the animated and static\n * paths agree. (On the web the DOM parses the string itself, which is why this\n * only shows up on a device.)\n */\nexport type Mat2D = [number, number, number, number, number, number];\n\nexport const IDENTITY: Mat2D = [1, 0, 0, 1, 0, 0];\n\nconst DEG = Math.PI / 180;\n\n/** `m1 · m2` — apply m2 first, then m1 (same convention as SVG's left-to-right list). */\nfunction multiply(m1: Mat2D, m2: Mat2D): Mat2D {\n const [a1, b1, c1, d1, e1, f1] = m1;\n const [a2, b2, c2, d2, e2, f2] = m2;\n return [\n a1 * a2 + c1 * b2,\n b1 * a2 + d1 * b2,\n a1 * c2 + c1 * d2,\n b1 * c2 + d1 * d2,\n a1 * e2 + c1 * f2 + e1,\n b1 * e2 + d1 * f2 + f1,\n ];\n}\n\n/** Splits `translate(1,2)rotate(45)` into `[['translate',[1,2]], ['rotate',[45]]]`. */\nconst FN_RE = /([a-zA-Z]+)\\s*\\(([^)]*)\\)/g;\n\nfunction numbers(raw: string): Array<number> {\n return raw\n .split(/[\\s,]+/)\n .filter(s => s.length > 0)\n .map(Number)\n .filter(n => Number.isFinite(n));\n}\n\n/**\n * Parses an SVG transform list. Returns `undefined` when the string contains no\n * recognisable function, so callers can leave the original value untouched\n * rather than silently replacing it with an identity matrix.\n */\nexport function svgTransformToMatrix(value: string): Mat2D | undefined {\n let m: Mat2D | undefined;\n FN_RE.lastIndex = 0;\n\n let match: RegExpExecArray | null;\n while ((match = FN_RE.exec(value)) !== null) {\n const fn = match[1].toLowerCase();\n const n = numbers(match[2]);\n let step: Mat2D | undefined;\n\n switch (fn) {\n case 'translate':\n step = [1, 0, 0, 1, n[0] || 0, n[1] || 0];\n break;\n case 'scale': {\n const sx = n[0] ?? 1;\n const sy = n.length > 1 ? n[1] : sx;\n step = [sx, 0, 0, sy, 0, 0];\n break;\n }\n case 'rotate': {\n const rad = (n[0] || 0) * DEG;\n const cos = Math.cos(rad), sin = Math.sin(rad);\n const rot: Mat2D = [cos, sin, -sin, cos, 0, 0];\n if (n.length >= 3) {\n // rotate(a, cx, cy) == translate(cx,cy) rotate(a) translate(-cx,-cy)\n const cx = n[1], cy = n[2];\n step = multiply(multiply([1, 0, 0, 1, cx, cy], rot), [1, 0, 0, 1, -cx, -cy]);\n } else {\n step = rot;\n }\n break;\n }\n case 'skewx':\n step = [1, 0, Math.tan((n[0] || 0) * DEG), 1, 0, 0];\n break;\n case 'skewy':\n step = [1, Math.tan((n[0] || 0) * DEG), 0, 1, 0, 0];\n break;\n case 'matrix':\n if (n.length >= 6) step = [n[0], n[1], n[2], n[3], n[4], n[5]];\n break;\n default:\n step = undefined; // unknown function — ignore it\n }\n\n if (step) m = m ? multiply(m, step) : step;\n }\n\n return m;\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 resolveStyle,\n sanitiseAttributeValue,\n DISALLOWED_SVG_TAGS_LOWER,\n TEXT_ATTR,\n TEXT_CONTENT_ATTR,\n type PxDefs,\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 /** `definitions` from the document, used to resolve named `style` presets. */\n defs?: PxDefs;\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 * `key` is handed over SEPARATELY and is deliberately absent from `props`:\n * React 19 warns when a props object containing `key` is spread into JSX,\n * and implementations of this hook do exactly that.\n */\n decorate?: (\n node: PxNode,\n Component: ComponentType<any>,\n props: Record<string, any>,\n children: ReactNode,\n key: string | number | undefined\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>, tag?: 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), tag);\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 // ESCAPE KEY (S2): elements whose SVG `type` ATTRIBUTE collides with the reserved\n // `type` node-tag key carry it under `domType` — `feColorMatrix` (matrix/saturate/…),\n // `feTurbulence` (fractalNoise/turbulence), `feFunc*` (identity/table/…).\n // Restore it as a real prop, mirroring the web renderer.\n const domType: string | undefined = props.domType;\n if (domType !== undefined) delete props.domType;\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 // NB: `key` is never written into this object — see `decorate` above.\n const rnProps = toRnProps(props, opts.warnings, tag);\n if (domType !== undefined) rnProps.type = domType;\n\n // `node.style` — a named preset from `definitions.styles`, or an inline\n // record. react-native-svg has no CSS, so the resolved declarations are\n // applied as ordinary props (the same names, e.g. `fill`, `strokeWidth`).\n // Explicit attributes on the node win over the style block.\n const resolved = resolveStyle(style, opts.defs);\n if (resolved) {\n for (const [k, v] of Object.entries(resolved)) {\n const rnKey = toRnPropName(k);\n if (!rnKey || rnKey in rnProps) continue;\n const sanitised = sanitiseAttributeValue(rnKey, v);\n if (sanitised === undefined) continue;\n rnProps[rnKey] = toRnPropValue(rnKey, String(sanitised), tag);\n }\n }\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) => {\n // One malformed child should cost that child, not the whole tree.\n try {\n return renderRnNode(ch, opts, i);\n } catch (e) {\n opts.warnings?.push('child failed to render: ' + (e instanceof Error ? e.message : String(e)));\n return null;\n }\n })\n .filter(Boolean);\n } else if (textContent !== undefined) {\n childElements = String(textContent);\n }\n\n const decorated = opts.decorate?.(node, Component, rnProps, childElements, key);\n if (decorated !== undefined) return decorated;\n\n // `createElement` takes `key` in its config object — that path does NOT\n // trigger React's JSX-spread warning.\n return createElement(\n Component,\n key !== undefined ? { ...rnProps, key } : rnProps,\n childElements\n );\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 FeBlend,\n FeColorMatrix,\n FeComponentTransfer,\n FeComposite,\n FeConvolveMatrix,\n FeDiffuseLighting,\n FeDisplacementMap,\n FeDistantLight,\n FeDropShadow,\n FeFlood,\n FeFuncA,\n FeFuncB,\n FeFuncG,\n FeFuncR,\n FeGaussianBlur,\n FeImage,\n FeMerge,\n FeMergeNode,\n FeMorphology,\n FeOffset,\n FePointLight,\n FeSpecularLighting,\n FeSpotLight,\n FeTile,\n FeTurbulence,\n Filter,\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 *\n * Keys are the wire-format `node.type` values, which follow SVG's own casing\n * (`clipPath`, `feGaussianBlur`, `linearGradient`, …).\n */\nexport const RN_SVG_COMPONENTS: Record<string, ComponentType<any>> = {\n // Root & containers\n svg: Svg,\n g: G,\n defs: Defs,\n symbol: SvgSymbol,\n use: Use,\n\n // Shapes\n rect: Rect,\n circle: Circle,\n ellipse: Ellipse,\n line: Line,\n path: Path,\n polygon: Polygon,\n polyline: Polyline,\n image: Image,\n\n // Text\n text: SvgText,\n tspan: TSpan,\n textPath: TextPath,\n\n // Paint servers & clipping\n linearGradient: LinearGradient,\n radialGradient: RadialGradient,\n stop: Stop,\n pattern: Pattern,\n mask: Mask,\n clipPath: ClipPath,\n marker: Marker,\n\n // Filters — react-native-svg implements the full primitive set.\n // NOTE: filter rendering requires the New Architecture (Fabric) and is\n // newer than the rest of react-native-svg; treat visual parity with the\n // web player as unverified until checked on a device.\n filter: Filter,\n feBlend: FeBlend,\n feColorMatrix: FeColorMatrix,\n feComponentTransfer: FeComponentTransfer,\n feComposite: FeComposite,\n feConvolveMatrix: FeConvolveMatrix,\n feDiffuseLighting: FeDiffuseLighting,\n feDisplacementMap: FeDisplacementMap,\n feDistantLight: FeDistantLight,\n feDropShadow: FeDropShadow,\n feFlood: FeFlood,\n feFuncA: FeFuncA,\n feFuncB: FeFuncB,\n feFuncG: FeFuncG,\n feFuncR: FeFuncR,\n feGaussianBlur: FeGaussianBlur,\n feImage: FeImage,\n feMerge: FeMerge,\n feMergeNode: FeMergeNode,\n feMorphology: FeMorphology,\n feOffset: FeOffset,\n fePointLight: FePointLight,\n feSpecularLighting: FeSpecularLighting,\n feSpotLight: FeSpotLight,\n feTile: FeTile,\n feTurbulence: FeTurbulence,\n};\n\nexport { toRnPropName } from './PxRnPropNames';\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 { Component, type ErrorInfo, type ReactNode } from 'react';\n\nexport interface PxRnErrorBoundaryProps {\n children: ReactNode;\n /** Rendered instead of the children once something has thrown. */\n fallback?: (error: Error) => ReactNode;\n onError?: (error: Error, info?: string) => void;\n}\n\ninterface State {\n error: Error | null;\n}\n\n/**\n * Keeps one bad animation from taking down the screen around it.\n *\n * A throw anywhere in the rendered SVG tree — an unsupported prop shape, a\n * react-native-svg internal, a reanimated attachment failure — otherwise\n * unmounts the whole React tree above it. Here it is contained to this one\n * animation, reported through `onError`, and replaced by `fallback`.\n *\n * NOTE the limit: this catches JavaScript errors only. A crash INSIDE the\n * native renderer (see `openClosedTextPathTargets` for a real example) never\n * reaches JavaScript and cannot be caught here — those have to be avoided\n * rather than handled.\n */\nexport class PxRnErrorBoundary extends Component<PxRnErrorBoundaryProps, State> {\n override state: State = { error: null };\n\n static getDerivedStateFromError(error: Error): State {\n return { error };\n }\n\n override componentDidCatch(error: Error, info: ErrorInfo): void {\n this.props.onError?.(error, info?.componentStack ?? undefined);\n console.warn('[PixodeskSvgAnimator] render failed:', error?.message ?? error);\n }\n\n override componentDidUpdate(prev: PxRnErrorBoundaryProps): void {\n // A new document deserves a fresh attempt — otherwise the boundary\n // would stay latched on the failure for the rest of its life.\n if (this.state.error && prev.children !== this.props.children) {\n this.setState({ error: null });\n }\n }\n\n override render(): ReactNode {\n const { error } = this.state;\n if (error) return this.props.fallback ? this.props.fallback(error) : null;\n return this.props.children;\n }\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 { deepClone, generateUniqueId, type PxNode } from '@pixodesk/svg-animator-core';\n\n/**\n * Workarounds for defects in react-native-svg's NATIVE renderer that would\n * otherwise take the whole app down.\n *\n * These are applied only when the native views are in use — never on the web,\n * where the DOM handles all of this correctly and the document must be left\n * exactly as the core pipeline produced it.\n */\n\n/** True when a path's `d` contains a close-subpath command. */\nfunction isClosedPath(d: unknown): boolean {\n return typeof d === 'string' && /[zZ]/.test(d);\n}\n\n/** Drops close-subpath commands, turning a closed outline into an open one. */\nfunction openPath(d: string): string {\n return d.replace(/[zZ]/g, '').trimEnd();\n}\n\n/** `#foo` → `foo`. Returns undefined for anything that is not a local ref. */\nfunction localRef(value: unknown): string | undefined {\n if (typeof value !== 'string') return undefined;\n const trimmed = value.trim();\n return trimmed.startsWith('#') ? trimmed.slice(1) : undefined;\n}\n\nfunction forEachNode(node: PxNode | undefined, visit: (n: PxNode, parent?: PxNode) => void, parent?: PxNode): void {\n if (!node) return;\n visit(node, parent);\n for (const child of (node.children ?? [])) forEachNode(child, visit, node);\n}\n\n/**\n * Gives every `<textPath>` that follows a CLOSED path its own OPEN copy of it.\n *\n * WHY: react-native-svg's native text-on-path layout crashes the app —\n * an uncatchable `NSRangeException` on iOS — for this combination.\n * `RNSVGTSpan.mm` skips glyphs outside `[startOfRendering, endOfRendering]`,\n * but for a closed path it sets those bounds to `startOffset … startOffset +\n * pathLength` instead of `0 … pathLength`. Any glyph past the end of the path\n * therefore survives the bounds check and reaches `getPosAndTan`, whose\n * `indexOfObjectPassingTest` returns `NSNotFound` — and indexing the lengths\n * array with `NSNotFound` throws. A non-zero `startOffset` on a closed path is\n * all it takes, and animating `startOffset` guarantees hitting it.\n *\n * Opening the path restores the `0 … pathLength` bounds, so out-of-range\n * glyphs are skipped as intended. The copy is private to the `<textPath>`, so\n * anything else drawing the same path still gets the closed original. For a\n * shape whose ends already meet (a circle, the usual case) the removed segment\n * has zero length and nothing changes visually at all.\n *\n * Returns the document unchanged — the same object — when nothing matches.\n */\nexport function openClosedTextPathTargets(doc: PxNode, warnings?: Array<string>): PxNode {\n // Cheap pre-check: the overwhelming majority of documents have no textPath.\n let hasTextPath = false;\n forEachNode(doc, n => { if (String(n.type) === 'textPath') hasTextPath = true; });\n if (!hasTextPath) return doc;\n\n const result = deepClone(doc);\n\n const byId = new Map<string, PxNode>();\n forEachNode(result, n => {\n const id = (n as any).id;\n if (typeof id === 'string') byId.set(id, n);\n });\n\n /** The copy is a geometry reference, never something to draw — so it goes\n * in `<defs>`, alongside the paths textPath targets normally live in. */\n let defs = (result.children ?? []).find(c => String(c.type) === 'defs');\n const ensureDefs = (): PxNode => {\n if (!defs) {\n defs = { type: 'defs', children: [] } as unknown as PxNode;\n (result.children ??= []).unshift(defs);\n }\n return defs;\n };\n\n /** Original path id → id of the open copy, so N textPaths share one copy. */\n const openCopies = new Map<string, string>();\n\n forEachNode(result, node => {\n if (String(node.type) !== 'textPath') return;\n\n const anyNode = node as any;\n const attr = anyNode.href !== undefined ? 'href' : 'xlink:href';\n const targetId = localRef(anyNode[attr]);\n if (!targetId) return;\n\n const target = byId.get(targetId);\n if (!target || !isClosedPath((target as any).d)) return;\n\n let copyId = openCopies.get(targetId);\n if (!copyId) {\n const copy = deepClone(target) as any;\n copyId = 'px_open_' + generateUniqueId();\n copy.id = copyId;\n copy.d = openPath(String(copy.d));\n // A copy that also carried animation would animate twice; the copy\n // exists purely as a geometry reference for the text.\n delete copy.animate;\n delete copy.effects;\n\n (ensureDefs().children ??= []).push(copy);\n openCopies.set(targetId, copyId);\n warnings?.push(\n 'textPath follows a closed path (#' + targetId + '); using an open copy to ' +\n 'avoid a react-native-svg native crash'\n );\n }\n\n anyNode[attr] = '#' + copyId;\n });\n\n return result;\n}\n"],"mappings":"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","names":["import_svg_animator_core","import_react","import_svg_animator_core","_a","import_svg_animator_core","SvgSymbol","SvgText","Component","_a","import_react","import_svg_animator_core","_a","Component","Animated","_a"]}
package/dist/index.js CHANGED
@@ -380,8 +380,8 @@ function renderRnNode(node, opts = {}, key) {
380
380
  if (!node) return null;
381
381
  const _a = node, { type, children, style, animate, meta, effects } = _a, props = __objRest(_a, ["type", "children", "style", "animate", "meta", "effects"]);
382
382
  const tag = String(type || "g");
383
- const feFuncType = props.funcType;
384
- if (feFuncType !== void 0) delete props.funcType;
383
+ const domType = props.domType;
384
+ if (domType !== void 0) delete props.domType;
385
385
  if (DISALLOWED_SVG_TAGS_LOWER.has(tag.toLowerCase())) {
386
386
  (_b = opts.warnings) == null ? void 0 : _b.push("tag blocked (dangerous): " + tag);
387
387
  return null;
@@ -392,7 +392,7 @@ function renderRnNode(node, opts = {}, key) {
392
392
  return null;
393
393
  }
394
394
  const rnProps = toRnProps(props, opts.warnings, tag);
395
- if (feFuncType !== void 0) rnProps.type = feFuncType;
395
+ if (domType !== void 0) rnProps.type = domType;
396
396
  const resolved = resolveStyle(style, opts.defs);
397
397
  if (resolved) {
398
398
  for (const [k, v] of Object.entries(resolved)) {
@@ -603,7 +603,7 @@ function compileDocument(doc, overrides) {
603
603
  const { duration, delay, iterations, fill, direction, resetOnFinish } = overrides;
604
604
  const warnings = validateNodeEffects(doc);
605
605
  for (const w of warnings) console.warn("[PixodeskSvgAnimator] effects shape warning:", w);
606
- let prepared = materialiseAllInTree(doc, PxAnimatorEngine2.webapi);
606
+ let prepared = materialiseAllInTree(doc, PxAnimatorEngine2.waapi);
607
607
  if (NATIVE_SVG_VIEWS) {
608
608
  prepared = openClosedTextPathTargets(prepared);
609
609
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/PixodeskSvgAnimator.tsx","../src/PxRnTracks.ts","../src/PxRnPropNames.ts","../src/PxRnMatrix.ts","../src/PxRnRender.tsx","../src/PxRnTypeMap.ts","../src/PxRnErrorBoundary.tsx","../src/PxRnSafety.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\nimport {\n generateNewIds,\n getAnimatorConfig,\n getDefs,\n materialiseAllInTree,\n validateNodeEffects,\n PxAnimatorEngine,\n type FillMode,\n type OutAction,\n type PlaybackDirection,\n type PxAnimatedSvgDocument,\n type PxNode,\n} from '@pixodesk/svg-animator-core';\nimport React, { createElement, useEffect, useImperativeHandle, useMemo, useRef, useState, type ComponentType, type ReactElement, type ReactNode } from 'react';\nimport { Dimensions, Platform, Pressable, View } from 'react-native';\nimport Animated, {\n cancelAnimation,\n useAnimatedReaction,\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, type RenderRnNodeOptions } from './PxRnRender';\nimport { PxRnErrorBoundary } from './PxRnErrorBoundary';\nimport { openClosedTextPathTargets } from './PxRnSafety';\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 /** Snap back to the start state after a natural finish. */\n resetOnFinish?: boolean;\n\n /**\n * What a second tap does when `startOn: 'click'` is active.\n * Defaults to the document's `trigger.outAction`, else `'pause'`.\n */\n outAction?: OutAction;\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 // -- Failure handling -----------------------------------------------------\n\n /**\n * Called when a document cannot be compiled or rendered. The component\n * renders {@link fallback} instead of throwing, so a single broken\n * animation never takes down the screen around it.\n *\n * Only JavaScript failures reach this — a crash inside react-native-svg's\n * native renderer bypasses JavaScript entirely.\n */\n onError?: (error: Error, componentStack?: string) => void;\n\n /** Rendered in place of the animation after a failure. Default: nothing. */\n fallback?: (error: Error) => ReactElement | null;\n}\n\n\n// -- Animated element wrapper ------------------------------------------------\n\n/**\n * Whether react-native-svg is backed by NATIVE views here, rather than by the\n * DOM through react-native-web.\n *\n * The two want different things from an animated `transform`: a native view\n * declares a `matrix` prop taking six numbers, while the DOM wants a\n * `transform` attribute holding an SVG string. Getting it wrong is silent —\n * the value is dropped and the element simply never moves — so this single\n * constant decides it once and feeds both the track compiler (value form) and\n * the sampler (prop name). Everything else in the package defaults to the\n * DOM-compatible form.\n */\nconst NATIVE_SVG_VIEWS = Platform.OS !== 'web';\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 // On iOS/Android these values bypass react-native-svg's JS prop layer\n // and land on the native view, which declares `matrix`, not\n // `transform`. The web build keeps the DOM-facing `transform` name.\n return sampleProps(tracks, progress.value, stepMs, sampleCount, NATIVE_SVG_VIEWS);\n }, [tracks, stepMs, sampleCount]);\n\n return (\n <AnimatedComponent {...staticProps} animatedProps={animatedProps}>\n {children}\n </AnimatedComponent>\n );\n}\n\n\n/**\n * react-native-svg elements whose `render()` returns `null`. They carry data for\n * their PARENT (a `<Stop>` is read by the gradient that owns it) rather than\n * producing a native view, so reanimated has nothing to attach to — wrapping one\n * in `Animated.createAnimatedComponent` throws\n * \"Cannot find host instance for this component\".\n */\nconst NON_HOST_TAGS = new Set(['stop', 'feMergeNode']);\n\n/**\n * Definition elements — they describe paint/geometry for something else rather\n * than drawing themselves. Their animated attributes (a gradient's `y1`, a\n * stop's `stop-color`) do not reliably flow through reanimated's animated-props\n * path, so an animated def is rendered by re-sampling from JS instead. There\n * are only ever a handful per document and they change slowly, so the cost is\n * negligible — visual elements still animate entirely on the UI thread.\n */\nconst SAMPLED_DEF_TAGS = new Set(['linearGradient', 'radialGradient', ...NON_HOST_TAGS]);\n\n/** True when this subtree must be driven from JS rather than the UI thread:\n * either the node itself is an animated def, or it owns an animated non-host\n * child (an animated `<Stop>` only re-renders via its parent gradient). */\nfunction needsJsSampling(node: PxNode, trackById: Map<string, PxElementTracks>): boolean {\n const id = (node as any).id;\n if (SAMPLED_DEF_TAGS.has(String(node.type)) && id && trackById.has(id)) return true;\n return (node.children ?? []).some(c => needsJsSampling(c, trackById));\n}\n\n/**\n * Renders a subtree whose animation cannot run on the UI thread (see\n * {@link NON_HOST_TAGS}) by re-rendering it from JS with sampled values.\n *\n * Changing a `<Stop>`'s props does not re-render its parent gradient, so the\n * whole subtree is rebuilt — which is why this wraps the gradient rather than\n * the stop. The reaction itself runs on the UI thread and only crosses to JS\n * when the QUANTISED sample index changes, capping these few elements at\n * ~30fps instead of a JS call every frame.\n */\nfunction SampledSubtree({\n node, trackById, progress, stepMs, sampleCount, renderOpts,\n}: {\n node: PxNode;\n trackById: Map<string, PxElementTracks>;\n progress: SharedValue<number>;\n stepMs: number;\n sampleCount: number;\n renderOpts: RenderRnNodeOptions;\n}) {\n const [idx, setIdx] = useState(0);\n\n useAnimatedReaction(\n () => Math.floor(Math.round(progress.value / stepMs) / 2) * 2, // half-rate\n (next, prev) => {\n if (next !== prev) runOnJS(setIdx)(next);\n },\n [stepMs]\n );\n\n const tMs = Math.min(Math.max(idx, 0), sampleCount - 1) * stepMs;\n\n return renderRnNode(node, {\n ...renderOpts,\n // Sampled values are baked in as PLAIN props — nothing reanimated-driven.\n decorate: (n, Component, staticProps, children, key) => {\n const id = (n as any).id;\n const tracks = id ? trackById.get(id) : undefined;\n if (!tracks) return undefined;\n // Wire prop names, NOT the native ones: these go back through\n // react-native-svg's JS prop layer, which does the renaming itself.\n const sampled = sampleProps(tracks, tMs, stepMs, sampleCount);\n return createElement(Component, { ...staticProps, ...sampled, key }, children);\n },\n });\n}\n\n\n\n/** Overrides that shadow the document's own `animator` config. */\ninterface ConfigOverrides {\n duration?: number;\n delay?: number;\n iterations?: number | 'infinite';\n fill?: FillMode;\n direction?: PlaybackDirection;\n resetOnFinish?: boolean;\n}\n\ninterface Compiled {\n /** Materialised document, or null when compilation failed. */\n doc: PxAnimatedSvgDocument | null;\n tracks: PxCompiledTracks;\n error: Error | null;\n}\n\n/** Playable-but-empty tracks, so a failed compile still satisfies every hook\n * below it — React forbids skipping hooks on an error path. */\nconst EMPTY_TRACKS: PxCompiledTracks = {\n duration: 1, iterations: 1, direction: 'normal', delay: 0,\n fill: 'forwards', resetOnFinish: false, stepMs: 1, sampleCount: 2, elements: [],\n};\n\n/**\n * Materialises + compiles a document. Extracted from the component so the\n * whole thing sits behind one try/catch, and so it can be tested directly.\n */\nfunction compileDocument(doc: PxAnimatedSvgDocument, overrides: ConfigOverrides): Compiled {\n const { duration, delay, iterations, fill, direction, resetOnFinish } = overrides;\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 // Sidestep a react-native-svg NATIVE crash (see PxRnSafety). Guarded on\n // the platform because the DOM renders this case correctly and the web\n // document must stay exactly as the core pipeline produced it.\n if (NATIVE_SVG_VIEWS) {\n prepared = openClosedTextPathTargets(prepared as PxNode) as PxAnimatedSvgDocument;\n }\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 resetOnFinish: resetOnFinish !== undefined ? resetOnFinish : animator.resetOnFinish,\n },\n };\n\n prepared = generateNewIds(prepared);\n const tracks = compileTracks(prepared, { native: NATIVE_SVG_VIEWS });\n return { doc: prepared, tracks, error: null };\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, resetOnFinish, outAction: outActionProp,\n autoplay, play, pause, apiRef, time, timeMs,\n onPlay, onStop, onPause, onCancel, onFinish, onError, fallback,\n}: PixodeskSvgAnimatorProps): ReactElement | null {\n\n // -- Compile the document (once per doc/override change) ------------------\n\n const compiled = useMemo((): Compiled => {\n try {\n return compileDocument(\n doc,\n { duration, delay, iterations, fill, direction, resetOnFinish }\n );\n } catch (e) {\n // A malformed document must not take the host screen down with it.\n const error = e instanceof Error ? e : new Error(String(e));\n console.warn('[PixodeskSvgAnimator] could not compile the document:', error.message);\n return { doc: null, tracks: EMPTY_TRACKS, error };\n }\n }, [doc, duration, delay, iterations, fill, direction, resetOnFinish]);\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 /** True when the current rate plays the timeline backwards. */\n const reversePlayback = () => rateRef.current < 0;\n\n /** Where the playhead rests once playback ends. `resetOnFinish` snaps back\n * to the start; otherwise `fill` decides whether the final frame is held. */\n const restingPosition = () => {\n if (tracks.resetOnFinish) return 0;\n if (tracks.fill === 'none' || tracks.fill === 'backwards') return 0;\n return reversePlayback() ? 0 : tracks.duration;\n };\n\n const notifyFinish = () => {\n playingRef.current = false;\n progress.value = restingPosition();\n onFinish?.();\n onStop?.();\n };\n\n const startFrom = (fromMs: number) => {\n const dur = tracks.duration;\n const rate = rateRef.current || 1;\n const backwards = rate < 0;\n const speed = Math.abs(rate);\n // `direction` decides which end a leg runs toward; a negative playback\n // rate flips it again (the two compose, as in the Web Animations API).\n const directionReversed = tracks.direction === 'reverse' || tracks.direction === 'alternate-reverse';\n const reversedStart = backwards ? !directionReversed : directionReversed;\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) / speed;\n const repeats = tracks.iterations === Infinity ? -1 : tracks.iterations;\n\n cancelAnimation(progress);\n progress.value = reversedStart ? (from <= 0 ? dur : from) : (from >= dur ? 0 : 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 / speed, animation)\n : animation;\n\n playingRef.current = true;\n };\n\n const api: RnAnimatorApi = {\n isPlaying: () => playingRef.current,\n play: () => {\n // `startFrom` rewinds to the opposite end when the playhead is\n // already resting at a boundary (mirrors WAAPI, where play() on a\n // finished animation auto-rewinds).\n startFrom(progress.value);\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 playingRef.current = false;\n progress.value = restingPosition();\n onFinish?.();\n onStop?.();\n },\n setPlaybackRate: (rate: number) => {\n if (!isFinite(rate) || rate === 0) {\n console.warn('setPlaybackRate: rate must be finite and non-zero');\n return;\n }\n rateRef.current = rate;\n if (playingRef.current) startFrom(progress.value);\n },\n getCurrentTime: () => progress.value,\n setCurrentTime: (t: number) => {\n const wasPlaying = playingRef.current;\n cancelAnimation(progress);\n playingRef.current = false;\n const clamped = Math.max(0, Math.min(t, totalDuration));\n const withinIteration = tracks.duration > 0\n ? (clamped % tracks.duration) || (clamped === 0 ? 0 : tracks.duration)\n : 0;\n progress.value = withinIteration;\n // Seeking mid-playback continues from the new position rather than\n // silently pausing.\n if (wasPlaying) startFrom(withinIteration);\n },\n };\n\n useImperativeHandle(apiRef, () => api, [compiled]);\n\n // -- Declarative control --------------------------------------------------\n\n const trigger = compiled.doc ? getAnimatorConfig(compiled.doc)?.trigger : undefined;\n const startOn = trigger?.startOn ?? 'load';\n const outAction = outActionProp ?? trigger?.outAction ?? 'pause';\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 // 'click' and 'scrollIntoView' start from their own handlers below.\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 // `startOn: 'scrollIntoView'` — react-native has no IntersectionObserver, so\n // visibility is sampled by measuring the view against the window box. The\n // poll is cheap (a native measure every 200ms) and only runs while this\n // trigger is active; `outAction` decides what leaving the viewport does.\n const scrollRef = useRef<View | null>(null);\n const inViewRef = useRef(false);\n useEffect(() => {\n if (!autoplay || startOn !== 'scrollIntoView') return;\n const threshold = trigger?.scrollIntoViewThreshold ?? 0;\n inViewRef.current = false;\n\n const check = () => {\n const node = scrollRef.current;\n if (!node) return;\n node.measureInWindow((_x, y, _w, h) => {\n if (!h) return;\n const screen = Dimensions.get('window').height;\n const visible = Math.max(0, Math.min(y + h, screen) - Math.max(y, 0));\n const ratio = visible / h;\n const isIn = ratio > 0 && ratio >= threshold;\n if (isIn === inViewRef.current) return;\n inViewRef.current = isIn;\n if (isIn) {\n if (rateRef.current < 0) api.setPlaybackRate(Math.abs(rateRef.current));\n api.play();\n } else if (outAction === 'reset') api.cancel();\n else if (outAction === 'reverse') { api.setPlaybackRate(-Math.abs(rateRef.current || 1)); api.play(); }\n else if (outAction !== 'continue') api.pause();\n });\n };\n\n check();\n const id = setInterval(check, 200);\n return () => clearInterval(id);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [compiled, autoplay, startOn, outAction]);\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 renderErrorRef = useRef<Error | null>(null);\n const root = useMemo(() => {\n warningsRef.current = [];\n renderErrorRef.current = null;\n if (!compiled.doc) return null;\n\n const renderOpts: RenderRnNodeOptions = {\n warnings: warningsRef.current,\n defs: getDefs(compiled.doc),\n };\n try {\n return renderRnNode(compiled.doc as PxNode, {\n ...renderOpts,\n decorate: (node, Component, staticProps, children, key) => {\n // An animated definition subtree (gradient / its stops) cannot be\n // driven on the UI thread — hand the WHOLE subtree to the\n // JS-sampled renderer and stop descending here.\n if (needsJsSampling(node, trackById)) {\n return (\n <SampledSubtree\n key={key}\n node={node}\n trackById={trackById}\n progress={progress}\n stepMs={tracks.stepMs}\n sampleCount={tracks.sampleCount}\n renderOpts={renderOpts}\n />\n );\n }\n\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={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 } catch (e) {\n // Building the element tree threw — report it and render nothing\n // rather than propagating and unmounting the host screen.\n const error = e instanceof Error ? e : new Error(String(e));\n renderErrorRef.current = error;\n console.warn('[PixodeskSvgAnimator] could not render the document:', error.message);\n return null;\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 // Surface compile/render failures to the host exactly once per occurrence.\n const failure = compiled.error ?? renderErrorRef.current;\n useEffect(() => {\n if (failure) onError?.(failure);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [failure]);\n\n if (failure) return fallback ? fallback(failure) : null;\n\n // `startOn: 'click'` — the touch analogue of the web player's click trigger:\n // tap to start, tap again to apply `outAction`. Hover (`mouseOver`) has no\n // touch equivalent and `scrollIntoView` needs the surrounding scroll view,\n // so both are left to the host app.\n let content: ReactElement | null = root;\n\n if (autoplay && startOn === 'scrollIntoView' && root) {\n // `collapsable={false}` keeps the view in the native tree so it can be measured.\n content = <View ref={scrollRef} collapsable={false}>{root}</View>;\n } else if (autoplay && startOn === 'click' && root) {\n content = (\n <Pressable\n onPress={() => {\n if (playingRef.current) {\n if (outAction === 'reset') api.cancel();\n else if (outAction === 'reverse') { api.setPlaybackRate(-Math.abs(rateRef.current || 1)); api.play(); }\n else if (outAction !== 'continue') api.pause();\n } else {\n if (rateRef.current < 0) api.setPlaybackRate(Math.abs(rateRef.current));\n api.play();\n }\n }}\n >\n {root}\n </Pressable>\n );\n }\n\n // Catches what the try/catch above cannot: throws during React's own render\n // and commit of the tree — react-native-svg internals, reanimated failing\n // to attach to a component that turns out not to be a host view, and so on.\n return (\n <PxRnErrorBoundary onError={onError} fallback={fallback}>\n {content}\n </PxRnErrorBoundary>\n );\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 /** When true, snap back to the start after a natural finish. */\n resetOnFinish: boolean;\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 * Sample values in the form the NATIVE react-native-svg views expect\n * (currently: `transform` as a 6-number matrix rather than an SVG string).\n *\n * Defaults to `false` — the plain SVG form, which is what react-native-web\n * hands straight to the DOM. Only the component knows the platform, so it\n * decides; every consumer that does not opt in keeps DOM-compatible values.\n */\n native?: boolean;\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 native = opts?.native ?? false;\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 // Element tag per id — `toRnPropValue` needs it to leave the root `<Svg>`'s\n // transform as a string (see its `tag` parameter).\n const tagById = new Map<string, string>();\n const indexTags = (n: any): void => {\n if (n && typeof n.id === 'string') tagById.set(n.id, String(n.type));\n (n?.children ?? []).forEach(indexTags);\n };\n indexTags(doc);\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, tagById.get(binding.id), native);\n }\n arr[i] = toRnPropValue(rnProp, value, tagById.get(binding.id), native);\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 resetOnFinish: !!config.resetOnFinish,\n stepMs,\n sampleCount,\n elements,\n };\n}\n\n/**\n * Wire prop → the prop name the NATIVE view actually declares.\n *\n * react-native-svg's JS layer renames some props on the way down: a\n * `transform` (string or matrix) is parsed by `extractProps` and handed to the\n * native component as `matrix` — the Fabric spec has no `transform` prop at\n * all. Values sent through reanimated's animated-props path skip that JS\n * rename, so they must already use the native name or the native view drops\n * them silently. This is ONLY for the animated path; plain React renders still\n * go through the JS layer and must keep the wire name.\n */\nexport const NATIVE_PROP_NAME: Record<string, string> = {\n transform: 'matrix',\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 *\n * `native = true` applies {@link NATIVE_PROP_NAME} — pass it only on the\n * reanimated animated-props path of a real device. Props that are applied by\n * re-rendering through React (and therefore still pass through react-native-svg's\n * JS layer), and every value on the web, must keep the wire name.\n */\nexport function sampleProps(\n tracks: PxElementTracks,\n tMs: number,\n stepMs: number,\n sampleCount: number,\n native = false\n): Record<string, string | number | Array<number>> {\n 'worklet';\n const out: Record<string, string | number | Array<number>> = {};\n // Defensive: this runs on the UI thread, where a throw is a hard crash\n // with no React boundary to catch it.\n if (!tracks || !tracks.props || !(stepMs > 0)) return out;\n\n let idx = Math.round(tMs / stepMs);\n if (idx < 0) idx = 0;\n if (idx >= sampleCount) idx = sampleCount - 1;\n for (const key in tracks.props) {\n const values = tracks.props[key];\n if (!values) continue;\n const value = values[idx];\n if (value === undefined) continue;\n const name = native && key === 'transform' ? 'matrix' : key;\n out[name] = value;\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';\nimport { svgTransformToMatrix } from './PxRnMatrix';\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(\n rnPropName: string,\n value: string | number,\n /** The owning element's tag. The ROOT `<Svg>` handles `transform` through a\n * different code path (`extractTransformSvgView`, which wants a string or\n * an RN style) — a matrix there would be dropped, so leave it alone. */\n tag?: string,\n /** Opt in to the NATIVE representation of a value (see below). Defaults to\n * off, so web keeps the plain SVG/DOM form it has always been given. */\n native = false,\n): string | number | Array<number> {\n // On a device `transform` must arrive as a matrix, not a string: the\n // string→matrix parse happens in JS during render, which reanimated's\n // animated-props path skips entirely. See PxRnMatrix for the full why.\n // On the web the DOM parses the string itself and an array would serialise\n // to a meaningless `transform=\"1,0,0,1,3,4\"`, so it must stay a string.\n if (native && rnPropName === 'transform' && typeof value === 'string' && tag !== 'svg') {\n const m = svgTransformToMatrix(value);\n if (m) return m;\n }\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\n/**\n * SVG transform string → 2D affine matrix, in the order react-native-svg's\n * native side expects: `[a, b, c, d, e, f]`, i.e. SVG's own `matrix(…)` order\n *\n * ```\n * | a c e |\n * | b d f |\n * | 0 0 1 |\n * ```\n *\n * WHY THIS EXISTS: react-native-svg parses a `transform` STRING into this matrix\n * in JavaScript, inside `extractTransform`, during render. Values delivered\n * through reanimated's `animatedProps` bypass that JS step and reach the native\n * view directly, where a raw string is meaningless — an animated transform\n * simply does nothing. Feeding the matrix instead makes the animated and static\n * paths agree. (On the web the DOM parses the string itself, which is why this\n * only shows up on a device.)\n */\nexport type Mat2D = [number, number, number, number, number, number];\n\nexport const IDENTITY: Mat2D = [1, 0, 0, 1, 0, 0];\n\nconst DEG = Math.PI / 180;\n\n/** `m1 · m2` — apply m2 first, then m1 (same convention as SVG's left-to-right list). */\nfunction multiply(m1: Mat2D, m2: Mat2D): Mat2D {\n const [a1, b1, c1, d1, e1, f1] = m1;\n const [a2, b2, c2, d2, e2, f2] = m2;\n return [\n a1 * a2 + c1 * b2,\n b1 * a2 + d1 * b2,\n a1 * c2 + c1 * d2,\n b1 * c2 + d1 * d2,\n a1 * e2 + c1 * f2 + e1,\n b1 * e2 + d1 * f2 + f1,\n ];\n}\n\n/** Splits `translate(1,2)rotate(45)` into `[['translate',[1,2]], ['rotate',[45]]]`. */\nconst FN_RE = /([a-zA-Z]+)\\s*\\(([^)]*)\\)/g;\n\nfunction numbers(raw: string): Array<number> {\n return raw\n .split(/[\\s,]+/)\n .filter(s => s.length > 0)\n .map(Number)\n .filter(n => Number.isFinite(n));\n}\n\n/**\n * Parses an SVG transform list. Returns `undefined` when the string contains no\n * recognisable function, so callers can leave the original value untouched\n * rather than silently replacing it with an identity matrix.\n */\nexport function svgTransformToMatrix(value: string): Mat2D | undefined {\n let m: Mat2D | undefined;\n FN_RE.lastIndex = 0;\n\n let match: RegExpExecArray | null;\n while ((match = FN_RE.exec(value)) !== null) {\n const fn = match[1].toLowerCase();\n const n = numbers(match[2]);\n let step: Mat2D | undefined;\n\n switch (fn) {\n case 'translate':\n step = [1, 0, 0, 1, n[0] || 0, n[1] || 0];\n break;\n case 'scale': {\n const sx = n[0] ?? 1;\n const sy = n.length > 1 ? n[1] : sx;\n step = [sx, 0, 0, sy, 0, 0];\n break;\n }\n case 'rotate': {\n const rad = (n[0] || 0) * DEG;\n const cos = Math.cos(rad), sin = Math.sin(rad);\n const rot: Mat2D = [cos, sin, -sin, cos, 0, 0];\n if (n.length >= 3) {\n // rotate(a, cx, cy) == translate(cx,cy) rotate(a) translate(-cx,-cy)\n const cx = n[1], cy = n[2];\n step = multiply(multiply([1, 0, 0, 1, cx, cy], rot), [1, 0, 0, 1, -cx, -cy]);\n } else {\n step = rot;\n }\n break;\n }\n case 'skewx':\n step = [1, 0, Math.tan((n[0] || 0) * DEG), 1, 0, 0];\n break;\n case 'skewy':\n step = [1, Math.tan((n[0] || 0) * DEG), 0, 1, 0, 0];\n break;\n case 'matrix':\n if (n.length >= 6) step = [n[0], n[1], n[2], n[3], n[4], n[5]];\n break;\n default:\n step = undefined; // unknown function — ignore it\n }\n\n if (step) m = m ? multiply(m, step) : step;\n }\n\n return m;\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 resolveStyle,\n sanitiseAttributeValue,\n DISALLOWED_SVG_TAGS_LOWER,\n TEXT_ATTR,\n TEXT_CONTENT_ATTR,\n type PxDefs,\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 /** `definitions` from the document, used to resolve named `style` presets. */\n defs?: PxDefs;\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 * `key` is handed over SEPARATELY and is deliberately absent from `props`:\n * React 19 warns when a props object containing `key` is spread into JSX,\n * and implementations of this hook do exactly that.\n */\n decorate?: (\n node: PxNode,\n Component: ComponentType<any>,\n props: Record<string, any>,\n children: ReactNode,\n key: string | number | undefined\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>, tag?: 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), tag);\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 // `feFuncR/G/B/A` carry their SVG `type` attribute (identity/table/…) under\n // `funcType`, because the wire format reserves `type` for the node tag.\n // Restore it as a real prop, mirroring the web renderer.\n const feFuncType: string | undefined = props.funcType;\n if (feFuncType !== undefined) delete props.funcType;\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 // NB: `key` is never written into this object — see `decorate` above.\n const rnProps = toRnProps(props, opts.warnings, tag);\n if (feFuncType !== undefined) rnProps.type = feFuncType;\n\n // `node.style` — a named preset from `definitions.styles`, or an inline\n // record. react-native-svg has no CSS, so the resolved declarations are\n // applied as ordinary props (the same names, e.g. `fill`, `strokeWidth`).\n // Explicit attributes on the node win over the style block.\n const resolved = resolveStyle(style, opts.defs);\n if (resolved) {\n for (const [k, v] of Object.entries(resolved)) {\n const rnKey = toRnPropName(k);\n if (!rnKey || rnKey in rnProps) continue;\n const sanitised = sanitiseAttributeValue(rnKey, v);\n if (sanitised === undefined) continue;\n rnProps[rnKey] = toRnPropValue(rnKey, String(sanitised), tag);\n }\n }\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) => {\n // One malformed child should cost that child, not the whole tree.\n try {\n return renderRnNode(ch, opts, i);\n } catch (e) {\n opts.warnings?.push('child failed to render: ' + (e instanceof Error ? e.message : String(e)));\n return null;\n }\n })\n .filter(Boolean);\n } else if (textContent !== undefined) {\n childElements = String(textContent);\n }\n\n const decorated = opts.decorate?.(node, Component, rnProps, childElements, key);\n if (decorated !== undefined) return decorated;\n\n // `createElement` takes `key` in its config object — that path does NOT\n // trigger React's JSX-spread warning.\n return createElement(\n Component,\n key !== undefined ? { ...rnProps, key } : rnProps,\n childElements\n );\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 FeBlend,\n FeColorMatrix,\n FeComponentTransfer,\n FeComposite,\n FeConvolveMatrix,\n FeDiffuseLighting,\n FeDisplacementMap,\n FeDistantLight,\n FeDropShadow,\n FeFlood,\n FeFuncA,\n FeFuncB,\n FeFuncG,\n FeFuncR,\n FeGaussianBlur,\n FeImage,\n FeMerge,\n FeMergeNode,\n FeMorphology,\n FeOffset,\n FePointLight,\n FeSpecularLighting,\n FeSpotLight,\n FeTile,\n FeTurbulence,\n Filter,\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 *\n * Keys are the wire-format `node.type` values, which follow SVG's own casing\n * (`clipPath`, `feGaussianBlur`, `linearGradient`, …).\n */\nexport const RN_SVG_COMPONENTS: Record<string, ComponentType<any>> = {\n // Root & containers\n svg: Svg,\n g: G,\n defs: Defs,\n symbol: SvgSymbol,\n use: Use,\n\n // Shapes\n rect: Rect,\n circle: Circle,\n ellipse: Ellipse,\n line: Line,\n path: Path,\n polygon: Polygon,\n polyline: Polyline,\n image: Image,\n\n // Text\n text: SvgText,\n tspan: TSpan,\n textPath: TextPath,\n\n // Paint servers & clipping\n linearGradient: LinearGradient,\n radialGradient: RadialGradient,\n stop: Stop,\n pattern: Pattern,\n mask: Mask,\n clipPath: ClipPath,\n marker: Marker,\n\n // Filters — react-native-svg implements the full primitive set.\n // NOTE: filter rendering requires the New Architecture (Fabric) and is\n // newer than the rest of react-native-svg; treat visual parity with the\n // web player as unverified until checked on a device.\n filter: Filter,\n feBlend: FeBlend,\n feColorMatrix: FeColorMatrix,\n feComponentTransfer: FeComponentTransfer,\n feComposite: FeComposite,\n feConvolveMatrix: FeConvolveMatrix,\n feDiffuseLighting: FeDiffuseLighting,\n feDisplacementMap: FeDisplacementMap,\n feDistantLight: FeDistantLight,\n feDropShadow: FeDropShadow,\n feFlood: FeFlood,\n feFuncA: FeFuncA,\n feFuncB: FeFuncB,\n feFuncG: FeFuncG,\n feFuncR: FeFuncR,\n feGaussianBlur: FeGaussianBlur,\n feImage: FeImage,\n feMerge: FeMerge,\n feMergeNode: FeMergeNode,\n feMorphology: FeMorphology,\n feOffset: FeOffset,\n fePointLight: FePointLight,\n feSpecularLighting: FeSpecularLighting,\n feSpotLight: FeSpotLight,\n feTile: FeTile,\n feTurbulence: FeTurbulence,\n};\n\nexport { toRnPropName } from './PxRnPropNames';\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 { Component, type ErrorInfo, type ReactNode } from 'react';\n\nexport interface PxRnErrorBoundaryProps {\n children: ReactNode;\n /** Rendered instead of the children once something has thrown. */\n fallback?: (error: Error) => ReactNode;\n onError?: (error: Error, info?: string) => void;\n}\n\ninterface State {\n error: Error | null;\n}\n\n/**\n * Keeps one bad animation from taking down the screen around it.\n *\n * A throw anywhere in the rendered SVG tree — an unsupported prop shape, a\n * react-native-svg internal, a reanimated attachment failure — otherwise\n * unmounts the whole React tree above it. Here it is contained to this one\n * animation, reported through `onError`, and replaced by `fallback`.\n *\n * NOTE the limit: this catches JavaScript errors only. A crash INSIDE the\n * native renderer (see `openClosedTextPathTargets` for a real example) never\n * reaches JavaScript and cannot be caught here — those have to be avoided\n * rather than handled.\n */\nexport class PxRnErrorBoundary extends Component<PxRnErrorBoundaryProps, State> {\n override state: State = { error: null };\n\n static getDerivedStateFromError(error: Error): State {\n return { error };\n }\n\n override componentDidCatch(error: Error, info: ErrorInfo): void {\n this.props.onError?.(error, info?.componentStack ?? undefined);\n console.warn('[PixodeskSvgAnimator] render failed:', error?.message ?? error);\n }\n\n override componentDidUpdate(prev: PxRnErrorBoundaryProps): void {\n // A new document deserves a fresh attempt — otherwise the boundary\n // would stay latched on the failure for the rest of its life.\n if (this.state.error && prev.children !== this.props.children) {\n this.setState({ error: null });\n }\n }\n\n override render(): ReactNode {\n const { error } = this.state;\n if (error) return this.props.fallback ? this.props.fallback(error) : null;\n return this.props.children;\n }\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 { deepClone, generateUniqueId, type PxNode } from '@pixodesk/svg-animator-core';\n\n/**\n * Workarounds for defects in react-native-svg's NATIVE renderer that would\n * otherwise take the whole app down.\n *\n * These are applied only when the native views are in use — never on the web,\n * where the DOM handles all of this correctly and the document must be left\n * exactly as the core pipeline produced it.\n */\n\n/** True when a path's `d` contains a close-subpath command. */\nfunction isClosedPath(d: unknown): boolean {\n return typeof d === 'string' && /[zZ]/.test(d);\n}\n\n/** Drops close-subpath commands, turning a closed outline into an open one. */\nfunction openPath(d: string): string {\n return d.replace(/[zZ]/g, '').trimEnd();\n}\n\n/** `#foo` → `foo`. Returns undefined for anything that is not a local ref. */\nfunction localRef(value: unknown): string | undefined {\n if (typeof value !== 'string') return undefined;\n const trimmed = value.trim();\n return trimmed.startsWith('#') ? trimmed.slice(1) : undefined;\n}\n\nfunction forEachNode(node: PxNode | undefined, visit: (n: PxNode, parent?: PxNode) => void, parent?: PxNode): void {\n if (!node) return;\n visit(node, parent);\n for (const child of (node.children ?? [])) forEachNode(child, visit, node);\n}\n\n/**\n * Gives every `<textPath>` that follows a CLOSED path its own OPEN copy of it.\n *\n * WHY: react-native-svg's native text-on-path layout crashes the app —\n * an uncatchable `NSRangeException` on iOS — for this combination.\n * `RNSVGTSpan.mm` skips glyphs outside `[startOfRendering, endOfRendering]`,\n * but for a closed path it sets those bounds to `startOffset … startOffset +\n * pathLength` instead of `0 … pathLength`. Any glyph past the end of the path\n * therefore survives the bounds check and reaches `getPosAndTan`, whose\n * `indexOfObjectPassingTest` returns `NSNotFound` — and indexing the lengths\n * array with `NSNotFound` throws. A non-zero `startOffset` on a closed path is\n * all it takes, and animating `startOffset` guarantees hitting it.\n *\n * Opening the path restores the `0 … pathLength` bounds, so out-of-range\n * glyphs are skipped as intended. The copy is private to the `<textPath>`, so\n * anything else drawing the same path still gets the closed original. For a\n * shape whose ends already meet (a circle, the usual case) the removed segment\n * has zero length and nothing changes visually at all.\n *\n * Returns the document unchanged — the same object — when nothing matches.\n */\nexport function openClosedTextPathTargets(doc: PxNode, warnings?: Array<string>): PxNode {\n // Cheap pre-check: the overwhelming majority of documents have no textPath.\n let hasTextPath = false;\n forEachNode(doc, n => { if (String(n.type) === 'textPath') hasTextPath = true; });\n if (!hasTextPath) return doc;\n\n const result = deepClone(doc);\n\n const byId = new Map<string, PxNode>();\n forEachNode(result, n => {\n const id = (n as any).id;\n if (typeof id === 'string') byId.set(id, n);\n });\n\n /** The copy is a geometry reference, never something to draw — so it goes\n * in `<defs>`, alongside the paths textPath targets normally live in. */\n let defs = (result.children ?? []).find(c => String(c.type) === 'defs');\n const ensureDefs = (): PxNode => {\n if (!defs) {\n defs = { type: 'defs', children: [] } as unknown as PxNode;\n (result.children ??= []).unshift(defs);\n }\n return defs;\n };\n\n /** Original path id → id of the open copy, so N textPaths share one copy. */\n const openCopies = new Map<string, string>();\n\n forEachNode(result, node => {\n if (String(node.type) !== 'textPath') return;\n\n const anyNode = node as any;\n const attr = anyNode.href !== undefined ? 'href' : 'xlink:href';\n const targetId = localRef(anyNode[attr]);\n if (!targetId) return;\n\n const target = byId.get(targetId);\n if (!target || !isClosedPath((target as any).d)) return;\n\n let copyId = openCopies.get(targetId);\n if (!copyId) {\n const copy = deepClone(target) as any;\n copyId = 'px_open_' + generateUniqueId();\n copy.id = copyId;\n copy.d = openPath(String(copy.d));\n // A copy that also carried animation would animate twice; the copy\n // exists purely as a geometry reference for the text.\n delete copy.animate;\n delete copy.effects;\n\n (ensureDefs().children ??= []).push(copy);\n openCopies.set(targetId, copyId);\n warnings?.push(\n 'textPath follows a closed path (#' + targetId + '); using an open copy to ' +\n 'avoid a react-native-svg native crash'\n );\n }\n\n anyNode[attr] = '#' + copyId;\n });\n\n return result;\n}\n"],"mappings":"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","names":["getAnimatorConfig","PxAnimatorEngine","createElement","_a","Component","_a","_a","Component","createElement","PxAnimatorEngine","getAnimatorConfig","_a"]}
1
+ {"version":3,"sources":["../src/PixodeskSvgAnimator.tsx","../src/PxRnTracks.ts","../src/PxRnPropNames.ts","../src/PxRnMatrix.ts","../src/PxRnRender.tsx","../src/PxRnTypeMap.ts","../src/PxRnErrorBoundary.tsx","../src/PxRnSafety.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\nimport {\n generateNewIds,\n getAnimatorConfig,\n getDefs,\n materialiseAllInTree,\n validateNodeEffects,\n PxAnimatorEngine,\n type FillMode,\n type OutAction,\n type PlaybackDirection,\n type PxAnimatedSvgDocument,\n type PxNode,\n} from '@pixodesk/svg-animator-core';\nimport React, { createElement, useEffect, useImperativeHandle, useMemo, useRef, useState, type ComponentType, type ReactElement, type ReactNode } from 'react';\nimport { Dimensions, Platform, Pressable, View } from 'react-native';\nimport Animated, {\n cancelAnimation,\n useAnimatedReaction,\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, type RenderRnNodeOptions } from './PxRnRender';\nimport { PxRnErrorBoundary } from './PxRnErrorBoundary';\nimport { openClosedTextPathTargets } from './PxRnSafety';\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 /** Snap back to the start state after a natural finish. */\n resetOnFinish?: boolean;\n\n /**\n * What a second tap does when `startOn: 'click'` is active.\n * Defaults to the document's `trigger.outAction`, else `'pause'`.\n */\n outAction?: OutAction;\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 // -- Failure handling -----------------------------------------------------\n\n /**\n * Called when a document cannot be compiled or rendered. The component\n * renders {@link fallback} instead of throwing, so a single broken\n * animation never takes down the screen around it.\n *\n * Only JavaScript failures reach this — a crash inside react-native-svg's\n * native renderer bypasses JavaScript entirely.\n */\n onError?: (error: Error, componentStack?: string) => void;\n\n /** Rendered in place of the animation after a failure. Default: nothing. */\n fallback?: (error: Error) => ReactElement | null;\n}\n\n\n// -- Animated element wrapper ------------------------------------------------\n\n/**\n * Whether react-native-svg is backed by NATIVE views here, rather than by the\n * DOM through react-native-web.\n *\n * The two want different things from an animated `transform`: a native view\n * declares a `matrix` prop taking six numbers, while the DOM wants a\n * `transform` attribute holding an SVG string. Getting it wrong is silent —\n * the value is dropped and the element simply never moves — so this single\n * constant decides it once and feeds both the track compiler (value form) and\n * the sampler (prop name). Everything else in the package defaults to the\n * DOM-compatible form.\n */\nconst NATIVE_SVG_VIEWS = Platform.OS !== 'web';\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 // On iOS/Android these values bypass react-native-svg's JS prop layer\n // and land on the native view, which declares `matrix`, not\n // `transform`. The web build keeps the DOM-facing `transform` name.\n return sampleProps(tracks, progress.value, stepMs, sampleCount, NATIVE_SVG_VIEWS);\n }, [tracks, stepMs, sampleCount]);\n\n return (\n <AnimatedComponent {...staticProps} animatedProps={animatedProps}>\n {children}\n </AnimatedComponent>\n );\n}\n\n\n/**\n * react-native-svg elements whose `render()` returns `null`. They carry data for\n * their PARENT (a `<Stop>` is read by the gradient that owns it) rather than\n * producing a native view, so reanimated has nothing to attach to — wrapping one\n * in `Animated.createAnimatedComponent` throws\n * \"Cannot find host instance for this component\".\n */\nconst NON_HOST_TAGS = new Set(['stop', 'feMergeNode']);\n\n/**\n * Definition elements — they describe paint/geometry for something else rather\n * than drawing themselves. Their animated attributes (a gradient's `y1`, a\n * stop's `stop-color`) do not reliably flow through reanimated's animated-props\n * path, so an animated def is rendered by re-sampling from JS instead. There\n * are only ever a handful per document and they change slowly, so the cost is\n * negligible — visual elements still animate entirely on the UI thread.\n */\nconst SAMPLED_DEF_TAGS = new Set(['linearGradient', 'radialGradient', ...NON_HOST_TAGS]);\n\n/** True when this subtree must be driven from JS rather than the UI thread:\n * either the node itself is an animated def, or it owns an animated non-host\n * child (an animated `<Stop>` only re-renders via its parent gradient). */\nfunction needsJsSampling(node: PxNode, trackById: Map<string, PxElementTracks>): boolean {\n const id = (node as any).id;\n if (SAMPLED_DEF_TAGS.has(String(node.type)) && id && trackById.has(id)) return true;\n return (node.children ?? []).some(c => needsJsSampling(c, trackById));\n}\n\n/**\n * Renders a subtree whose animation cannot run on the UI thread (see\n * {@link NON_HOST_TAGS}) by re-rendering it from JS with sampled values.\n *\n * Changing a `<Stop>`'s props does not re-render its parent gradient, so the\n * whole subtree is rebuilt — which is why this wraps the gradient rather than\n * the stop. The reaction itself runs on the UI thread and only crosses to JS\n * when the QUANTISED sample index changes, capping these few elements at\n * ~30fps instead of a JS call every frame.\n */\nfunction SampledSubtree({\n node, trackById, progress, stepMs, sampleCount, renderOpts,\n}: {\n node: PxNode;\n trackById: Map<string, PxElementTracks>;\n progress: SharedValue<number>;\n stepMs: number;\n sampleCount: number;\n renderOpts: RenderRnNodeOptions;\n}) {\n const [idx, setIdx] = useState(0);\n\n useAnimatedReaction(\n () => Math.floor(Math.round(progress.value / stepMs) / 2) * 2, // half-rate\n (next, prev) => {\n if (next !== prev) runOnJS(setIdx)(next);\n },\n [stepMs]\n );\n\n const tMs = Math.min(Math.max(idx, 0), sampleCount - 1) * stepMs;\n\n return renderRnNode(node, {\n ...renderOpts,\n // Sampled values are baked in as PLAIN props — nothing reanimated-driven.\n decorate: (n, Component, staticProps, children, key) => {\n const id = (n as any).id;\n const tracks = id ? trackById.get(id) : undefined;\n if (!tracks) return undefined;\n // Wire prop names, NOT the native ones: these go back through\n // react-native-svg's JS prop layer, which does the renaming itself.\n const sampled = sampleProps(tracks, tMs, stepMs, sampleCount);\n return createElement(Component, { ...staticProps, ...sampled, key }, children);\n },\n });\n}\n\n\n\n/** Overrides that shadow the document's own `animator` config. */\ninterface ConfigOverrides {\n duration?: number;\n delay?: number;\n iterations?: number | 'infinite';\n fill?: FillMode;\n direction?: PlaybackDirection;\n resetOnFinish?: boolean;\n}\n\ninterface Compiled {\n /** Materialised document, or null when compilation failed. */\n doc: PxAnimatedSvgDocument | null;\n tracks: PxCompiledTracks;\n error: Error | null;\n}\n\n/** Playable-but-empty tracks, so a failed compile still satisfies every hook\n * below it — React forbids skipping hooks on an error path. */\nconst EMPTY_TRACKS: PxCompiledTracks = {\n duration: 1, iterations: 1, direction: 'normal', delay: 0,\n fill: 'forwards', resetOnFinish: false, stepMs: 1, sampleCount: 2, elements: [],\n};\n\n/**\n * Materialises + compiles a document. Extracted from the component so the\n * whole thing sits behind one try/catch, and so it can be tested directly.\n */\nfunction compileDocument(doc: PxAnimatedSvgDocument, overrides: ConfigOverrides): Compiled {\n const { duration, delay, iterations, fill, direction, resetOnFinish } = overrides;\n const warnings = validateNodeEffects(doc as PxNode);\n for (const w of warnings) console.warn('[PixodeskSvgAnimator] effects shape warning:', w);\n\n // `waapi` = 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.waapi);\n\n // Sidestep a react-native-svg NATIVE crash (see PxRnSafety). Guarded on\n // the platform because the DOM renders this case correctly and the web\n // document must stay exactly as the core pipeline produced it.\n if (NATIVE_SVG_VIEWS) {\n prepared = openClosedTextPathTargets(prepared as PxNode) as PxAnimatedSvgDocument;\n }\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 resetOnFinish: resetOnFinish !== undefined ? resetOnFinish : animator.resetOnFinish,\n },\n };\n\n prepared = generateNewIds(prepared);\n const tracks = compileTracks(prepared, { native: NATIVE_SVG_VIEWS });\n return { doc: prepared, tracks, error: null };\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, resetOnFinish, outAction: outActionProp,\n autoplay, play, pause, apiRef, time, timeMs,\n onPlay, onStop, onPause, onCancel, onFinish, onError, fallback,\n}: PixodeskSvgAnimatorProps): ReactElement | null {\n\n // -- Compile the document (once per doc/override change) ------------------\n\n const compiled = useMemo((): Compiled => {\n try {\n return compileDocument(\n doc,\n { duration, delay, iterations, fill, direction, resetOnFinish }\n );\n } catch (e) {\n // A malformed document must not take the host screen down with it.\n const error = e instanceof Error ? e : new Error(String(e));\n console.warn('[PixodeskSvgAnimator] could not compile the document:', error.message);\n return { doc: null, tracks: EMPTY_TRACKS, error };\n }\n }, [doc, duration, delay, iterations, fill, direction, resetOnFinish]);\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 /** True when the current rate plays the timeline backwards. */\n const reversePlayback = () => rateRef.current < 0;\n\n /** Where the playhead rests once playback ends. `resetOnFinish` snaps back\n * to the start; otherwise `fill` decides whether the final frame is held. */\n const restingPosition = () => {\n if (tracks.resetOnFinish) return 0;\n if (tracks.fill === 'none' || tracks.fill === 'backwards') return 0;\n return reversePlayback() ? 0 : tracks.duration;\n };\n\n const notifyFinish = () => {\n playingRef.current = false;\n progress.value = restingPosition();\n onFinish?.();\n onStop?.();\n };\n\n const startFrom = (fromMs: number) => {\n const dur = tracks.duration;\n const rate = rateRef.current || 1;\n const backwards = rate < 0;\n const speed = Math.abs(rate);\n // `direction` decides which end a leg runs toward; a negative playback\n // rate flips it again (the two compose, as in the Web Animations API).\n const directionReversed = tracks.direction === 'reverse' || tracks.direction === 'alternate-reverse';\n const reversedStart = backwards ? !directionReversed : directionReversed;\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) / speed;\n const repeats = tracks.iterations === Infinity ? -1 : tracks.iterations;\n\n cancelAnimation(progress);\n progress.value = reversedStart ? (from <= 0 ? dur : from) : (from >= dur ? 0 : 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 / speed, animation)\n : animation;\n\n playingRef.current = true;\n };\n\n const api: RnAnimatorApi = {\n isPlaying: () => playingRef.current,\n play: () => {\n // `startFrom` rewinds to the opposite end when the playhead is\n // already resting at a boundary (mirrors WAAPI, where play() on a\n // finished animation auto-rewinds).\n startFrom(progress.value);\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 playingRef.current = false;\n progress.value = restingPosition();\n onFinish?.();\n onStop?.();\n },\n setPlaybackRate: (rate: number) => {\n if (!isFinite(rate) || rate === 0) {\n console.warn('setPlaybackRate: rate must be finite and non-zero');\n return;\n }\n rateRef.current = rate;\n if (playingRef.current) startFrom(progress.value);\n },\n getCurrentTime: () => progress.value,\n setCurrentTime: (t: number) => {\n const wasPlaying = playingRef.current;\n cancelAnimation(progress);\n playingRef.current = false;\n const clamped = Math.max(0, Math.min(t, totalDuration));\n const withinIteration = tracks.duration > 0\n ? (clamped % tracks.duration) || (clamped === 0 ? 0 : tracks.duration)\n : 0;\n progress.value = withinIteration;\n // Seeking mid-playback continues from the new position rather than\n // silently pausing.\n if (wasPlaying) startFrom(withinIteration);\n },\n };\n\n useImperativeHandle(apiRef, () => api, [compiled]);\n\n // -- Declarative control --------------------------------------------------\n\n const trigger = compiled.doc ? getAnimatorConfig(compiled.doc)?.trigger : undefined;\n const startOn = trigger?.startOn ?? 'load';\n const outAction = outActionProp ?? trigger?.outAction ?? 'pause';\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 // 'click' and 'scrollIntoView' start from their own handlers below.\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 // `startOn: 'scrollIntoView'` — react-native has no IntersectionObserver, so\n // visibility is sampled by measuring the view against the window box. The\n // poll is cheap (a native measure every 200ms) and only runs while this\n // trigger is active; `outAction` decides what leaving the viewport does.\n const scrollRef = useRef<View | null>(null);\n const inViewRef = useRef(false);\n useEffect(() => {\n if (!autoplay || startOn !== 'scrollIntoView') return;\n const threshold = trigger?.scrollIntoViewThreshold ?? 0;\n inViewRef.current = false;\n\n const check = () => {\n const node = scrollRef.current;\n if (!node) return;\n node.measureInWindow((_x, y, _w, h) => {\n if (!h) return;\n const screen = Dimensions.get('window').height;\n const visible = Math.max(0, Math.min(y + h, screen) - Math.max(y, 0));\n const ratio = visible / h;\n const isIn = ratio > 0 && ratio >= threshold;\n if (isIn === inViewRef.current) return;\n inViewRef.current = isIn;\n if (isIn) {\n if (rateRef.current < 0) api.setPlaybackRate(Math.abs(rateRef.current));\n api.play();\n } else if (outAction === 'reset') api.cancel();\n else if (outAction === 'reverse') { api.setPlaybackRate(-Math.abs(rateRef.current || 1)); api.play(); }\n else if (outAction !== 'continue') api.pause();\n });\n };\n\n check();\n const id = setInterval(check, 200);\n return () => clearInterval(id);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [compiled, autoplay, startOn, outAction]);\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 renderErrorRef = useRef<Error | null>(null);\n const root = useMemo(() => {\n warningsRef.current = [];\n renderErrorRef.current = null;\n if (!compiled.doc) return null;\n\n const renderOpts: RenderRnNodeOptions = {\n warnings: warningsRef.current,\n defs: getDefs(compiled.doc),\n };\n try {\n return renderRnNode(compiled.doc as PxNode, {\n ...renderOpts,\n decorate: (node, Component, staticProps, children, key) => {\n // An animated definition subtree (gradient / its stops) cannot be\n // driven on the UI thread — hand the WHOLE subtree to the\n // JS-sampled renderer and stop descending here.\n if (needsJsSampling(node, trackById)) {\n return (\n <SampledSubtree\n key={key}\n node={node}\n trackById={trackById}\n progress={progress}\n stepMs={tracks.stepMs}\n sampleCount={tracks.sampleCount}\n renderOpts={renderOpts}\n />\n );\n }\n\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={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 } catch (e) {\n // Building the element tree threw — report it and render nothing\n // rather than propagating and unmounting the host screen.\n const error = e instanceof Error ? e : new Error(String(e));\n renderErrorRef.current = error;\n console.warn('[PixodeskSvgAnimator] could not render the document:', error.message);\n return null;\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 // Surface compile/render failures to the host exactly once per occurrence.\n const failure = compiled.error ?? renderErrorRef.current;\n useEffect(() => {\n if (failure) onError?.(failure);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [failure]);\n\n if (failure) return fallback ? fallback(failure) : null;\n\n // `startOn: 'click'` — the touch analogue of the web player's click trigger:\n // tap to start, tap again to apply `outAction`. Hover (`mouseOver`) has no\n // touch equivalent and `scrollIntoView` needs the surrounding scroll view,\n // so both are left to the host app.\n let content: ReactElement | null = root;\n\n if (autoplay && startOn === 'scrollIntoView' && root) {\n // `collapsable={false}` keeps the view in the native tree so it can be measured.\n content = <View ref={scrollRef} collapsable={false}>{root}</View>;\n } else if (autoplay && startOn === 'click' && root) {\n content = (\n <Pressable\n onPress={() => {\n if (playingRef.current) {\n if (outAction === 'reset') api.cancel();\n else if (outAction === 'reverse') { api.setPlaybackRate(-Math.abs(rateRef.current || 1)); api.play(); }\n else if (outAction !== 'continue') api.pause();\n } else {\n if (rateRef.current < 0) api.setPlaybackRate(Math.abs(rateRef.current));\n api.play();\n }\n }}\n >\n {root}\n </Pressable>\n );\n }\n\n // Catches what the try/catch above cannot: throws during React's own render\n // and commit of the tree — react-native-svg internals, reanimated failing\n // to attach to a component that turns out not to be a host view, and so on.\n return (\n <PxRnErrorBoundary onError={onError} fallback={fallback}>\n {content}\n </PxRnErrorBoundary>\n );\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 /** When true, snap back to the start after a natural finish. */\n resetOnFinish: boolean;\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 * Sample values in the form the NATIVE react-native-svg views expect\n * (currently: `transform` as a 6-number matrix rather than an SVG string).\n *\n * Defaults to `false` — the plain SVG form, which is what react-native-web\n * hands straight to the DOM. Only the component knows the platform, so it\n * decides; every consumer that does not opt in keeps DOM-compatible values.\n */\n native?: boolean;\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 native = opts?.native ?? false;\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 // Element tag per id — `toRnPropValue` needs it to leave the root `<Svg>`'s\n // transform as a string (see its `tag` parameter).\n const tagById = new Map<string, string>();\n const indexTags = (n: any): void => {\n if (n && typeof n.id === 'string') tagById.set(n.id, String(n.type));\n (n?.children ?? []).forEach(indexTags);\n };\n indexTags(doc);\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, tagById.get(binding.id), native);\n }\n arr[i] = toRnPropValue(rnProp, value, tagById.get(binding.id), native);\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 resetOnFinish: !!config.resetOnFinish,\n stepMs,\n sampleCount,\n elements,\n };\n}\n\n/**\n * Wire prop → the prop name the NATIVE view actually declares.\n *\n * react-native-svg's JS layer renames some props on the way down: a\n * `transform` (string or matrix) is parsed by `extractProps` and handed to the\n * native component as `matrix` — the Fabric spec has no `transform` prop at\n * all. Values sent through reanimated's animated-props path skip that JS\n * rename, so they must already use the native name or the native view drops\n * them silently. This is ONLY for the animated path; plain React renders still\n * go through the JS layer and must keep the wire name.\n */\nexport const NATIVE_PROP_NAME: Record<string, string> = {\n transform: 'matrix',\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 *\n * `native = true` applies {@link NATIVE_PROP_NAME} — pass it only on the\n * reanimated animated-props path of a real device. Props that are applied by\n * re-rendering through React (and therefore still pass through react-native-svg's\n * JS layer), and every value on the web, must keep the wire name.\n */\nexport function sampleProps(\n tracks: PxElementTracks,\n tMs: number,\n stepMs: number,\n sampleCount: number,\n native = false\n): Record<string, string | number | Array<number>> {\n 'worklet';\n const out: Record<string, string | number | Array<number>> = {};\n // Defensive: this runs on the UI thread, where a throw is a hard crash\n // with no React boundary to catch it.\n if (!tracks || !tracks.props || !(stepMs > 0)) return out;\n\n let idx = Math.round(tMs / stepMs);\n if (idx < 0) idx = 0;\n if (idx >= sampleCount) idx = sampleCount - 1;\n for (const key in tracks.props) {\n const values = tracks.props[key];\n if (!values) continue;\n const value = values[idx];\n if (value === undefined) continue;\n const name = native && key === 'transform' ? 'matrix' : key;\n out[name] = value;\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';\nimport { svgTransformToMatrix } from './PxRnMatrix';\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(\n rnPropName: string,\n value: string | number,\n /** The owning element's tag. The ROOT `<Svg>` handles `transform` through a\n * different code path (`extractTransformSvgView`, which wants a string or\n * an RN style) — a matrix there would be dropped, so leave it alone. */\n tag?: string,\n /** Opt in to the NATIVE representation of a value (see below). Defaults to\n * off, so web keeps the plain SVG/DOM form it has always been given. */\n native = false,\n): string | number | Array<number> {\n // On a device `transform` must arrive as a matrix, not a string: the\n // string→matrix parse happens in JS during render, which reanimated's\n // animated-props path skips entirely. See PxRnMatrix for the full why.\n // On the web the DOM parses the string itself and an array would serialise\n // to a meaningless `transform=\"1,0,0,1,3,4\"`, so it must stay a string.\n if (native && rnPropName === 'transform' && typeof value === 'string' && tag !== 'svg') {\n const m = svgTransformToMatrix(value);\n if (m) return m;\n }\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\n/**\n * SVG transform string → 2D affine matrix, in the order react-native-svg's\n * native side expects: `[a, b, c, d, e, f]`, i.e. SVG's own `matrix(…)` order\n *\n * ```\n * | a c e |\n * | b d f |\n * | 0 0 1 |\n * ```\n *\n * WHY THIS EXISTS: react-native-svg parses a `transform` STRING into this matrix\n * in JavaScript, inside `extractTransform`, during render. Values delivered\n * through reanimated's `animatedProps` bypass that JS step and reach the native\n * view directly, where a raw string is meaningless — an animated transform\n * simply does nothing. Feeding the matrix instead makes the animated and static\n * paths agree. (On the web the DOM parses the string itself, which is why this\n * only shows up on a device.)\n */\nexport type Mat2D = [number, number, number, number, number, number];\n\nexport const IDENTITY: Mat2D = [1, 0, 0, 1, 0, 0];\n\nconst DEG = Math.PI / 180;\n\n/** `m1 · m2` — apply m2 first, then m1 (same convention as SVG's left-to-right list). */\nfunction multiply(m1: Mat2D, m2: Mat2D): Mat2D {\n const [a1, b1, c1, d1, e1, f1] = m1;\n const [a2, b2, c2, d2, e2, f2] = m2;\n return [\n a1 * a2 + c1 * b2,\n b1 * a2 + d1 * b2,\n a1 * c2 + c1 * d2,\n b1 * c2 + d1 * d2,\n a1 * e2 + c1 * f2 + e1,\n b1 * e2 + d1 * f2 + f1,\n ];\n}\n\n/** Splits `translate(1,2)rotate(45)` into `[['translate',[1,2]], ['rotate',[45]]]`. */\nconst FN_RE = /([a-zA-Z]+)\\s*\\(([^)]*)\\)/g;\n\nfunction numbers(raw: string): Array<number> {\n return raw\n .split(/[\\s,]+/)\n .filter(s => s.length > 0)\n .map(Number)\n .filter(n => Number.isFinite(n));\n}\n\n/**\n * Parses an SVG transform list. Returns `undefined` when the string contains no\n * recognisable function, so callers can leave the original value untouched\n * rather than silently replacing it with an identity matrix.\n */\nexport function svgTransformToMatrix(value: string): Mat2D | undefined {\n let m: Mat2D | undefined;\n FN_RE.lastIndex = 0;\n\n let match: RegExpExecArray | null;\n while ((match = FN_RE.exec(value)) !== null) {\n const fn = match[1].toLowerCase();\n const n = numbers(match[2]);\n let step: Mat2D | undefined;\n\n switch (fn) {\n case 'translate':\n step = [1, 0, 0, 1, n[0] || 0, n[1] || 0];\n break;\n case 'scale': {\n const sx = n[0] ?? 1;\n const sy = n.length > 1 ? n[1] : sx;\n step = [sx, 0, 0, sy, 0, 0];\n break;\n }\n case 'rotate': {\n const rad = (n[0] || 0) * DEG;\n const cos = Math.cos(rad), sin = Math.sin(rad);\n const rot: Mat2D = [cos, sin, -sin, cos, 0, 0];\n if (n.length >= 3) {\n // rotate(a, cx, cy) == translate(cx,cy) rotate(a) translate(-cx,-cy)\n const cx = n[1], cy = n[2];\n step = multiply(multiply([1, 0, 0, 1, cx, cy], rot), [1, 0, 0, 1, -cx, -cy]);\n } else {\n step = rot;\n }\n break;\n }\n case 'skewx':\n step = [1, 0, Math.tan((n[0] || 0) * DEG), 1, 0, 0];\n break;\n case 'skewy':\n step = [1, Math.tan((n[0] || 0) * DEG), 0, 1, 0, 0];\n break;\n case 'matrix':\n if (n.length >= 6) step = [n[0], n[1], n[2], n[3], n[4], n[5]];\n break;\n default:\n step = undefined; // unknown function — ignore it\n }\n\n if (step) m = m ? multiply(m, step) : step;\n }\n\n return m;\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 resolveStyle,\n sanitiseAttributeValue,\n DISALLOWED_SVG_TAGS_LOWER,\n TEXT_ATTR,\n TEXT_CONTENT_ATTR,\n type PxDefs,\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 /** `definitions` from the document, used to resolve named `style` presets. */\n defs?: PxDefs;\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 * `key` is handed over SEPARATELY and is deliberately absent from `props`:\n * React 19 warns when a props object containing `key` is spread into JSX,\n * and implementations of this hook do exactly that.\n */\n decorate?: (\n node: PxNode,\n Component: ComponentType<any>,\n props: Record<string, any>,\n children: ReactNode,\n key: string | number | undefined\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>, tag?: 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), tag);\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 // ESCAPE KEY (S2): elements whose SVG `type` ATTRIBUTE collides with the reserved\n // `type` node-tag key carry it under `domType` — `feColorMatrix` (matrix/saturate/…),\n // `feTurbulence` (fractalNoise/turbulence), `feFunc*` (identity/table/…).\n // Restore it as a real prop, mirroring the web renderer.\n const domType: string | undefined = props.domType;\n if (domType !== undefined) delete props.domType;\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 // NB: `key` is never written into this object — see `decorate` above.\n const rnProps = toRnProps(props, opts.warnings, tag);\n if (domType !== undefined) rnProps.type = domType;\n\n // `node.style` — a named preset from `definitions.styles`, or an inline\n // record. react-native-svg has no CSS, so the resolved declarations are\n // applied as ordinary props (the same names, e.g. `fill`, `strokeWidth`).\n // Explicit attributes on the node win over the style block.\n const resolved = resolveStyle(style, opts.defs);\n if (resolved) {\n for (const [k, v] of Object.entries(resolved)) {\n const rnKey = toRnPropName(k);\n if (!rnKey || rnKey in rnProps) continue;\n const sanitised = sanitiseAttributeValue(rnKey, v);\n if (sanitised === undefined) continue;\n rnProps[rnKey] = toRnPropValue(rnKey, String(sanitised), tag);\n }\n }\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) => {\n // One malformed child should cost that child, not the whole tree.\n try {\n return renderRnNode(ch, opts, i);\n } catch (e) {\n opts.warnings?.push('child failed to render: ' + (e instanceof Error ? e.message : String(e)));\n return null;\n }\n })\n .filter(Boolean);\n } else if (textContent !== undefined) {\n childElements = String(textContent);\n }\n\n const decorated = opts.decorate?.(node, Component, rnProps, childElements, key);\n if (decorated !== undefined) return decorated;\n\n // `createElement` takes `key` in its config object — that path does NOT\n // trigger React's JSX-spread warning.\n return createElement(\n Component,\n key !== undefined ? { ...rnProps, key } : rnProps,\n childElements\n );\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 FeBlend,\n FeColorMatrix,\n FeComponentTransfer,\n FeComposite,\n FeConvolveMatrix,\n FeDiffuseLighting,\n FeDisplacementMap,\n FeDistantLight,\n FeDropShadow,\n FeFlood,\n FeFuncA,\n FeFuncB,\n FeFuncG,\n FeFuncR,\n FeGaussianBlur,\n FeImage,\n FeMerge,\n FeMergeNode,\n FeMorphology,\n FeOffset,\n FePointLight,\n FeSpecularLighting,\n FeSpotLight,\n FeTile,\n FeTurbulence,\n Filter,\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 *\n * Keys are the wire-format `node.type` values, which follow SVG's own casing\n * (`clipPath`, `feGaussianBlur`, `linearGradient`, …).\n */\nexport const RN_SVG_COMPONENTS: Record<string, ComponentType<any>> = {\n // Root & containers\n svg: Svg,\n g: G,\n defs: Defs,\n symbol: SvgSymbol,\n use: Use,\n\n // Shapes\n rect: Rect,\n circle: Circle,\n ellipse: Ellipse,\n line: Line,\n path: Path,\n polygon: Polygon,\n polyline: Polyline,\n image: Image,\n\n // Text\n text: SvgText,\n tspan: TSpan,\n textPath: TextPath,\n\n // Paint servers & clipping\n linearGradient: LinearGradient,\n radialGradient: RadialGradient,\n stop: Stop,\n pattern: Pattern,\n mask: Mask,\n clipPath: ClipPath,\n marker: Marker,\n\n // Filters — react-native-svg implements the full primitive set.\n // NOTE: filter rendering requires the New Architecture (Fabric) and is\n // newer than the rest of react-native-svg; treat visual parity with the\n // web player as unverified until checked on a device.\n filter: Filter,\n feBlend: FeBlend,\n feColorMatrix: FeColorMatrix,\n feComponentTransfer: FeComponentTransfer,\n feComposite: FeComposite,\n feConvolveMatrix: FeConvolveMatrix,\n feDiffuseLighting: FeDiffuseLighting,\n feDisplacementMap: FeDisplacementMap,\n feDistantLight: FeDistantLight,\n feDropShadow: FeDropShadow,\n feFlood: FeFlood,\n feFuncA: FeFuncA,\n feFuncB: FeFuncB,\n feFuncG: FeFuncG,\n feFuncR: FeFuncR,\n feGaussianBlur: FeGaussianBlur,\n feImage: FeImage,\n feMerge: FeMerge,\n feMergeNode: FeMergeNode,\n feMorphology: FeMorphology,\n feOffset: FeOffset,\n fePointLight: FePointLight,\n feSpecularLighting: FeSpecularLighting,\n feSpotLight: FeSpotLight,\n feTile: FeTile,\n feTurbulence: FeTurbulence,\n};\n\nexport { toRnPropName } from './PxRnPropNames';\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 { Component, type ErrorInfo, type ReactNode } from 'react';\n\nexport interface PxRnErrorBoundaryProps {\n children: ReactNode;\n /** Rendered instead of the children once something has thrown. */\n fallback?: (error: Error) => ReactNode;\n onError?: (error: Error, info?: string) => void;\n}\n\ninterface State {\n error: Error | null;\n}\n\n/**\n * Keeps one bad animation from taking down the screen around it.\n *\n * A throw anywhere in the rendered SVG tree — an unsupported prop shape, a\n * react-native-svg internal, a reanimated attachment failure — otherwise\n * unmounts the whole React tree above it. Here it is contained to this one\n * animation, reported through `onError`, and replaced by `fallback`.\n *\n * NOTE the limit: this catches JavaScript errors only. A crash INSIDE the\n * native renderer (see `openClosedTextPathTargets` for a real example) never\n * reaches JavaScript and cannot be caught here — those have to be avoided\n * rather than handled.\n */\nexport class PxRnErrorBoundary extends Component<PxRnErrorBoundaryProps, State> {\n override state: State = { error: null };\n\n static getDerivedStateFromError(error: Error): State {\n return { error };\n }\n\n override componentDidCatch(error: Error, info: ErrorInfo): void {\n this.props.onError?.(error, info?.componentStack ?? undefined);\n console.warn('[PixodeskSvgAnimator] render failed:', error?.message ?? error);\n }\n\n override componentDidUpdate(prev: PxRnErrorBoundaryProps): void {\n // A new document deserves a fresh attempt — otherwise the boundary\n // would stay latched on the failure for the rest of its life.\n if (this.state.error && prev.children !== this.props.children) {\n this.setState({ error: null });\n }\n }\n\n override render(): ReactNode {\n const { error } = this.state;\n if (error) return this.props.fallback ? this.props.fallback(error) : null;\n return this.props.children;\n }\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 { deepClone, generateUniqueId, type PxNode } from '@pixodesk/svg-animator-core';\n\n/**\n * Workarounds for defects in react-native-svg's NATIVE renderer that would\n * otherwise take the whole app down.\n *\n * These are applied only when the native views are in use — never on the web,\n * where the DOM handles all of this correctly and the document must be left\n * exactly as the core pipeline produced it.\n */\n\n/** True when a path's `d` contains a close-subpath command. */\nfunction isClosedPath(d: unknown): boolean {\n return typeof d === 'string' && /[zZ]/.test(d);\n}\n\n/** Drops close-subpath commands, turning a closed outline into an open one. */\nfunction openPath(d: string): string {\n return d.replace(/[zZ]/g, '').trimEnd();\n}\n\n/** `#foo` → `foo`. Returns undefined for anything that is not a local ref. */\nfunction localRef(value: unknown): string | undefined {\n if (typeof value !== 'string') return undefined;\n const trimmed = value.trim();\n return trimmed.startsWith('#') ? trimmed.slice(1) : undefined;\n}\n\nfunction forEachNode(node: PxNode | undefined, visit: (n: PxNode, parent?: PxNode) => void, parent?: PxNode): void {\n if (!node) return;\n visit(node, parent);\n for (const child of (node.children ?? [])) forEachNode(child, visit, node);\n}\n\n/**\n * Gives every `<textPath>` that follows a CLOSED path its own OPEN copy of it.\n *\n * WHY: react-native-svg's native text-on-path layout crashes the app —\n * an uncatchable `NSRangeException` on iOS — for this combination.\n * `RNSVGTSpan.mm` skips glyphs outside `[startOfRendering, endOfRendering]`,\n * but for a closed path it sets those bounds to `startOffset … startOffset +\n * pathLength` instead of `0 … pathLength`. Any glyph past the end of the path\n * therefore survives the bounds check and reaches `getPosAndTan`, whose\n * `indexOfObjectPassingTest` returns `NSNotFound` — and indexing the lengths\n * array with `NSNotFound` throws. A non-zero `startOffset` on a closed path is\n * all it takes, and animating `startOffset` guarantees hitting it.\n *\n * Opening the path restores the `0 … pathLength` bounds, so out-of-range\n * glyphs are skipped as intended. The copy is private to the `<textPath>`, so\n * anything else drawing the same path still gets the closed original. For a\n * shape whose ends already meet (a circle, the usual case) the removed segment\n * has zero length and nothing changes visually at all.\n *\n * Returns the document unchanged — the same object — when nothing matches.\n */\nexport function openClosedTextPathTargets(doc: PxNode, warnings?: Array<string>): PxNode {\n // Cheap pre-check: the overwhelming majority of documents have no textPath.\n let hasTextPath = false;\n forEachNode(doc, n => { if (String(n.type) === 'textPath') hasTextPath = true; });\n if (!hasTextPath) return doc;\n\n const result = deepClone(doc);\n\n const byId = new Map<string, PxNode>();\n forEachNode(result, n => {\n const id = (n as any).id;\n if (typeof id === 'string') byId.set(id, n);\n });\n\n /** The copy is a geometry reference, never something to draw — so it goes\n * in `<defs>`, alongside the paths textPath targets normally live in. */\n let defs = (result.children ?? []).find(c => String(c.type) === 'defs');\n const ensureDefs = (): PxNode => {\n if (!defs) {\n defs = { type: 'defs', children: [] } as unknown as PxNode;\n (result.children ??= []).unshift(defs);\n }\n return defs;\n };\n\n /** Original path id → id of the open copy, so N textPaths share one copy. */\n const openCopies = new Map<string, string>();\n\n forEachNode(result, node => {\n if (String(node.type) !== 'textPath') return;\n\n const anyNode = node as any;\n const attr = anyNode.href !== undefined ? 'href' : 'xlink:href';\n const targetId = localRef(anyNode[attr]);\n if (!targetId) return;\n\n const target = byId.get(targetId);\n if (!target || !isClosedPath((target as any).d)) return;\n\n let copyId = openCopies.get(targetId);\n if (!copyId) {\n const copy = deepClone(target) as any;\n copyId = 'px_open_' + generateUniqueId();\n copy.id = copyId;\n copy.d = openPath(String(copy.d));\n // A copy that also carried animation would animate twice; the copy\n // exists purely as a geometry reference for the text.\n delete copy.animate;\n delete copy.effects;\n\n (ensureDefs().children ??= []).push(copy);\n openCopies.set(targetId, copyId);\n warnings?.push(\n 'textPath follows a closed path (#' + targetId + '); using an open copy to ' +\n 'avoid a react-native-svg native crash'\n );\n }\n\n anyNode[attr] = '#' + copyId;\n });\n\n return result;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA;AAAA,EACI;AAAA,EACA,qBAAAA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,oBAAAC;AAAA,OAMG;AACP,SAAgB,iBAAAC,gBAAe,WAAW,qBAAqB,SAAS,QAAQ,gBAAuE;AACvJ,SAAS,YAAY,UAAU,WAAW,YAAY;AACtD,OAAO;AAAA,EACH;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEG;;;AC1BP;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGG;;;ACRP,SAAS,4BAA4B;;;ACsBrC,IAAM,MAAM,KAAK,KAAK;AAGtB,SAAS,SAAS,IAAW,IAAkB;AAC3C,QAAM,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,IAAI;AACjC,QAAM,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,IAAI;AACjC,SAAO;AAAA,IACH,KAAK,KAAK,KAAK;AAAA,IACf,KAAK,KAAK,KAAK;AAAA,IACf,KAAK,KAAK,KAAK;AAAA,IACf,KAAK,KAAK,KAAK;AAAA,IACf,KAAK,KAAK,KAAK,KAAK;AAAA,IACpB,KAAK,KAAK,KAAK,KAAK;AAAA,EACxB;AACJ;AAGA,IAAM,QAAQ;AAEd,SAAS,QAAQ,KAA4B;AACzC,SAAO,IACF,MAAM,QAAQ,EACd,OAAO,OAAK,EAAE,SAAS,CAAC,EACxB,IAAI,MAAM,EACV,OAAO,OAAK,OAAO,SAAS,CAAC,CAAC;AACvC;AAOO,SAAS,qBAAqB,OAAkC;AA3DvE;AA4DI,MAAI;AACJ,QAAM,YAAY;AAElB,MAAI;AACJ,UAAQ,QAAQ,MAAM,KAAK,KAAK,OAAO,MAAM;AACzC,UAAM,KAAK,MAAM,CAAC,EAAE,YAAY;AAChC,UAAM,IAAI,QAAQ,MAAM,CAAC,CAAC;AAC1B,QAAI;AAEJ,YAAQ,IAAI;AAAA,MACR,KAAK;AACD,eAAO,CAAC,GAAG,GAAG,GAAG,GAAG,EAAE,CAAC,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC;AACxC;AAAA,MACJ,KAAK,SAAS;AACV,cAAM,MAAK,OAAE,CAAC,MAAH,YAAQ;AACnB,cAAM,KAAK,EAAE,SAAS,IAAI,EAAE,CAAC,IAAI;AACjC,eAAO,CAAC,IAAI,GAAG,GAAG,IAAI,GAAG,CAAC;AAC1B;AAAA,MACJ;AAAA,MACA,KAAK,UAAU;AACX,cAAM,OAAO,EAAE,CAAC,KAAK,KAAK;AAC1B,cAAM,MAAM,KAAK,IAAI,GAAG,GAAG,MAAM,KAAK,IAAI,GAAG;AAC7C,cAAM,MAAa,CAAC,KAAK,KAAK,CAAC,KAAK,KAAK,GAAG,CAAC;AAC7C,YAAI,EAAE,UAAU,GAAG;AAEf,gBAAM,KAAK,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC;AACzB,iBAAO,SAAS,SAAS,CAAC,GAAG,GAAG,GAAG,GAAG,IAAI,EAAE,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;AAAA,QAC/E,OAAO;AACH,iBAAO;AAAA,QACX;AACA;AAAA,MACJ;AAAA,MACA,KAAK;AACD,eAAO,CAAC,GAAG,GAAG,KAAK,KAAK,EAAE,CAAC,KAAK,KAAK,GAAG,GAAG,GAAG,GAAG,CAAC;AAClD;AAAA,MACJ,KAAK;AACD,eAAO,CAAC,GAAG,KAAK,KAAK,EAAE,CAAC,KAAK,KAAK,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAClD;AAAA,MACJ,KAAK;AACD,YAAI,EAAE,UAAU,EAAG,QAAO,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;AAC7D;AAAA,MACJ;AACI,eAAO;AAAA,IACf;AAEA,QAAI,KAAM,KAAI,IAAI,SAAS,GAAG,IAAI,IAAI;AAAA,EAC1C;AAEA,SAAO;AACX;;;ADnGA,IAAM,sBAA8C;AAAA,EAChD,cAAc;AAClB;AAGA,IAAM,gBAAgB,oBAAI,IAAI,CAAC,SAAS,aAAa,SAAS,SAAS,eAAe,cAAc,CAAC;AAU9F,SAAS,aAAa,UAAsC;AAC/D,MAAI,cAAc,IAAI,QAAQ,EAAG,QAAO;AACxC,QAAM,WAAW,oBAAoB,QAAQ;AAC7C,MAAI,SAAU,QAAO;AAGrB,SAAO,qBAAqB,QAAQ;AACxC;AAMA,IAAM,oBAAoB,oBAAI,IAAI,CAAC,iBAAiB,CAAC;AAO9C,SAAS,cACZ,YACA,OAIA,KAGA,SAAS,OACsB;AAM/B,MAAI,UAAU,eAAe,eAAe,OAAO,UAAU,YAAY,QAAQ,OAAO;AACpF,UAAM,IAAI,qBAAqB,KAAK;AACpC,QAAI,EAAG,QAAO;AAAA,EAClB;AACA,MAAI,kBAAkB,IAAI,UAAU,GAAG;AACnC,UAAM,QAAQ,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,MAAM,GAAG,EAAE,MAAM,KAAK,EAAE,IAAI,MAAM,EAAE,OAAO,OAAK,OAAO,SAAS,CAAC,CAAC;AAG7G,WAAO,MAAM,SAAS,MAAM,IAAI,MAAM,OAAO,KAAK,IAAI;AAAA,EAC1D;AACA,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,MAAM,CAAC;AACb,SAAO,OAAO,SAAS,GAAG,KAAK,OAAO,GAAG,MAAM,QAAQ,MAAM;AACjE;;;ADCO,SAAS,cAAc,KAA4B,MAA+C;AA3EzG;AA4EI,QAAM,SAAS,kBAAkB,GAAG,KAAK,CAAC;AAE1C,QAAM,WAAW,EAAE,OAAO,YAAY;AACtC,QAAM,cAAc,OAAO;AAC3B,MAAI,aAAa;AACjB,MAAI,OAAO,gBAAgB,SAAU,cAAa,eAAe;AACjE,MAAI,gBAAgB,WAAY,cAAa;AAC7C,MAAI,aAAa,EAAG,cAAa;AAEjC,QAAM,UAAS,kCAAM,WAAN,YAAgB;AAC/B,QAAM,cAAa,kCAAM,eAAN,YAAoB;AACvC,QAAM,cAAa,kCAAM,eAAN,YAAoB;AACvC,MAAI,cAAc,KAAK,IAAI,GAAG,KAAK,MAAO,WAAW,MAAQ,UAAU,IAAI,CAAC;AAC5E,MAAI,cAAc,WAAY,eAAc;AAC5C,QAAM,SAAS,YAAY,cAAc;AAIzC,QAAM,UAAU,oBAAI,IAAoB;AACxC,QAAM,YAAY,CAAC,MAAiB;AA/FxC,QAAAC;AAgGQ,QAAI,KAAK,OAAO,EAAE,OAAO,SAAU,SAAQ,IAAI,EAAE,IAAI,OAAO,EAAE,IAAI,CAAC;AACnE,MAACA,MAAA,uBAAG,aAAH,OAAAA,MAAe,CAAC,GAAG,QAAQ,SAAS;AAAA,EACzC;AACA,YAAU,GAAG;AAEb,QAAM,WAAW,sBAAsB,KAAK,iBAAiB,MAAM,KAAK,CAAC;AAEzE,QAAM,WAAmC,CAAC;AAC1C,aAAW,WAAW,UAAU;AAC5B,UAAM,UAAU,QAAQ;AACxB,QAAI,CAAC,WAAW,OAAO,YAAY,YAAY,MAAM,QAAQ,OAAO,EAAG;AAEvE,UAAM,QAAgE,CAAC;AACvE,aAAS,IAAI,GAAG,IAAI,aAAa,KAAK;AAClC,YAAM,IAAI,MAAM,cAAc,IAAI,WAAW,IAAI;AACjD,YAAM,SAAS,oBAAoB,SAAkC,CAAC;AACtE,iBAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AAChD,cAAM,SAAS,aAAa,IAAI;AAChC,YAAI,CAAC,OAAQ;AACb,YAAI,MAAM,MAAM,MAAM;AACtB,YAAI,CAAC,KAAK;AACN,gBAAM,MAAM,MAAM,IAAI,IAAI,MAAM,WAAW;AAI3C,mBAAS,IAAI,GAAG,IAAI,GAAG,IAAK,KAAI,CAAC,IAAI,cAAc,QAAQ,OAAO,QAAQ,IAAI,QAAQ,EAAE,GAAG,MAAM;AAAA,QACrG;AACA,YAAI,CAAC,IAAI,cAAc,QAAQ,OAAO,QAAQ,IAAI,QAAQ,EAAE,GAAG,MAAM;AAAA,MACzE;AAAA,IACJ;AAEA,eAAW,OAAO,OAAO,OAAO,KAAK,GAAG;AACpC,eAAS,IAAI,GAAG,IAAI,aAAa,KAAK;AAClC,YAAI,IAAI,CAAC,MAAM,OAAW,KAAI,CAAC,IAAI,IAAI,IAAI,CAAC;AAAA,MAChD;AAAA,IACJ;AAEA,QAAI,OAAO,KAAK,KAAK,EAAE,SAAS,GAAG;AAC/B,eAAS,KAAK,EAAE,IAAI,QAAQ,IAAI,MAAM,CAAC;AAAA,IAC3C;AAAA,EACJ;AAEA,SAAO;AAAA,IACH;AAAA,IACA;AAAA,IACA,WAAW,OAAO,aAAa;AAAA,IAC/B,OAAO,OAAO,SAAS;AAAA,IACvB,OAAM,YAAO,SAAP,YAAe;AAAA,IACrB,eAAe,CAAC,CAAC,OAAO;AAAA,IACxB;AAAA,IACA;AAAA,IACA;AAAA,EACJ;AACJ;AA2BO,SAAS,YACZ,QACA,KACA,QACA,aACA,SAAS,OACsC;AAC/C;AACA,QAAM,MAAuD,CAAC;AAG9D,MAAI,CAAC,UAAU,CAAC,OAAO,SAAS,EAAE,SAAS,GAAI,QAAO;AAEtD,MAAI,MAAM,KAAK,MAAM,MAAM,MAAM;AACjC,MAAI,MAAM,EAAG,OAAM;AACnB,MAAI,OAAO,YAAa,OAAM,cAAc;AAC5C,aAAW,OAAO,OAAO,OAAO;AAC5B,UAAM,SAAS,OAAO,MAAM,GAAG;AAC/B,QAAI,CAAC,OAAQ;AACb,UAAM,QAAQ,OAAO,GAAG;AACxB,QAAI,UAAU,OAAW;AACzB,UAAM,OAAO,UAAU,QAAQ,cAAc,WAAW;AACxD,QAAI,IAAI,IAAI;AAAA,EAChB;AACA,SAAO;AACX;;;AGpMA;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGG;AACP,SAAS,qBAA4E;;;ACVrF;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,OACG;AAWA,IAAM,oBAAwD;AAAA;AAAA,EAEjE,KAAK;AAAA,EACL,GAAG;AAAA,EACH,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,KAAK;AAAA;AAAA,EAGL,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,MAAM;AAAA,EACN,MAAM;AAAA,EACN,SAAS;AAAA,EACT,UAAU;AAAA,EACV,OAAO;AAAA;AAAA,EAGP,MAAM;AAAA,EACN,OAAO;AAAA,EACP,UAAU;AAAA;AAAA,EAGV,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,MAAM;AAAA,EACN,SAAS;AAAA,EACT,MAAM;AAAA,EACN,UAAU;AAAA,EACV,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMR,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,eAAe;AAAA,EACf,qBAAqB;AAAA,EACrB,aAAa;AAAA,EACb,kBAAkB;AAAA,EAClB,mBAAmB;AAAA,EACnB,mBAAmB;AAAA,EACnB,gBAAgB;AAAA,EAChB,cAAc;AAAA,EACd,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AAAA,EACT,gBAAgB;AAAA,EAChB,SAAS;AAAA,EACT,SAAS;AAAA,EACT,aAAa;AAAA,EACb,cAAc;AAAA,EACd,UAAU;AAAA,EACV,cAAc;AAAA,EACd,oBAAoB;AAAA,EACpB,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,cAAc;AAClB;;;ADhFO,SAAS,UAAU,OAA4B,UAA0B,KAAmC;AAC/G,QAAM,aAAa,mBAAmB,KAAK;AAC3C,QAAM,MAA2B,CAAC;AAClC,aAAW,OAAO,OAAO,KAAK,UAAU,GAAG;AACvC,UAAM,YAAY,uBAAuB,KAAK,WAAW,GAAG,CAAC;AAC7D,QAAI,cAAc,OAAW;AAC7B,UAAM,QAAQ,aAAa,GAAG;AAC9B,QAAI,CAAC,MAAO;AACZ,QAAI,KAAK,IAAI,cAAc,OAAO,OAAO,SAAS,GAAG,GAAG;AAAA,EAC5D;AACA,SAAO;AACX;AAOO,SAAS,aAAa,MAAc,OAA4B,CAAC,GAAG,KAA4C;AAlEvH;AAmEI,MAAI,CAAC,KAAM,QAAO;AAElB,QAAoE,WAA5D,QAAM,UAAU,OAAO,SAAS,MAAM,QArElD,IAqEwE,IAAV,kBAAU,IAAV,CAAlD,QAAM,YAAU,SAAO,WAAS,QAAM;AAC9C,QAAM,MAAM,OAAO,QAAQ,GAAG;AAM9B,QAAM,UAA8B,MAAM;AAC1C,MAAI,YAAY,OAAW,QAAO,MAAM;AAExC,MAAI,0BAA0B,IAAI,IAAI,YAAY,CAAC,GAAG;AAClD,eAAK,aAAL,mBAAe,KAAK,8BAA8B;AAClD,WAAO;AAAA,EACX;AAEA,QAAMC,aAAY,kBAAkB,GAAG;AACvC,MAAI,CAACA,YAAW;AACZ,eAAK,aAAL,mBAAe,KAAK,oDAAoD;AACxE,WAAO;AAAA,EACX;AAGA,QAAM,UAAU,UAAU,OAAO,KAAK,UAAU,GAAG;AACnD,MAAI,YAAY,OAAW,SAAQ,OAAO;AAM1C,QAAM,WAAW,aAAa,OAAO,KAAK,IAAI;AAC9C,MAAI,UAAU;AACV,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,QAAQ,GAAG;AAC3C,YAAM,QAAQ,aAAa,CAAC;AAC5B,UAAI,CAAC,SAAS,SAAS,QAAS;AAChC,YAAM,YAAY,uBAAuB,OAAO,CAAC;AACjD,UAAI,cAAc,OAAW;AAC7B,cAAQ,KAAK,IAAI,cAAc,OAAO,OAAO,SAAS,GAAG,GAAG;AAAA,IAChE;AAAA,EACJ;AAGA,QAAM,cAAkC,MAAM,SAAS,KAAK,MAAM,iBAAiB;AAEnF,MAAI,gBAA2B;AAC/B,MAAI,MAAM,QAAQ,QAAQ,KAAK,SAAS,SAAS,GAAG;AAChD,oBAAgB,SACX,IAAI,CAAC,IAAY,MAAc;AAnH5C,UAAAC;AAqHgB,UAAI;AACA,eAAO,aAAa,IAAI,MAAM,CAAC;AAAA,MACnC,SAAS,GAAG;AACR,SAAAA,MAAA,KAAK,aAAL,gBAAAA,IAAe,KAAK,8BAA8B,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;AAC3F,eAAO;AAAA,MACX;AAAA,IACJ,CAAC,EACA,OAAO,OAAO;AAAA,EACvB,WAAW,gBAAgB,QAAW;AAClC,oBAAgB,OAAO,WAAW;AAAA,EACtC;AAEA,QAAM,aAAY,UAAK,aAAL,8BAAgB,MAAMD,YAAW,SAAS,eAAe;AAC3E,MAAI,cAAc,OAAW,QAAO;AAIpC,SAAO;AAAA,IACHA;AAAA,IACA,QAAQ,SAAY,iCAAK,UAAL,EAAc,IAAI,KAAI;AAAA,IAC1C;AAAA,EACJ;AACJ;;;AEtIA,SAAS,iBAAiD;AA0BnD,IAAM,oBAAN,cAAgC,UAAyC;AAAA,EAAzE;AAAA;AACH,SAAS,QAAe,EAAE,OAAO,KAAK;AAAA;AAAA,EAEtC,OAAO,yBAAyB,OAAqB;AACjD,WAAO,EAAE,MAAM;AAAA,EACnB;AAAA,EAES,kBAAkB,OAAc,MAAuB;AAtCpE;AAuCQ,qBAAK,OAAM,YAAX,4BAAqB,QAAO,kCAAM,mBAAN,YAAwB;AACpD,YAAQ,KAAK,yCAAwC,oCAAO,YAAP,YAAkB,KAAK;AAAA,EAChF;AAAA,EAES,mBAAmB,MAAoC;AAG5D,QAAI,KAAK,MAAM,SAAS,KAAK,aAAa,KAAK,MAAM,UAAU;AAC3D,WAAK,SAAS,EAAE,OAAO,KAAK,CAAC;AAAA,IACjC;AAAA,EACJ;AAAA,EAES,SAAoB;AACzB,UAAM,EAAE,MAAM,IAAI,KAAK;AACvB,QAAI,MAAO,QAAO,KAAK,MAAM,WAAW,KAAK,MAAM,SAAS,KAAK,IAAI;AACrE,WAAO,KAAK,MAAM;AAAA,EACtB;AACJ;;;ACnDA,SAAS,WAAW,wBAAqC;AAYzD,SAAS,aAAa,GAAqB;AACvC,SAAO,OAAO,MAAM,YAAY,OAAO,KAAK,CAAC;AACjD;AAGA,SAAS,SAAS,GAAmB;AACjC,SAAO,EAAE,QAAQ,SAAS,EAAE,EAAE,QAAQ;AAC1C;AAGA,SAAS,SAAS,OAAoC;AAClD,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,UAAU,MAAM,KAAK;AAC3B,SAAO,QAAQ,WAAW,GAAG,IAAI,QAAQ,MAAM,CAAC,IAAI;AACxD;AAEA,SAAS,YAAY,MAA0B,OAA6C,QAAuB;AAjCnH;AAkCI,MAAI,CAAC,KAAM;AACX,QAAM,MAAM,MAAM;AAClB,aAAW,UAAU,UAAK,aAAL,YAAiB,CAAC,EAAI,aAAY,OAAO,OAAO,IAAI;AAC7E;AAuBO,SAAS,0BAA0B,KAAa,UAAkC;AA5DzF;AA8DI,MAAI,cAAc;AAClB,cAAY,KAAK,OAAK;AAAE,QAAI,OAAO,EAAE,IAAI,MAAM,WAAY,eAAc;AAAA,EAAM,CAAC;AAChF,MAAI,CAAC,YAAa,QAAO;AAEzB,QAAM,SAAS,UAAU,GAAG;AAE5B,QAAM,OAAO,oBAAI,IAAoB;AACrC,cAAY,QAAQ,OAAK;AACrB,UAAM,KAAM,EAAU;AACtB,QAAI,OAAO,OAAO,SAAU,MAAK,IAAI,IAAI,CAAC;AAAA,EAC9C,CAAC;AAID,MAAI,SAAQ,YAAO,aAAP,YAAmB,CAAC,GAAG,KAAK,OAAK,OAAO,EAAE,IAAI,MAAM,MAAM;AACtE,QAAM,aAAa,MAAc;AA7ErC,QAAAE;AA8EQ,QAAI,CAAC,MAAM;AACP,aAAO,EAAE,MAAM,QAAQ,UAAU,CAAC,EAAE;AACpC,QAACA,MAAA,OAAO,aAAP,OAAAA,MAAA,OAAO,WAAa,CAAC,GAAG,QAAQ,IAAI;AAAA,IACzC;AACA,WAAO;AAAA,EACX;AAGA,QAAM,aAAa,oBAAI,IAAoB;AAE3C,cAAY,QAAQ,UAAQ;AAxFhC,QAAAA,KAAA;AAyFQ,QAAI,OAAO,KAAK,IAAI,MAAM,WAAY;AAEtC,UAAM,UAAU;AAChB,UAAM,OAAO,QAAQ,SAAS,SAAY,SAAS;AACnD,UAAM,WAAW,SAAS,QAAQ,IAAI,CAAC;AACvC,QAAI,CAAC,SAAU;AAEf,UAAM,SAAS,KAAK,IAAI,QAAQ;AAChC,QAAI,CAAC,UAAU,CAAC,aAAc,OAAe,CAAC,EAAG;AAEjD,QAAI,SAAS,WAAW,IAAI,QAAQ;AACpC,QAAI,CAAC,QAAQ;AACT,YAAM,OAAO,UAAU,MAAM;AAC7B,eAAS,aAAa,iBAAiB;AACvC,WAAK,KAAK;AACV,WAAK,IAAI,SAAS,OAAO,KAAK,CAAC,CAAC;AAGhC,aAAO,KAAK;AACZ,aAAO,KAAK;AAEZ,QAAC,MAAAA,MAAA,WAAW,GAAE,aAAb,YAAAA,IAAa,WAAa,CAAC,GAAG,KAAK,IAAI;AACxC,iBAAW,IAAI,UAAU,MAAM;AAC/B,2CAAU;AAAA,QACN,sCAAsC,WAAW;AAAA;AAAA,IAGzD;AAEA,YAAQ,IAAI,IAAI,MAAM;AAAA,EAC1B,CAAC;AAED,SAAO;AACX;;;AP+EQ;AArCR,IAAM,mBAAmB,SAAS,OAAO;AAEzC,IAAM,yBAAyB,oBAAI,IAA4C;AAE/E,SAAS,qBAAqBC,YAAmD;AAC7E,MAAI,SAAS,uBAAuB,IAAIA,UAAS;AACjD,MAAI,CAAC,QAAQ;AACT,aAAS,SAAS,wBAAwBA,UAAgB;AAC1D,2BAAuB,IAAIA,YAAW,MAAM;AAAA,EAChD;AACA,SAAO;AACX;AAGA,SAAS,kBAAkB;AAAA,EACvB,WAAAA;AAAA,EAAW;AAAA,EAAa;AAAA,EAAU;AAAA,EAAQ;AAAA,EAAU;AAAA,EAAQ;AAChE,GAQG;AACC,QAAM,oBAAoB,QAAQ,MAAM,qBAAqBA,UAAS,GAAG,CAACA,UAAS,CAAC;AAIpF,QAAM,gBAAgB,iBAAiB,MAAM;AAIzC,WAAO,YAAY,QAAQ,SAAS,OAAO,QAAQ,aAAa,gBAAgB;AAAA,EACpF,GAAG,CAAC,QAAQ,QAAQ,WAAW,CAAC;AAEhC,SACI,oBAAC,oDAAsB,cAAtB,EAAmC,eAC/B,WACL;AAER;AAUA,IAAM,gBAAgB,oBAAI,IAAI,CAAC,QAAQ,aAAa,CAAC;AAUrD,IAAM,mBAAmB,oBAAI,IAAI,CAAC,kBAAkB,kBAAkB,GAAG,aAAa,CAAC;AAKvF,SAAS,gBAAgB,MAAc,WAAkD;AAtOzF;AAuOI,QAAM,KAAM,KAAa;AACzB,MAAI,iBAAiB,IAAI,OAAO,KAAK,IAAI,CAAC,KAAK,MAAM,UAAU,IAAI,EAAE,EAAG,QAAO;AAC/E,WAAQ,UAAK,aAAL,YAAiB,CAAC,GAAG,KAAK,OAAK,gBAAgB,GAAG,SAAS,CAAC;AACxE;AAYA,SAAS,eAAe;AAAA,EACpB;AAAA,EAAM;AAAA,EAAW;AAAA,EAAU;AAAA,EAAQ;AAAA,EAAa;AACpD,GAOG;AACC,QAAM,CAAC,KAAK,MAAM,IAAI,SAAS,CAAC;AAEhC;AAAA,IACI,MAAM,KAAK,MAAM,KAAK,MAAM,SAAS,QAAQ,MAAM,IAAI,CAAC,IAAI;AAAA;AAAA,IAC5D,CAAC,MAAM,SAAS;AACZ,UAAI,SAAS,KAAM,SAAQ,MAAM,EAAE,IAAI;AAAA,IAC3C;AAAA,IACA,CAAC,MAAM;AAAA,EACX;AAEA,QAAM,MAAM,KAAK,IAAI,KAAK,IAAI,KAAK,CAAC,GAAG,cAAc,CAAC,IAAI;AAE1D,SAAO,aAAa,MAAM,iCACnB,aADmB;AAAA;AAAA,IAGtB,UAAU,CAAC,GAAGA,YAAW,aAAa,UAAU,QAAQ;AACpD,YAAM,KAAM,EAAU;AACtB,YAAM,SAAS,KAAK,UAAU,IAAI,EAAE,IAAI;AACxC,UAAI,CAAC,OAAQ,QAAO;AAGpB,YAAM,UAAU,YAAY,QAAQ,KAAK,QAAQ,WAAW;AAC5D,aAAOC,eAAcD,YAAW,gDAAK,cAAgB,UAArB,EAA8B,IAAI,IAAG,QAAQ;AAAA,IACjF;AAAA,EACJ,EAAC;AACL;AAuBA,IAAM,eAAiC;AAAA,EACnC,UAAU;AAAA,EAAG,YAAY;AAAA,EAAG,WAAW;AAAA,EAAU,OAAO;AAAA,EACxD,MAAM;AAAA,EAAY,eAAe;AAAA,EAAO,QAAQ;AAAA,EAAG,aAAa;AAAA,EAAG,UAAU,CAAC;AAClF;AAMA,SAAS,gBAAgB,KAA4B,WAAsC;AACvF,QAAM,EAAE,UAAU,OAAO,YAAY,MAAM,WAAW,cAAc,IAAI;AACxE,QAAM,WAAW,oBAAoB,GAAa;AAClD,aAAW,KAAK,SAAU,SAAQ,KAAK,gDAAgD,CAAC;AASxF,MAAI,WAAW,qBAAqB,KAAKE,kBAAiB,KAAK;AAK/D,MAAI,kBAAkB;AAClB,eAAW,0BAA0B,QAAkB;AAAA,EAC3D;AAGA,QAAM,WAAWC,mBAAkB,QAAQ,KAAK,CAAC;AACjD,aAAW,iCACJ,WADI;AAAA,IAEP,UAAU,iCACH,WADG;AAAA,MAEN,UAAU,aAAa,SAAY,WAAW,SAAS;AAAA,MACvD,OAAO,UAAU,SAAY,QAAQ,SAAS;AAAA,MAC9C,YAAY,eAAe,SAAY,aAAa,SAAS;AAAA,MAC7D,MAAM,SAAS,SAAY,OAAO,SAAS;AAAA,MAC3C,WAAW,cAAc,SAAY,YAAY,SAAS;AAAA,MAC1D,eAAe,kBAAkB,SAAY,gBAAgB,SAAS;AAAA,IAC1E;AAAA,EACJ;AAEA,aAAW,eAAe,QAAQ;AAClC,QAAM,SAAS,cAAc,UAAU,EAAE,QAAQ,iBAAiB,CAAC;AACnE,SAAO,EAAE,KAAK,UAAU,QAAQ,OAAO,KAAK;AAChD;AAeO,SAAS,oBAAoB;AAAA,EAChC;AAAA,EAAK;AAAA,EAAU;AAAA,EAAO;AAAA,EAAY;AAAA,EAAM;AAAA,EAAW;AAAA,EAAe,WAAW;AAAA,EAC7E;AAAA,EAAU;AAAA,EAAM;AAAA,EAAO;AAAA,EAAQ;AAAA,EAAM;AAAA,EACrC;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAS;AAAA,EAAU;AAAA,EAAU;AAAA,EAAS;AAC1D,GAAkD;AAnXlD;AAuXI,QAAM,WAAW,QAAQ,MAAgB;AACrC,QAAI;AACA,aAAO;AAAA,QACH;AAAA,QACA,EAAE,UAAU,OAAO,YAAY,MAAM,WAAW,cAAc;AAAA,MAClE;AAAA,IACJ,SAAS,GAAG;AAER,YAAM,QAAQ,aAAa,QAAQ,IAAI,IAAI,MAAM,OAAO,CAAC,CAAC;AAC1D,cAAQ,KAAK,yDAAyD,MAAM,OAAO;AACnF,aAAO,EAAE,KAAK,MAAM,QAAQ,cAAc,MAAM;AAAA,IACpD;AAAA,EACJ,GAAG,CAAC,KAAK,UAAU,OAAO,YAAY,MAAM,WAAW,aAAa,CAAC;AAErE,QAAM,SAA2B,SAAS;AAC1C,QAAM,gBAAgB,OAAO,YAAY,OAAO,eAAe,WAAW,IAAI,OAAO;AAMrF,QAAM,WAAW,eAAe,CAAC;AACjC,QAAM,aAAa,OAAO,KAAK;AAC/B,QAAM,UAAU,OAAO,CAAC;AAGxB,QAAM,kBAAkB,MAAM,QAAQ,UAAU;AAIhD,QAAM,kBAAkB,MAAM;AAC1B,QAAI,OAAO,cAAe,QAAO;AACjC,QAAI,OAAO,SAAS,UAAU,OAAO,SAAS,YAAa,QAAO;AAClE,WAAO,gBAAgB,IAAI,IAAI,OAAO;AAAA,EAC1C;AAEA,QAAM,eAAe,MAAM;AACvB,eAAW,UAAU;AACrB,aAAS,QAAQ,gBAAgB;AACjC;AACA;AAAA,EACJ;AAEA,QAAM,YAAY,CAAC,WAAmB;AAClC,UAAM,MAAM,OAAO;AACnB,UAAM,OAAO,QAAQ,WAAW;AAChC,UAAM,YAAY,OAAO;AACzB,UAAM,QAAQ,KAAK,IAAI,IAAI;AAG3B,UAAM,oBAAoB,OAAO,cAAc,aAAa,OAAO,cAAc;AACjF,UAAM,gBAAgB,YAAY,CAAC,oBAAoB;AACvD,UAAM,aAAa,OAAO,cAAc,eAAe,OAAO,cAAc;AAC5E,UAAM,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,QAAQ,GAAG,CAAC;AAE9C,UAAM,YAAY,gBAAgB,IAAI;AACtC,UAAM,eAAe,KAAK,IAAI,YAAY,IAAI,IAAI;AAClD,UAAM,UAAU,OAAO,eAAe,WAAW,KAAK,OAAO;AAE7D,oBAAgB,QAAQ;AACxB,aAAS,QAAQ,gBAAiB,QAAQ,IAAI,MAAM,OAAS,QAAQ,MAAM,IAAI;AAE/E,UAAM,YAAY,YAAY,IACxB,WAAW,WAAW,EAAE,UAAU,cAAc,QAAQ,OAAO,OAAO,GAAG,CAAC,aAAa;AACrF;AACA,UAAI,SAAU,SAAQ,YAAY,EAAE;AAAA,IACxC,CAAC,IACC;AAAA,MACE,WAAW,WAAW,EAAE,UAAU,cAAc,QAAQ,OAAO,OAAO,CAAC;AAAA,MACvE;AAAA,MAAS;AAAA,MACT,CAAC,aAAa;AACV;AACA,YAAI,SAAU,SAAQ,YAAY,EAAE;AAAA,MACxC;AAAA,IACJ;AAEJ,aAAS,QAAQ,OAAO,QAAQ,KAAK,SAAS,IACxC,UAAU,OAAO,QAAQ,OAAO,SAAS,IACzC;AAEN,eAAW,UAAU;AAAA,EACzB;AAEA,QAAM,MAAqB;AAAA,IACvB,WAAW,MAAM,WAAW;AAAA,IAC5B,MAAM,MAAM;AAIR,gBAAU,SAAS,KAAK;AACxB;AAAA,IACJ;AAAA,IACA,OAAO,MAAM;AACT,sBAAgB,QAAQ;AACxB,iBAAW,UAAU;AACrB;AACA;AAAA,IACJ;AAAA,IACA,QAAQ,MAAM;AACV,sBAAgB,QAAQ;AACxB,eAAS,QAAQ;AACjB,iBAAW,UAAU;AACrB;AACA;AAAA,IACJ;AAAA,IACA,QAAQ,MAAM;AACV,sBAAgB,QAAQ;AACxB,iBAAW,UAAU;AACrB,eAAS,QAAQ,gBAAgB;AACjC;AACA;AAAA,IACJ;AAAA,IACA,iBAAiB,CAAC,SAAiB;AAC/B,UAAI,CAAC,SAAS,IAAI,KAAK,SAAS,GAAG;AAC/B,gBAAQ,KAAK,mDAAmD;AAChE;AAAA,MACJ;AACA,cAAQ,UAAU;AAClB,UAAI,WAAW,QAAS,WAAU,SAAS,KAAK;AAAA,IACpD;AAAA,IACA,gBAAgB,MAAM,SAAS;AAAA,IAC/B,gBAAgB,CAAC,MAAc;AAC3B,YAAM,aAAa,WAAW;AAC9B,sBAAgB,QAAQ;AACxB,iBAAW,UAAU;AACrB,YAAM,UAAU,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,aAAa,CAAC;AACtD,YAAM,kBAAkB,OAAO,WAAW,IACnC,UAAU,OAAO,aAAc,YAAY,IAAI,IAAI,OAAO,YAC3D;AACN,eAAS,QAAQ;AAGjB,UAAI,WAAY,WAAU,eAAe;AAAA,IAC7C;AAAA,EACJ;AAEA,sBAAoB,QAAQ,MAAM,KAAK,CAAC,QAAQ,CAAC;AAIjD,QAAM,UAAU,SAAS,OAAM,KAAAA,mBAAkB,SAAS,GAAG,MAA9B,mBAAiC,UAAU;AAC1E,QAAM,WAAU,wCAAS,YAAT,YAAoB;AACpC,QAAM,aAAY,6CAAiB,mCAAS,cAA1B,YAAuC;AAEzD,YAAU,MAAM;AACZ,QAAI,SAAS,UAAa,WAAW,QAAW;AAC5C,YAAM,SAAS,WAAW,SAAY,UAAU,sBAAQ,KAAK;AAC7D,UAAI,eAAe,MAAM;AACzB;AAAA,IACJ;AACA,QAAI,SAAS,UAAa,UAAU,QAAW;AAC3C,UAAI,QAAQ,CAAC,MAAO,KAAI,KAAK;AAAA,eACpB,MAAO,KAAI,MAAM;AAAA,eACjB,SAAS,MAAO,KAAI,OAAO;AAAA,UAC/B,KAAI,KAAK;AACd;AAAA,IACJ;AAEA,QAAI,YAAY,YAAY,QAAQ;AAChC,UAAI,KAAK;AAAA,IACb;AAAA,EAEJ,GAAG,CAAC,UAAU,UAAU,MAAM,OAAO,MAAM,MAAM,CAAC;AAMlD,QAAM,YAAY,OAAoB,IAAI;AAC1C,QAAM,YAAY,OAAO,KAAK;AAC9B,YAAU,MAAM;AAjiBpB,QAAAC;AAkiBQ,QAAI,CAAC,YAAY,YAAY,iBAAkB;AAC/C,UAAM,aAAYA,MAAA,mCAAS,4BAAT,OAAAA,MAAoC;AACtD,cAAU,UAAU;AAEpB,UAAM,QAAQ,MAAM;AAChB,YAAM,OAAO,UAAU;AACvB,UAAI,CAAC,KAAM;AACX,WAAK,gBAAgB,CAAC,IAAI,GAAG,IAAI,MAAM;AACnC,YAAI,CAAC,EAAG;AACR,cAAM,SAAS,WAAW,IAAI,QAAQ,EAAE;AACxC,cAAM,UAAU,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,MAAM,IAAI,KAAK,IAAI,GAAG,CAAC,CAAC;AACpE,cAAM,QAAQ,UAAU;AACxB,cAAM,OAAO,QAAQ,KAAK,SAAS;AACnC,YAAI,SAAS,UAAU,QAAS;AAChC,kBAAU,UAAU;AACpB,YAAI,MAAM;AACN,cAAI,QAAQ,UAAU,EAAG,KAAI,gBAAgB,KAAK,IAAI,QAAQ,OAAO,CAAC;AACtE,cAAI,KAAK;AAAA,QACb,WAAW,cAAc,QAAS,KAAI,OAAO;AAAA,iBACpC,cAAc,WAAW;AAAE,cAAI,gBAAgB,CAAC,KAAK,IAAI,QAAQ,WAAW,CAAC,CAAC;AAAG,cAAI,KAAK;AAAA,QAAG,WAC7F,cAAc,WAAY,KAAI,MAAM;AAAA,MACjD,CAAC;AAAA,IACL;AAEA,UAAM;AACN,UAAM,KAAK,YAAY,OAAO,GAAG;AACjC,WAAO,MAAM,cAAc,EAAE;AAAA,EAEjC,GAAG,CAAC,UAAU,UAAU,SAAS,SAAS,CAAC;AAG3C,YAAU,MAAM;AACZ,WAAO,MAAM;AACT,sBAAgB,QAAQ;AACxB,iBAAW,UAAU;AAAA,IACzB;AAAA,EAEJ,GAAG,CAAC,QAAQ,CAAC;AAIb,QAAM,YAAY,QAAQ,MAAM;AAC5B,UAAM,MAAM,oBAAI,IAA6B;AAC7C,eAAW,MAAM,OAAO,SAAU,KAAI,IAAI,GAAG,IAAI,EAAE;AACnD,WAAO;AAAA,EACX,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,cAAc,OAAsB,CAAC,CAAC;AAC5C,QAAM,iBAAiB,OAAqB,IAAI;AAChD,QAAM,OAAO,QAAQ,MAAM;AACvB,gBAAY,UAAU,CAAC;AACvB,mBAAe,UAAU;AACzB,QAAI,CAAC,SAAS,IAAK,QAAO;AAE1B,UAAM,aAAkC;AAAA,MACpC,UAAU,YAAY;AAAA,MACtB,MAAM,QAAQ,SAAS,GAAG;AAAA,IAC9B;AACA,QAAI;AACA,aAAO,aAAa,SAAS,KAAe,iCACrC,aADqC;AAAA,QAExC,UAAU,CAAC,MAAMJ,YAAW,aAAa,UAAU,QAAQ;AAIvD,cAAI,gBAAgB,MAAM,SAAS,GAAG;AAClC,mBACI;AAAA,cAAC;AAAA;AAAA,gBAEG;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA,QAAQ,OAAO;AAAA,gBACf,aAAa,OAAO;AAAA,gBACpB;AAAA;AAAA,cANK;AAAA,YAOT;AAAA,UAER;AAEA,gBAAM,KAAM,KAAa;AACzB,gBAAM,WAAW,KAAK,UAAU,IAAI,EAAE,IAAI;AAC1C,cAAI,CAAC,SAAU,QAAO;AACtB,iBACI;AAAA,YAAC;AAAA;AAAA,cAEG,WAAWA;AAAA,cACX;AAAA,cACA,QAAQ;AAAA,cACR;AAAA,cACA,QAAQ,OAAO;AAAA,cACf,aAAa,OAAO;AAAA,cAEnB;AAAA;AAAA,YARI;AAAA,UAST;AAAA,QAER;AAAA,MACJ,EAAC;AAAA,IACL,SAAS,GAAG;AAGR,YAAM,QAAQ,aAAa,QAAQ,IAAI,IAAI,MAAM,OAAO,CAAC,CAAC;AAC1D,qBAAe,UAAU;AACzB,cAAQ,KAAK,wDAAwD,MAAM,OAAO;AAClF,aAAO;AAAA,IACX;AAAA,EAEJ,GAAG,CAAC,UAAU,SAAS,CAAC;AAExB,YAAU,MAAM;AACZ,eAAW,KAAK,YAAY,QAAS,SAAQ,KAAK,yBAAyB,CAAC;AAAA,EAChF,GAAG,CAAC,IAAI,CAAC;AAGT,QAAM,WAAU,cAAS,UAAT,YAAkB,eAAe;AACjD,YAAU,MAAM;AACZ,QAAI,QAAS,oCAAU;AAAA,EAE3B,GAAG,CAAC,OAAO,CAAC;AAEZ,MAAI,QAAS,QAAO,WAAW,SAAS,OAAO,IAAI;AAMnD,MAAI,UAA+B;AAEnC,MAAI,YAAY,YAAY,oBAAoB,MAAM;AAElD,cAAU,oBAAC,QAAK,KAAK,WAAW,aAAa,OAAQ,gBAAK;AAAA,EAC9D,WAAW,YAAY,YAAY,WAAW,MAAM;AAChD,cACI;AAAA,MAAC;AAAA;AAAA,QACG,SAAS,MAAM;AACX,cAAI,WAAW,SAAS;AACpB,gBAAI,cAAc,QAAS,KAAI,OAAO;AAAA,qBAC7B,cAAc,WAAW;AAAE,kBAAI,gBAAgB,CAAC,KAAK,IAAI,QAAQ,WAAW,CAAC,CAAC;AAAG,kBAAI,KAAK;AAAA,YAAG,WAC7F,cAAc,WAAY,KAAI,MAAM;AAAA,UACjD,OAAO;AACH,gBAAI,QAAQ,UAAU,EAAG,KAAI,gBAAgB,KAAK,IAAI,QAAQ,OAAO,CAAC;AACtE,gBAAI,KAAK;AAAA,UACb;AAAA,QACJ;AAAA,QAEC;AAAA;AAAA,IACL;AAAA,EAER;AAKA,SACI,oBAAC,qBAAkB,SAAkB,UAChC,mBACL;AAER;AAEA,IAAO,8BAAQ;","names":["getAnimatorConfig","PxAnimatorEngine","createElement","_a","Component","_a","_a","Component","createElement","PxAnimatorEngine","getAnimatorConfig","_a"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixodesk/svg-animator-rn",
3
- "version": "1.0.22",
3
+ "version": "1.0.26",
4
4
  "description": "Pixodesk SVG animator for React Native — renders animator documents via react-native-svg, driven natively by react-native-reanimated",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -26,7 +26,7 @@
26
26
  "src"
27
27
  ],
28
28
  "dependencies": {
29
- "@pixodesk/svg-animator-core": "^1.0.22"
29
+ "@pixodesk/svg-animator-core": "^1.0.26"
30
30
  },
31
31
  "peerDependencies": {
32
32
  "react": ">=18",
@@ -316,14 +316,14 @@ function compileDocument(doc: PxAnimatedSvgDocument, overrides: ConfigOverrides)
316
316
  const warnings = validateNodeEffects(doc as PxNode);
317
317
  for (const w of warnings) console.warn('[PixodeskSvgAnimator] effects shape warning:', w);
318
318
 
319
- // `webapi` = the FULLY-FLATTENED materialisation: effects + loops +
319
+ // `waapi` = the FULLY-FLATTENED materialisation: effects + loops +
320
320
  // sampled motion paths + animated `<use>` inlined into real `<g>`
321
321
  // clones + orphaned defs pruned. That last part is why RN must not use
322
322
  // the `frames` flavour: frames keeps `<use href="#animatedTarget">`
323
323
  // live references, which only work because the DOM propagates
324
324
  // attribute writes through `<use>` shadow trees. react-native-svg has
325
325
  // no such live propagation, so an animated `<use>` would render frozen.
326
- let prepared = materialiseAllInTree(doc, PxAnimatorEngine.webapi);
326
+ let prepared = materialiseAllInTree(doc, PxAnimatorEngine.waapi);
327
327
 
328
328
  // Sidestep a react-native-svg NATIVE crash (see PxRnSafety). Guarded on
329
329
  // the platform because the DOM renders this case correctly and the web
@@ -70,11 +70,12 @@ export function renderRnNode(node: PxNode, opts: RenderRnNodeOptions = {}, key?:
70
70
  const { type, children, style, animate, meta, effects, ...props } = node as any;
71
71
  const tag = String(type || 'g');
72
72
 
73
- // `feFuncR/G/B/A` carry their SVG `type` attribute (identity/table/…) under
74
- // `funcType`, because the wire format reserves `type` for the node tag.
73
+ // ESCAPE KEY (S2): elements whose SVG `type` ATTRIBUTE collides with the reserved
74
+ // `type` node-tag key carry it under `domType` `feColorMatrix` (matrix/saturate/…),
75
+ // `feTurbulence` (fractalNoise/turbulence), `feFunc*` (identity/table/…).
75
76
  // Restore it as a real prop, mirroring the web renderer.
76
- const feFuncType: string | undefined = props.funcType;
77
- if (feFuncType !== undefined) delete props.funcType;
77
+ const domType: string | undefined = props.domType;
78
+ if (domType !== undefined) delete props.domType;
78
79
 
79
80
  if (DISALLOWED_SVG_TAGS_LOWER.has(tag.toLowerCase())) {
80
81
  opts.warnings?.push('tag blocked (dangerous): ' + tag);
@@ -89,7 +90,7 @@ export function renderRnNode(node: PxNode, opts: RenderRnNodeOptions = {}, key?:
89
90
 
90
91
  // NB: `key` is never written into this object — see `decorate` above.
91
92
  const rnProps = toRnProps(props, opts.warnings, tag);
92
- if (feFuncType !== undefined) rnProps.type = feFuncType;
93
+ if (domType !== undefined) rnProps.type = domType;
93
94
 
94
95
  // `node.style` — a named preset from `definitions.styles`, or an inline
95
96
  // record. react-native-svg has no CSS, so the resolved declarations are
@@ -156,7 +156,7 @@ describe('length-list props (stroke-dasharray)', () => {
156
156
  effects: { trimPath: { range: { keyframes: [{ time: 0, value: [0, 0.1] }, { time: 1000, value: [0, 1] }] } } },
157
157
  }],
158
158
  };
159
- const materialised = generateNewIds(materialiseAllInTree(doc, PxAnimatorEngine.webapi));
159
+ const materialised = generateNewIds(materialiseAllInTree(doc, PxAnimatorEngine.waapi));
160
160
  const tracks = compileTracks(materialised);
161
161
  const el = tracks.elements.find(e => 'strokeDasharray' in e.props)!;
162
162
  expect(el).toBeDefined();
@@ -167,7 +167,7 @@ describe('length-list props (stroke-dasharray)', () => {
167
167
  });
168
168
  });
169
169
 
170
- describe('animated <use> flattening (webapi materialisation)', () => {
170
+ describe('animated <use> flattening (waapi materialisation)', () => {
171
171
  it('inlines animated <use> clones so no live references remain', () => {
172
172
  const doc: PxAnimatedSvgDocument = {
173
173
  type: 'svg', viewBox: '0 0 300 200',
@@ -178,10 +178,10 @@ describe('animated <use> flattening (webapi materialisation)', () => {
178
178
  animate: { cy: { keyframes: [{ time: 0, value: 40 }, { time: 2000, value: 160 }] } },
179
179
  }] }] },
180
180
  { type: 'use', id: 'u1', href: '#sym' },
181
- { type: 'use', id: 'u2', href: '#sym', x: 80, effects: { clone: { baseId: 'sym', retime: { start: -600 } } } },
181
+ { type: 'use', id: 'u2', href: '#sym', x: 80, effects: { clone: { sourceId: '#sym', retime: { start: -600 } } } },
182
182
  ],
183
183
  };
184
- const materialised = generateNewIds(materialiseAllInTree(doc, PxAnimatorEngine.webapi));
184
+ const materialised = generateNewIds(materialiseAllInTree(doc, PxAnimatorEngine.waapi));
185
185
  const countUse = (n: any): number =>
186
186
  (n.type === 'use' ? 1 : 0) + (n.children || []).reduce((s: number, c: any) => s + countUse(c), 0);
187
187
  expect(countUse(materialised)).toBe(0);