@ng-native/fabric 0.13.0 → 0.15.0
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/dist/css.d.ts +63 -6
- package/dist/css.js +268 -59
- package/dist/css.js.map +1 -1
- package/dist/defer-triggers.js +2 -8
- package/dist/defer-triggers.js.map +1 -1
- package/dist/engine.d.ts +201 -21
- package/dist/engine.js +915 -125
- package/dist/engine.js.map +1 -1
- package/dist/fabric.d.ts +1 -1
- package/dist/fabric.js +25 -0
- package/dist/fabric.js.map +1 -1
- package/dist/font-faces.d.ts +19 -0
- package/dist/font-faces.js +42 -0
- package/dist/font-faces.js.map +1 -1
- package/dist/forms-inputs.d.ts +1 -1
- package/dist/forms-inputs.js +2 -2
- package/dist/forms-inputs.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/inline-derived-token.js +56 -7
- package/dist/inline-derived-token.js.map +1 -1
- package/dist/inline-token.d.ts +4 -3
- package/dist/inline-token.js +41 -8
- package/dist/inline-token.js.map +1 -1
- package/dist/native-drive.d.ts +42 -1
- package/dist/native-drive.js +135 -9
- package/dist/native-drive.js.map +1 -1
- package/dist/node-global.d.ts +9 -0
- package/dist/node-global.js +41 -0
- package/dist/node-global.js.map +1 -0
- package/dist/relative-colour.d.ts +2 -2
- package/dist/relative-colour.js +4 -0
- package/dist/relative-colour.js.map +1 -1
- package/dist/scroll-animation.d.ts +12 -0
- package/dist/scroll-animation.js +10 -0
- package/dist/scroll-animation.js.map +1 -1
- package/dist/transition.d.ts +3 -2
- package/dist/transition.js +17 -8
- package/dist/transition.js.map +1 -1
- package/package.json +1 -1
package/dist/native-drive.js
CHANGED
|
@@ -13,13 +13,133 @@
|
|
|
13
13
|
* It goes through React Native's own `NativeAnimatedHelper`, whose node tags every other animated
|
|
14
14
|
* value in the app also comes from, so none of them can collide.
|
|
15
15
|
*/
|
|
16
|
+
/** The style keys a graph's channels set. */
|
|
17
|
+
function channelKeys(channels) {
|
|
18
|
+
const keys = Object.keys(channels.colors ?? {});
|
|
19
|
+
if (channels.opacity)
|
|
20
|
+
keys.push('opacity');
|
|
21
|
+
if (channels.transform.length)
|
|
22
|
+
keys.push('transform');
|
|
23
|
+
return keys;
|
|
24
|
+
}
|
|
25
|
+
/** Every number a set of values holds, by its path in the graph. */
|
|
26
|
+
function leavesOf(values) {
|
|
27
|
+
const leaves = new Map();
|
|
28
|
+
if (values.opacity !== undefined)
|
|
29
|
+
leaves.set('opacity', values.opacity);
|
|
30
|
+
values.transform?.forEach((entry, at) => leaves.set(`transform.${at}`, entry.value));
|
|
31
|
+
return leaves;
|
|
32
|
+
}
|
|
33
|
+
/** What makes two sets of values the same graph: which keys, and the transform's properties. */
|
|
34
|
+
function shapeOf(values) {
|
|
35
|
+
const transform = values.transform?.map((entry) => entry.property).join(',');
|
|
36
|
+
return `${values.opacity === undefined ? '' : 'o'}|${transform ?? '-'}`;
|
|
37
|
+
}
|
|
38
|
+
const NONE_HELD = new Set();
|
|
16
39
|
export class NativeScrollDriver {
|
|
17
40
|
native;
|
|
41
|
+
touched;
|
|
18
42
|
/** One value per source view and feed, by the feed's key. */
|
|
19
43
|
offsets = new Map();
|
|
20
44
|
pending = new Set();
|
|
21
|
-
|
|
45
|
+
/** The keys each graph connected to a view sets, by its props node, while it is connected. */
|
|
46
|
+
live = new WeakMap();
|
|
47
|
+
/** The graph setting each view's values, where one does: see `set`. */
|
|
48
|
+
setters = new WeakMap();
|
|
49
|
+
constructor(native, touched) {
|
|
22
50
|
this.native = native;
|
|
51
|
+
this.touched = touched;
|
|
52
|
+
}
|
|
53
|
+
/** The style keys a graph of this driver's playing or driving a view sets on it now. */
|
|
54
|
+
held(view) {
|
|
55
|
+
const graphs = this.live.get(view);
|
|
56
|
+
return graphs ? new Set([...graphs.values()].flat()) : NONE_HELD;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Set a view's values on native, where a graph that has let it go set them before and no commit
|
|
60
|
+
* can now (see `Touched`). One graph per view, connected until the view is let go or a graph
|
|
61
|
+
* that plays it is connected: a value node for each number, set where it changed.
|
|
62
|
+
*/
|
|
63
|
+
set(view, viewTag, values) {
|
|
64
|
+
const { API } = this.native;
|
|
65
|
+
const shape = shapeOf(values);
|
|
66
|
+
let setter = this.setters.get(view);
|
|
67
|
+
const fresh = setter?.tag !== viewTag || setter.shape !== shape;
|
|
68
|
+
if (fresh) {
|
|
69
|
+
this.forget(view);
|
|
70
|
+
setter = this.buildSetter(viewTag, shape, values);
|
|
71
|
+
this.setters.set(view, setter);
|
|
72
|
+
this.touched?.(view, viewTag, Object.keys(values));
|
|
73
|
+
}
|
|
74
|
+
for (const [path, value] of leavesOf(values)) {
|
|
75
|
+
API.setAnimatedNodeValue(setter.leaves.get(path), value);
|
|
76
|
+
}
|
|
77
|
+
this.flush();
|
|
78
|
+
}
|
|
79
|
+
/** Let go of a view `set` set values on: it is made again, or gone. */
|
|
80
|
+
forget(view) {
|
|
81
|
+
const setter = this.setters.get(view);
|
|
82
|
+
if (!setter)
|
|
83
|
+
return;
|
|
84
|
+
this.setters.delete(view);
|
|
85
|
+
const { API } = this.native;
|
|
86
|
+
API.disconnectAnimatedNodeFromView(setter.props, setter.tag);
|
|
87
|
+
for (const node of setter.nodes)
|
|
88
|
+
API.dropAnimatedNode(node);
|
|
89
|
+
this.flush();
|
|
90
|
+
}
|
|
91
|
+
buildSetter(viewTag, shape, values) {
|
|
92
|
+
const { API } = this.native;
|
|
93
|
+
const nodes = [];
|
|
94
|
+
const leaves = new Map();
|
|
95
|
+
const made = (config) => {
|
|
96
|
+
const node = this.native.generateNewNodeTag();
|
|
97
|
+
API.createAnimatedNode(node, config);
|
|
98
|
+
nodes.push(node);
|
|
99
|
+
return node;
|
|
100
|
+
};
|
|
101
|
+
const leaf = (path, value) => {
|
|
102
|
+
const node = made({ type: 'value', value, offset: 0 });
|
|
103
|
+
leaves.set(path, node);
|
|
104
|
+
return node;
|
|
105
|
+
};
|
|
106
|
+
const style = {};
|
|
107
|
+
if (values.opacity !== undefined)
|
|
108
|
+
style['opacity'] = leaf('opacity', values.opacity);
|
|
109
|
+
if (values.transform) {
|
|
110
|
+
const transforms = values.transform.map((entry, at) => ({
|
|
111
|
+
type: 'animated',
|
|
112
|
+
property: entry.property,
|
|
113
|
+
nodeTag: leaf(`transform.${at}`, entry.value),
|
|
114
|
+
}));
|
|
115
|
+
const transform = made({ type: 'transform', transforms });
|
|
116
|
+
for (const entry of transforms)
|
|
117
|
+
API.connectAnimatedNodes(entry.nodeTag, transform);
|
|
118
|
+
style['transform'] = transform;
|
|
119
|
+
}
|
|
120
|
+
// A style node between, as `Animated` builds it: see `build`.
|
|
121
|
+
const styleNode = made({ type: 'style', style });
|
|
122
|
+
for (const node of Object.values(style))
|
|
123
|
+
API.connectAnimatedNodes(node, styleNode);
|
|
124
|
+
const props = made({ type: 'props', props: { style: styleNode } });
|
|
125
|
+
API.connectAnimatedNodes(styleNode, props);
|
|
126
|
+
API.connectAnimatedNodeToView(props, viewTag);
|
|
127
|
+
return { tag: viewTag, shape, props, nodes: nodes.reverse(), leaves };
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Note a graph connected to a view, for `held`, and tell whoever asked of it. The graph that
|
|
131
|
+
* set the view's values lets go: the one that plays it sets them from here.
|
|
132
|
+
*/
|
|
133
|
+
hold(view, viewTag, props, keys) {
|
|
134
|
+
this.forget(view);
|
|
135
|
+
const graphs = this.live.get(view) ?? new Map();
|
|
136
|
+
this.live.set(view, graphs.set(props, keys));
|
|
137
|
+
this.touched?.(view, viewTag, keys);
|
|
138
|
+
}
|
|
139
|
+
letGo(view, props) {
|
|
140
|
+
const graphs = this.live.get(view);
|
|
141
|
+
if (graphs?.delete(props) && !graphs.size)
|
|
142
|
+
this.live.delete(view);
|
|
23
143
|
}
|
|
24
144
|
/**
|
|
25
145
|
* Move a view by a scroll. `tagOf` answers a node's view tag once it has been committed, and
|
|
@@ -39,6 +159,7 @@ export class NativeScrollDriver {
|
|
|
39
159
|
drive.viewTag = viewTag;
|
|
40
160
|
const offset = this.offset(source, sourceTag, feed, key);
|
|
41
161
|
drive.nodes = this.build(offset.value, viewTag, property, drive, statics);
|
|
162
|
+
this.hold(view, viewTag, drive.nodes.props, ['transform']);
|
|
42
163
|
this.flush();
|
|
43
164
|
return true;
|
|
44
165
|
};
|
|
@@ -52,8 +173,10 @@ export class NativeScrollDriver {
|
|
|
52
173
|
if (!drive.nodes || drive.viewTag === null)
|
|
53
174
|
return;
|
|
54
175
|
this.tearDown(drive.nodes, drive.viewTag);
|
|
176
|
+
this.letGo(view, drive.nodes.props);
|
|
55
177
|
const offset = this.offsets.get(source).get(key);
|
|
56
178
|
drive.nodes = this.build(offset.value, drive.viewTag, property, drive, statics);
|
|
179
|
+
this.hold(view, drive.viewTag, drive.nodes.props, ['transform']);
|
|
57
180
|
this.flush();
|
|
58
181
|
},
|
|
59
182
|
shift: (amount) => {
|
|
@@ -73,6 +196,7 @@ export class NativeScrollDriver {
|
|
|
73
196
|
if (!drive.nodes || drive.viewTag === null)
|
|
74
197
|
return;
|
|
75
198
|
this.tearDown(drive.nodes, drive.viewTag);
|
|
199
|
+
this.letGo(view, drive.nodes.props);
|
|
76
200
|
this.release(source, key);
|
|
77
201
|
this.flush();
|
|
78
202
|
},
|
|
@@ -100,7 +224,7 @@ export class NativeScrollDriver {
|
|
|
100
224
|
return false;
|
|
101
225
|
state.viewTag = viewTag;
|
|
102
226
|
const offset = this.offset(source, sourceTag, feed, key);
|
|
103
|
-
state.nodes = this.buildChannels(offset.value, viewTag, state.channels);
|
|
227
|
+
state.nodes = this.buildChannels(view, offset.value, viewTag, state.channels);
|
|
104
228
|
this.flush();
|
|
105
229
|
return true;
|
|
106
230
|
};
|
|
@@ -113,9 +237,9 @@ export class NativeScrollDriver {
|
|
|
113
237
|
state.channels = next;
|
|
114
238
|
if (!state.nodes || state.viewTag === null)
|
|
115
239
|
return;
|
|
116
|
-
this.dropChannels(state.nodes, state.viewTag);
|
|
240
|
+
this.dropChannels(view, state.nodes, state.viewTag);
|
|
117
241
|
const offset = this.offsets.get(source).get(key);
|
|
118
|
-
state.nodes = this.buildChannels(offset.value, state.viewTag, next);
|
|
242
|
+
state.nodes = this.buildChannels(view, offset.value, state.viewTag, next);
|
|
119
243
|
this.flush();
|
|
120
244
|
},
|
|
121
245
|
stop: () => {
|
|
@@ -125,7 +249,7 @@ export class NativeScrollDriver {
|
|
|
125
249
|
this.pending.delete(connect);
|
|
126
250
|
if (!state.nodes || state.viewTag === null)
|
|
127
251
|
return;
|
|
128
|
-
this.dropChannels(state.nodes, state.viewTag);
|
|
252
|
+
this.dropChannels(view, state.nodes, state.viewTag);
|
|
129
253
|
this.release(source, key);
|
|
130
254
|
this.flush();
|
|
131
255
|
},
|
|
@@ -160,7 +284,7 @@ export class NativeScrollDriver {
|
|
|
160
284
|
state.viewTag = viewTag;
|
|
161
285
|
state.value = this.native.generateNewNodeTag();
|
|
162
286
|
API.createAnimatedNode(state.value, { type: 'value', value: 0, offset: 0 });
|
|
163
|
-
state.nodes = this.buildChannels(state.value, viewTag, channels);
|
|
287
|
+
state.nodes = this.buildChannels(view, state.value, viewTag, channels);
|
|
164
288
|
state.id = this.native.generateNewAnimationId();
|
|
165
289
|
const config = { type: 'frames', frames: [...timing.frames], toValue: timing.toValue };
|
|
166
290
|
start(state.id, state.value, { ...config, iterations: timing.iterations }, (result) => {
|
|
@@ -190,14 +314,14 @@ export class NativeScrollDriver {
|
|
|
190
314
|
return;
|
|
191
315
|
if (state.id)
|
|
192
316
|
API.stopAnimation(state.id);
|
|
193
|
-
this.dropChannels(state.nodes, state.viewTag);
|
|
317
|
+
this.dropChannels(view, state.nodes, state.viewTag);
|
|
194
318
|
API.dropAnimatedNode(state.value);
|
|
195
319
|
this.flush();
|
|
196
320
|
},
|
|
197
321
|
};
|
|
198
322
|
}
|
|
199
323
|
/** The nodes for a set of channels, connected to the view; the props node first. */
|
|
200
|
-
buildChannels(value, viewTag, channels) {
|
|
324
|
+
buildChannels(view, value, viewTag, channels) {
|
|
201
325
|
const { API } = this.native;
|
|
202
326
|
const made = [];
|
|
203
327
|
const interpolation = (range) => {
|
|
@@ -246,10 +370,12 @@ export class NativeScrollDriver {
|
|
|
246
370
|
API.createAnimatedNode(props, { type: 'props', props: { style: styleTag } });
|
|
247
371
|
API.connectAnimatedNodes(styleTag, props);
|
|
248
372
|
API.connectAnimatedNodeToView(props, viewTag);
|
|
373
|
+
this.hold(view, viewTag, props, channelKeys(channels));
|
|
249
374
|
return [props, styleTag, ...made.reverse()];
|
|
250
375
|
}
|
|
251
|
-
dropChannels(nodes, viewTag) {
|
|
376
|
+
dropChannels(view, nodes, viewTag) {
|
|
252
377
|
const { API } = this.native;
|
|
378
|
+
this.letGo(view, nodes[0]);
|
|
253
379
|
API.disconnectAnimatedNodeFromView(nodes[0], viewTag);
|
|
254
380
|
for (const tag of nodes)
|
|
255
381
|
API.dropAnimatedNode(tag);
|
package/dist/native-drive.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native-drive.js","sourceRoot":"","sources":["../src/native-drive.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A view moved by a scroll view's offset on the native side, with no JavaScript in between.\n *\n * A sticky header moved by a transform set from each scroll event lags the scroll: the event\n * reaches JavaScript, the transform is committed, and by the time Fabric mounts it the content has\n * moved on, so on a fast fling the header shudders and comes away from the edge it is pinned to.\n * React Native's own sticky headers do not, because `ScrollViewStickyHeader` maps the offset onto\n * an animated value on the native side and interpolates the header's translate from it there.\n * This is that mapping, for the engine's nodes: the scroll view's offset along one axis feeds a\n * value, the value an interpolation, the interpolation a translate, and native applies it on every\n * frame the scroll view moves.\n *\n * It goes through React Native's own `NativeAnimatedHelper`, whose node tags every other animated\n * value in the app also comes from, so none of them can collide.\n */\n\n/** The part of React Native's `NativeAnimatedHelper` default export this uses. */\nexport interface NativeAnimated {\n generateNewNodeTag(): number;\n generateNewAnimationId?(): number;\n readonly API: {\n /** Run a value through `config` on the native side, and say when it has ended. */\n startAnimatingNode?(\n animationId: number,\n nodeTag: number,\n config: object,\n end: (result: { finished: boolean }) => void,\n ): void;\n stopAnimation?(animationId: number): void;\n createAnimatedNode(tag: number, config: object): void;\n connectAnimatedNodes(parentTag: number, childTag: number): void;\n disconnectAnimatedNodes(parentTag: number, childTag: number): void;\n connectAnimatedNodeToView(nodeTag: number, viewTag: number): void;\n disconnectAnimatedNodeFromView(nodeTag: number, viewTag: number): void;\n dropAnimatedNode(tag: number): void;\n addAnimatedEventToView(\n viewTag: number,\n eventName: string,\n mapping: { nativeEventPath: string[]; animatedValueTag: number },\n ): void;\n removeAnimatedEventFromView(viewTag: number, eventName: string, nodeTag: number): void;\n setAnimatedNodeValue(nodeTag: number, value: number): void;\n flushQueue?(): void;\n };\n}\n\nimport type { DrivenChannels } from './scroll-animation.ts';\n\nexport type ScrollAxis = 'x' | 'y';\n\n/** A native event that feeds a value: the events carrying it, and the path to it in each. */\nexport interface EventFeed {\n readonly events: readonly string[];\n readonly path: readonly string[];\n}\n\n/** What a driven view moves along. */\nexport type DrivenProperty = 'translateX' | 'translateY';\n\n/** Where a driven view sits for each scroll offset, as an interpolation clamped at both ends. */\nexport interface ScrollRange {\n readonly input: readonly number[];\n readonly output: readonly number[];\n}\n\n/** A transform native keeps beside the driven translate, such as an inverted list's flip. */\nexport type StaticTransform = Readonly<Record<string, number>>;\n\n/**\n * A view moved by a scroll. `update` moves it by a new range; `shift` adds an amount to where the\n * range puts it, for a drive made with one; `stop` lets it go.\n */\nexport interface ScrollDrive {\n update(range: ScrollRange): void;\n shift(amount: number): void;\n stop(): void;\n}\n\ninterface Offset {\n readonly value: number;\n readonly viewTag: number;\n readonly feed: EventFeed;\n users: number;\n}\n\ninterface Nodes {\n interpolation: number;\n /** The shift JavaScript sets, and the sum of it and the interpolation, for a shifted drive. */\n shift: number | null;\n sum: number | null;\n transform: number;\n style: number;\n props: number;\n}\n\ninterface Drive {\n viewTag: number | null;\n range: ScrollRange;\n /** The amount added to the range's translate, or null for a drive without one. */\n shift: number | null;\n nodes: Nodes | null;\n stopped: boolean;\n}\n\nexport class NativeScrollDriver {\n private readonly native: NativeAnimated;\n /** One value per source view and feed, by the feed's key. */\n private readonly offsets = new Map<object, Map<string, Offset>>();\n private readonly pending = new Set<() => boolean>();\n\n constructor(native: NativeAnimated) {\n this.native = native;\n }\n\n /**\n * Move a view by a scroll. `tagOf` answers a node's view tag once it has been committed, and\n * null before, which is why the connection may wait for a commit: `connect` is tried again by\n * `afterCommit` until both views exist.\n */\n drive(\n view: object,\n source: object,\n feed: EventFeed,\n property: DrivenProperty,\n range: ScrollRange,\n statics: readonly StaticTransform[],\n tagOf: (node: object) => number | null,\n shift: number | null = null,\n ): ScrollDrive {\n const drive: Drive = { viewTag: null, range, shift, nodes: null, stopped: false };\n const key = feedKey(feed);\n const connect = (): boolean => {\n if (drive.stopped) return true;\n const viewTag = tagOf(view);\n const sourceTag = tagOf(source);\n if (viewTag === null || sourceTag === null) return false;\n drive.viewTag = viewTag;\n const offset = this.offset(source, sourceTag, feed, key);\n drive.nodes = this.build(offset.value, viewTag, property, drive, statics);\n this.flush();\n return true;\n };\n if (!connect()) this.pending.add(connect);\n return {\n update: (next) => {\n if (drive.stopped || sameRange(drive.range, next)) return;\n drive.range = next;\n if (!drive.nodes || drive.viewTag === null) return;\n this.tearDown(drive.nodes, drive.viewTag);\n const offset = this.offsets.get(source)!.get(key)!;\n drive.nodes = this.build(offset.value, drive.viewTag, property, drive, statics);\n this.flush();\n },\n shift: (amount) => {\n if (drive.stopped || drive.shift === null || drive.shift === amount) return;\n drive.shift = amount;\n if (drive.nodes?.shift == null) return;\n this.native.API.setAnimatedNodeValue(drive.nodes.shift, amount);\n this.flush();\n },\n stop: () => {\n if (drive.stopped) return;\n drive.stopped = true;\n this.pending.delete(connect);\n if (!drive.nodes || drive.viewTag === null) return;\n this.tearDown(drive.nodes, drive.viewTag);\n this.release(source, key);\n this.flush();\n },\n };\n }\n\n /**\n * Play a view's opacity and transform by a scroll: each channel an interpolation from the\n * offset, as `scroll-animation.ts` lays a `@keyframes` animation along it. `update` rebuilds\n * the channels, when the scroll view says how far it scrolls; `stop` lets the view go.\n */\n animate(\n view: object,\n source: object,\n feed: EventFeed,\n channels: DrivenChannels,\n tagOf: (node: object) => number | null,\n ): { update(channels: DrivenChannels): void; stop(): void } {\n const state = {\n channels,\n viewTag: null as number | null,\n nodes: null as number[] | null,\n stopped: false,\n };\n const key = feedKey(feed);\n const connect = (): boolean => {\n if (state.stopped) return true;\n const viewTag = tagOf(view);\n const sourceTag = tagOf(source);\n if (viewTag === null || sourceTag === null) return false;\n state.viewTag = viewTag;\n const offset = this.offset(source, sourceTag, feed, key);\n state.nodes = this.buildChannels(offset.value, viewTag, state.channels);\n this.flush();\n return true;\n };\n if (!connect()) this.pending.add(connect);\n return {\n update: (next) => {\n if (state.stopped) return;\n state.channels = next;\n if (!state.nodes || state.viewTag === null) return;\n this.dropChannels(state.nodes, state.viewTag);\n const offset = this.offsets.get(source)!.get(key)!;\n state.nodes = this.buildChannels(offset.value, state.viewTag, next);\n this.flush();\n },\n stop: () => {\n if (state.stopped) return;\n state.stopped = true;\n this.pending.delete(connect);\n if (!state.nodes || state.viewTag === null) return;\n this.dropChannels(state.nodes, state.viewTag);\n this.release(source, key);\n this.flush();\n },\n };\n }\n\n /**\n * Play a view's opacity and transform by the clock: each channel an interpolation from a value\n * native runs from nothing to `timing.toValue`, over the frames it is given, as many times as\n * asked. Nothing runs in JavaScript while it plays. `ended` is told when native reaches the end\n * of the last iteration; `stop` lets the view go, and stops an animation still playing.\n *\n * Null where the native module cannot start an animation, and the caller plays it itself.\n */\n play(\n view: object,\n channels: DrivenChannels,\n timing: { frames: readonly number[]; toValue: number; iterations: number },\n tagOf: (node: object) => number | null,\n ended: () => void,\n ): { stop(): void } | null {\n const { API } = this.native;\n const start = API.startAnimatingNode;\n if (!start || !API.stopAnimation || !this.native.generateNewAnimationId) return null;\n const state = {\n viewTag: null as number | null,\n nodes: null as number[] | null,\n value: 0,\n id: 0,\n over: false,\n };\n const connect = (): boolean => {\n if (state.over) return true;\n const viewTag = tagOf(view);\n if (viewTag === null) return false;\n state.viewTag = viewTag;\n state.value = this.native.generateNewNodeTag();\n API.createAnimatedNode(state.value, { type: 'value', value: 0, offset: 0 });\n state.nodes = this.buildChannels(state.value, viewTag, channels);\n state.id = this.native.generateNewAnimationId!();\n const config = { type: 'frames', frames: [...timing.frames], toValue: timing.toValue };\n start(state.id, state.value, { ...config, iterations: timing.iterations }, (result) => {\n // Stopped rather than finished is the caller's own doing, and it knows.\n if (!result.finished || state.over) return;\n state.id = 0;\n // Written once more, to the view as it is now. A view is mounted when the task that\n // made it is over, and an animation no longer than that task is over before there is a\n // view to move: the view is then mounted at the frame the animation started from.\n API.setAnimatedNodeValue(state.value, timing.toValue);\n this.flush();\n ended();\n });\n this.flush();\n return true;\n };\n if (!connect()) this.pending.add(connect);\n return {\n stop: () => {\n if (state.over) return;\n state.over = true;\n this.pending.delete(connect);\n if (!state.nodes || state.viewTag === null) return;\n if (state.id) API.stopAnimation!(state.id);\n this.dropChannels(state.nodes, state.viewTag);\n API.dropAnimatedNode(state.value);\n this.flush();\n },\n };\n }\n\n /** The nodes for a set of channels, connected to the view; the props node first. */\n private buildChannels(value: number, viewTag: number, channels: DrivenChannels): number[] {\n const { API } = this.native;\n const made: number[] = [];\n const interpolation = (range: ScrollRange): number => {\n const tag = this.native.generateNewNodeTag();\n API.createAnimatedNode(tag, {\n type: 'interpolation',\n inputRange: [...range.input],\n outputRange: [...range.output],\n extrapolateLeft: 'clamp',\n extrapolateRight: 'clamp',\n });\n API.connectAnimatedNodes(value, tag);\n made.push(tag);\n return tag;\n };\n const style: Record<string, number> = {};\n if (channels.opacity) style['opacity'] = interpolation(channels.opacity);\n for (const [property, parts] of Object.entries(channels.colors ?? {})) {\n const [r, g, b, a] = parts.map(interpolation);\n const colour = this.native.generateNewNodeTag();\n API.createAnimatedNode(colour, { type: 'color', r, g, b, a });\n for (const part of [r, g, b, a]) API.connectAnimatedNodes(part!, colour);\n style[property] = colour;\n made.push(colour);\n }\n if (channels.transform.length) {\n const transforms = channels.transform.map((channel) =>\n 'range' in channel\n ? { type: 'animated', property: channel.property, nodeTag: interpolation(channel.range) }\n : { type: 'static', property: channel.property, value: channel.value },\n );\n const transform = this.native.generateNewNodeTag();\n API.createAnimatedNode(transform, { type: 'transform', transforms });\n for (const entry of transforms) {\n if (entry.type === 'animated') API.connectAnimatedNodes(entry.nodeTag!, transform);\n }\n style['transform'] = transform;\n made.push(transform);\n }\n const styleTag = this.native.generateNewNodeTag();\n API.createAnimatedNode(styleTag, { type: 'style', style });\n for (const tag of Object.values(style)) API.connectAnimatedNodes(tag, styleTag);\n const props = this.native.generateNewNodeTag();\n API.createAnimatedNode(props, { type: 'props', props: { style: styleTag } });\n API.connectAnimatedNodes(styleTag, props);\n API.connectAnimatedNodeToView(props, viewTag);\n return [props, styleTag, ...made.reverse()];\n }\n\n private dropChannels(nodes: readonly number[], viewTag: number): void {\n const { API } = this.native;\n API.disconnectAnimatedNodeFromView(nodes[0]!, viewTag);\n for (const tag of nodes) API.dropAnimatedNode(tag);\n }\n\n /** Connects every drive still waiting for its views, now that a commit may have made them. */\n afterCommit(): void {\n for (const connect of [...this.pending]) if (connect()) this.pending.delete(connect);\n }\n\n /** One value per source view and feed, fed by its events, shared by every view it drives. */\n private offset(source: object, viewTag: number, feed: EventFeed, key: string): Offset {\n let feeds = this.offsets.get(source);\n if (!feeds) this.offsets.set(source, (feeds = new Map()));\n let offset = feeds.get(key);\n if (!offset) {\n const value = this.native.generateNewNodeTag();\n this.native.API.createAnimatedNode(value, { type: 'value', value: 0, offset: 0 });\n for (const event of feed.events) {\n this.native.API.addAnimatedEventToView(viewTag, event, {\n nativeEventPath: [...feed.path],\n animatedValueTag: value,\n });\n }\n offset = { value, viewTag, feed, users: 0 };\n feeds.set(key, offset);\n }\n offset.users++;\n return offset;\n }\n\n private release(source: object, key: string): void {\n const feeds = this.offsets.get(source);\n const offset = feeds?.get(key);\n if (!feeds || !offset || --offset.users > 0) return;\n feeds.delete(key);\n if (feeds.size === 0) this.offsets.delete(source);\n for (const event of offset.feed.events) {\n this.native.API.removeAnimatedEventFromView(offset.viewTag, event, offset.value);\n }\n this.native.API.dropAnimatedNode(offset.value);\n }\n\n private build(\n value: number,\n viewTag: number,\n property: DrivenProperty,\n drive: Drive,\n statics: readonly StaticTransform[],\n ): Nodes {\n const { API } = this.native;\n const range = drive.range;\n const interpolation = this.native.generateNewNodeTag();\n API.createAnimatedNode(interpolation, {\n type: 'interpolation',\n inputRange: [...range.input],\n outputRange: [...range.output],\n extrapolateLeft: 'clamp',\n extrapolateRight: 'clamp',\n });\n let shift: number | null = null;\n let sum: number | null = null;\n if (drive.shift !== null) {\n shift = this.native.generateNewNodeTag();\n API.createAnimatedNode(shift, { type: 'value', value: drive.shift, offset: 0 });\n sum = this.native.generateNewNodeTag();\n API.createAnimatedNode(sum, { type: 'addition', input: [interpolation, shift] });\n }\n const transform = this.native.generateNewNodeTag();\n API.createAnimatedNode(transform, {\n type: 'transform',\n transforms: [\n {\n type: 'animated',\n property,\n nodeTag: sum ?? interpolation,\n },\n ...statics.flatMap((entry) =>\n Object.entries(entry).map(([property, amount]) => ({\n type: 'static',\n property,\n value: amount,\n })),\n ),\n ],\n });\n // A style node between, as `Animated` builds it: RN's props node on iOS reads its values from\n // a style node and ignores a transform node connected to it directly.\n const style = this.native.generateNewNodeTag();\n API.createAnimatedNode(style, { type: 'style', style: { transform } });\n const props = this.native.generateNewNodeTag();\n API.createAnimatedNode(props, { type: 'props', props: { style } });\n API.connectAnimatedNodes(value, interpolation);\n if (shift !== null && sum !== null) {\n API.connectAnimatedNodes(interpolation, sum);\n API.connectAnimatedNodes(shift, sum);\n API.connectAnimatedNodes(sum, transform);\n } else {\n API.connectAnimatedNodes(interpolation, transform);\n }\n API.connectAnimatedNodes(transform, style);\n API.connectAnimatedNodes(style, props);\n API.connectAnimatedNodeToView(props, viewTag);\n return { interpolation, shift, sum, transform, style, props };\n }\n\n private tearDown(nodes: Nodes, viewTag: number): void {\n const { API } = this.native;\n API.disconnectAnimatedNodeFromView(nodes.props, viewTag);\n API.dropAnimatedNode(nodes.props);\n API.dropAnimatedNode(nodes.style);\n API.dropAnimatedNode(nodes.transform);\n if (nodes.sum !== null) API.dropAnimatedNode(nodes.sum);\n if (nodes.shift !== null) API.dropAnimatedNode(nodes.shift);\n API.dropAnimatedNode(nodes.interpolation);\n }\n\n private flush(): void {\n this.native.API.flushQueue?.();\n }\n}\n\nfunction feedKey(feed: EventFeed): string {\n return `${feed.events.join(',')}:${feed.path.join('.')}`;\n}\n\n/** A scroll view's offset along an axis, as `onScroll` carries it. */\nexport function scrollFeed(axis: ScrollAxis): EventFeed {\n return { events: ['onScroll'], path: ['contentOffset', axis] };\n}\n\nfunction sameRange(a: ScrollRange, b: ScrollRange): boolean {\n return (\n a.input.length === b.input.length &&\n a.input.every((value, i) => value === b.input[i]) &&\n a.output.every((value, i) => value === b.output[i])\n );\n}\n\n/**\n * The translate a pinned view needs at each scroll offset: none until the offset reaches where\n * the view starts, then the offset past that, until `until`, where the next pinned view pushes it\n * off and it stays. `start` and `until` are in the scroll view's own coordinates.\n */\nexport function pinnedRange(start: number, until = Infinity): ScrollRange {\n if (!Number.isFinite(until) || until <= start) {\n // A large finite end, since native interpolation takes numbers and extends nothing here.\n return { input: [start, start + 1e7], output: [0, 1e7] };\n }\n return { input: [start, until], output: [0, until - start] };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"native-drive.js","sourceRoot":"","sources":["../src/native-drive.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A view moved by a scroll view's offset on the native side, with no JavaScript in between.\n *\n * A sticky header moved by a transform set from each scroll event lags the scroll: the event\n * reaches JavaScript, the transform is committed, and by the time Fabric mounts it the content has\n * moved on, so on a fast fling the header shudders and comes away from the edge it is pinned to.\n * React Native's own sticky headers do not, because `ScrollViewStickyHeader` maps the offset onto\n * an animated value on the native side and interpolates the header's translate from it there.\n * This is that mapping, for the engine's nodes: the scroll view's offset along one axis feeds a\n * value, the value an interpolation, the interpolation a translate, and native applies it on every\n * frame the scroll view moves.\n *\n * It goes through React Native's own `NativeAnimatedHelper`, whose node tags every other animated\n * value in the app also comes from, so none of them can collide.\n */\n\n/** The part of React Native's `NativeAnimatedHelper` default export this uses. */\nexport interface NativeAnimated {\n generateNewNodeTag(): number;\n generateNewAnimationId?(): number;\n readonly API: {\n /** Run a value through `config` on the native side, and say when it has ended. */\n startAnimatingNode?(\n animationId: number,\n nodeTag: number,\n config: object,\n end: (result: { finished: boolean }) => void,\n ): void;\n stopAnimation?(animationId: number): void;\n createAnimatedNode(tag: number, config: object): void;\n connectAnimatedNodes(parentTag: number, childTag: number): void;\n disconnectAnimatedNodes(parentTag: number, childTag: number): void;\n connectAnimatedNodeToView(nodeTag: number, viewTag: number): void;\n disconnectAnimatedNodeFromView(nodeTag: number, viewTag: number): void;\n dropAnimatedNode(tag: number): void;\n addAnimatedEventToView(\n viewTag: number,\n eventName: string,\n mapping: { nativeEventPath: string[]; animatedValueTag: number },\n ): void;\n removeAnimatedEventFromView(viewTag: number, eventName: string, nodeTag: number): void;\n setAnimatedNodeValue(nodeTag: number, value: number): void;\n flushQueue?(): void;\n };\n}\n\nimport type { DrivenChannels } from './scroll-animation.ts';\n\nexport type ScrollAxis = 'x' | 'y';\n\n/** A native event that feeds a value: the events carrying it, and the path to it in each. */\nexport interface EventFeed {\n readonly events: readonly string[];\n readonly path: readonly string[];\n}\n\n/** What a driven view moves along. */\nexport type DrivenProperty = 'translateX' | 'translateY';\n\n/** Where a driven view sits for each scroll offset, as an interpolation clamped at both ends. */\nexport interface ScrollRange {\n readonly input: readonly number[];\n readonly output: readonly number[];\n}\n\n/** A transform native keeps beside the driven translate, such as an inverted list's flip. */\nexport type StaticTransform = Readonly<Record<string, number>>;\n\n/**\n * A view moved by a scroll. `update` moves it by a new range; `shift` adds an amount to where the\n * range puts it, for a drive made with one; `stop` lets it go.\n */\nexport interface ScrollDrive {\n update(range: ScrollRange): void;\n shift(amount: number): void;\n stop(): void;\n}\n\ninterface Offset {\n readonly value: number;\n readonly viewTag: number;\n readonly feed: EventFeed;\n users: number;\n}\n\ninterface Nodes {\n interpolation: number;\n /** The shift JavaScript sets, and the sum of it and the interpolation, for a shifted drive. */\n shift: number | null;\n sum: number | null;\n transform: number;\n style: number;\n props: number;\n}\n\ninterface Drive {\n viewTag: number | null;\n range: ScrollRange;\n /** The amount added to the range's translate, or null for a drive without one. */\n shift: number | null;\n nodes: Nodes | null;\n stopped: boolean;\n}\n\n/**\n * Told of each view a graph is connected to, with the props it sets there. Once a graph has set\n * a view's `transform` or `opacity`, React Native lets no commit change it again: iOS skips both\n * for good (`propKeysManagedByAnimated`), and Android puts the last value set back over each\n * commit's (`overrideBySynchronousMountPropsAtMountingAndroid`), until the view is made again.\n */\nexport type Touched = (view: object, viewTag: number, keys: readonly string[]) => void;\n\n/**\n * What a view is set to on native with no animation, where a graph has set it before: see\n * `NativeScrollDriver.set`. A transform is each entry's amount: points, a factor, or an angle in\n * radians.\n */\nexport interface SetValues {\n opacity?: number;\n transform?: readonly { readonly property: string; readonly value: number }[];\n}\n\n/** The graph that sets a view's values: a value node for each number, by its path. */\ninterface Setter {\n readonly tag: number;\n readonly shape: string;\n readonly props: number;\n /** Every node made, the props node first, for dropping them. */\n readonly nodes: readonly number[];\n readonly leaves: ReadonlyMap<string, number>;\n}\n\n/** The style keys a graph's channels set. */\nfunction channelKeys(channels: DrivenChannels): string[] {\n const keys = Object.keys(channels.colors ?? {});\n if (channels.opacity) keys.push('opacity');\n if (channels.transform.length) keys.push('transform');\n return keys;\n}\n\n/** Every number a set of values holds, by its path in the graph. */\nfunction leavesOf(values: SetValues): Map<string, number> {\n const leaves = new Map<string, number>();\n if (values.opacity !== undefined) leaves.set('opacity', values.opacity);\n values.transform?.forEach((entry, at) => leaves.set(`transform.${at}`, entry.value));\n return leaves;\n}\n\n/** What makes two sets of values the same graph: which keys, and the transform's properties. */\nfunction shapeOf(values: SetValues): string {\n const transform = values.transform?.map((entry) => entry.property).join(',');\n return `${values.opacity === undefined ? '' : 'o'}|${transform ?? '-'}`;\n}\n\nconst NONE_HELD: ReadonlySet<string> = new Set();\n\nexport class NativeScrollDriver {\n private readonly native: NativeAnimated;\n private readonly touched: Touched | undefined;\n /** One value per source view and feed, by the feed's key. */\n private readonly offsets = new Map<object, Map<string, Offset>>();\n private readonly pending = new Set<() => boolean>();\n /** The keys each graph connected to a view sets, by its props node, while it is connected. */\n private readonly live = new WeakMap<object, Map<number, readonly string[]>>();\n /** The graph setting each view's values, where one does: see `set`. */\n private readonly setters = new WeakMap<object, Setter>();\n\n constructor(native: NativeAnimated, touched?: Touched) {\n this.native = native;\n this.touched = touched;\n }\n\n /** The style keys a graph of this driver's playing or driving a view sets on it now. */\n held(view: object): ReadonlySet<string> {\n const graphs = this.live.get(view);\n return graphs ? new Set([...graphs.values()].flat()) : NONE_HELD;\n }\n\n /**\n * Set a view's values on native, where a graph that has let it go set them before and no commit\n * can now (see `Touched`). One graph per view, connected until the view is let go or a graph\n * that plays it is connected: a value node for each number, set where it changed.\n */\n set(view: object, viewTag: number, values: SetValues): void {\n const { API } = this.native;\n const shape = shapeOf(values);\n let setter = this.setters.get(view);\n const fresh = setter?.tag !== viewTag || setter.shape !== shape;\n if (fresh) {\n this.forget(view);\n setter = this.buildSetter(viewTag, shape, values);\n this.setters.set(view, setter);\n this.touched?.(view, viewTag, Object.keys(values));\n }\n for (const [path, value] of leavesOf(values)) {\n API.setAnimatedNodeValue(setter!.leaves.get(path)!, value);\n }\n this.flush();\n }\n\n /** Let go of a view `set` set values on: it is made again, or gone. */\n forget(view: object): void {\n const setter = this.setters.get(view);\n if (!setter) return;\n this.setters.delete(view);\n const { API } = this.native;\n API.disconnectAnimatedNodeFromView(setter.props, setter.tag);\n for (const node of setter.nodes) API.dropAnimatedNode(node);\n this.flush();\n }\n\n private buildSetter(viewTag: number, shape: string, values: SetValues): Setter {\n const { API } = this.native;\n const nodes: number[] = [];\n const leaves = new Map<string, number>();\n const made = (config: object): number => {\n const node = this.native.generateNewNodeTag();\n API.createAnimatedNode(node, config);\n nodes.push(node);\n return node;\n };\n const leaf = (path: string, value: number): number => {\n const node = made({ type: 'value', value, offset: 0 });\n leaves.set(path, node);\n return node;\n };\n const style: Record<string, number> = {};\n if (values.opacity !== undefined) style['opacity'] = leaf('opacity', values.opacity);\n if (values.transform) {\n const transforms = values.transform.map((entry, at) => ({\n type: 'animated',\n property: entry.property,\n nodeTag: leaf(`transform.${at}`, entry.value),\n }));\n const transform = made({ type: 'transform', transforms });\n for (const entry of transforms) API.connectAnimatedNodes(entry.nodeTag, transform);\n style['transform'] = transform;\n }\n // A style node between, as `Animated` builds it: see `build`.\n const styleNode = made({ type: 'style', style });\n for (const node of Object.values(style)) API.connectAnimatedNodes(node, styleNode);\n const props = made({ type: 'props', props: { style: styleNode } });\n API.connectAnimatedNodes(styleNode, props);\n API.connectAnimatedNodeToView(props, viewTag);\n return { tag: viewTag, shape, props, nodes: nodes.reverse(), leaves };\n }\n\n /**\n * Note a graph connected to a view, for `held`, and tell whoever asked of it. The graph that\n * set the view's values lets go: the one that plays it sets them from here.\n */\n private hold(view: object, viewTag: number, props: number, keys: readonly string[]): void {\n this.forget(view);\n const graphs = this.live.get(view) ?? new Map<number, readonly string[]>();\n this.live.set(view, graphs.set(props, keys));\n this.touched?.(view, viewTag, keys);\n }\n\n private letGo(view: object, props: number): void {\n const graphs = this.live.get(view);\n if (graphs?.delete(props) && !graphs.size) this.live.delete(view);\n }\n\n /**\n * Move a view by a scroll. `tagOf` answers a node's view tag once it has been committed, and\n * null before, which is why the connection may wait for a commit: `connect` is tried again by\n * `afterCommit` until both views exist.\n */\n drive(\n view: object,\n source: object,\n feed: EventFeed,\n property: DrivenProperty,\n range: ScrollRange,\n statics: readonly StaticTransform[],\n tagOf: (node: object) => number | null,\n shift: number | null = null,\n ): ScrollDrive {\n const drive: Drive = { viewTag: null, range, shift, nodes: null, stopped: false };\n const key = feedKey(feed);\n const connect = (): boolean => {\n if (drive.stopped) return true;\n const viewTag = tagOf(view);\n const sourceTag = tagOf(source);\n if (viewTag === null || sourceTag === null) return false;\n drive.viewTag = viewTag;\n const offset = this.offset(source, sourceTag, feed, key);\n drive.nodes = this.build(offset.value, viewTag, property, drive, statics);\n this.hold(view, viewTag, drive.nodes.props, ['transform']);\n this.flush();\n return true;\n };\n if (!connect()) this.pending.add(connect);\n return {\n update: (next) => {\n if (drive.stopped || sameRange(drive.range, next)) return;\n drive.range = next;\n if (!drive.nodes || drive.viewTag === null) return;\n this.tearDown(drive.nodes, drive.viewTag);\n this.letGo(view, drive.nodes.props);\n const offset = this.offsets.get(source)!.get(key)!;\n drive.nodes = this.build(offset.value, drive.viewTag, property, drive, statics);\n this.hold(view, drive.viewTag, drive.nodes.props, ['transform']);\n this.flush();\n },\n shift: (amount) => {\n if (drive.stopped || drive.shift === null || drive.shift === amount) return;\n drive.shift = amount;\n if (drive.nodes?.shift == null) return;\n this.native.API.setAnimatedNodeValue(drive.nodes.shift, amount);\n this.flush();\n },\n stop: () => {\n if (drive.stopped) return;\n drive.stopped = true;\n this.pending.delete(connect);\n if (!drive.nodes || drive.viewTag === null) return;\n this.tearDown(drive.nodes, drive.viewTag);\n this.letGo(view, drive.nodes.props);\n this.release(source, key);\n this.flush();\n },\n };\n }\n\n /**\n * Play a view's opacity and transform by a scroll: each channel an interpolation from the\n * offset, as `scroll-animation.ts` lays a `@keyframes` animation along it. `update` rebuilds\n * the channels, when the scroll view says how far it scrolls; `stop` lets the view go.\n */\n animate(\n view: object,\n source: object,\n feed: EventFeed,\n channels: DrivenChannels,\n tagOf: (node: object) => number | null,\n ): { update(channels: DrivenChannels): void; stop(): void } {\n const state = {\n channels,\n viewTag: null as number | null,\n nodes: null as number[] | null,\n stopped: false,\n };\n const key = feedKey(feed);\n const connect = (): boolean => {\n if (state.stopped) return true;\n const viewTag = tagOf(view);\n const sourceTag = tagOf(source);\n if (viewTag === null || sourceTag === null) return false;\n state.viewTag = viewTag;\n const offset = this.offset(source, sourceTag, feed, key);\n state.nodes = this.buildChannels(view, offset.value, viewTag, state.channels);\n this.flush();\n return true;\n };\n if (!connect()) this.pending.add(connect);\n return {\n update: (next) => {\n if (state.stopped) return;\n state.channels = next;\n if (!state.nodes || state.viewTag === null) return;\n this.dropChannels(view, state.nodes, state.viewTag);\n const offset = this.offsets.get(source)!.get(key)!;\n state.nodes = this.buildChannels(view, offset.value, state.viewTag, next);\n this.flush();\n },\n stop: () => {\n if (state.stopped) return;\n state.stopped = true;\n this.pending.delete(connect);\n if (!state.nodes || state.viewTag === null) return;\n this.dropChannels(view, state.nodes, state.viewTag);\n this.release(source, key);\n this.flush();\n },\n };\n }\n\n /**\n * Play a view's opacity and transform by the clock: each channel an interpolation from a value\n * native runs from nothing to `timing.toValue`, over the frames it is given, as many times as\n * asked. Nothing runs in JavaScript while it plays. `ended` is told when native reaches the end\n * of the last iteration; `stop` lets the view go, and stops an animation still playing.\n *\n * Null where the native module cannot start an animation, and the caller plays it itself.\n */\n play(\n view: object,\n channels: DrivenChannels,\n timing: { frames: readonly number[]; toValue: number; iterations: number },\n tagOf: (node: object) => number | null,\n ended: () => void,\n ): { stop(): void } | null {\n const { API } = this.native;\n const start = API.startAnimatingNode;\n if (!start || !API.stopAnimation || !this.native.generateNewAnimationId) return null;\n const state = {\n viewTag: null as number | null,\n nodes: null as number[] | null,\n value: 0,\n id: 0,\n over: false,\n };\n const connect = (): boolean => {\n if (state.over) return true;\n const viewTag = tagOf(view);\n if (viewTag === null) return false;\n state.viewTag = viewTag;\n state.value = this.native.generateNewNodeTag();\n API.createAnimatedNode(state.value, { type: 'value', value: 0, offset: 0 });\n state.nodes = this.buildChannels(view, state.value, viewTag, channels);\n state.id = this.native.generateNewAnimationId!();\n const config = { type: 'frames', frames: [...timing.frames], toValue: timing.toValue };\n start(state.id, state.value, { ...config, iterations: timing.iterations }, (result) => {\n // Stopped rather than finished is the caller's own doing, and it knows.\n if (!result.finished || state.over) return;\n state.id = 0;\n // Written once more, to the view as it is now. A view is mounted when the task that\n // made it is over, and an animation no longer than that task is over before there is a\n // view to move: the view is then mounted at the frame the animation started from.\n API.setAnimatedNodeValue(state.value, timing.toValue);\n this.flush();\n ended();\n });\n this.flush();\n return true;\n };\n if (!connect()) this.pending.add(connect);\n return {\n stop: () => {\n if (state.over) return;\n state.over = true;\n this.pending.delete(connect);\n if (!state.nodes || state.viewTag === null) return;\n if (state.id) API.stopAnimation!(state.id);\n this.dropChannels(view, state.nodes, state.viewTag);\n API.dropAnimatedNode(state.value);\n this.flush();\n },\n };\n }\n\n /** The nodes for a set of channels, connected to the view; the props node first. */\n private buildChannels(\n view: object,\n value: number,\n viewTag: number,\n channels: DrivenChannels,\n ): number[] {\n const { API } = this.native;\n const made: number[] = [];\n const interpolation = (range: ScrollRange): number => {\n const tag = this.native.generateNewNodeTag();\n API.createAnimatedNode(tag, {\n type: 'interpolation',\n inputRange: [...range.input],\n outputRange: [...range.output],\n extrapolateLeft: 'clamp',\n extrapolateRight: 'clamp',\n });\n API.connectAnimatedNodes(value, tag);\n made.push(tag);\n return tag;\n };\n const style: Record<string, number> = {};\n if (channels.opacity) style['opacity'] = interpolation(channels.opacity);\n for (const [property, parts] of Object.entries(channels.colors ?? {})) {\n const [r, g, b, a] = parts.map(interpolation);\n const colour = this.native.generateNewNodeTag();\n API.createAnimatedNode(colour, { type: 'color', r, g, b, a });\n for (const part of [r, g, b, a]) API.connectAnimatedNodes(part!, colour);\n style[property] = colour;\n made.push(colour);\n }\n if (channels.transform.length) {\n const transforms = channels.transform.map((channel) =>\n 'range' in channel\n ? { type: 'animated', property: channel.property, nodeTag: interpolation(channel.range) }\n : { type: 'static', property: channel.property, value: channel.value },\n );\n const transform = this.native.generateNewNodeTag();\n API.createAnimatedNode(transform, { type: 'transform', transforms });\n for (const entry of transforms) {\n if (entry.type === 'animated') API.connectAnimatedNodes(entry.nodeTag!, transform);\n }\n style['transform'] = transform;\n made.push(transform);\n }\n const styleTag = this.native.generateNewNodeTag();\n API.createAnimatedNode(styleTag, { type: 'style', style });\n for (const tag of Object.values(style)) API.connectAnimatedNodes(tag, styleTag);\n const props = this.native.generateNewNodeTag();\n API.createAnimatedNode(props, { type: 'props', props: { style: styleTag } });\n API.connectAnimatedNodes(styleTag, props);\n API.connectAnimatedNodeToView(props, viewTag);\n this.hold(view, viewTag, props, channelKeys(channels));\n return [props, styleTag, ...made.reverse()];\n }\n\n private dropChannels(view: object, nodes: readonly number[], viewTag: number): void {\n const { API } = this.native;\n this.letGo(view, nodes[0]!);\n API.disconnectAnimatedNodeFromView(nodes[0]!, viewTag);\n for (const tag of nodes) API.dropAnimatedNode(tag);\n }\n\n /** Connects every drive still waiting for its views, now that a commit may have made them. */\n afterCommit(): void {\n for (const connect of [...this.pending]) if (connect()) this.pending.delete(connect);\n }\n\n /** One value per source view and feed, fed by its events, shared by every view it drives. */\n private offset(source: object, viewTag: number, feed: EventFeed, key: string): Offset {\n let feeds = this.offsets.get(source);\n if (!feeds) this.offsets.set(source, (feeds = new Map()));\n let offset = feeds.get(key);\n if (!offset) {\n const value = this.native.generateNewNodeTag();\n this.native.API.createAnimatedNode(value, { type: 'value', value: 0, offset: 0 });\n for (const event of feed.events) {\n this.native.API.addAnimatedEventToView(viewTag, event, {\n nativeEventPath: [...feed.path],\n animatedValueTag: value,\n });\n }\n offset = { value, viewTag, feed, users: 0 };\n feeds.set(key, offset);\n }\n offset.users++;\n return offset;\n }\n\n private release(source: object, key: string): void {\n const feeds = this.offsets.get(source);\n const offset = feeds?.get(key);\n if (!feeds || !offset || --offset.users > 0) return;\n feeds.delete(key);\n if (feeds.size === 0) this.offsets.delete(source);\n for (const event of offset.feed.events) {\n this.native.API.removeAnimatedEventFromView(offset.viewTag, event, offset.value);\n }\n this.native.API.dropAnimatedNode(offset.value);\n }\n\n private build(\n value: number,\n viewTag: number,\n property: DrivenProperty,\n drive: Drive,\n statics: readonly StaticTransform[],\n ): Nodes {\n const { API } = this.native;\n const range = drive.range;\n const interpolation = this.native.generateNewNodeTag();\n API.createAnimatedNode(interpolation, {\n type: 'interpolation',\n inputRange: [...range.input],\n outputRange: [...range.output],\n extrapolateLeft: 'clamp',\n extrapolateRight: 'clamp',\n });\n let shift: number | null = null;\n let sum: number | null = null;\n if (drive.shift !== null) {\n shift = this.native.generateNewNodeTag();\n API.createAnimatedNode(shift, { type: 'value', value: drive.shift, offset: 0 });\n sum = this.native.generateNewNodeTag();\n API.createAnimatedNode(sum, { type: 'addition', input: [interpolation, shift] });\n }\n const transform = this.native.generateNewNodeTag();\n API.createAnimatedNode(transform, {\n type: 'transform',\n transforms: [\n {\n type: 'animated',\n property,\n nodeTag: sum ?? interpolation,\n },\n ...statics.flatMap((entry) =>\n Object.entries(entry).map(([property, amount]) => ({\n type: 'static',\n property,\n value: amount,\n })),\n ),\n ],\n });\n // A style node between, as `Animated` builds it: RN's props node on iOS reads its values from\n // a style node and ignores a transform node connected to it directly.\n const style = this.native.generateNewNodeTag();\n API.createAnimatedNode(style, { type: 'style', style: { transform } });\n const props = this.native.generateNewNodeTag();\n API.createAnimatedNode(props, { type: 'props', props: { style } });\n API.connectAnimatedNodes(value, interpolation);\n if (shift !== null && sum !== null) {\n API.connectAnimatedNodes(interpolation, sum);\n API.connectAnimatedNodes(shift, sum);\n API.connectAnimatedNodes(sum, transform);\n } else {\n API.connectAnimatedNodes(interpolation, transform);\n }\n API.connectAnimatedNodes(transform, style);\n API.connectAnimatedNodes(style, props);\n API.connectAnimatedNodeToView(props, viewTag);\n return { interpolation, shift, sum, transform, style, props };\n }\n\n private tearDown(nodes: Nodes, viewTag: number): void {\n const { API } = this.native;\n API.disconnectAnimatedNodeFromView(nodes.props, viewTag);\n API.dropAnimatedNode(nodes.props);\n API.dropAnimatedNode(nodes.style);\n API.dropAnimatedNode(nodes.transform);\n if (nodes.sum !== null) API.dropAnimatedNode(nodes.sum);\n if (nodes.shift !== null) API.dropAnimatedNode(nodes.shift);\n API.dropAnimatedNode(nodes.interpolation);\n }\n\n private flush(): void {\n this.native.API.flushQueue?.();\n }\n}\n\nfunction feedKey(feed: EventFeed): string {\n return `${feed.events.join(',')}:${feed.path.join('.')}`;\n}\n\n/** A scroll view's offset along an axis, as `onScroll` carries it. */\nexport function scrollFeed(axis: ScrollAxis): EventFeed {\n return { events: ['onScroll'], path: ['contentOffset', axis] };\n}\n\nfunction sameRange(a: ScrollRange, b: ScrollRange): boolean {\n return (\n a.input.length === b.input.length &&\n a.input.every((value, i) => value === b.input[i]) &&\n a.output.every((value, i) => value === b.output[i])\n );\n}\n\n/**\n * The translate a pinned view needs at each scroll offset: none until the offset reaches where\n * the view starts, then the offset past that, until `until`, where the next pinned view pushes it\n * off and it stays. `start` and `until` are in the scroll view's own coordinates.\n */\nexport function pinnedRange(start: number, until = Infinity): ScrollRange {\n if (!Number.isFinite(until) || until <= start) {\n // A large finite end, since native interpolation takes numbers and extends nothing here.\n return { input: [start, start + 1e7], output: [0, 1e7] };\n }\n return { input: [start, until], output: [0, until - start] };\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type Constructor = abstract new (...args: never[]) => object;
|
|
2
|
+
/**
|
|
3
|
+
* Make `target` answer `instanceof` for engine nodes as well, and for everything it did before: its
|
|
4
|
+
* own `Symbol.hasInstance` if it defines one, and the ordinary prototype walk if not. Only for
|
|
5
|
+
* `target` itself, not a subclass that inherits the check: `Text` and `Element` answer for
|
|
6
|
+
* themselves.
|
|
7
|
+
*/
|
|
8
|
+
export declare function letEngineNodesPass(target: Constructor): void;
|
|
9
|
+
export declare function installNodeGlobal(): void;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Let an engine node pass Angular's `instanceof Node` checks, whichever `Node` the app has.
|
|
3
|
+
*
|
|
4
|
+
* Angular's development build asserts that a node is a `Node` where it creates and inserts one, and
|
|
5
|
+
* the i18n runtime tests it for each node of an ICU plural or select. An engine node is not a DOM
|
|
6
|
+
* node, so the Metro preset's `animation-globals` polyfill defines a `Node` that recognises them.
|
|
7
|
+
* But a polyfill runs before `InitializeCore`, and React Native 0.8x sets up its own `Node` there,
|
|
8
|
+
* with `polyfillGlobal`, which replaces whatever is on the global. The app was left with a `Node`
|
|
9
|
+
* that no engine node is an instance of, and every plural or select threw `The provided value must
|
|
10
|
+
* be an instance of a DOM Node but got #anchor` in a development build.
|
|
11
|
+
*
|
|
12
|
+
* This runs from `mount()`, after both, and makes the `Node` that is on the global then answer for
|
|
13
|
+
* engine nodes too. Nothing else about that class changes: its own instances still pass, and so
|
|
14
|
+
* does everything its own check accepts.
|
|
15
|
+
*/
|
|
16
|
+
import { isEngineNode } from "./engine.js";
|
|
17
|
+
/**
|
|
18
|
+
* Make `target` answer `instanceof` for engine nodes as well, and for everything it did before: its
|
|
19
|
+
* own `Symbol.hasInstance` if it defines one, and the ordinary prototype walk if not. Only for
|
|
20
|
+
* `target` itself, not a subclass that inherits the check: `Text` and `Element` answer for
|
|
21
|
+
* themselves.
|
|
22
|
+
*/
|
|
23
|
+
export function letEngineNodesPass(target) {
|
|
24
|
+
const own = target[Symbol.hasInstance];
|
|
25
|
+
Object.defineProperty(target, Symbol.hasInstance, {
|
|
26
|
+
configurable: true,
|
|
27
|
+
value(value) {
|
|
28
|
+
return (this === target && isEngineNode(value)) || own.call(this, value);
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
/** The classes already patched, so one `Node` is patched once however often an app is mounted. */
|
|
33
|
+
const patched = new WeakSet();
|
|
34
|
+
export function installNodeGlobal() {
|
|
35
|
+
const node = globalThis.Node;
|
|
36
|
+
if (typeof node !== 'function' || patched.has(node))
|
|
37
|
+
return;
|
|
38
|
+
patched.add(node);
|
|
39
|
+
letEngineNodesPass(node);
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=node-global.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-global.js","sourceRoot":"","sources":["../src/node-global.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAI3C;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAmB;IACpD,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IACvC,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,WAAW,EAAE;QAChD,YAAY,EAAE,IAAI;QAClB,KAAK,CAAoB,KAAc;YACrC,OAAO,CAAC,IAAI,KAAK,MAAM,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC3E,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,kGAAkG;AAClG,MAAM,OAAO,GAAG,IAAI,OAAO,EAAU,CAAC;AAEtC,MAAM,UAAU,iBAAiB;IAC/B,MAAM,IAAI,GAAI,UAAqC,CAAC,IAAI,CAAC;IACzD,IAAI,OAAO,IAAI,KAAK,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO;IAC5D,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClB,kBAAkB,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC","sourcesContent":["/**\n * Let an engine node pass Angular's `instanceof Node` checks, whichever `Node` the app has.\n *\n * Angular's development build asserts that a node is a `Node` where it creates and inserts one, and\n * the i18n runtime tests it for each node of an ICU plural or select. An engine node is not a DOM\n * node, so the Metro preset's `animation-globals` polyfill defines a `Node` that recognises them.\n * But a polyfill runs before `InitializeCore`, and React Native 0.8x sets up its own `Node` there,\n * with `polyfillGlobal`, which replaces whatever is on the global. The app was left with a `Node`\n * that no engine node is an instance of, and every plural or select threw `The provided value must\n * be an instance of a DOM Node but got #anchor` in a development build.\n *\n * This runs from `mount()`, after both, and makes the `Node` that is on the global then answer for\n * engine nodes too. Nothing else about that class changes: its own instances still pass, and so\n * does everything its own check accepts.\n */\nimport { isEngineNode } from './engine.ts';\n\nexport type Constructor = abstract new (...args: never[]) => object;\n\n/**\n * Make `target` answer `instanceof` for engine nodes as well, and for everything it did before: its\n * own `Symbol.hasInstance` if it defines one, and the ordinary prototype walk if not. Only for\n * `target` itself, not a subclass that inherits the check: `Text` and `Element` answer for\n * themselves.\n */\nexport function letEngineNodesPass(target: Constructor): void {\n const own = target[Symbol.hasInstance];\n Object.defineProperty(target, Symbol.hasInstance, {\n configurable: true,\n value(this: Constructor, value: unknown): boolean {\n return (this === target && isEngineNode(value)) || own.call(this, value);\n },\n });\n}\n\n/** The classes already patched, so one `Node` is patched once however often an app is mounted. */\nconst patched = new WeakSet<object>();\n\nexport function installNodeGlobal(): void {\n const node = (globalThis as { Node?: Constructor }).Node;\n if (typeof node !== 'function' || patched.has(node)) return;\n patched.add(node);\n letEngineNodesPass(node);\n}\n"]}
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
* the channels written make the new colour, brought back into sRGB as a mix is.
|
|
9
9
|
*/
|
|
10
10
|
import { type MixSpace } from './color-mix.ts';
|
|
11
|
-
/** A channel: a number, a keyword, or arithmetic on two channels. */
|
|
12
|
-
export type Channel = number | string | readonly [op: '+' | '-' | '*' | '/', Channel, Channel];
|
|
11
|
+
/** A channel: a number, a keyword, or arithmetic on two channels, `min()` and `max()` included. */
|
|
12
|
+
export type Channel = number | string | readonly [op: '+' | '-' | '*' | '/' | 'min' | 'max', Channel, Channel];
|
|
13
13
|
/**
|
|
14
14
|
* The colour the channels make from `origin`, as the `rgb()` or `rgba()` native reads. Undefined
|
|
15
15
|
* when the origin is not a colour this can read, such as a platform colour.
|
package/dist/relative-colour.js
CHANGED
|
@@ -66,6 +66,10 @@ function evaluate(channel, values) {
|
|
|
66
66
|
return left - right;
|
|
67
67
|
if (op === '*')
|
|
68
68
|
return left * right;
|
|
69
|
+
if (op === 'min')
|
|
70
|
+
return Math.min(left, right);
|
|
71
|
+
if (op === 'max')
|
|
72
|
+
return Math.max(left, right);
|
|
69
73
|
return left / right;
|
|
70
74
|
}
|
|
71
75
|
//# sourceMappingURL=relative-colour.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relative-colour.js","sourceRoot":"","sources":["../src/relative-colour.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,IAAI,EAAE,KAAK,EAA8B,MAAM,gBAAgB,CAAC;AACzE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"relative-colour.js","sourceRoot":"","sources":["../src/relative-colour.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A relative colour with a token in it, worked out on device: `oklch(from var(--brand) l c h /\n * 0.2)`. The compiler settles a relative colour of literals itself; one with a `var()` in it waits\n * for the token.\n *\n * The origin is converted into the function's space, each channel keyword is the number it is\n * there, on CSS Color 5's scale for it (`r g b` 0 to 255, hsl and hwb's `s l w b` 0 to 100), and\n * the channels written make the new colour, brought back into sRGB as a mix is.\n */\nimport { into, outOf, type MixSpace, type Vector } from './color-mix.ts';\nimport { parseColor } from './transition.ts';\n\n/** A channel: a number, a keyword, or arithmetic on two channels, `min()` and `max()` included. */\nexport type Channel =\n number | string | readonly [op: '+' | '-' | '*' | '/' | 'min' | 'max', Channel, Channel];\n\n/** What a keyword's number is, per unit of the space's own coordinate. */\nconst SCALES: Record<MixSpace, Vector> = {\n srgb: [255, 255, 255],\n hsl: [1, 100, 100],\n hwb: [1, 100, 100],\n lab: [1, 1, 1],\n lch: [1, 1, 1],\n oklab: [1, 1, 1],\n oklch: [1, 1, 1],\n};\n\nconst KEYWORDS: Record<MixSpace, readonly [string, string, string]> = {\n srgb: ['r', 'g', 'b'],\n hsl: ['h', 's', 'l'],\n hwb: ['h', 'w', 'b'],\n lab: ['l', 'a', 'b'],\n lch: ['l', 'c', 'h'],\n oklab: ['l', 'a', 'b'],\n oklch: ['l', 'c', 'h'],\n};\n\n/**\n * The colour the channels make from `origin`, as the `rgb()` or `rgba()` native reads. Undefined\n * when the origin is not a colour this can read, such as a platform colour.\n */\nexport function relativeColour(\n space: MixSpace,\n origin: string,\n channels: readonly [Channel, Channel, Channel],\n alpha?: Channel,\n): string | undefined {\n const parsed = parseColor(origin);\n if (!parsed) return undefined;\n const [r, g, b, originAlpha] = parsed;\n const coords = into(space, [r / 255, g / 255, b / 255]);\n const scale = SCALES[space];\n const values: Record<string, number> = { alpha: originAlpha };\n KEYWORDS[space].forEach((keyword, i) => {\n // A missing component is zero in relative syntax: a grey has no hue.\n values[keyword] = Number.isFinite(coords[i]) ? coords[i]! * scale[i]! : 0;\n });\n const made = channels.map((channel, i) => evaluate(channel, values) / scale[i]!) as Vector;\n const opacity = Math.min(\n 1,\n Math.max(0, alpha === undefined ? originAlpha : evaluate(alpha, values)),\n );\n const [red, green, blue] = outOf(space, made).map((c) => Math.round(c * 255));\n const rounded = Math.round(opacity * 1000) / 1000;\n return rounded >= 1\n ? `rgb(${red}, ${green}, ${blue})`\n : `rgba(${red}, ${green}, ${blue}, ${rounded})`;\n}\n\nfunction evaluate(channel: Channel, values: Readonly<Record<string, number>>): number {\n if (typeof channel === 'number') return channel;\n if (typeof channel === 'string') return values[channel] ?? 0;\n const [op, a, b] = channel;\n const left = evaluate(a, values);\n const right = evaluate(b, values);\n if (op === '+') return left + right;\n if (op === '-') return left - right;\n if (op === '*') return left * right;\n if (op === 'min') return Math.min(left, right);\n if (op === 'max') return Math.max(left, right);\n return left / right;\n}\n"]}
|
|
@@ -58,6 +58,18 @@ export declare function clockChannels(tracks: ReadonlyMap<string, Track>, spec:
|
|
|
58
58
|
held: string[];
|
|
59
59
|
span: number;
|
|
60
60
|
};
|
|
61
|
+
/**
|
|
62
|
+
* A transform as native's transform node holds it, entry by entry, each move by a share as the
|
|
63
|
+
* points it is of the box `sizeOf` answers. Null for one native cannot take that way: a matrix,
|
|
64
|
+
* or a share of a box with no size yet.
|
|
65
|
+
*/
|
|
66
|
+
export declare function heldTransform(value: unknown, sizeOf: () => {
|
|
67
|
+
width: number;
|
|
68
|
+
height: number;
|
|
69
|
+
} | undefined): {
|
|
70
|
+
property: string;
|
|
71
|
+
value: number;
|
|
72
|
+
}[] | null;
|
|
61
73
|
/** Whether an animation moves a box by a share of its own size, in a frame or at rest. */
|
|
62
74
|
export declare function movesByShare(tracks: ReadonlyMap<string, Track>, resting: Readonly<Record<string, unknown>>): boolean;
|
|
63
75
|
/**
|
package/dist/scroll-animation.js
CHANGED
|
@@ -153,6 +153,16 @@ function heldGroup(resting) {
|
|
|
153
153
|
}
|
|
154
154
|
return channels;
|
|
155
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* A transform as native's transform node holds it, entry by entry, each move by a share as the
|
|
158
|
+
* points it is of the box `sizeOf` answers. Null for one native cannot take that way: a matrix,
|
|
159
|
+
* or a share of a box with no size yet.
|
|
160
|
+
*/
|
|
161
|
+
export function heldTransform(value, sizeOf) {
|
|
162
|
+
const size = sharesIn(value) ? sizeOf() : undefined;
|
|
163
|
+
const channels = heldGroup(size ? inPoints(value, size) : value);
|
|
164
|
+
return channels;
|
|
165
|
+
}
|
|
156
166
|
function restingAmount(resting, index, key, identity) {
|
|
157
167
|
const entry = Array.isArray(resting) ? resting[index] : undefined;
|
|
158
168
|
return (entry && key in entry ? amount(key, entry[key]) : null) ?? identity;
|