react-native-gtkx 0.3.0-alpha.1 → 0.4.0-alpha.2
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 +1 -1
- package/dist/adw/index.d.ts +3 -2
- package/dist/adw/index.js +21 -4
- package/dist/adw/index.js.map +1 -1
- package/dist/adw/widgets.generated.d.ts +1 -1
- package/dist/adw/widgets.generated.js +2 -2
- package/dist/adw/widgets.generated.js.map +1 -1
- package/dist/animated/create-animated.d.ts +2 -0
- package/dist/animated/create-animated.js +2 -0
- package/dist/animated/create-animated.js.map +1 -1
- package/dist/animated/event.d.ts +15 -0
- package/dist/animated/event.js +80 -0
- package/dist/animated/event.js.map +1 -0
- package/dist/animated/index.d.ts +4 -0
- package/dist/animated/index.js +8 -0
- package/dist/animated/index.js.map +1 -1
- package/dist/animated/spring.d.ts +10 -0
- package/dist/animated/spring.js +20 -6
- package/dist/animated/spring.js.map +1 -1
- package/dist/animated/timing.d.ts +10 -0
- package/dist/animated/timing.js +21 -13
- package/dist/animated/timing.js.map +1 -1
- package/dist/apis/host.gtkx.js +70 -11
- package/dist/apis/host.gtkx.js.map +1 -1
- package/dist/common/navigation-stack.d.ts +6 -3
- package/dist/common/navigation-stack.js +8 -1
- package/dist/common/navigation-stack.js.map +1 -1
- package/dist/common/widget.js +2 -11
- package/dist/common/widget.js.map +1 -1
- package/dist/components/animated.d.ts +1 -0
- package/dist/components/animated.js +28 -4
- package/dist/components/animated.js.map +1 -1
- package/dist/components/app-registry.js +32 -8
- package/dist/components/app-registry.js.map +1 -1
- package/dist/components/request-animation-frame.d.ts +33 -0
- package/dist/components/request-animation-frame.js +83 -0
- package/dist/components/request-animation-frame.js.map +1 -0
- package/dist/components/scroll-view.js +60 -2
- package/dist/components/scroll-view.js.map +1 -1
- package/dist/components/virtualized-list.js +1 -4
- package/dist/components/virtualized-list.js.map +1 -1
- package/dist/dnd/autoscroll.d.ts +44 -0
- package/dist/dnd/autoscroll.js +176 -0
- package/dist/dnd/autoscroll.js.map +1 -0
- package/dist/dnd/grid-order.d.ts +45 -0
- package/dist/dnd/grid-order.js +151 -0
- package/dist/dnd/grid-order.js.map +1 -0
- package/dist/dnd/grid.d.ts +44 -0
- package/dist/dnd/grid.js +397 -0
- package/dist/dnd/grid.js.map +1 -0
- package/dist/dnd/gtk-controllers.d.ts +16 -2
- package/dist/dnd/gtk-controllers.js +23 -3
- package/dist/dnd/gtk-controllers.js.map +1 -1
- package/dist/dnd/index.d.ts +4 -2
- package/dist/dnd/index.js +9 -2
- package/dist/dnd/index.js.map +1 -1
- package/dist/dnd/order-state.d.ts +14 -0
- package/dist/dnd/order-state.js +55 -0
- package/dist/dnd/order-state.js.map +1 -0
- package/dist/dnd/order.d.ts +19 -0
- package/dist/dnd/order.js +19 -0
- package/dist/dnd/order.js.map +1 -1
- package/dist/dnd/sortable.d.ts +29 -4
- package/dist/dnd/sortable.js +308 -115
- package/dist/dnd/sortable.js.map +1 -1
- package/dist/dnd/types.d.ts +236 -14
- package/dist/dnd/types.js +30 -0
- package/dist/dnd/types.js.map +1 -1
- package/dist/gesture-handler-compat/attach-context.d.ts +29 -0
- package/dist/gesture-handler-compat/attach-context.js +90 -0
- package/dist/gesture-handler-compat/attach-context.js.map +1 -0
- package/dist/gesture-handler-compat/detector-runtime.d.ts +14 -3
- package/dist/gesture-handler-compat/detector-runtime.js +15 -5
- package/dist/gesture-handler-compat/detector-runtime.js.map +1 -1
- package/dist/gesture-handler-compat/detector.js +57 -2
- package/dist/gesture-handler-compat/detector.js.map +1 -1
- package/dist/gesture-handler-compat/gesture-state-manager.d.ts +5 -0
- package/dist/gesture-handler-compat/gesture-state-manager.js +77 -0
- package/dist/gesture-handler-compat/gesture-state-manager.js.map +1 -0
- package/dist/gesture-handler-compat/index.d.ts +2 -2
- package/dist/gesture-handler-compat/index.js +38 -33
- package/dist/gesture-handler-compat/index.js.map +1 -1
- package/dist/gesture-handler-compat/recognizer.d.ts +12 -1
- package/dist/gesture-handler-compat/recognizer.js +23 -9
- package/dist/gesture-handler-compat/recognizer.js.map +1 -1
- package/dist/gesture-handler-compat/tag-registry.d.ts +14 -0
- package/dist/gesture-handler-compat/tag-registry.js +19 -0
- package/dist/gesture-handler-compat/tag-registry.js.map +1 -0
- package/dist/globals/index.d.ts +47 -0
- package/dist/globals/index.js +181 -0
- package/dist/globals/index.js.map +1 -0
- package/dist/globals/install.d.ts +1 -0
- package/dist/globals/install.js +14 -0
- package/dist/globals/install.js.map +1 -0
- package/dist/gtkx/bridge/adw-namespace.d.ts +2 -0
- package/dist/gtkx/bridge/adw-namespace.js +26 -0
- package/dist/gtkx/bridge/adw-namespace.js.map +1 -0
- package/dist/gtkx/bridge/adw.d.ts +23 -0
- package/dist/gtkx/bridge/adw.js +93 -0
- package/dist/gtkx/bridge/adw.js.map +1 -0
- package/dist/gtkx/bridge/color-scheme-parse.d.ts +11 -0
- package/dist/gtkx/bridge/color-scheme-parse.js +42 -0
- package/dist/gtkx/bridge/color-scheme-parse.js.map +1 -0
- package/dist/gtkx/bridge/color-scheme-portal.d.ts +24 -0
- package/dist/gtkx/bridge/color-scheme-portal.js +172 -0
- package/dist/gtkx/bridge/color-scheme-portal.js.map +1 -0
- package/dist/gtkx/bridge/core.d.ts +25 -0
- package/dist/gtkx/bridge/core.js +69 -0
- package/dist/gtkx/bridge/core.js.map +1 -0
- package/dist/gtkx/bridge/drag-layer.d.ts +27 -0
- package/dist/gtkx/bridge/drag-layer.js +177 -0
- package/dist/gtkx/bridge/drag-layer.js.map +1 -0
- package/dist/gtkx/bridge/index.d.ts +1 -27
- package/dist/gtkx/bridge/index.js +12 -71
- package/dist/gtkx/bridge/index.js.map +1 -1
- package/dist/gtkx/bridge/widgets.generated.adw.d.ts +1 -0
- package/dist/gtkx/bridge/widgets.generated.adw.js +16 -0
- package/dist/gtkx/bridge/widgets.generated.adw.js.map +1 -0
- package/dist/gtkx/bridge/widgets.generated.d.ts +0 -1
- package/dist/gtkx/bridge/widgets.generated.js +3 -3
- package/dist/gtkx/bridge/widgets.generated.js.map +1 -1
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/data/generated.d.ts +41 -20
- package/dist/mcp/data/generated.js +46 -20
- package/dist/mcp/data/generated.js.map +1 -1
- package/dist/metro/index.d.ts +1 -0
- package/dist/metro/index.js +12 -0
- package/dist/metro/index.js.map +1 -1
- package/dist/navigation/sidebar.js +2 -45
- package/dist/navigation/sidebar.js.map +1 -1
- package/dist/reanimated-compat/animatable-value.d.ts +158 -0
- package/dist/reanimated-compat/animatable-value.js +316 -0
- package/dist/reanimated-compat/animatable-value.js.map +1 -0
- package/dist/reanimated-compat/animation.d.ts +34 -13
- package/dist/reanimated-compat/animation.js +97 -25
- package/dist/reanimated-compat/animation.js.map +1 -1
- package/dist/reanimated-compat/mutable.js +6 -6
- package/dist/reanimated-compat/mutable.js.map +1 -1
- package/dist/reanimated-compat/updater-animations.js +32 -12
- package/dist/reanimated-compat/updater-animations.js.map +1 -1
- package/dist/runner/host-dev.js +5 -1
- package/dist/runner/host-dev.js.map +1 -1
- package/dist/runner/host.js +9 -1
- package/dist/runner/host.js.map +1 -1
- package/dist/vite/index.js +130 -0
- package/dist/vite/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/gtkx/bridge/theme.d.ts +0 -4
- package/dist/gtkx/bridge/theme.js +0 -5
- package/dist/gtkx/bridge/theme.js.map +0 -1
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import type { CompositeAnimation, EasingFunction, FrameScheduler, MakeStep } from "../animated/index";
|
|
2
|
+
import { springStep } from "../animated/index";
|
|
3
|
+
import type { WithSpringConfig } from "./animation";
|
|
4
|
+
/** Upstream's `AnimatableValue`, minus colour strings — those keep the
|
|
5
|
+
* existing, separate `interpolateColor` path (docs/api.md), so a leaf here
|
|
6
|
+
* is always a number. */
|
|
7
|
+
export type AnimatableValue = number | AnimatableArray | AnimatableObject;
|
|
8
|
+
export type AnimatableArray = readonly number[];
|
|
9
|
+
export type AnimatableObject = {
|
|
10
|
+
readonly [key: string]: AnimatableValue;
|
|
11
|
+
};
|
|
12
|
+
/** A path from the root of an `AnimatableValue` to one of its number leaves. */
|
|
13
|
+
export type LeafPath = ReadonlyArray<string | number>;
|
|
14
|
+
/**
|
|
15
|
+
* True for anything `withTiming`/`withSpring` can legally target: a finite
|
|
16
|
+
* number, a plain object of these (recursively — upstream's `objectOnStart`
|
|
17
|
+
* re-decorates its clones' `onStart`, so nested objects genuinely work), or
|
|
18
|
+
* a plain array of finite numbers (upstream's arrays are flat: a clone's
|
|
19
|
+
* `onStart` is the undecorated base one, so an array element is always a
|
|
20
|
+
* number, never itself an object or array).
|
|
21
|
+
*/
|
|
22
|
+
export declare const isAnimatableValue: (value: unknown) => value is AnimatableValue;
|
|
23
|
+
/**
|
|
24
|
+
* Validates and returns `value` unchanged — no cloning, exactly upstream's
|
|
25
|
+
* `defineAnimation` returning `starting` by reference under
|
|
26
|
+
* `IN_STYLE_UPDATER`. Throws the same shape of error the number-only gate
|
|
27
|
+
* always has, widened to name the actual offending leaf.
|
|
28
|
+
*/
|
|
29
|
+
export declare const assertAnimatableValue: <T>(value: T, api: string) => T;
|
|
30
|
+
/** A single leaf: where it lives in the shape, and its two endpoints. */
|
|
31
|
+
type LeafEndpoints = {
|
|
32
|
+
path: LeafPath;
|
|
33
|
+
from: number;
|
|
34
|
+
to: number;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* The shape a merged frame is rebuilt from: a tree with the SAME keys/indices
|
|
38
|
+
* as the origin value, and a leaf index in place of every number — recorded
|
|
39
|
+
* once, at the start of an animation, and reused every frame
|
|
40
|
+
* (`rebuildAnimatableValue`) rather than re-walked.
|
|
41
|
+
*/
|
|
42
|
+
export type AnimatableShape = {
|
|
43
|
+
kind: "leaf";
|
|
44
|
+
index: number;
|
|
45
|
+
} | {
|
|
46
|
+
kind: "array";
|
|
47
|
+
children: readonly AnimatableShape[];
|
|
48
|
+
} | {
|
|
49
|
+
kind: "object";
|
|
50
|
+
children: Readonly<Record<string, AnimatableShape>>;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Walks `from` and `to` together into a flat leaf list plus the shape to
|
|
54
|
+
* rebuild frames from. Throws when the two do not line up — see the header:
|
|
55
|
+
* this is the one place this platform's behaviour is a deliberate, documented
|
|
56
|
+
* departure from upstream's silent drop.
|
|
57
|
+
*/
|
|
58
|
+
export declare const zipAnimatableLeaves: (api: string, from: AnimatableValue, to: AnimatableValue) => {
|
|
59
|
+
shape: AnimatableShape;
|
|
60
|
+
leaves: LeafEndpoints[];
|
|
61
|
+
};
|
|
62
|
+
/** The inverse of the walk above: leaf values, in `zipAnimatableLeaves` order, folded back into `shape`'s structure. */
|
|
63
|
+
export declare const rebuildAnimatableValue: (shape: AnimatableShape, values: readonly number[]) => AnimatableValue;
|
|
64
|
+
/**
|
|
65
|
+
* A deterministic string for an `AnimatableValue`, key order independent —
|
|
66
|
+
* `animationSignature` (animation.ts) uses this so two target objects built
|
|
67
|
+
* with the same keys in a different order (`{x, y}` vs `{y, x}`, both
|
|
68
|
+
* entirely normal across two renders) are recognised as the same animation
|
|
69
|
+
* rather than restarting it.
|
|
70
|
+
*/
|
|
71
|
+
export declare const animatableValueSignature: (value: AnimatableValue) => string;
|
|
72
|
+
/**
|
|
73
|
+
* Structural, not reference, equality — an object rebuilt fresh every frame
|
|
74
|
+
* (`rebuildAnimatableValue`) is never `Object.is` the value it replaces even
|
|
75
|
+
* when every leaf agrees. Used where the number-only code compared with
|
|
76
|
+
* `Object.is` (`updater-animations.ts`'s snap-on-replacement rule); returns
|
|
77
|
+
* `false` on a shape it cannot line up rather than throwing — this is a
|
|
78
|
+
* comparison, not a build, and "different" is always a safe answer here.
|
|
79
|
+
*/
|
|
80
|
+
export declare const sameAnimatableValue: (a: AnimatableValue, b: AnimatableValue) => boolean;
|
|
81
|
+
/**
|
|
82
|
+
* The largest change any single leaf underwent, for the landing cadence's
|
|
83
|
+
* epsilon check (`updater-animations.ts`): the old question — did the number
|
|
84
|
+
* move a pixel — becomes: did any leaf move a pixel. A `{x, y}` position where
|
|
85
|
+
* only `y` is moving still has to land.
|
|
86
|
+
*/
|
|
87
|
+
export declare const maxAnimatableLeafDelta: (a: AnimatableValue, b: AnimatableValue) => number;
|
|
88
|
+
/**
|
|
89
|
+
* A `MakeStep` over a whole `AnimatableValue`: every leaf gets its own
|
|
90
|
+
* `timingStep`/`springStep` (upstream's per-leaf clone, `objectOnStart`) —
|
|
91
|
+
* SAME duration/easing/config for a timing leaf, an INDEPENDENTLY solved
|
|
92
|
+
* spring per leaf (each one's stiffness/damping only depends on ITS OWN
|
|
93
|
+
* displacement — `toPlatformSpringConfig` already computes it that way for
|
|
94
|
+
* the single-number case, called once per leaf here) — stepped in lockstep
|
|
95
|
+
* off ONE elapsed clock so the merged object publishes exactly once a frame,
|
|
96
|
+
* never once per leaf. `done` is the AND across every leaf, matching
|
|
97
|
+
* upstream's `objectOnFrame`.
|
|
98
|
+
*/
|
|
99
|
+
export type LeafStepFactory = (from: number, to: number) => MakeStep;
|
|
100
|
+
export declare const shapeMakeSteps: (api: string, toValue: AnimatableValue, leafStepFor: LeafStepFactory) => ((startValue: AnimatableValue) => (elapsedMs: number) => {
|
|
101
|
+
position: AnimatableValue | null;
|
|
102
|
+
done: boolean;
|
|
103
|
+
});
|
|
104
|
+
/** `shapeMakeSteps` specialised for `withTiming`: every leaf shares the same duration/easing. */
|
|
105
|
+
export declare const timingShapeMakeSteps: (toValue: AnimatableValue, duration: number, easing: EasingFunction) => (startValue: AnimatableValue) => (elapsedMs: number) => {
|
|
106
|
+
position: AnimatableValue | null;
|
|
107
|
+
done: boolean;
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* `shapeMakeSteps` specialised for `withSpring`: each leaf's physical
|
|
111
|
+
* parameters are solved independently, via `toPlatformSpringConfig` (passed
|
|
112
|
+
* in — animation.ts owns it — rather than duplicated here).
|
|
113
|
+
*/
|
|
114
|
+
export declare const springShapeMakeSteps: (toValue: AnimatableValue, toPlatformSpringConfig: (config: WithSpringConfig, toValue: number, from: number) => Parameters<typeof springStep>[0], config: WithSpringConfig) => (startValue: AnimatableValue) => (elapsedMs: number) => {
|
|
115
|
+
position: AnimatableValue | null;
|
|
116
|
+
done: boolean;
|
|
117
|
+
};
|
|
118
|
+
type ShapeListener = (event: {
|
|
119
|
+
value: AnimatableValue;
|
|
120
|
+
}) => void;
|
|
121
|
+
/**
|
|
122
|
+
* The object/array counterpart of `AnimatedValue` — deliberately minimal
|
|
123
|
+
* rather than a generalisation of that class: no offset, no `interpolate`,
|
|
124
|
+
* no self-tracked "current animation" (every caller here already stops the
|
|
125
|
+
* previous `CompositeAnimation` itself before starting a new one — mutable.ts
|
|
126
|
+
* and updater-animations.ts both do, same as they always have). What it DOES
|
|
127
|
+
* match is the structural shape `buildAnimation`, mutable.ts and
|
|
128
|
+
* updater-animations.ts actually read off a driver: `__getValue`,
|
|
129
|
+
* `addListener`/`removeListener`, and `setValue` for `buildRepeat`'s replay
|
|
130
|
+
* branch (the one place a driver is force-set from outside an animation).
|
|
131
|
+
*/
|
|
132
|
+
export declare class AnimatedShapeValue {
|
|
133
|
+
private _value;
|
|
134
|
+
private readonly _listeners;
|
|
135
|
+
private _nextListenerId;
|
|
136
|
+
constructor(value: AnimatableValue);
|
|
137
|
+
__getValue(): AnimatableValue;
|
|
138
|
+
/** @internal Called once per animation frame, after every leaf has stepped. */
|
|
139
|
+
__updateValue(value: AnimatableValue): void;
|
|
140
|
+
/** RN's own escape hatch: force the value, notifying listeners — what `withRepeat`'s non-reverse replay uses to snap back between iterations. */
|
|
141
|
+
setValue(value: AnimatableValue): void;
|
|
142
|
+
addListener(listener: ShapeListener): string;
|
|
143
|
+
removeListener(id: string): void;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* `createValueAnimation`'s counterpart for an `AnimatedShapeValue` — same
|
|
147
|
+
* start/stop/preemption contract (a second `start()` on the same
|
|
148
|
+
* `CompositeAnimation` preempts the first, reporting `{finished: false}`),
|
|
149
|
+
* deliberately re-implemented rather than generalising `createValueAnimation`
|
|
150
|
+
* itself: that function is `src/animated`'s, i.e. RN's own Animated engine,
|
|
151
|
+
* scalar by the RN spec it mirrors (`Animated.ValueXY` is RN's own answer to
|
|
152
|
+
* a pair, and is a different, narrower thing). This is reanimated-compat's
|
|
153
|
+
* own extension point, the same way `decayStep` + the PUBLIC
|
|
154
|
+
* `createValueAnimation` was for `withDecay` — except here the driver itself
|
|
155
|
+
* is not the platform's, so the harness around it is not either.
|
|
156
|
+
*/
|
|
157
|
+
export declare const createShapeValueAnimation: (scheduler: FrameScheduler, value: AnimatedShapeValue, makeSteps: ReturnType<typeof shapeMakeSteps>) => CompositeAnimation;
|
|
158
|
+
export {};
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import { springStep, timingStep } from "../animated/index";
|
|
2
|
+
const pathToString = (path) => path.length === 0 ? "(root)" : path.join(".");
|
|
3
|
+
/**
|
|
4
|
+
* True for anything `withTiming`/`withSpring` can legally target: a finite
|
|
5
|
+
* number, a plain object of these (recursively — upstream's `objectOnStart`
|
|
6
|
+
* re-decorates its clones' `onStart`, so nested objects genuinely work), or
|
|
7
|
+
* a plain array of finite numbers (upstream's arrays are flat: a clone's
|
|
8
|
+
* `onStart` is the undecorated base one, so an array element is always a
|
|
9
|
+
* number, never itself an object or array).
|
|
10
|
+
*/
|
|
11
|
+
export const isAnimatableValue = (value) => {
|
|
12
|
+
if (typeof value === "number") {
|
|
13
|
+
return Number.isFinite(value);
|
|
14
|
+
}
|
|
15
|
+
if (Array.isArray(value)) {
|
|
16
|
+
return value.every((item) => typeof item === "number" && Number.isFinite(item));
|
|
17
|
+
}
|
|
18
|
+
if (typeof value === "object" && value !== null) {
|
|
19
|
+
return Object.values(value).every(isAnimatableValue);
|
|
20
|
+
}
|
|
21
|
+
return false;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Validates and returns `value` unchanged — no cloning, exactly upstream's
|
|
25
|
+
* `defineAnimation` returning `starting` by reference under
|
|
26
|
+
* `IN_STYLE_UPDATER`. Throws the same shape of error the number-only gate
|
|
27
|
+
* always has, widened to name the actual offending leaf.
|
|
28
|
+
*/
|
|
29
|
+
export const assertAnimatableValue = (value, api) => {
|
|
30
|
+
if (!isAnimatableValue(value)) {
|
|
31
|
+
throw new Error(`react-native-reanimated: ${api}() on this platform animates finite numbers, and plain objects/arrays whose leaves are finite numbers. Got ${typeof value === "string" ? `"${String(value)}"` : String(value)}. Colors and layout properties cannot be driven imperatively here yet — see docs/api.md.`);
|
|
32
|
+
}
|
|
33
|
+
return value;
|
|
34
|
+
};
|
|
35
|
+
const shapeMismatch = (api, path, from, to) => new Error(`react-native-reanimated: ${api}() was given a target whose shape does not match the value it is animating from, at ${pathToString(path)} ` +
|
|
36
|
+
`(from ${JSON.stringify(from)}, to ${JSON.stringify(to)}). ` +
|
|
37
|
+
"Upstream drives this from the FROM value's own keys and silently leaves a mismatched one at its previous value forever — " +
|
|
38
|
+
"this platform throws instead, naming where the shapes disagree. See docs/api.md, “Animated values”.");
|
|
39
|
+
const buildShape = (api, from, to, path, leaves) => {
|
|
40
|
+
if (typeof from === "number") {
|
|
41
|
+
if (typeof to !== "number") {
|
|
42
|
+
throw shapeMismatch(api, path, from, to);
|
|
43
|
+
}
|
|
44
|
+
const index = leaves.length;
|
|
45
|
+
leaves.push({ path, from, to });
|
|
46
|
+
return { kind: "leaf", index };
|
|
47
|
+
}
|
|
48
|
+
if (Array.isArray(from)) {
|
|
49
|
+
if (!Array.isArray(to) || to.length !== from.length) {
|
|
50
|
+
throw shapeMismatch(api, path, from, to);
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
kind: "array",
|
|
54
|
+
children: from.map((item, index) => buildShape(api, item, to[index], [...path, index], leaves)),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
// A plain object (isAnimatableValue already refused everything else).
|
|
58
|
+
const fromObject = from;
|
|
59
|
+
if (typeof to !== "object" || to === null || Array.isArray(to)) {
|
|
60
|
+
throw shapeMismatch(api, path, from, to);
|
|
61
|
+
}
|
|
62
|
+
const toObject = to;
|
|
63
|
+
const fromKeys = Object.keys(fromObject).sort();
|
|
64
|
+
const toKeys = Object.keys(toObject).sort();
|
|
65
|
+
if (fromKeys.length !== toKeys.length ||
|
|
66
|
+
fromKeys.some((key, index) => key !== toKeys[index])) {
|
|
67
|
+
throw shapeMismatch(api, path, from, to);
|
|
68
|
+
}
|
|
69
|
+
const children = {};
|
|
70
|
+
for (const key of fromKeys) {
|
|
71
|
+
children[key] = buildShape(api, fromObject[key], toObject[key], [...path, key], leaves);
|
|
72
|
+
}
|
|
73
|
+
return { kind: "object", children };
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Walks `from` and `to` together into a flat leaf list plus the shape to
|
|
77
|
+
* rebuild frames from. Throws when the two do not line up — see the header:
|
|
78
|
+
* this is the one place this platform's behaviour is a deliberate, documented
|
|
79
|
+
* departure from upstream's silent drop.
|
|
80
|
+
*/
|
|
81
|
+
export const zipAnimatableLeaves = (api, from, to) => {
|
|
82
|
+
const leaves = [];
|
|
83
|
+
const shape = buildShape(api, from, to, [], leaves);
|
|
84
|
+
return { shape, leaves };
|
|
85
|
+
};
|
|
86
|
+
/** The inverse of the walk above: leaf values, in `zipAnimatableLeaves` order, folded back into `shape`'s structure. */
|
|
87
|
+
export const rebuildAnimatableValue = (shape, values) => {
|
|
88
|
+
switch (shape.kind) {
|
|
89
|
+
case "leaf":
|
|
90
|
+
return values[shape.index];
|
|
91
|
+
case "array":
|
|
92
|
+
return shape.children.map((child) => rebuildAnimatableValue(child, values));
|
|
93
|
+
case "object": {
|
|
94
|
+
const result = {};
|
|
95
|
+
for (const key of Object.keys(shape.children)) {
|
|
96
|
+
result[key] = rebuildAnimatableValue(shape.children[key], values);
|
|
97
|
+
}
|
|
98
|
+
return result;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* A deterministic string for an `AnimatableValue`, key order independent —
|
|
104
|
+
* `animationSignature` (animation.ts) uses this so two target objects built
|
|
105
|
+
* with the same keys in a different order (`{x, y}` vs `{y, x}`, both
|
|
106
|
+
* entirely normal across two renders) are recognised as the same animation
|
|
107
|
+
* rather than restarting it.
|
|
108
|
+
*/
|
|
109
|
+
export const animatableValueSignature = (value) => {
|
|
110
|
+
if (typeof value === "number") {
|
|
111
|
+
return String(value);
|
|
112
|
+
}
|
|
113
|
+
if (Array.isArray(value)) {
|
|
114
|
+
return `[${value.map((item) => item).join(",")}]`;
|
|
115
|
+
}
|
|
116
|
+
const object = value;
|
|
117
|
+
const keys = Object.keys(object).sort();
|
|
118
|
+
return `{${keys.map((key) => `${key}:${animatableValueSignature(object[key])}`).join(",")}}`;
|
|
119
|
+
};
|
|
120
|
+
/**
|
|
121
|
+
* Structural, not reference, equality — an object rebuilt fresh every frame
|
|
122
|
+
* (`rebuildAnimatableValue`) is never `Object.is` the value it replaces even
|
|
123
|
+
* when every leaf agrees. Used where the number-only code compared with
|
|
124
|
+
* `Object.is` (`updater-animations.ts`'s snap-on-replacement rule); returns
|
|
125
|
+
* `false` on a shape it cannot line up rather than throwing — this is a
|
|
126
|
+
* comparison, not a build, and "different" is always a safe answer here.
|
|
127
|
+
*/
|
|
128
|
+
export const sameAnimatableValue = (a, b) => {
|
|
129
|
+
if (typeof a === "number" || typeof b === "number") {
|
|
130
|
+
// Object.is, not ===: -0/0 and NaN/NaN are distinct/equal respectively,
|
|
131
|
+
// matching what the number-only code compared landed values with before
|
|
132
|
+
// this function existed.
|
|
133
|
+
return Object.is(a, b);
|
|
134
|
+
}
|
|
135
|
+
if (Array.isArray(a) || Array.isArray(b)) {
|
|
136
|
+
if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
return a.every((item, index) => Object.is(item, b[index]));
|
|
140
|
+
}
|
|
141
|
+
const objectA = a;
|
|
142
|
+
const objectB = b;
|
|
143
|
+
const keysA = Object.keys(objectA);
|
|
144
|
+
const keysB = Object.keys(objectB);
|
|
145
|
+
if (keysA.length !== keysB.length) {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
return keysA.every((key) => key in objectB && sameAnimatableValue(objectA[key], objectB[key]));
|
|
149
|
+
};
|
|
150
|
+
/**
|
|
151
|
+
* The largest change any single leaf underwent, for the landing cadence's
|
|
152
|
+
* epsilon check (`updater-animations.ts`): the old question — did the number
|
|
153
|
+
* move a pixel — becomes: did any leaf move a pixel. A `{x, y}` position where
|
|
154
|
+
* only `y` is moving still has to land.
|
|
155
|
+
*/
|
|
156
|
+
export const maxAnimatableLeafDelta = (a, b) => {
|
|
157
|
+
if (typeof a === "number") {
|
|
158
|
+
return typeof b === "number" ? Math.abs(a - b) : Number.POSITIVE_INFINITY;
|
|
159
|
+
}
|
|
160
|
+
if (Array.isArray(a)) {
|
|
161
|
+
if (!Array.isArray(b) || a.length !== b.length) {
|
|
162
|
+
return Number.POSITIVE_INFINITY;
|
|
163
|
+
}
|
|
164
|
+
return Math.max(0, ...a.map((item, index) => maxAnimatableLeafDelta(item, b[index])));
|
|
165
|
+
}
|
|
166
|
+
const objectA = a;
|
|
167
|
+
const objectB = b;
|
|
168
|
+
const keys = Object.keys(objectA);
|
|
169
|
+
if (typeof b !== "object" || b === null || Array.isArray(b)) {
|
|
170
|
+
return Number.POSITIVE_INFINITY;
|
|
171
|
+
}
|
|
172
|
+
return Math.max(0, ...keys.map((key) => key in objectB
|
|
173
|
+
? maxAnimatableLeafDelta(objectA[key], objectB[key])
|
|
174
|
+
: Number.POSITIVE_INFINITY));
|
|
175
|
+
};
|
|
176
|
+
export const shapeMakeSteps = (api, toValue, leafStepFor) => {
|
|
177
|
+
return (startValue) => {
|
|
178
|
+
const { shape, leaves } = zipAnimatableLeaves(api, startValue, toValue);
|
|
179
|
+
const stepFns = leaves.map(({ from, to }) => leafStepFor(from, to)(from));
|
|
180
|
+
return (elapsedMs) => {
|
|
181
|
+
let allDone = true;
|
|
182
|
+
const positions = [];
|
|
183
|
+
for (const stepFn of stepFns) {
|
|
184
|
+
const result = stepFn(elapsedMs);
|
|
185
|
+
// Every leaf here has delay 0 (withDelay wraps the WHOLE animation,
|
|
186
|
+
// never one leaf) so a step never actually returns a null position —
|
|
187
|
+
// this is defensive, not a case that fires.
|
|
188
|
+
positions.push(result.position ?? Number.NaN);
|
|
189
|
+
if (!result.done) {
|
|
190
|
+
allDone = false;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return {
|
|
194
|
+
position: rebuildAnimatableValue(shape, positions),
|
|
195
|
+
done: allDone,
|
|
196
|
+
};
|
|
197
|
+
};
|
|
198
|
+
};
|
|
199
|
+
};
|
|
200
|
+
/** `shapeMakeSteps` specialised for `withTiming`: every leaf shares the same duration/easing. */
|
|
201
|
+
export const timingShapeMakeSteps = (toValue, duration, easing) => shapeMakeSteps("withTiming", toValue, (from, to) => timingStep(to, duration, easing));
|
|
202
|
+
/**
|
|
203
|
+
* `shapeMakeSteps` specialised for `withSpring`: each leaf's physical
|
|
204
|
+
* parameters are solved independently, via `toPlatformSpringConfig` (passed
|
|
205
|
+
* in — animation.ts owns it — rather than duplicated here).
|
|
206
|
+
*/
|
|
207
|
+
export const springShapeMakeSteps = (toValue, toPlatformSpringConfig, config) => shapeMakeSteps("withSpring", toValue, (from, to) => springStep(toPlatformSpringConfig(config, to, from)));
|
|
208
|
+
/**
|
|
209
|
+
* The object/array counterpart of `AnimatedValue` — deliberately minimal
|
|
210
|
+
* rather than a generalisation of that class: no offset, no `interpolate`,
|
|
211
|
+
* no self-tracked "current animation" (every caller here already stops the
|
|
212
|
+
* previous `CompositeAnimation` itself before starting a new one — mutable.ts
|
|
213
|
+
* and updater-animations.ts both do, same as they always have). What it DOES
|
|
214
|
+
* match is the structural shape `buildAnimation`, mutable.ts and
|
|
215
|
+
* updater-animations.ts actually read off a driver: `__getValue`,
|
|
216
|
+
* `addListener`/`removeListener`, and `setValue` for `buildRepeat`'s replay
|
|
217
|
+
* branch (the one place a driver is force-set from outside an animation).
|
|
218
|
+
*/
|
|
219
|
+
export class AnimatedShapeValue {
|
|
220
|
+
_value;
|
|
221
|
+
_listeners = new Map();
|
|
222
|
+
_nextListenerId = 1;
|
|
223
|
+
constructor(value) {
|
|
224
|
+
this._value = value;
|
|
225
|
+
}
|
|
226
|
+
__getValue() {
|
|
227
|
+
return this._value;
|
|
228
|
+
}
|
|
229
|
+
/** @internal Called once per animation frame, after every leaf has stepped. */
|
|
230
|
+
__updateValue(value) {
|
|
231
|
+
this._value = value;
|
|
232
|
+
for (const listener of [...this._listeners.values()]) {
|
|
233
|
+
listener({ value });
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
/** RN's own escape hatch: force the value, notifying listeners — what `withRepeat`'s non-reverse replay uses to snap back between iterations. */
|
|
237
|
+
setValue(value) {
|
|
238
|
+
this.__updateValue(value);
|
|
239
|
+
}
|
|
240
|
+
addListener(listener) {
|
|
241
|
+
const id = String(this._nextListenerId++);
|
|
242
|
+
this._listeners.set(id, listener);
|
|
243
|
+
return id;
|
|
244
|
+
}
|
|
245
|
+
removeListener(id) {
|
|
246
|
+
this._listeners.delete(id);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* `createValueAnimation`'s counterpart for an `AnimatedShapeValue` — same
|
|
251
|
+
* start/stop/preemption contract (a second `start()` on the same
|
|
252
|
+
* `CompositeAnimation` preempts the first, reporting `{finished: false}`),
|
|
253
|
+
* deliberately re-implemented rather than generalising `createValueAnimation`
|
|
254
|
+
* itself: that function is `src/animated`'s, i.e. RN's own Animated engine,
|
|
255
|
+
* scalar by the RN spec it mirrors (`Animated.ValueXY` is RN's own answer to
|
|
256
|
+
* a pair, and is a different, narrower thing). This is reanimated-compat's
|
|
257
|
+
* own extension point, the same way `decayStep` + the PUBLIC
|
|
258
|
+
* `createValueAnimation` was for `withDecay` — except here the driver itself
|
|
259
|
+
* is not the platform's, so the harness around it is not either.
|
|
260
|
+
*/
|
|
261
|
+
export const createShapeValueAnimation = (scheduler, value, makeSteps) => {
|
|
262
|
+
let activeStop = null;
|
|
263
|
+
const start = (callback) => {
|
|
264
|
+
// A second start() on the SAME CompositeAnimation preempts the first,
|
|
265
|
+
// reporting { finished: false } to its own callback — RN parity, and
|
|
266
|
+
// resolved fully before the new run's state exists below, so there is no
|
|
267
|
+
// reentrancy between the two.
|
|
268
|
+
activeStop?.();
|
|
269
|
+
const step = makeSteps(value.__getValue());
|
|
270
|
+
let startTime = scheduler.now?.() ?? null;
|
|
271
|
+
let ended = false;
|
|
272
|
+
let cancelFrame = null;
|
|
273
|
+
const end = (finished) => {
|
|
274
|
+
if (ended) {
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
ended = true;
|
|
278
|
+
cancelFrame?.();
|
|
279
|
+
cancelFrame = null;
|
|
280
|
+
if (activeStop === stop) {
|
|
281
|
+
activeStop = null;
|
|
282
|
+
}
|
|
283
|
+
callback?.({ finished });
|
|
284
|
+
};
|
|
285
|
+
const stop = () => end(false);
|
|
286
|
+
const onFrame = (timeMs) => {
|
|
287
|
+
cancelFrame = null;
|
|
288
|
+
if (ended) {
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
if (startTime === null) {
|
|
292
|
+
startTime = timeMs;
|
|
293
|
+
}
|
|
294
|
+
const { position, done } = step(timeMs - startTime);
|
|
295
|
+
if (position !== null) {
|
|
296
|
+
value.__updateValue(position);
|
|
297
|
+
}
|
|
298
|
+
if (done) {
|
|
299
|
+
end(true);
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
cancelFrame = scheduler.schedule(onFrame);
|
|
303
|
+
};
|
|
304
|
+
activeStop = stop;
|
|
305
|
+
cancelFrame = scheduler.schedule(onFrame);
|
|
306
|
+
};
|
|
307
|
+
return {
|
|
308
|
+
start,
|
|
309
|
+
stop: () => activeStop?.(),
|
|
310
|
+
// No known caller resets a shape animation (loop()/withRepeat's own
|
|
311
|
+
// reverse and replay branches drive the value directly) — a snap back to
|
|
312
|
+
// a construction-time value would need one, and nothing needs it yet.
|
|
313
|
+
reset: () => { },
|
|
314
|
+
};
|
|
315
|
+
};
|
|
316
|
+
//# sourceMappingURL=animatable-value.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"animatable-value.js","sourceRoot":"","sources":["../../src/reanimated-compat/animatable-value.ts"],"names":[],"mappings":"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","sourcesContent":["// `AnimatableValue`: upstream's real contract for what `withTiming`/\n// `withSpring` accept, read out of `react-native-reanimated` 4.5.3's\n// `src/animation/util.ts` (`decorateAnimation`) and `src/hook/useAnimatedStyle.ts`\n// (`prepareAnimation`) — not inferred, not guessed at \"probably per-key\n// seeding\" the way the task that asked for this started out.\n//\n// UPSTREAM'S RECURSIVE RULE, transcribed from `decorateAnimation`. The\n// factory-built animation (a `TimingAnimation`/`SpringAnimation`) is generic\n// over a single number; `decorateAnimation` wraps its `onStart`/`onFrame` so\n// the SAME animation can drive a colour, a matrix, an array or an object,\n// dispatched once per `onStart` call on the VALUE it is handed:\n//\n// - a plain number: the base numeric step runs unchanged (untouched here).\n// - an object (`typeof value === \"object\"`, not an array, not a colour):\n// `objectOnStart` walks `for (const key in value)` — the FROM value's\n// OWN keys, not the target's — clones the (callback-stripped) animation\n// once per key, sets that clone's `toValue` to `toValue[key]` (which is\n// `undefined` for a key the target does not have), and re-assigns the\n// clone's `onStart` to the SAME decorated dispatcher, so a nested object\n// recurses. `objectOnFrame` steps every clone and folds a FRESH object\n// together every frame; the whole animation is `finished` only when every\n// clone is (`finished = finished && result`, an AND across every leaf).\n// - an array (`Array.isArray(value)`): `arrayOnStart`/`arrayOnFrame` walk\n// the SAME way, index by index, but the clones keep the animation's own\n// BASE (undecorated) `onStart` rather than the dispatcher — an array's\n// elements are always plain numbers upstream, never nested objects.\n//\n// Two consequences worth stating because they are easy to get backwards:\n//\n// 1. Upstream's own object/array walk is driven by the FROM value's shape,\n// and a target key the from-value lacks is silently never animated (its\n// clone is never created). This is what \"an accident, not a feature\"\n// looks like in practice — a target that grew a key nobody notices.\n// THIS PLATFORM THROWS INSTEAD, at the point an object-targeted\n// animation is built (`buildAnimation`/`zipAnimatableLeaves` below): the\n// \"fail loudly, not silently\" rule this whole layer already follows for\n// a non-finite target (`assertAnimatableValue`) extends to a reshaped\n// one. docs/api.md's Differences row says so.\n// 2. There is exactly ONE callback per animation, at the top of the tree —\n// `animationCopy` used for every leaf clone has `delete\n// animationCopy.callback`, so a leaf can never report its own\n// completion. Only the root's callback exists, and it fires once, when\n// the root's `onFrame` returns `finished`.\n//\n// THE SEEDING RULE upstream's `prepareAnimation` adds on top (useAnimatedStyle.ts):\n// a key that is newly animating this run starts from `oldValues[key]` — the\n// PREVIOUS updater result's raw value at that key — but only when that value\n// is USABLE as a starting point:\n//\n// let value = animation.current // default: the target\n// if (lastValue is a number or anything non-object) value = lastValue\n// else if (lastValue has an own `.value`) value = lastValue.value // was a shared value\n// else if (lastValue has an own `.onFrame`) value = (previous animation's .current)\n// // a lastValue that is a PLAIN OBJECT — no `.value`, no `.onFrame` — is\n// // NEVER read from. `value` stays the default: the target.\n//\n// So a key that held a plain NUMBER seeds from it (already this platform's\n// rule, `updater-animations.ts`'s `startingPoint` — unchanged by this file).\n// A key that held a plain OBJECT — an ordinary `{x, y}`, not a shared value\n// or an animation node — does NOT seed from it, upstream's `typeof lastValue\n// === \"object\"` branch simply has no case that matches a plain data object.\n// It is treated exactly like a key that was ABSENT: seeded at the target,\n// never animated to it. This is the one genuinely surprising rule this file\n// exists to pin down, and it costs nothing extra to implement: this\n// platform's `startingPoint` already returns `undefined` for anything that\n// is not a finite number, which — now that objects are legal targets too —\n// already IS upstream's rule, unchanged.\nimport type {\n CompositeAnimation,\n EasingFunction,\n EndCallback,\n FrameScheduler,\n MakeStep,\n} from \"../animated/index\"\nimport { springStep, timingStep } from \"../animated/index\"\nimport type { WithSpringConfig } from \"./animation\"\n\n/** Upstream's `AnimatableValue`, minus colour strings — those keep the\n * existing, separate `interpolateColor` path (docs/api.md), so a leaf here\n * is always a number. */\nexport type AnimatableValue = number | AnimatableArray | AnimatableObject\n\nexport type AnimatableArray = readonly number[]\n\nexport type AnimatableObject = { readonly [key: string]: AnimatableValue }\n\n/** A path from the root of an `AnimatableValue` to one of its number leaves. */\nexport type LeafPath = ReadonlyArray<string | number>\n\nconst pathToString = (path: LeafPath): string =>\n path.length === 0 ? \"(root)\" : path.join(\".\")\n\n/**\n * True for anything `withTiming`/`withSpring` can legally target: a finite\n * number, a plain object of these (recursively — upstream's `objectOnStart`\n * re-decorates its clones' `onStart`, so nested objects genuinely work), or\n * a plain array of finite numbers (upstream's arrays are flat: a clone's\n * `onStart` is the undecorated base one, so an array element is always a\n * number, never itself an object or array).\n */\nexport const isAnimatableValue = (value: unknown): value is AnimatableValue => {\n if (typeof value === \"number\") {\n return Number.isFinite(value)\n }\n if (Array.isArray(value)) {\n return value.every(\n (item) => typeof item === \"number\" && Number.isFinite(item),\n )\n }\n if (typeof value === \"object\" && value !== null) {\n return Object.values(value).every(isAnimatableValue)\n }\n return false\n}\n\n/**\n * Validates and returns `value` unchanged — no cloning, exactly upstream's\n * `defineAnimation` returning `starting` by reference under\n * `IN_STYLE_UPDATER`. Throws the same shape of error the number-only gate\n * always has, widened to name the actual offending leaf.\n */\nexport const assertAnimatableValue = <T>(value: T, api: string): T => {\n if (!isAnimatableValue(value)) {\n throw new Error(\n `react-native-reanimated: ${api}() on this platform animates finite numbers, and plain objects/arrays whose leaves are finite numbers. Got ${\n typeof value === \"string\" ? `\"${String(value)}\"` : String(value)\n }. Colors and layout properties cannot be driven imperatively here yet — see docs/api.md.`,\n )\n }\n return value\n}\n\n/** A single leaf: where it lives in the shape, and its two endpoints. */\ntype LeafEndpoints = { path: LeafPath; from: number; to: number }\n\n/**\n * The shape a merged frame is rebuilt from: a tree with the SAME keys/indices\n * as the origin value, and a leaf index in place of every number — recorded\n * once, at the start of an animation, and reused every frame\n * (`rebuildAnimatableValue`) rather than re-walked.\n */\nexport type AnimatableShape =\n | { kind: \"leaf\"; index: number }\n | { kind: \"array\"; children: readonly AnimatableShape[] }\n | { kind: \"object\"; children: Readonly<Record<string, AnimatableShape>> }\n\nconst shapeMismatch = (\n api: string,\n path: LeafPath,\n from: unknown,\n to: unknown,\n): Error =>\n new Error(\n `react-native-reanimated: ${api}() was given a target whose shape does not match the value it is animating from, at ${pathToString(path)} ` +\n `(from ${JSON.stringify(from)}, to ${JSON.stringify(to)}). ` +\n \"Upstream drives this from the FROM value's own keys and silently leaves a mismatched one at its previous value forever — \" +\n \"this platform throws instead, naming where the shapes disagree. See docs/api.md, “Animated values”.\",\n )\n\nconst buildShape = (\n api: string,\n from: AnimatableValue,\n to: AnimatableValue,\n path: LeafPath,\n leaves: LeafEndpoints[],\n): AnimatableShape => {\n if (typeof from === \"number\") {\n if (typeof to !== \"number\") {\n throw shapeMismatch(api, path, from, to)\n }\n const index = leaves.length\n leaves.push({ path, from, to })\n return { kind: \"leaf\", index }\n }\n if (Array.isArray(from)) {\n if (!Array.isArray(to) || to.length !== from.length) {\n throw shapeMismatch(api, path, from, to)\n }\n return {\n kind: \"array\",\n children: from.map((item, index) =>\n buildShape(api, item, to[index]!, [...path, index], leaves),\n ),\n }\n }\n // A plain object (isAnimatableValue already refused everything else).\n const fromObject = from as AnimatableObject\n if (typeof to !== \"object\" || to === null || Array.isArray(to)) {\n throw shapeMismatch(api, path, from, to)\n }\n const toObject = to as AnimatableObject\n const fromKeys = Object.keys(fromObject).sort()\n const toKeys = Object.keys(toObject).sort()\n if (\n fromKeys.length !== toKeys.length ||\n fromKeys.some((key, index) => key !== toKeys[index])\n ) {\n throw shapeMismatch(api, path, from, to)\n }\n const children: Record<string, AnimatableShape> = {}\n for (const key of fromKeys) {\n children[key] = buildShape(\n api,\n fromObject[key]!,\n toObject[key]!,\n [...path, key],\n leaves,\n )\n }\n return { kind: \"object\", children }\n}\n\n/**\n * Walks `from` and `to` together into a flat leaf list plus the shape to\n * rebuild frames from. Throws when the two do not line up — see the header:\n * this is the one place this platform's behaviour is a deliberate, documented\n * departure from upstream's silent drop.\n */\nexport const zipAnimatableLeaves = (\n api: string,\n from: AnimatableValue,\n to: AnimatableValue,\n): { shape: AnimatableShape; leaves: LeafEndpoints[] } => {\n const leaves: LeafEndpoints[] = []\n const shape = buildShape(api, from, to, [], leaves)\n return { shape, leaves }\n}\n\n/** The inverse of the walk above: leaf values, in `zipAnimatableLeaves` order, folded back into `shape`'s structure. */\nexport const rebuildAnimatableValue = (\n shape: AnimatableShape,\n values: readonly number[],\n): AnimatableValue => {\n switch (shape.kind) {\n case \"leaf\":\n return values[shape.index]!\n case \"array\":\n return shape.children.map(\n (child) => rebuildAnimatableValue(child, values) as number,\n )\n case \"object\": {\n const result: Record<string, AnimatableValue> = {}\n for (const key of Object.keys(shape.children)) {\n result[key] = rebuildAnimatableValue(shape.children[key]!, values)\n }\n return result\n }\n }\n}\n\n/**\n * A deterministic string for an `AnimatableValue`, key order independent —\n * `animationSignature` (animation.ts) uses this so two target objects built\n * with the same keys in a different order (`{x, y}` vs `{y, x}`, both\n * entirely normal across two renders) are recognised as the same animation\n * rather than restarting it.\n */\nexport const animatableValueSignature = (value: AnimatableValue): string => {\n if (typeof value === \"number\") {\n return String(value)\n }\n if (Array.isArray(value)) {\n return `[${value.map((item) => item).join(\",\")}]`\n }\n const object = value as AnimatableObject\n const keys = Object.keys(object).sort()\n return `{${keys.map((key) => `${key}:${animatableValueSignature(object[key]!)}`).join(\",\")}}`\n}\n\n/**\n * Structural, not reference, equality — an object rebuilt fresh every frame\n * (`rebuildAnimatableValue`) is never `Object.is` the value it replaces even\n * when every leaf agrees. Used where the number-only code compared with\n * `Object.is` (`updater-animations.ts`'s snap-on-replacement rule); returns\n * `false` on a shape it cannot line up rather than throwing — this is a\n * comparison, not a build, and \"different\" is always a safe answer here.\n */\nexport const sameAnimatableValue = (\n a: AnimatableValue,\n b: AnimatableValue,\n): boolean => {\n if (typeof a === \"number\" || typeof b === \"number\") {\n // Object.is, not ===: -0/0 and NaN/NaN are distinct/equal respectively,\n // matching what the number-only code compared landed values with before\n // this function existed.\n return Object.is(a, b)\n }\n if (Array.isArray(a) || Array.isArray(b)) {\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) {\n return false\n }\n return a.every((item, index) => Object.is(item, b[index]))\n }\n const objectA = a as AnimatableObject\n const objectB = b as AnimatableObject\n const keysA = Object.keys(objectA)\n const keysB = Object.keys(objectB)\n if (keysA.length !== keysB.length) {\n return false\n }\n return keysA.every(\n (key) =>\n key in objectB && sameAnimatableValue(objectA[key]!, objectB[key]!),\n )\n}\n\n/**\n * The largest change any single leaf underwent, for the landing cadence's\n * epsilon check (`updater-animations.ts`): the old question — did the number\n * move a pixel — becomes: did any leaf move a pixel. A `{x, y}` position where\n * only `y` is moving still has to land.\n */\nexport const maxAnimatableLeafDelta = (\n a: AnimatableValue,\n b: AnimatableValue,\n): number => {\n if (typeof a === \"number\") {\n return typeof b === \"number\" ? Math.abs(a - b) : Number.POSITIVE_INFINITY\n }\n if (Array.isArray(a)) {\n if (!Array.isArray(b) || a.length !== b.length) {\n return Number.POSITIVE_INFINITY\n }\n return Math.max(\n 0,\n ...a.map((item, index) => maxAnimatableLeafDelta(item, b[index]!)),\n )\n }\n const objectA = a as AnimatableObject\n const objectB = b as AnimatableObject\n const keys = Object.keys(objectA)\n if (typeof b !== \"object\" || b === null || Array.isArray(b)) {\n return Number.POSITIVE_INFINITY\n }\n return Math.max(\n 0,\n ...keys.map((key) =>\n key in objectB\n ? maxAnimatableLeafDelta(objectA[key]!, objectB[key]!)\n : Number.POSITIVE_INFINITY,\n ),\n )\n}\n\n/**\n * A `MakeStep` over a whole `AnimatableValue`: every leaf gets its own\n * `timingStep`/`springStep` (upstream's per-leaf clone, `objectOnStart`) —\n * SAME duration/easing/config for a timing leaf, an INDEPENDENTLY solved\n * spring per leaf (each one's stiffness/damping only depends on ITS OWN\n * displacement — `toPlatformSpringConfig` already computes it that way for\n * the single-number case, called once per leaf here) — stepped in lockstep\n * off ONE elapsed clock so the merged object publishes exactly once a frame,\n * never once per leaf. `done` is the AND across every leaf, matching\n * upstream's `objectOnFrame`.\n */\nexport type LeafStepFactory = (from: number, to: number) => MakeStep\n\nexport const shapeMakeSteps = (\n api: string,\n toValue: AnimatableValue,\n leafStepFor: LeafStepFactory,\n): ((startValue: AnimatableValue) => (elapsedMs: number) => {\n position: AnimatableValue | null\n done: boolean\n}) => {\n return (startValue) => {\n const { shape, leaves } = zipAnimatableLeaves(api, startValue, toValue)\n const stepFns = leaves.map(({ from, to }) => leafStepFor(from, to)(from))\n return (elapsedMs) => {\n let allDone = true\n const positions: number[] = []\n for (const stepFn of stepFns) {\n const result = stepFn(elapsedMs)\n // Every leaf here has delay 0 (withDelay wraps the WHOLE animation,\n // never one leaf) so a step never actually returns a null position —\n // this is defensive, not a case that fires.\n positions.push(result.position ?? Number.NaN)\n if (!result.done) {\n allDone = false\n }\n }\n return {\n position: rebuildAnimatableValue(shape, positions),\n done: allDone,\n }\n }\n }\n}\n\n/** `shapeMakeSteps` specialised for `withTiming`: every leaf shares the same duration/easing. */\nexport const timingShapeMakeSteps = (\n toValue: AnimatableValue,\n duration: number,\n easing: EasingFunction,\n) =>\n shapeMakeSteps(\"withTiming\", toValue, (from, to) =>\n timingStep(to, duration, easing),\n )\n\n/**\n * `shapeMakeSteps` specialised for `withSpring`: each leaf's physical\n * parameters are solved independently, via `toPlatformSpringConfig` (passed\n * in — animation.ts owns it — rather than duplicated here).\n */\nexport const springShapeMakeSteps = (\n toValue: AnimatableValue,\n toPlatformSpringConfig: (\n config: WithSpringConfig,\n toValue: number,\n from: number,\n ) => Parameters<typeof springStep>[0],\n config: WithSpringConfig,\n) =>\n shapeMakeSteps(\"withSpring\", toValue, (from, to) =>\n springStep(toPlatformSpringConfig(config, to, from)),\n )\n\ntype ShapeListener = (event: { value: AnimatableValue }) => void\n\n/**\n * The object/array counterpart of `AnimatedValue` — deliberately minimal\n * rather than a generalisation of that class: no offset, no `interpolate`,\n * no self-tracked \"current animation\" (every caller here already stops the\n * previous `CompositeAnimation` itself before starting a new one — mutable.ts\n * and updater-animations.ts both do, same as they always have). What it DOES\n * match is the structural shape `buildAnimation`, mutable.ts and\n * updater-animations.ts actually read off a driver: `__getValue`,\n * `addListener`/`removeListener`, and `setValue` for `buildRepeat`'s replay\n * branch (the one place a driver is force-set from outside an animation).\n */\nexport class AnimatedShapeValue {\n private _value: AnimatableValue\n private readonly _listeners = new Map<string, ShapeListener>()\n private _nextListenerId = 1\n\n constructor(value: AnimatableValue) {\n this._value = value\n }\n\n __getValue(): AnimatableValue {\n return this._value\n }\n\n /** @internal Called once per animation frame, after every leaf has stepped. */\n __updateValue(value: AnimatableValue): void {\n this._value = value\n for (const listener of [...this._listeners.values()]) {\n listener({ value })\n }\n }\n\n /** RN's own escape hatch: force the value, notifying listeners — what `withRepeat`'s non-reverse replay uses to snap back between iterations. */\n setValue(value: AnimatableValue): void {\n this.__updateValue(value)\n }\n\n addListener(listener: ShapeListener): string {\n const id = String(this._nextListenerId++)\n this._listeners.set(id, listener)\n return id\n }\n\n removeListener(id: string): void {\n this._listeners.delete(id)\n }\n}\n\n/**\n * `createValueAnimation`'s counterpart for an `AnimatedShapeValue` — same\n * start/stop/preemption contract (a second `start()` on the same\n * `CompositeAnimation` preempts the first, reporting `{finished: false}`),\n * deliberately re-implemented rather than generalising `createValueAnimation`\n * itself: that function is `src/animated`'s, i.e. RN's own Animated engine,\n * scalar by the RN spec it mirrors (`Animated.ValueXY` is RN's own answer to\n * a pair, and is a different, narrower thing). This is reanimated-compat's\n * own extension point, the same way `decayStep` + the PUBLIC\n * `createValueAnimation` was for `withDecay` — except here the driver itself\n * is not the platform's, so the harness around it is not either.\n */\nexport const createShapeValueAnimation = (\n scheduler: FrameScheduler,\n value: AnimatedShapeValue,\n makeSteps: ReturnType<typeof shapeMakeSteps>,\n): CompositeAnimation => {\n let activeStop: (() => void) | null = null\n\n const start = (callback?: EndCallback): void => {\n // A second start() on the SAME CompositeAnimation preempts the first,\n // reporting { finished: false } to its own callback — RN parity, and\n // resolved fully before the new run's state exists below, so there is no\n // reentrancy between the two.\n activeStop?.()\n\n const step = makeSteps(value.__getValue())\n let startTime: number | null = scheduler.now?.() ?? null\n let ended = false\n let cancelFrame: (() => void) | null = null\n\n const end = (finished: boolean): void => {\n if (ended) {\n return\n }\n ended = true\n cancelFrame?.()\n cancelFrame = null\n if (activeStop === stop) {\n activeStop = null\n }\n callback?.({ finished })\n }\n\n const stop = (): void => end(false)\n\n const onFrame = (timeMs: number): void => {\n cancelFrame = null\n if (ended) {\n return\n }\n if (startTime === null) {\n startTime = timeMs\n }\n const { position, done } = step(timeMs - startTime)\n if (position !== null) {\n value.__updateValue(position)\n }\n if (done) {\n end(true)\n return\n }\n cancelFrame = scheduler.schedule(onFrame)\n }\n\n activeStop = stop\n cancelFrame = scheduler.schedule(onFrame)\n }\n\n return {\n start,\n stop: () => activeStop?.(),\n // No known caller resets a shape animation (loop()/withRepeat's own\n // reverse and replay branches drive the value directly) — a snap back to\n // a construction-time value would need one, and nothing needs it yet.\n reset: () => {},\n }\n}\n"]}
|
|
@@ -1,8 +1,26 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AnimatedValue, type AnimatedApi, type CompositeAnimation, type FrameScheduler } from "../animated/index";
|
|
2
|
+
import { AnimatedShapeValue, type AnimatableValue } from "./animatable-value";
|
|
2
3
|
import { resolveDecayConfig, type WithDecayConfig } from "./decay";
|
|
3
4
|
import { type EasingFunction } from "./easing";
|
|
5
|
+
export type { AnimatableArray, AnimatableObject, AnimatableValue, } from "./animatable-value";
|
|
4
6
|
/** Called when an animation settles or is cancelled, as upstream. */
|
|
5
|
-
export type AnimationCallback = (finished?: boolean, current?:
|
|
7
|
+
export type AnimationCallback = (finished?: boolean, current?: AnimatableValue) => void;
|
|
8
|
+
/**
|
|
9
|
+
* What every animation in this layer runs on: a single-number `AnimatedValue`
|
|
10
|
+
* for a number target, or an `AnimatedShapeValue` (animatable-value.ts) for
|
|
11
|
+
* an object/array one — the SAME driver a spec was built against throughout
|
|
12
|
+
* its whole tree (a `withSequence`'s steps, a `withRepeat`'s iterations),
|
|
13
|
+
* because the driver IS the value being animated, not a detail of one step.
|
|
14
|
+
*/
|
|
15
|
+
export type AnimationDriver = AnimatedValue | AnimatedShapeValue;
|
|
16
|
+
/**
|
|
17
|
+
* Builds the right driver for `seed`'s type — the ONE place mutable.ts
|
|
18
|
+
* (a shared-value write) and updater-animations.ts (a key newly animating)
|
|
19
|
+
* both make this decision, so a number and a shape are dispatched the same
|
|
20
|
+
* way in both. Throws the same "not animatable" shape of error either module
|
|
21
|
+
* used to throw on its own number-only gate, widened to name what it got.
|
|
22
|
+
*/
|
|
23
|
+
export declare const makeAnimationDriver: (api: AnimatedApi, seed: unknown, context: string) => AnimationDriver;
|
|
6
24
|
export type WithTimingConfig = {
|
|
7
25
|
duration?: number;
|
|
8
26
|
easing?: EasingFunction | {
|
|
@@ -31,13 +49,13 @@ export type WithSpringConfig = {
|
|
|
31
49
|
};
|
|
32
50
|
type TimingSpec = {
|
|
33
51
|
kind: "timing";
|
|
34
|
-
toValue:
|
|
52
|
+
toValue: AnimatableValue;
|
|
35
53
|
config: WithTimingConfig;
|
|
36
54
|
callback?: AnimationCallback;
|
|
37
55
|
};
|
|
38
56
|
type SpringSpec = {
|
|
39
57
|
kind: "spring";
|
|
40
|
-
toValue:
|
|
58
|
+
toValue: AnimatableValue;
|
|
41
59
|
config: WithSpringConfig;
|
|
42
60
|
callback?: AnimationCallback;
|
|
43
61
|
};
|
|
@@ -77,20 +95,23 @@ export declare const isAnimationSpec: (value: unknown) => value is AnimationSpec
|
|
|
77
95
|
export declare const initialUpdaterRun: <T>(updater: () => T) => T;
|
|
78
96
|
/**
|
|
79
97
|
* Lets you animate a value over a duration with an easing curve. Assign the
|
|
80
|
-
* result to a shared value to start it.
|
|
98
|
+
* result to a shared value to start it. `toValue` is upstream's
|
|
99
|
+
* `AnimatableValue`: a finite number, or a plain object/array whose leaves
|
|
100
|
+
* are — a colour string is not (that keeps the separate `interpolateColor`
|
|
101
|
+
* path, docs/api.md).
|
|
81
102
|
*/
|
|
82
|
-
export declare const withTiming: (toValue:
|
|
83
|
-
/** Lets you animate a value with spring physics. */
|
|
84
|
-
export declare const withSpring: (toValue:
|
|
103
|
+
export declare const withTiming: <T extends AnimatableValue>(toValue: T, config?: WithTimingConfig, callback?: AnimationCallback) => T;
|
|
104
|
+
/** Lets you animate a value with spring physics. See withTiming for `toValue`'s shape. */
|
|
105
|
+
export declare const withSpring: <T extends AnimatableValue>(toValue: T, config?: WithSpringConfig, callback?: AnimationCallback) => T;
|
|
85
106
|
/** Delays another animation by `delayMs`. */
|
|
86
|
-
export declare const withDelay: (delayMs: number, animation:
|
|
107
|
+
export declare const withDelay: <T extends AnimatableValue>(delayMs: number, animation: T) => T;
|
|
87
108
|
/** Runs animations one after another on the same shared value. */
|
|
88
|
-
export declare const withSequence: (...animations:
|
|
109
|
+
export declare const withSequence: <T extends AnimatableValue>(...animations: T[]) => T;
|
|
89
110
|
/**
|
|
90
111
|
* Repeats an animation. `numberOfReps <= 0` repeats forever; `reverse` plays
|
|
91
112
|
* every other repetition backwards.
|
|
92
113
|
*/
|
|
93
|
-
export declare const withRepeat: (animation:
|
|
114
|
+
export declare const withRepeat: <T extends AnimatableValue>(animation: T, numberOfReps?: number, reverse?: boolean, callback?: AnimationCallback) => T;
|
|
94
115
|
/**
|
|
95
116
|
* Coasts to a stop from an initial velocity — the release half of a fling.
|
|
96
117
|
* Unlike every other animation here it has no target: where it lands is the
|
|
@@ -145,7 +166,7 @@ export declare const toPlatformSpringConfig: (config: WithSpringConfig, toValue:
|
|
|
145
166
|
* The last value an animation aims at, used by `withRepeat`'s reverse and by
|
|
146
167
|
* `updater-animations.ts` to seed a key that is animating for the first time.
|
|
147
168
|
*/
|
|
148
|
-
export declare const targetOf: (spec: AnimationSpec) =>
|
|
169
|
+
export declare const targetOf: (spec: AnimationSpec) => AnimatableValue | null;
|
|
149
170
|
/**
|
|
150
171
|
* What makes two descriptors the SAME animation, for a caller that gets a
|
|
151
172
|
* freshly built one on every evaluation and must decide whether to restart.
|
|
@@ -174,4 +195,4 @@ export type AnimationEngine = {
|
|
|
174
195
|
* of the platform's own animations, so the whole tree runs off the single
|
|
175
196
|
* injected frame scheduler.
|
|
176
197
|
*/
|
|
177
|
-
export declare const buildAnimation: (engine: AnimationEngine, driver:
|
|
198
|
+
export declare const buildAnimation: (engine: AnimationEngine, driver: AnimationDriver, spec: AnimationSpec) => CompositeAnimation;
|