@rootnative/inertia 0.0.0-alpha.2 → 0.0.0-alpha.4

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/CHANGELOG.md CHANGED
@@ -4,6 +4,18 @@ All notable changes to `@rootnative/inertia` are documented here. The format fol
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.0.0-alpha.2] - 2026-07-20
8
+
9
+ ### Added
10
+
11
+ - **`useGestureLayer` returns per-state progress** — the result now carries `states: GestureLayerProgress`, the five 0↔1 progress shared values behind the composed style (`hovered` / `focused` / `focusVisible` / `pressed` from the underlying `useGesture`, plus the hook-owned `disabled` progress). Lets styles derived from the same gesture wiring — an elevation crossfade via `useShadow({ from, to, progress: states.hovered })`, an icon tint — reuse the hook's progress values instead of duplicating the cascade through a parallel `useGesture` call. Purely additive; the exposed shared values are identity-stable across renders and are the same objects the worklet reads (treat as read-only — the handlers own the writes). The `GestureLayerProgress` type is exported from the `/gesture-layer` subpath.
12
+
13
+ ### Changed
14
+
15
+ - Published bundles no longer include sourcemaps, and the `__type-tests__` directories are excluded from the npm package (packaging-only; no runtime change).
16
+
17
+ ## [0.0.0-alpha.1] - 2026-07-19
18
+
7
19
  ### Added
8
20
 
9
21
  - **Named transition registry** — `<MotionConfig transitions={{ name: TransitionConfig }}>` registers named transitions for the subtree; the name is accepted everywhere a `TransitionConfig` is: the `transition` prop (top-level, per-property, per gesture layer), the `layout` prop, and `useAnimation` / `useSpring` / `useBooleanSpring` / `useGesture` / `useGestureLayer`. Names resolve at the nearest provider; nested providers merge with child-overrides-per-name; unknown names warn in dev and fall back to the default spring. No presets ship — names are consumer vocabulary. New exports: `useNamedTransitions()`, `resolveNamedTransition()`, and the `TransitionName` / `TransitionInput` / `NamedTransitions` / `RegisteredTransitions` types (`RegisteredTransitions` is the augmentation point for compile-time-typed names).
@@ -39,5 +51,7 @@ Initial alpha publish. The full v0.1 surface is in place; APIs are still subject
39
51
  - SVG path morphing, gradient interpolation, and shared-element transitions across screens are out of scope until `0.2.x` / `1.x` per the roadmap.
40
52
  - `react-native-gesture-handler` integration (drag, pan, swipe sub-states) lands in `0.2` via the optional `@rootnative/inertia-gestures` adapter.
41
53
 
42
- [unreleased]: https://github.com/rootnative/inertia/compare/v0.0.0-alpha.0...HEAD
54
+ [unreleased]: https://github.com/rootnative/inertia/compare/core+gestures+gradients+svg@0.0.0-alpha.2...HEAD
55
+ [0.0.0-alpha.2]: https://github.com/rootnative/inertia/releases/tag/core+gestures+gradients+svg@0.0.0-alpha.2
56
+ [0.0.0-alpha.1]: https://github.com/rootnative/inertia/releases/tag/core+gestures+gradients+svg@0.0.0-alpha.1
43
57
  [0.0.0-alpha.0]: https://github.com/rootnative/inertia/releases/tag/v0.0.0-alpha.0
@@ -0,0 +1,8 @@
1
+ 'use strict';
2
+
3
+ var chunk6UQ4KA6V_js = require('./chunk-6UQ4KA6V.js');
4
+ var reactNative = require('react-native');
5
+
6
+ var MotionScrollView = chunk6UQ4KA6V_js.createMotionComponent(reactNative.ScrollView);
7
+
8
+ exports.MotionScrollView = MotionScrollView;
@@ -0,0 +1,113 @@
1
+ 'use strict';
2
+
3
+ var chunkSFRNO6AW_js = require('./chunk-SFRNO6AW.js');
4
+ var react = require('react');
5
+ var reactNativeReanimated = require('react-native-reanimated');
6
+ var jsxRuntime = require('react/jsx-runtime');
7
+ var reactNative = require('react-native');
8
+
9
+ var DEFAULT_MOTION_CONFIG = {
10
+ reducedMotion: "user",
11
+ transitions: {}
12
+ };
13
+ var MotionConfigContext = react.createContext(
14
+ DEFAULT_MOTION_CONFIG
15
+ );
16
+ function useMotionConfig() {
17
+ return react.useContext(MotionConfigContext);
18
+ }
19
+ function useNamedTransitions() {
20
+ return useMotionConfig().transitions;
21
+ }
22
+ function useShouldReduceMotion() {
23
+ const { reducedMotion } = useMotionConfig();
24
+ const osReduced = reactNativeReanimated.useReducedMotion();
25
+ if (reducedMotion === "never") return false;
26
+ if (reducedMotion === "always") return true;
27
+ return osReduced;
28
+ }
29
+ function MotionConfig({
30
+ reducedMotion,
31
+ transitions,
32
+ children
33
+ }) {
34
+ const parent = useMotionConfig();
35
+ const transitionsSig = chunkSFRNO6AW_js.stableSig(transitions);
36
+ const value = react.useMemo(
37
+ () => ({
38
+ reducedMotion: reducedMotion ?? parent.reducedMotion,
39
+ transitions: transitions ? { ...parent.transitions, ...transitions } : parent.transitions
40
+ }),
41
+ // eslint-disable-next-line react-hooks/exhaustive-deps
42
+ [reducedMotion, transitionsSig, parent]
43
+ );
44
+ return /* @__PURE__ */ jsxRuntime.jsx(MotionConfigContext.Provider, { value, children });
45
+ }
46
+
47
+ // src/config/namedTransitions.ts
48
+ var UNKNOWN_NAME_FALLBACK = { type: "spring" };
49
+ function lookupNamedTransition(name, registry) {
50
+ const cfg = registry[name];
51
+ if (cfg) return cfg;
52
+ if (__DEV__) {
53
+ console.warn(
54
+ `[inertia] Unknown transition name "${name}" \u2014 falling back to the default spring. Register it on a provider: <MotionConfig transitions={{ '${name}': { ... } }}>.`
55
+ );
56
+ }
57
+ return UNKNOWN_NAME_FALLBACK;
58
+ }
59
+ function resolveNamedTransition(input, registry) {
60
+ if (input === void 0) return void 0;
61
+ if (typeof input === "string") return lookupNamedTransition(input, registry);
62
+ return input;
63
+ }
64
+ function resolveNamedTransitionProp(transition, registry) {
65
+ if (transition === void 0) return void 0;
66
+ if (typeof transition === "string") {
67
+ return lookupNamedTransition(transition, registry);
68
+ }
69
+ if (chunkSFRNO6AW_js.isTopLevelTransition(transition)) return transition;
70
+ const map = transition;
71
+ let out = null;
72
+ for (const key in map) {
73
+ const value = map[key];
74
+ if (typeof value === "string") {
75
+ if (out === null) out = { ...map };
76
+ out[key] = lookupNamedTransition(value, registry);
77
+ }
78
+ }
79
+ return out ?? transition;
80
+ }
81
+ var modality = "keyboard";
82
+ var installed = false;
83
+ function setKeyboard() {
84
+ modality = "keyboard";
85
+ }
86
+ function setPointer() {
87
+ modality = "pointer";
88
+ }
89
+ function ensureInstalled() {
90
+ if (installed) return;
91
+ if (reactNative.Platform.OS !== "web") return;
92
+ if (typeof document === "undefined") return;
93
+ document.addEventListener("keydown", setKeyboard, true);
94
+ document.addEventListener("mousedown", setPointer, true);
95
+ document.addEventListener("pointerdown", setPointer, true);
96
+ document.addEventListener("touchstart", setPointer, true);
97
+ installed = true;
98
+ }
99
+ ensureInstalled();
100
+ function isFocusVisible() {
101
+ if (reactNative.Platform.OS !== "web") return true;
102
+ ensureInstalled();
103
+ return modality === "keyboard";
104
+ }
105
+
106
+ exports.MotionConfig = MotionConfig;
107
+ exports.isFocusVisible = isFocusVisible;
108
+ exports.lookupNamedTransition = lookupNamedTransition;
109
+ exports.resolveNamedTransition = resolveNamedTransition;
110
+ exports.resolveNamedTransitionProp = resolveNamedTransitionProp;
111
+ exports.useMotionConfig = useMotionConfig;
112
+ exports.useNamedTransitions = useNamedTransitions;
113
+ exports.useShouldReduceMotion = useShouldReduceMotion;
@@ -0,0 +1,257 @@
1
+ import { isWorkletFunction } from 'react-native-worklets';
2
+ import { withSequence, Easing, withDecay, withTiming, withSpring, withRepeat, withDelay } from 'react-native-reanimated';
3
+
4
+ // src/transitions/easing.ts
5
+ function ensureWorkletEasing(easing) {
6
+ if (!easing) return void 0;
7
+ const fn = isEasingFactory(easing) ? easing.factory() : easing;
8
+ if (isWorkletFunction(fn)) return fn;
9
+ const wrapped = (t) => {
10
+ "worklet";
11
+ return fn(t);
12
+ };
13
+ return wrapped;
14
+ }
15
+ function isEasingFactory(value) {
16
+ return typeof value === "object" && value !== null && "factory" in value && typeof value.factory === "function";
17
+ }
18
+
19
+ // src/transitions/spring.ts
20
+ var DEFAULT_SPRING = {
21
+ tension: 170,
22
+ friction: 26,
23
+ mass: 1
24
+ };
25
+ function springToReanimated(t) {
26
+ "worklet";
27
+ return {
28
+ stiffness: t.tension ?? DEFAULT_SPRING.tension,
29
+ damping: t.friction ?? DEFAULT_SPRING.friction,
30
+ mass: t.mass ?? DEFAULT_SPRING.mass,
31
+ velocity: t.velocity,
32
+ restSpeedThreshold: t.restSpeedThreshold,
33
+ restDisplacementThreshold: t.restDisplacementThreshold
34
+ };
35
+ }
36
+
37
+ // src/transitions/resolve.ts
38
+ var DEFAULT_TIMING_DURATION = 250;
39
+ function buildSpring(cfg, toValue, cb) {
40
+ return withSpring(toValue, springToReanimated(cfg), cb);
41
+ }
42
+ function buildTiming(cfg, toValue, cb) {
43
+ return withTiming(
44
+ toValue,
45
+ {
46
+ duration: cfg.duration ?? DEFAULT_TIMING_DURATION,
47
+ easing: ensureWorkletEasing(cfg.easing) ?? Easing.inOut(Easing.ease)
48
+ },
49
+ cb
50
+ );
51
+ }
52
+ function buildDecay(cfg, cb) {
53
+ return withDecay(
54
+ {
55
+ velocity: cfg.velocity ?? 0,
56
+ deceleration: cfg.deceleration,
57
+ clamp: cfg.clamp
58
+ },
59
+ cb
60
+ );
61
+ }
62
+ function buildOne(cfg, toValue, cb) {
63
+ if (cfg.type === "no-animation") {
64
+ if (cb) cb(true, toValue);
65
+ return toValue;
66
+ }
67
+ if (cfg.type === "decay") return buildDecay(cfg, cb);
68
+ if (cfg.type === "timing") return buildTiming(cfg, toValue, cb);
69
+ return buildSpring(cfg, toValue, cb);
70
+ }
71
+ function applyRepeat(animation, repeat) {
72
+ if (repeat === void 0) return animation;
73
+ if (repeat === "infinite") {
74
+ return withRepeat(animation, -1, true);
75
+ }
76
+ if (typeof repeat === "number") {
77
+ return withRepeat(animation, repeat, true);
78
+ }
79
+ const count = repeat.count === "infinite" ? -1 : repeat.count;
80
+ const alternate = repeat.alternate ?? true;
81
+ return withRepeat(animation, count, alternate);
82
+ }
83
+ function applyDelay(animation, delay) {
84
+ if (!delay || delay <= 0) return animation;
85
+ return withDelay(delay, animation);
86
+ }
87
+ function resolveTransition(config, toValue, callback) {
88
+ const cfg = config ?? { type: "spring" };
89
+ const base = buildOne(cfg, toValue, callback);
90
+ const repeated = applyRepeat(base, repeatOf(cfg));
91
+ return applyDelay(repeated, delayOf(cfg));
92
+ }
93
+ function repeatOf(cfg) {
94
+ if (cfg.type === "no-animation" || cfg.type === "decay") return void 0;
95
+ return cfg.repeat;
96
+ }
97
+ function stripRepeat(cfg) {
98
+ if (!cfg) return cfg;
99
+ if (cfg.type === "no-animation" || cfg.type === "decay") return cfg;
100
+ if (cfg.repeat === void 0) return cfg;
101
+ const next = { ...cfg };
102
+ delete next.repeat;
103
+ return next;
104
+ }
105
+ function delayOf(cfg) {
106
+ if (cfg.type === "no-animation") return void 0;
107
+ return cfg.delay;
108
+ }
109
+ function isStepObject(v) {
110
+ return typeof v === "object" && v !== null && !Array.isArray(v) && "to" in v;
111
+ }
112
+ function resolveAnimatableValue(value, base, factory) {
113
+ if (Array.isArray(value)) {
114
+ const steps = value;
115
+ const stepBase = stripRepeat(base);
116
+ const animations = steps.map(
117
+ (step2, i) => resolveStep(step2, stepBase, factory?.("step", i))
118
+ );
119
+ const seq = withSequence(...animations);
120
+ return applyRepeat(seq, base ? repeatOf(base) : void 0);
121
+ }
122
+ const step = value;
123
+ const cb = factory?.("animation", void 0);
124
+ if (isStepObject(step)) {
125
+ return resolveStep(step, base, cb);
126
+ }
127
+ return resolveTransition(base, step, cb);
128
+ }
129
+ function resolveStep(step, base, cb) {
130
+ if (isStepObject(step)) {
131
+ const { to, ...override } = step;
132
+ const merged = mergeTransition(base, override);
133
+ return resolveTransition(merged, to, cb);
134
+ }
135
+ return resolveTransition(base, step, cb);
136
+ }
137
+ function mergeTransition(base, override) {
138
+ if (override.type && base && override.type !== base.type) {
139
+ return override;
140
+ }
141
+ return { ...base ?? { type: "spring" }, ...override };
142
+ }
143
+ var CSS_KEYWORDS = {
144
+ ease: [0.25, 0.1, 0.25, 1],
145
+ "ease-in": [0.42, 0, 1, 1],
146
+ "ease-out": [0, 0, 0.58, 1],
147
+ "ease-in-out": [0.42, 0, 0.58, 1]
148
+ };
149
+ var CSS_FUNCTION = /^cubic-bezier\((.*)\)$/;
150
+ function cubicBezier(first, y1, x2, y2) {
151
+ if (typeof first === "string") return fromCss(first);
152
+ return bezier(first, y1, x2, y2, void 0);
153
+ }
154
+ function fromCss(input) {
155
+ const token = input.trim().toLowerCase();
156
+ if (token === "linear") return Easing.linear;
157
+ const keyword = CSS_KEYWORDS[token];
158
+ if (keyword) return bezier(...keyword, input);
159
+ const match = CSS_FUNCTION.exec(token);
160
+ if (!match) {
161
+ throw new Error(
162
+ `[inertia] cubicBezier: unsupported easing token ${JSON.stringify(input)}. Expected four numbers, a 'cubic-bezier(x1, y1, x2, y2)' string, or one of the CSS keywords 'linear' | 'ease' | 'ease-in' | 'ease-out' | 'ease-in-out'.`
163
+ );
164
+ }
165
+ const parts = match[1].split(",").map((p) => Number(p.trim()));
166
+ if (parts.length !== 4 || parts.some((n) => !Number.isFinite(n))) {
167
+ throw new Error(
168
+ `[inertia] cubicBezier: could not parse ${JSON.stringify(input)} \u2014 expected exactly four finite numbers inside cubic-bezier(...).`
169
+ );
170
+ }
171
+ return bezier(parts[0], parts[1], parts[2], parts[3], input);
172
+ }
173
+ function bezier(x1, y1, x2, y2, source) {
174
+ const describe = () => source !== void 0 ? JSON.stringify(source) : `cubicBezier(${x1}, ${y1}, ${x2}, ${y2})`;
175
+ for (const n of [x1, y1, x2, y2]) {
176
+ if (typeof n !== "number" || !Number.isFinite(n)) {
177
+ throw new Error(
178
+ `[inertia] cubicBezier: ${describe()} \u2014 every control point must be a finite number.`
179
+ );
180
+ }
181
+ }
182
+ if (x1 < 0 || x1 > 1 || x2 < 0 || x2 > 1) {
183
+ throw new Error(
184
+ `[inertia] cubicBezier: ${describe()} \u2014 x1 and x2 must be within [0, 1] (got x1=${x1}, x2=${x2}).`
185
+ );
186
+ }
187
+ return Easing.bezier(x1, y1, x2, y2);
188
+ }
189
+ var DEFAULT_TIMING_DURATION2 = 250;
190
+ function buildReleaseAnimation(transition, toValue) {
191
+ "worklet";
192
+ if (transition.type === "no-animation") return toValue;
193
+ if (transition.type === "decay") {
194
+ const cfg = { velocity: transition.velocity ?? 0 };
195
+ if (transition.deceleration !== void 0) {
196
+ cfg.deceleration = transition.deceleration;
197
+ }
198
+ if (transition.clamp !== void 0) cfg.clamp = transition.clamp;
199
+ return withDecay(cfg);
200
+ }
201
+ if (transition.type === "timing") {
202
+ const e = transition.easing;
203
+ const easingFn = e && typeof e === "object" && "factory" in e ? e.factory() : e ?? Easing.inOut(Easing.ease);
204
+ return withTiming(toValue, {
205
+ duration: transition.duration ?? DEFAULT_TIMING_DURATION2,
206
+ easing: easingFn
207
+ });
208
+ }
209
+ return withSpring(toValue, springToReanimated(transition));
210
+ }
211
+
212
+ // src/transitions/keys.ts
213
+ var TRANSITION_CONFIG_KEYS = /* @__PURE__ */ new Set([
214
+ "type",
215
+ "tension",
216
+ "friction",
217
+ "mass",
218
+ "velocity",
219
+ "restSpeedThreshold",
220
+ "restDisplacementThreshold",
221
+ "duration",
222
+ "easing",
223
+ "delay",
224
+ "repeat",
225
+ "deceleration",
226
+ "clamp"
227
+ ]);
228
+ function isTopLevelTransition(t) {
229
+ if (t === null || typeof t !== "object") return false;
230
+ const keys = Object.keys(t);
231
+ if (keys.length === 0) return false;
232
+ return keys.every((k) => TRANSITION_CONFIG_KEYS.has(k));
233
+ }
234
+
235
+ // src/transitions/sig.ts
236
+ function stableSig(value) {
237
+ if (value === void 0) return "";
238
+ try {
239
+ return stableStringify(value);
240
+ } catch {
241
+ return String(value);
242
+ }
243
+ }
244
+ function stableStringify(v) {
245
+ if (v === null || typeof v !== "object") {
246
+ if (typeof v === "function" || v === void 0) return "null";
247
+ return JSON.stringify(v);
248
+ }
249
+ if (Array.isArray(v)) {
250
+ return "[" + v.map(stableStringify).join(",") + "]";
251
+ }
252
+ const obj = v;
253
+ const keys = Object.keys(obj).sort();
254
+ return "{" + keys.map((k) => JSON.stringify(k) + ":" + stableStringify(obj[k])).join(",") + "}";
255
+ }
256
+
257
+ export { DEFAULT_SPRING, buildReleaseAnimation, cubicBezier, ensureWorkletEasing, isTopLevelTransition, resolveAnimatableValue, resolveTransition, springToReanimated, stableSig };