@onlynative/inertia-svg 0.0.1-alpha.6 → 0.0.1-alpha.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/llms.txt +156 -0
  3. package/package.json +4 -3
package/CHANGELOG.md ADDED
@@ -0,0 +1,16 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@onlynative/inertia-svg` are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Pre-`1.0`, breaking changes may land in minor versions and are called out under their release.
4
+
5
+ This package ships in lockstep with `@onlynative/inertia` — version numbers track the core release that introduced or last touched the adapter.
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.0.1-alpha.6] — 2026-05-22
10
+
11
+ ### Added
12
+
13
+ - `MotionPath` over `react-native-svg`. Animatable: `d` (element-wise scalar interpolation on structurally-compatible paths), `fill`, `stroke`, `strokeWidth`, opacities, `strokeDashoffset`. Source and target paths must share the same command sequence after implicit-repeat expansion; remount with `key` to switch shape.
14
+
15
+ [unreleased]: https://github.com/onlynative/inertia/compare/v0.0.1-alpha.6...HEAD
16
+ [0.0.1-alpha.6]: https://github.com/onlynative/inertia/releases/tag/v0.0.1-alpha.6
package/llms.txt ADDED
@@ -0,0 +1,156 @@
1
+ > @onlynative/inertia-svg — adapter package for @onlynative/inertia.
2
+ > This file is generated from the matching docs page by scripts/build-llms.mjs — do not edit by hand.
3
+
4
+ > Full docs: https://onlynative.github.io/inertia/
5
+ > Core overview: see @onlynative/inertia/llms.txt (or docs/static/llms.txt in the repo)
6
+ > Source: https://github.com/onlynative/inertia
7
+
8
+ ---
9
+ # SVG
10
+
11
+ `@onlynative/inertia-svg` adds animatable SVG primitives built on [`react-native-svg`](https://github.com/software-mansion/react-native-svg). It is an **optional** sibling package — install it only when you need to morph paths or animate `fill` / `stroke`. The core library has no required `react-native-svg` dependency.
12
+
13
+ `MotionPath` wraps `<Path>` and accepts the same `initial` / `animate` / `transition` shape as the core `Motion.*` primitives, with animatable keys for the path data (`d`) plus color and numeric paint properties.
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ yarn add @onlynative/inertia-svg react-native-svg
19
+ ```
20
+
21
+ `react-native-svg` works in bare React Native projects as well as Expo.
22
+
23
+ ## Usage
24
+
25
+ ```tsx
26
+ import Svg from 'react-native-svg'
27
+ import { MotionPath } from '@onlynative/inertia-svg'
28
+
29
+ function Toggle({ open }) {
30
+ return (
31
+ <Svg viewBox="0 0 100 100" width={120} height={120}>
32
+ <MotionPath
33
+ d="M 20 30 L 50 60 L 80 30 L 80 30 L 50 60 L 20 30"
34
+ animate={{
35
+ d: open
36
+ ? 'M 20 30 L 50 60 L 80 30 L 80 30 L 50 60 L 20 30'
37
+ : 'M 20 50 L 50 20 L 80 50 L 80 50 L 50 80 L 20 50',
38
+ fill: open ? '#0ea5e9' : '#1f2937',
39
+ }}
40
+ transition={{ type: 'spring', tension: 140, friction: 12 }}
41
+ fill="#1f2937"
42
+ />
43
+ </Svg>
44
+ )
45
+ }
46
+ ```
47
+
48
+ The static `d` prop is required. Its **command sequence is locked at first render** — every target `d` you pass via `animate` or `initial` must produce the same command letters in the same order after implicit-repeat expansion. Element-wise scalar interpolation is the entire morphing model.
49
+
50
+ ## Structural compatibility
51
+
52
+ Two paths are morphable iff their normalized template (command letters, in order, with case preserved) is equal. Examples:
53
+
54
+ ```
55
+ ✅ M 0 0 L 10 10 Z ↔ M 50 50 L 80 80 Z same: M L Z
56
+ ✅ M 0 0 L 10 10 L 20 20 ↔ M 0 0 50 50 60 60 same: M L L
57
+ (implicit repeats after M expand to L)
58
+ ❌ M 0 0 L 10 10 Z ↔ M 0 0 L 10 10 differs: count
59
+ ❌ M 0 0 L 10 10 ↔ M 0 0 l 10 10 differs: absolute L vs relative l
60
+ ❌ M 0 0 L 10 10 ↔ M 0 0 C 1 1 2 2 3 3 differs: L vs C
61
+ ```
62
+
63
+ The component throws in dev when the templates diverge — either at mount (if `initial.d` mismatches the static `d`), when `animate.d` changes shape, or when the static `d` prop itself changes shape between renders. In production those throws degrade to a no-op snap so a single bad target doesn't crash the screen, but you should treat dev errors as bugs.
64
+
65
+ To switch between structurally different shapes, **remount with a new `key`**:
66
+
67
+ ```tsx
68
+ <MotionPath
69
+ key={open ? 'hexagon' : 'circle'}
70
+ d={open ? HEXAGON_D : CIRCLE_AS_QUADS_D}
71
+ />
72
+ ```
73
+
74
+ Path normalization that resamples between arbitrary shapes (the flubber-style approach) is out of scope for v0.2.
75
+
76
+ ## Animatable props
77
+
78
+ | Key | Shape | Notes |
79
+ | ------------------ | -------- | --------------------------------------------------------------------------------------------------------------------------- |
80
+ | `d` | `string` | Path data. Source and target must share the same template — see above. Each scalar param springs / times independently. |
81
+ | `fill` | `string` | Color, interpolated via Reanimated's color setter. Defaults to `'transparent'` if neither static nor `initial` is supplied. |
82
+ | `stroke` | `string` | Same as `fill`. |
83
+ | `strokeWidth` | `number` | Numeric. Default seed `1`. |
84
+ | `strokeOpacity` | `number` | Numeric, 0–1. |
85
+ | `fillOpacity` | `number` | Numeric, 0–1. |
86
+ | `opacity` | `number` | Numeric, 0–1. |
87
+ | `strokeDashoffset` | `number` | Useful for "draw" animations on a dashed stroke. |
88
+
89
+ Per-property transitions work just like the core primitives:
90
+
91
+ ```tsx
92
+ <MotionPath
93
+ d={SOURCE_D}
94
+ fill="#000"
95
+ animate={{ d: TARGET_D, fill: '#7c3aed' }}
96
+ transition={{
97
+ d: { type: 'spring', tension: 160, friction: 14 },
98
+ fill: { type: 'timing', duration: 300 },
99
+ }}
100
+ />
101
+ ```
102
+
103
+ ## `initial`
104
+
105
+ Pass `initial` to override the mount-frame values (so the component starts somewhere other than the static props), or `initial={false}` to start at the `animate` target with no mount animation.
106
+
107
+ ```tsx
108
+ <MotionPath
109
+ d={STAR_D}
110
+ initial={{ d: TINY_STAR_D, opacity: 0 }} // hatch from a smaller star, fading in
111
+ animate={{ d: STAR_D, opacity: 1 }}
112
+ />
113
+
114
+ <MotionPath
115
+ d={STAR_D}
116
+ initial={false} // skip the mount animation
117
+ animate={{ d: HEART_D }}
118
+ />
119
+ ```
120
+
121
+ If `initial.d` is provided, it must be template-compatible with the static `d` — same rule as `animate.d`.
122
+
123
+ ## Reduced motion
124
+
125
+ `MotionPath` participates in [`<MotionConfig reducedMotion>`](./motion-config.md) the same way the core primitives do — when the OS reduce-motion setting is on (or you pass `reducedMotion="always"`), transitions resolve as direct assignment instead of `withSpring` / `withTiming`.
126
+
127
+ ## What this primitive doesn't do (v0.2)
128
+
129
+ - **Path resampling** between structurally different shapes. Same-template morphs only — the rest is your `key` to remount.
130
+ - **Other SVG shapes** (`Circle`, `Rect`, `Line`, `Ellipse`). They land in a follow-up release; pencil them in if you need them.
131
+ - **Gradient fills inside the SVG**. For gradient fills use `<Defs>` + `<LinearGradient>` from `react-native-svg` and animate the stops via [`MotionLinearGradient`](./gradients.mdx)'s patterns; the path itself just references the gradient by `url(#id)`.
132
+ - **Path command interpolation** (e.g. morphing an `L` into a `C`). Element-wise scalar interpolation is intentional — it's predictable, cheap, and matches what designers reach for 95% of the time.
133
+
134
+ ## Path utilities
135
+
136
+ The tokenizer and template helpers are exported for downstream tooling:
137
+
138
+ ```ts
139
+ import {
140
+ parsePathD,
141
+ templateOf,
142
+ diffTemplate,
143
+ flattenParams,
144
+ serializePath,
145
+ } from '@onlynative/inertia-svg'
146
+
147
+ const segs = parsePathD('M 0 0 L 10 10 Z') // [{ cmd: 'M', args: [0, 0] }, …]
148
+ const t = templateOf(segs) // { cmds: ['M','L','Z'], widths: [2,2,0], size: 4 }
149
+ const params = flattenParams(segs) // [0, 0, 10, 10]
150
+ const out = serializePath(t, [5, 5, 20, 20]) // 'M 5 5L 20 20Z'
151
+
152
+ const err = diffTemplate(t, templateOf(parsePathD('M 0 0 L 1 1')))
153
+ // → 'command count differs: …'
154
+ ```
155
+
156
+ `serializePath` is a worklet — call it inside `useAnimatedProps` if you build your own SVG primitives on top of this layer.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onlynative/inertia-svg",
3
- "version": "0.0.1-alpha.6",
3
+ "version": "0.0.1-alpha.7",
4
4
  "description": "Animatable SVG primitives (path morphing, fill/stroke) for @onlynative/inertia, built on react-native-svg.",
5
5
  "license": "MIT",
6
6
  "author": "OnlyNative",
@@ -41,6 +41,7 @@
41
41
  "files": [
42
42
  "dist",
43
43
  "src",
44
+ "llms.txt",
44
45
  "README.md",
45
46
  "LICENSE",
46
47
  "CHANGELOG.md",
@@ -48,7 +49,7 @@
48
49
  "!**/*.test.*"
49
50
  ],
50
51
  "peerDependencies": {
51
- "@onlynative/inertia": ">=0.0.1-alpha.6",
52
+ "@onlynative/inertia": ">=0.0.1-alpha.7",
52
53
  "react": ">=19.0.0",
53
54
  "react-native": ">=0.81.0",
54
55
  "react-native-reanimated": ">=4.0.0",
@@ -67,7 +68,7 @@
67
68
  "react-test-renderer": "19.1.0",
68
69
  "tsup": "^8.3.5",
69
70
  "typescript": "^5.7.3",
70
- "@onlynative/inertia": "0.0.1-alpha.6"
71
+ "@onlynative/inertia": "0.0.1-alpha.7"
71
72
  },
72
73
  "publishConfig": {
73
74
  "access": "public"