@ng-native/fabric 0.4.0 → 0.6.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/color-mix.js +1 -16
- package/dist/color-mix.js.map +1 -1
- package/dist/css.d.ts +299 -28
- package/dist/css.js +1093 -122
- package/dist/css.js.map +1 -1
- package/dist/engine.d.ts +267 -3
- package/dist/engine.js +1209 -76
- package/dist/engine.js.map +1 -1
- package/dist/inline-token.js +27 -15
- package/dist/inline-token.js.map +1 -1
- package/dist/inline-transform.js +21 -3
- package/dist/inline-transform.js.map +1 -1
- package/dist/native-drive.d.ts +21 -0
- package/dist/native-drive.js +65 -0
- package/dist/native-drive.js.map +1 -1
- package/dist/premultiplied-stops.d.ts +7 -0
- package/dist/premultiplied-stops.js +131 -0
- package/dist/premultiplied-stops.js.map +1 -0
- package/dist/scroll-animation.d.ts +24 -0
- package/dist/scroll-animation.js +82 -4
- package/dist/scroll-animation.js.map +1 -1
- package/dist/transition.d.ts +15 -0
- package/dist/transition.js +134 -11
- package/dist/transition.js.map +1 -1
- package/package.json +1 -1
package/dist/inline-token.js
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import { CSS_SPACE } from "./css.js";
|
|
15
15
|
import { derivedToken } from "./inline-derived-token.js";
|
|
16
|
-
import { isNamedColor } from "./transition.js";
|
|
16
|
+
import { HUE_DEGREES, isNamedColor } from "./transition.js";
|
|
17
17
|
const PX = /^(-?\d*\.?\d+)px$/;
|
|
18
18
|
const PERCENT = /^-?\d*\.?\d+%$/;
|
|
19
19
|
const NUMBER = /^-?\d*\.?\d+$/;
|
|
@@ -23,7 +23,6 @@ const COLOR_FUNCTION = /^(#[\da-f]{3,8}|(rgba?|hsla?|hwb)\(.*\))$/i;
|
|
|
23
23
|
const WORD = /^-?[a-z][\w-]*$/i;
|
|
24
24
|
/** One colour channel: a number, a percentage, or a hue with its unit. */
|
|
25
25
|
const CHANNEL = /^(-?(?:\d+\.?\d*|\.\d+))(%|deg|grad|rad|turn)?$/;
|
|
26
|
-
const HUE_UNITS = { deg: 1, grad: 0.9, rad: 180 / Math.PI, turn: 360 };
|
|
27
26
|
/** `var(--name)` or `var(--name, <fallback>)`, the whole value. */
|
|
28
27
|
const VAR = /^var\([ \t\n\r\f]*(--[\w-]+)[ \t\n\r\f]*(?:,([\s\S]*))?\)$/i;
|
|
29
28
|
/**
|
|
@@ -140,7 +139,7 @@ function rgbChannels(values) {
|
|
|
140
139
|
}
|
|
141
140
|
/** As `hsl()` reads them: a hue, then two percentages, which the space syntax may write bare. */
|
|
142
141
|
function hslOf([hue, ...rest], spaced) {
|
|
143
|
-
const degrees = hue.n * (hue.unit === '' ? 1 : (
|
|
142
|
+
const degrees = hue.n * (hue.unit === '' ? 1 : (HUE_DEGREES[hue.unit] ?? NaN));
|
|
144
143
|
const fractions = rest.map((v) => v.unit === '%' || (spaced && v.unit === '') ? clamp(v.n / 100, 0, 1) : NaN);
|
|
145
144
|
const hsl = [degrees, ...fractions];
|
|
146
145
|
return hsl.every(Number.isFinite) ? hsl : undefined;
|
|
@@ -172,6 +171,28 @@ function balanced(text) {
|
|
|
172
171
|
}
|
|
173
172
|
return depth === 0;
|
|
174
173
|
}
|
|
174
|
+
/** A time as CSS writes one: a number of seconds or milliseconds. */
|
|
175
|
+
const TIME = /^([+-]?(?:\d+\.?\d*|\.\d+))(ms|s)$/i;
|
|
176
|
+
/** A number with a unit, as the token each is: a length, a percentage, an angle or a time. */
|
|
177
|
+
function withUnit(text) {
|
|
178
|
+
const px = PX.exec(text);
|
|
179
|
+
if (px)
|
|
180
|
+
return { length: Number(px[1]) };
|
|
181
|
+
// A percentage is a fraction as well, and an angle its degrees, as the build-time conversion
|
|
182
|
+
// reads them: an hsl() of tokens takes its saturation and its hue so.
|
|
183
|
+
if (PERCENT.test(text))
|
|
184
|
+
return { length: text, number: Number(text.slice(0, -1)) / 100 };
|
|
185
|
+
const angle = ANGLE.exec(text);
|
|
186
|
+
if (angle) {
|
|
187
|
+
const [, value, unit] = angle;
|
|
188
|
+
return { angle: Number(value) * HUE_DEGREES[unit.toLowerCase()], number: Number(value) };
|
|
189
|
+
}
|
|
190
|
+
const time = TIME.exec(text);
|
|
191
|
+
// In milliseconds, as the build reads a time: what a transition or an animation takes.
|
|
192
|
+
if (time)
|
|
193
|
+
return { time: Number(time[1]) * (time[2].toLowerCase() === 's' ? 1000 : 1) };
|
|
194
|
+
return undefined;
|
|
195
|
+
}
|
|
175
196
|
/**
|
|
176
197
|
* A value with a token in it: another token, or one made of others, worked out where it is set.
|
|
177
198
|
* Any other shape is a word no use site reads, as a colour function with a `var()` left in it is
|
|
@@ -188,18 +209,9 @@ export function tokenFromValue(value) {
|
|
|
188
209
|
const text = cssTrim(value);
|
|
189
210
|
if (!text)
|
|
190
211
|
return undefined;
|
|
191
|
-
const
|
|
192
|
-
if (
|
|
193
|
-
return
|
|
194
|
-
// A percentage is a fraction as well, and an angle its degrees, as the build-time conversion
|
|
195
|
-
// reads them: an hsl() of tokens takes its saturation and its hue so.
|
|
196
|
-
if (PERCENT.test(text))
|
|
197
|
-
return { length: text, number: Number(text.slice(0, -1)) / 100 };
|
|
198
|
-
const angle = ANGLE.exec(text);
|
|
199
|
-
if (angle) {
|
|
200
|
-
const [, value, unit] = angle;
|
|
201
|
-
return { angle: Number(value) * HUE_UNITS[unit.toLowerCase()], number: Number(value) };
|
|
202
|
-
}
|
|
212
|
+
const measure = withUnit(text);
|
|
213
|
+
if (measure)
|
|
214
|
+
return measure;
|
|
203
215
|
if (NUMBER.test(text))
|
|
204
216
|
return fromNumber(Number(text));
|
|
205
217
|
if (DERIVED.test(text))
|
package/dist/inline-token.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inline-token.js","sourceRoot":"","sources":["../src/inline-token.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A custom property's value set on an element at run time, `[style.--tint]=\"tint()\"` or\n * `style=\"--gap: 4px\"`, as a token the cascade can read.\n *\n * A stylesheet's custom properties are converted when the app is built, where there is a CSS\n * parser (`@ng-native/metro/css/values.cjs`). A bound one only exists here, where there is not,\n * so this takes the shapes a binding actually holds and nothing more: a length in `px` or `%`, a\n * number, a colour as React Native writes one, a colour's three channels, a word, another token,\n * `var(--brand)`, and one made of others, `calc(var(--gap) * 2)` or a `color-mix()` (see\n * inline-derived-token.ts).\n * Anything else is kept as a word, which leaves a use site that wants a length or a colour unset,\n * as a token of the wrong kind does.\n */\nimport { CSS_SPACE, type TokenValue } from './css.ts';\nimport { derivedToken } from './inline-derived-token.ts';\nimport { isNamedColor } from './transition.ts';\n\nconst PX = /^(-?\\d*\\.?\\d+)px$/;\nconst PERCENT = /^-?\\d*\\.?\\d+%$/;\nconst NUMBER = /^-?\\d*\\.?\\d+$/;\nconst ANGLE = /^(-?\\d*\\.?\\d+)(deg|grad|rad|turn)$/i;\n/** `#fff`, `rgb()`, `rgba()`, `hsl()`, `hsla()` and `hwb()`: what React Native's `processColor` reads. */\nconst COLOR_FUNCTION = /^(#[\\da-f]{3,8}|(rgba?|hsla?|hwb)\\(.*\\))$/i;\nconst WORD = /^-?[a-z][\\w-]*$/i;\n/** One colour channel: a number, a percentage, or a hue with its unit. */\nconst CHANNEL = /^(-?(?:\\d+\\.?\\d*|\\.\\d+))(%|deg|grad|rad|turn)?$/;\nconst HUE_UNITS: Record<string, number> = { deg: 1, grad: 0.9, rad: 180 / Math.PI, turn: 360 };\n/** `var(--name)` or `var(--name, <fallback>)`, the whole value. */\nconst VAR = /^var\\([ \\t\\n\\r\\f]*(--[\\w-]+)[ \\t\\n\\r\\f]*(?:,([\\s\\S]*))?\\)$/i;\n/**\n * A value worked out where it is set: one with a `var()` in it, a `color-mix()`, or a relative\n * colour, of tokens or of colours written out.\n */\nconst DERIVED = /var\\(|^color-mix\\(|^[a-z]+\\([ \\t\\n\\r\\f]*from[ \\t\\n\\r\\f]/i;\nconst WEIGHTS: Record<string, string> = { normal: '400', bold: '700' };\n/**\n * CSS whitespace at either end: a space, a tab, a newline, a carriage return or a form feed. A\n * no-break space is part of the value, as it is in a browser, where `trim()` would drop it.\n */\nconst PADDED = new RegExp(`^${CSS_SPACE.source}|${CSS_SPACE.source}$`, 'g');\nexport const cssTrim = (text: string): string => text.replace(PADDED, '');\n/** A family name's parts: a quoted string, which may hold escapes, or a bare word. */\nconst FAMILY_PART = /^(?:'((?:[^'\\\\]|\\\\[\\s\\S])*)'|\"((?:[^\"\\\\]|\\\\[\\s\\S])*)\"|(-?[a-z_][\\w-]*))/i;\nconst LEADING_SPACE = new RegExp(`^${CSS_SPACE.source}`);\n/**\n * A CSS escape: up to six hex digits and one whitespace after them, a newline, which only joins\n * the lines either side, or any other character.\n */\nconst ESCAPE = /\\\\([\\da-f]{1,6})(?:\\r\\n|[ \\t\\n\\r\\f])?|\\\\(\\r\\n|[\\n\\r\\f])|\\\\([\\s\\S])/gi;\n\n/** A quoted string's text with its escapes decoded. One naming no character is U+FFFD. */\nconst decodeEscapes = (text: string): string =>\n text.replace(ESCAPE, (_, hex: string | undefined, newline: string | undefined, char: string) => {\n if (newline !== undefined) return '';\n if (hex === undefined) return char;\n const code = parseInt(hex, 16);\n return code && code <= 0x10ffff && (code < 0xd800 || code > 0xdfff)\n ? String.fromCodePoint(code)\n : '\\ufffd';\n });\n\n/**\n * The first family of a `font-family` stack, as a stylesheet reads it (`firstFamily` in\n * values.cjs): `'Inter Display', sans-serif` is `Inter Display`, and `Segoe UI` is one name of two\n * words. Undefined for anything that is not a stack.\n */\nexport function firstFamily(value: string): string | undefined {\n let rest = cssTrim(value);\n const words: string[] = [];\n while (rest && !rest.startsWith(',')) {\n const part = FAMILY_PART.exec(rest);\n if (!part) return undefined;\n const quoted = part[1] ?? part[2];\n words.push(quoted === undefined ? part[3]! : decodeEscapes(quoted));\n rest = rest.slice(part[0].length).replace(LEADING_SPACE, '');\n }\n return words.length ? words.join(' ') : undefined;\n}\n\n/**\n * A value kept as written, and a family too when it reads as one: `'Inter-Bold'` is the family\n * `Inter-Bold`, and a stack its first. The written word stays the keyword, so a quoted `\"none\"` is\n * still no display.\n */\nfunction fromText(text: string): TokenValue {\n const family = firstFamily(text);\n return family === undefined || family === text ? { keyword: text } : { keyword: text, family };\n}\n\n/**\n * CSS takes a bare 0 wherever it takes a length, and no other bare number. A number from 1 to 1000\n * is a weight as well, at the nearest hundred, which is every weight native draws.\n */\nfunction fromNumber(value: number): TokenValue | undefined {\n if (!Number.isFinite(value)) return undefined;\n const weight =\n value >= 1 && value <= 1000\n ? { weight: String(Math.min(900, Math.max(100, Math.round(value / 100) * 100))) }\n : {};\n return value === 0 ? { number: 0, length: 0 } : { number: value, ...weight };\n}\n\n/**\n * A word is a keyword, `row`, and may be a colour, `red`, or a weight, `bold`, as well: every form\n * it can take, as the build-time conversion gives, and a use site reads the one it needs.\n */\nfunction fromWord(text: string): TokenValue {\n const weight = WEIGHTS[text.toLowerCase()];\n return {\n keyword: text,\n ...(isNamedColor(text) ? { color: text } : {}),\n ...(weight ? { weight } : {}),\n };\n}\n\nconst clamp = (value: number, low: number, high: number) => Math.min(high, Math.max(low, value));\n\n/**\n * `13 110 253`, `13, 110, 253`, `100% 0% 0%` or `0 100% 50%`, in the forms `rgb()` and `hsl()` read\n * channels in, by the same rules the build-time conversion uses (`channelForms` in values.cjs).\n */\nfunction fromChannels(text: string): TokenValue | undefined {\n const commas = text.split(',');\n const spaced = commas.length === 1;\n const words = spaced ? text.split(CSS_SPACE) : commas.map(cssTrim);\n const parsed = words.map((word) => CHANNEL.exec(word));\n if (parsed.length !== 3 || parsed.some((match) => !match)) return undefined;\n const values = parsed.map((match) => ({ n: Number(match![1]), unit: match![2] ?? '' }));\n const channels = rgbChannels(values);\n const hslChannels = hslOf(values, spaced);\n if (!channels && !hslChannels) return undefined;\n return { ...(channels ? { channels } : {}), ...(hslChannels ? { hslChannels } : {}) };\n}\n\ninterface Channel {\n readonly n: number;\n readonly unit: string;\n}\n\n/** As `rgb()` reads them: three numbers, or three percentages of 255. */\nfunction rgbChannels(values: readonly Channel[]): number[] | undefined {\n const scale = values.every((v) => v.unit === '')\n ? 1\n : values.every((v) => v.unit === '%')\n ? 255 / 100\n : 0;\n if (!scale) return undefined;\n return values.map((v) => Math.round(clamp(v.n * scale, 0, 255) * 1000) / 1000);\n}\n\n/** As `hsl()` reads them: a hue, then two percentages, which the space syntax may write bare. */\nfunction hslOf([hue, ...rest]: readonly Channel[], spaced: boolean): number[] | undefined {\n const degrees = hue!.n * (hue!.unit === '' ? 1 : (HUE_UNITS[hue!.unit] ?? NaN));\n const fractions = rest.map((v) =>\n v.unit === '%' || (spaced && v.unit === '') ? clamp(v.n / 100, 0, 1) : NaN,\n );\n const hsl = [degrees, ...fractions];\n return hsl.every(Number.isFinite) ? hsl : undefined;\n}\n\n/**\n * Another token, kept as an alias and resolved where it is set, as a stylesheet's `--x: var(--y)`\n * is. Undefined when the parentheses do not close where the value ends: `var(--a, 1px) var(--b)`.\n */\nfunction fromVar(text: string): TokenValue | undefined {\n const match = VAR.exec(text);\n if (!match) return undefined;\n const alias = match[1]!;\n const rest = match[2];\n if (rest === undefined) return { alias };\n if (!balanced(rest)) return undefined;\n const fallback = tokenFromValue(rest);\n return fallback ? { alias, fallback } : { alias };\n}\n\nfunction balanced(text: string): boolean {\n let depth = 0;\n for (const char of text) {\n if (char === '(') depth++;\n else if (char === ')' && --depth < 0) return false;\n }\n return depth === 0;\n}\n\n/**\n * A value with a token in it: another token, or one made of others, worked out where it is set.\n * Any other shape is a word no use site reads, as a colour function with a `var()` left in it is\n * not a colour native can draw.\n */\nfunction withTokens(text: string): TokenValue {\n return fromVar(text) ?? derivedToken(text) ?? { keyword: text };\n}\n\nexport function tokenFromValue(value: unknown): TokenValue | undefined {\n if (typeof value === 'number') return fromNumber(value);\n if (typeof value !== 'string') return undefined;\n const text = cssTrim(value);\n if (!text) return undefined;\n const px = PX.exec(text);\n if (px) return { length: Number(px[1]) };\n // A percentage is a fraction as well, and an angle its degrees, as the build-time conversion\n // reads them: an hsl() of tokens takes its saturation and its hue so.\n if (PERCENT.test(text)) return { length: text, number: Number(text.slice(0, -1)) / 100 };\n const angle = ANGLE.exec(text);\n if (angle) {\n const [, value, unit] = angle;\n return { angle: Number(value) * HUE_UNITS[unit!.toLowerCase()]!, number: Number(value) };\n }\n if (NUMBER.test(text)) return fromNumber(Number(text));\n if (DERIVED.test(text)) return withTokens(text);\n if (COLOR_FUNCTION.test(text)) return { color: text };\n return fromChannels(text) ?? (WORD.test(text) ? fromWord(text) : fromText(text));\n}\n"]}
|
|
1
|
+
{"version":3,"file":"inline-token.js","sourceRoot":"","sources":["../src/inline-token.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A custom property's value set on an element at run time, `[style.--tint]=\"tint()\"` or\n * `style=\"--gap: 4px\"`, as a token the cascade can read.\n *\n * A stylesheet's custom properties are converted when the app is built, where there is a CSS\n * parser (`@ng-native/metro/css/values.cjs`). A bound one only exists here, where there is not,\n * so this takes the shapes a binding actually holds and nothing more: a length in `px` or `%`, a\n * number, a colour as React Native writes one, a colour's three channels, a word, another token,\n * `var(--brand)`, and one made of others, `calc(var(--gap) * 2)` or a `color-mix()` (see\n * inline-derived-token.ts).\n * Anything else is kept as a word, which leaves a use site that wants a length or a colour unset,\n * as a token of the wrong kind does.\n */\nimport { CSS_SPACE, type TokenValue } from './css.ts';\nimport { derivedToken } from './inline-derived-token.ts';\nimport { HUE_DEGREES, isNamedColor } from './transition.ts';\n\nconst PX = /^(-?\\d*\\.?\\d+)px$/;\nconst PERCENT = /^-?\\d*\\.?\\d+%$/;\nconst NUMBER = /^-?\\d*\\.?\\d+$/;\nconst ANGLE = /^(-?\\d*\\.?\\d+)(deg|grad|rad|turn)$/i;\n/** `#fff`, `rgb()`, `rgba()`, `hsl()`, `hsla()` and `hwb()`: what React Native's `processColor` reads. */\nconst COLOR_FUNCTION = /^(#[\\da-f]{3,8}|(rgba?|hsla?|hwb)\\(.*\\))$/i;\nconst WORD = /^-?[a-z][\\w-]*$/i;\n/** One colour channel: a number, a percentage, or a hue with its unit. */\nconst CHANNEL = /^(-?(?:\\d+\\.?\\d*|\\.\\d+))(%|deg|grad|rad|turn)?$/;\n/** `var(--name)` or `var(--name, <fallback>)`, the whole value. */\nconst VAR = /^var\\([ \\t\\n\\r\\f]*(--[\\w-]+)[ \\t\\n\\r\\f]*(?:,([\\s\\S]*))?\\)$/i;\n/**\n * A value worked out where it is set: one with a `var()` in it, a `color-mix()`, or a relative\n * colour, of tokens or of colours written out.\n */\nconst DERIVED = /var\\(|^color-mix\\(|^[a-z]+\\([ \\t\\n\\r\\f]*from[ \\t\\n\\r\\f]/i;\nconst WEIGHTS: Record<string, string> = { normal: '400', bold: '700' };\n/**\n * CSS whitespace at either end: a space, a tab, a newline, a carriage return or a form feed. A\n * no-break space is part of the value, as it is in a browser, where `trim()` would drop it.\n */\nconst PADDED = new RegExp(`^${CSS_SPACE.source}|${CSS_SPACE.source}$`, 'g');\nexport const cssTrim = (text: string): string => text.replace(PADDED, '');\n/** A family name's parts: a quoted string, which may hold escapes, or a bare word. */\nconst FAMILY_PART = /^(?:'((?:[^'\\\\]|\\\\[\\s\\S])*)'|\"((?:[^\"\\\\]|\\\\[\\s\\S])*)\"|(-?[a-z_][\\w-]*))/i;\nconst LEADING_SPACE = new RegExp(`^${CSS_SPACE.source}`);\n/**\n * A CSS escape: up to six hex digits and one whitespace after them, a newline, which only joins\n * the lines either side, or any other character.\n */\nconst ESCAPE = /\\\\([\\da-f]{1,6})(?:\\r\\n|[ \\t\\n\\r\\f])?|\\\\(\\r\\n|[\\n\\r\\f])|\\\\([\\s\\S])/gi;\n\n/** A quoted string's text with its escapes decoded. One naming no character is U+FFFD. */\nconst decodeEscapes = (text: string): string =>\n text.replace(ESCAPE, (_, hex: string | undefined, newline: string | undefined, char: string) => {\n if (newline !== undefined) return '';\n if (hex === undefined) return char;\n const code = parseInt(hex, 16);\n return code && code <= 0x10ffff && (code < 0xd800 || code > 0xdfff)\n ? String.fromCodePoint(code)\n : '\\ufffd';\n });\n\n/**\n * The first family of a `font-family` stack, as a stylesheet reads it (`firstFamily` in\n * values.cjs): `'Inter Display', sans-serif` is `Inter Display`, and `Segoe UI` is one name of two\n * words. Undefined for anything that is not a stack.\n */\nexport function firstFamily(value: string): string | undefined {\n let rest = cssTrim(value);\n const words: string[] = [];\n while (rest && !rest.startsWith(',')) {\n const part = FAMILY_PART.exec(rest);\n if (!part) return undefined;\n const quoted = part[1] ?? part[2];\n words.push(quoted === undefined ? part[3]! : decodeEscapes(quoted));\n rest = rest.slice(part[0].length).replace(LEADING_SPACE, '');\n }\n return words.length ? words.join(' ') : undefined;\n}\n\n/**\n * A value kept as written, and a family too when it reads as one: `'Inter-Bold'` is the family\n * `Inter-Bold`, and a stack its first. The written word stays the keyword, so a quoted `\"none\"` is\n * still no display.\n */\nfunction fromText(text: string): TokenValue {\n const family = firstFamily(text);\n return family === undefined || family === text ? { keyword: text } : { keyword: text, family };\n}\n\n/**\n * CSS takes a bare 0 wherever it takes a length, and no other bare number. A number from 1 to 1000\n * is a weight as well, at the nearest hundred, which is every weight native draws.\n */\nfunction fromNumber(value: number): TokenValue | undefined {\n if (!Number.isFinite(value)) return undefined;\n const weight =\n value >= 1 && value <= 1000\n ? { weight: String(Math.min(900, Math.max(100, Math.round(value / 100) * 100))) }\n : {};\n return value === 0 ? { number: 0, length: 0 } : { number: value, ...weight };\n}\n\n/**\n * A word is a keyword, `row`, and may be a colour, `red`, or a weight, `bold`, as well: every form\n * it can take, as the build-time conversion gives, and a use site reads the one it needs.\n */\nfunction fromWord(text: string): TokenValue {\n const weight = WEIGHTS[text.toLowerCase()];\n return {\n keyword: text,\n ...(isNamedColor(text) ? { color: text } : {}),\n ...(weight ? { weight } : {}),\n };\n}\n\nconst clamp = (value: number, low: number, high: number) => Math.min(high, Math.max(low, value));\n\n/**\n * `13 110 253`, `13, 110, 253`, `100% 0% 0%` or `0 100% 50%`, in the forms `rgb()` and `hsl()` read\n * channels in, by the same rules the build-time conversion uses (`channelForms` in values.cjs).\n */\nfunction fromChannels(text: string): TokenValue | undefined {\n const commas = text.split(',');\n const spaced = commas.length === 1;\n const words = spaced ? text.split(CSS_SPACE) : commas.map(cssTrim);\n const parsed = words.map((word) => CHANNEL.exec(word));\n if (parsed.length !== 3 || parsed.some((match) => !match)) return undefined;\n const values = parsed.map((match) => ({ n: Number(match![1]), unit: match![2] ?? '' }));\n const channels = rgbChannels(values);\n const hslChannels = hslOf(values, spaced);\n if (!channels && !hslChannels) return undefined;\n return { ...(channels ? { channels } : {}), ...(hslChannels ? { hslChannels } : {}) };\n}\n\ninterface Channel {\n readonly n: number;\n readonly unit: string;\n}\n\n/** As `rgb()` reads them: three numbers, or three percentages of 255. */\nfunction rgbChannels(values: readonly Channel[]): number[] | undefined {\n const scale = values.every((v) => v.unit === '')\n ? 1\n : values.every((v) => v.unit === '%')\n ? 255 / 100\n : 0;\n if (!scale) return undefined;\n return values.map((v) => Math.round(clamp(v.n * scale, 0, 255) * 1000) / 1000);\n}\n\n/** As `hsl()` reads them: a hue, then two percentages, which the space syntax may write bare. */\nfunction hslOf([hue, ...rest]: readonly Channel[], spaced: boolean): number[] | undefined {\n const degrees = hue!.n * (hue!.unit === '' ? 1 : (HUE_DEGREES[hue!.unit] ?? NaN));\n const fractions = rest.map((v) =>\n v.unit === '%' || (spaced && v.unit === '') ? clamp(v.n / 100, 0, 1) : NaN,\n );\n const hsl = [degrees, ...fractions];\n return hsl.every(Number.isFinite) ? hsl : undefined;\n}\n\n/**\n * Another token, kept as an alias and resolved where it is set, as a stylesheet's `--x: var(--y)`\n * is. Undefined when the parentheses do not close where the value ends: `var(--a, 1px) var(--b)`.\n */\nfunction fromVar(text: string): TokenValue | undefined {\n const match = VAR.exec(text);\n if (!match) return undefined;\n const alias = match[1]!;\n const rest = match[2];\n if (rest === undefined) return { alias };\n if (!balanced(rest)) return undefined;\n const fallback = tokenFromValue(rest);\n return fallback ? { alias, fallback } : { alias };\n}\n\nfunction balanced(text: string): boolean {\n let depth = 0;\n for (const char of text) {\n if (char === '(') depth++;\n else if (char === ')' && --depth < 0) return false;\n }\n return depth === 0;\n}\n\n/** A time as CSS writes one: a number of seconds or milliseconds. */\nconst TIME = /^([+-]?(?:\\d+\\.?\\d*|\\.\\d+))(ms|s)$/i;\n\n/** A number with a unit, as the token each is: a length, a percentage, an angle or a time. */\nfunction withUnit(text: string): TokenValue | undefined {\n const px = PX.exec(text);\n if (px) return { length: Number(px[1]) };\n // A percentage is a fraction as well, and an angle its degrees, as the build-time conversion\n // reads them: an hsl() of tokens takes its saturation and its hue so.\n if (PERCENT.test(text)) return { length: text, number: Number(text.slice(0, -1)) / 100 };\n const angle = ANGLE.exec(text);\n if (angle) {\n const [, value, unit] = angle;\n return { angle: Number(value) * HUE_DEGREES[unit!.toLowerCase()]!, number: Number(value) };\n }\n const time = TIME.exec(text);\n // In milliseconds, as the build reads a time: what a transition or an animation takes.\n if (time) return { time: Number(time[1]) * (time[2]!.toLowerCase() === 's' ? 1000 : 1) };\n return undefined;\n}\n\n/**\n * A value with a token in it: another token, or one made of others, worked out where it is set.\n * Any other shape is a word no use site reads, as a colour function with a `var()` left in it is\n * not a colour native can draw.\n */\nfunction withTokens(text: string): TokenValue {\n return fromVar(text) ?? derivedToken(text) ?? { keyword: text };\n}\n\nexport function tokenFromValue(value: unknown): TokenValue | undefined {\n if (typeof value === 'number') return fromNumber(value);\n if (typeof value !== 'string') return undefined;\n const text = cssTrim(value);\n if (!text) return undefined;\n const measure = withUnit(text);\n if (measure) return measure;\n if (NUMBER.test(text)) return fromNumber(Number(text));\n if (DERIVED.test(text)) return withTokens(text);\n if (COLOR_FUNCTION.test(text)) return { color: text };\n return fromChannels(text) ?? (WORD.test(text) ? fromWord(text) : fromText(text));\n}\n"]}
|
package/dist/inline-transform.js
CHANGED
|
@@ -10,15 +10,32 @@ const ARGUMENT = /^[+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?(?:%|[a-z]+)?$/i;
|
|
|
10
10
|
const SPACE = /^[ \t\n\r\f]*$/;
|
|
11
11
|
const PADDED = /^[ \t\n\r\f]+|[ \t\n\r\f]+$/g;
|
|
12
12
|
const FUNCTIONS = /([a-zA-Z0-9]+)\(([^)]*)\)/g;
|
|
13
|
+
/** The two axes a function is along, and whether it was given a value for each. */
|
|
14
|
+
function axesOf(name, given) {
|
|
15
|
+
return { axes: AXES[THREE_D[name] ?? name], both: given === 2 || name in THREE_D };
|
|
16
|
+
}
|
|
17
|
+
/** The spellings with a third axis, by the flat one each is on a view. */
|
|
18
|
+
const THREE_D = { scale3d: 'scale', translate3d: 'translate' };
|
|
13
19
|
/** The transform functions native has, by their name in any case, as CSS reads one. */
|
|
14
20
|
const NAMES = new Map([
|
|
15
21
|
...['matrix', 'matrix3d', 'perspective', 'rotate', 'rotateX', 'rotateY', 'rotateZ'],
|
|
16
22
|
...['scale', 'scaleX', 'scaleY', 'skew', 'skewX', 'skewY'],
|
|
17
23
|
...['translate', 'translateX', 'translateY'],
|
|
24
|
+
// A flat transform spelt with a third axis, which a view has nothing along.
|
|
25
|
+
...['scale3d', 'translate3d'],
|
|
18
26
|
].map((name) => [name.toLowerCase(), name]));
|
|
19
27
|
function argument(raw) {
|
|
20
28
|
return PX.test(raw) ? parseFloat(raw) : raw;
|
|
21
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Whether a spelling with a third axis is one a view can have: all three values, as CSS takes no
|
|
32
|
+
* fewer, and nothing along z for a move, in any unit, since a view has nowhere to go there.
|
|
33
|
+
*/
|
|
34
|
+
function onAView(name, raw) {
|
|
35
|
+
if (raw.length !== 3)
|
|
36
|
+
return false;
|
|
37
|
+
return name !== 'translate3d' || Number.parseFloat(raw[2]) === 0;
|
|
38
|
+
}
|
|
22
39
|
/** Each function and its arguments, or undefined where anything else is in the value. */
|
|
23
40
|
function readCalls(value) {
|
|
24
41
|
const calls = [...value.matchAll(FUNCTIONS)].map(([, name, body]) => ({
|
|
@@ -29,7 +46,8 @@ function readCalls(value) {
|
|
|
29
46
|
const readable = calls.length &&
|
|
30
47
|
SPACE.test(value.replace(FUNCTIONS, '')) &&
|
|
31
48
|
calls.every(({ name, raw }) => name && raw.length && raw.every((arg) => ARGUMENT.test(arg)));
|
|
32
|
-
|
|
49
|
+
const flat = calls.every(({ name, raw }) => !(name in THREE_D) || onAView(name, raw));
|
|
50
|
+
return readable && flat ? calls : undefined;
|
|
33
51
|
}
|
|
34
52
|
/**
|
|
35
53
|
* The list, or undefined for a value CSS cannot read, which a browser drops: the transform a rule
|
|
@@ -44,8 +62,8 @@ export function transformList(value) {
|
|
|
44
62
|
return undefined;
|
|
45
63
|
for (const { name, raw } of calls) {
|
|
46
64
|
const args = raw.map(argument);
|
|
47
|
-
const axes =
|
|
48
|
-
if (axes &&
|
|
65
|
+
const { axes, both } = axesOf(name, args.length);
|
|
66
|
+
if (axes && both) {
|
|
49
67
|
out.push({ [axes[0]]: args[0] }, { [axes[1]]: args[1] });
|
|
50
68
|
}
|
|
51
69
|
else if (axes && name !== 'scale') {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inline-transform.js","sourceRoot":"","sources":["../src/inline-transform.ts"],"names":[],"mappings":"AAcA,MAAM,IAAI,GAAwD;IAChE,SAAS,EAAE,CAAC,YAAY,EAAE,YAAY,CAAC;IACvC,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC3B,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,MAAM,EAAE,GAAG,oBAAoB,CAAC;AAChC,qFAAqF;AACrF,MAAM,QAAQ,GAAG,wDAAwD,CAAC;AAC1E,iGAAiG;AACjG,MAAM,KAAK,GAAG,gBAAgB,CAAC;AAC/B,MAAM,MAAM,GAAG,8BAA8B,CAAC;AAC9C,MAAM,SAAS,GAAG,4BAA4B,CAAC;AAC/C,uFAAuF;AACvF,MAAM,KAAK,GAAG,IAAI,GAAG,CACnB;IACE,GAAG,CAAC,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC;IACnF,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC;IAC1D,GAAG,CAAC,WAAW,EAAE,YAAY,EAAE,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"inline-transform.js","sourceRoot":"","sources":["../src/inline-transform.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A CSS transform string, as the list React Native's Fabric reads.\n *\n * A class's transform is compiled to this list at build time. A bound style -\n * `[style.transform]=\"'rotate(' + angle + 'deg)'\"` - has no build step, and Fabric drops a string\n * without a word. React Native's JavaScript would have run `processTransform` over it first; there\n * is none of that JavaScript between this engine and Fabric, so this does the same job.\n *\n * Lengths in pixels become numbers, angles and percentages stay strings, as React Native keeps\n * them. A two-argument `translate`, `scale` or `skew` is split into its axes, and a 2D `matrix()`\n * is widened to the sixteen values native wants.\n */\nexport type TransformEntry = Readonly<Record<string, number | string | readonly number[]>>;\n\nconst AXES: Readonly<Record<string, readonly [string, string]>> = {\n translate: ['translateX', 'translateY'],\n scale: ['scaleX', 'scaleY'],\n skew: ['skewX', 'skewY'],\n};\n\nconst PX = /^-?\\d*\\.?\\d+(px)?$/;\n/** A transform function's argument: a number, a length, an angle or a percentage. */\nconst ARGUMENT = /^[+-]?(?:\\d+\\.?\\d*|\\.\\d+)(?:e[+-]?\\d+)?(?:%|[a-z]+)?$/i;\n/** CSS whitespace: a space, a tab, a newline, a carriage return or a form feed, and no other. */\nconst SPACE = /^[ \\t\\n\\r\\f]*$/;\nconst PADDED = /^[ \\t\\n\\r\\f]+|[ \\t\\n\\r\\f]+$/g;\nconst FUNCTIONS = /([a-zA-Z0-9]+)\\(([^)]*)\\)/g;\n/** The two axes a function is along, and whether it was given a value for each. */\nfunction axesOf(name: string, given: number) {\n return { axes: AXES[THREE_D[name] ?? name], both: given === 2 || name in THREE_D };\n}\n\n/** The spellings with a third axis, by the flat one each is on a view. */\nconst THREE_D: Readonly<Record<string, string>> = { scale3d: 'scale', translate3d: 'translate' };\n/** The transform functions native has, by their name in any case, as CSS reads one. */\nconst NAMES = new Map(\n [\n ...['matrix', 'matrix3d', 'perspective', 'rotate', 'rotateX', 'rotateY', 'rotateZ'],\n ...['scale', 'scaleX', 'scaleY', 'skew', 'skewX', 'skewY'],\n ...['translate', 'translateX', 'translateY'],\n // A flat transform spelt with a third axis, which a view has nothing along.\n ...['scale3d', 'translate3d'],\n ].map((name) => [name.toLowerCase(), name]),\n);\n\nfunction argument(raw: string): number | string {\n return PX.test(raw) ? parseFloat(raw) : raw;\n}\n\n/**\n * Whether a spelling with a third axis is one a view can have: all three values, as CSS takes no\n * fewer, and nothing along z for a move, in any unit, since a view has nowhere to go there.\n */\nfunction onAView(name: string, raw: readonly string[]): boolean {\n if (raw.length !== 3) return false;\n return name !== 'translate3d' || Number.parseFloat(raw[2]!) === 0;\n}\n\n/** Each function and its arguments, or undefined where anything else is in the value. */\nfunction readCalls(value: string): { name: string; raw: string[] }[] | undefined {\n const calls = [...value.matchAll(FUNCTIONS)].map(([, name, body]) => ({\n name: NAMES.get(name!.toLowerCase())!,\n raw: body!.split(/[ \\t\\n\\r\\f,]+/).filter(Boolean),\n }));\n // Functions native has, CSS whitespace between them and nothing else, and arguments CSS reads.\n const readable =\n calls.length &&\n SPACE.test(value.replace(FUNCTIONS, '')) &&\n calls.every(({ name, raw }) => name && raw.length && raw.every((arg) => ARGUMENT.test(arg)));\n const flat = calls.every(({ name, raw }) => !(name in THREE_D) || onAView(name, raw));\n return readable && flat ? calls : undefined;\n}\n\n/**\n * The list, or undefined for a value CSS cannot read, which a browser drops: the transform a rule\n * sets then applies instead.\n */\nexport function transformList(value: string): TransformEntry[] | undefined {\n const out: TransformEntry[] = [];\n if (value.replace(PADDED, '').toLowerCase() === 'none') return out;\n const calls = readCalls(value);\n if (!calls) return undefined;\n for (const { name, raw } of calls) {\n const args = raw.map(argument);\n const { axes, both } = axesOf(name, args.length);\n if (axes && both) {\n out.push({ [axes[0]]: args[0]! }, { [axes[1]]: args[1]! });\n } else if (axes && name !== 'scale') {\n // `translate(4px)` and `skew(10deg)` move along the first axis only; `scale(2)` is both,\n // which React Native spells as a key of its own and falls through to below.\n out.push({ [axes[0]]: args[0]! });\n } else if (name === 'matrix' && args.length === 6) {\n const [a, b, c, d, e, f] = args as number[];\n out.push({ matrix: [a!, b!, 0, 0, c!, d!, 0, 0, 0, 0, 1, 0, e!, f!, 0, 1] });\n } else if (name === 'matrix3d') {\n out.push({ matrix: args as number[] });\n } else {\n out.push({ [name!]: args[0]! });\n }\n }\n return out;\n}\n"]}
|
package/dist/native-drive.d.ts
CHANGED
|
@@ -16,7 +16,13 @@
|
|
|
16
16
|
/** The part of React Native's `NativeAnimatedHelper` default export this uses. */
|
|
17
17
|
export interface NativeAnimated {
|
|
18
18
|
generateNewNodeTag(): number;
|
|
19
|
+
generateNewAnimationId?(): number;
|
|
19
20
|
readonly API: {
|
|
21
|
+
/** Run a value through `config` on the native side, and say when it has ended. */
|
|
22
|
+
startAnimatingNode?(animationId: number, nodeTag: number, config: object, end: (result: {
|
|
23
|
+
finished: boolean;
|
|
24
|
+
}) => void): void;
|
|
25
|
+
stopAnimation?(animationId: number): void;
|
|
20
26
|
createAnimatedNode(tag: number, config: object): void;
|
|
21
27
|
connectAnimatedNodes(parentTag: number, childTag: number): void;
|
|
22
28
|
disconnectAnimatedNodes(parentTag: number, childTag: number): void;
|
|
@@ -78,6 +84,21 @@ export declare class NativeScrollDriver {
|
|
|
78
84
|
update(channels: DrivenChannels): void;
|
|
79
85
|
stop(): void;
|
|
80
86
|
};
|
|
87
|
+
/**
|
|
88
|
+
* Play a view's opacity and transform by the clock: each channel an interpolation from a value
|
|
89
|
+
* native runs from nothing to `timing.toValue`, over the frames it is given, as many times as
|
|
90
|
+
* asked. Nothing runs in JavaScript while it plays. `ended` is told when native reaches the end
|
|
91
|
+
* of the last iteration; `stop` lets the view go, and stops an animation still playing.
|
|
92
|
+
*
|
|
93
|
+
* Null where the native module cannot start an animation, and the caller plays it itself.
|
|
94
|
+
*/
|
|
95
|
+
play(view: object, channels: DrivenChannels, timing: {
|
|
96
|
+
frames: readonly number[];
|
|
97
|
+
toValue: number;
|
|
98
|
+
iterations: number;
|
|
99
|
+
}, tagOf: (node: object) => number | null, ended: () => void): {
|
|
100
|
+
stop(): void;
|
|
101
|
+
} | null;
|
|
81
102
|
/** The nodes for a set of channels, connected to the view; the props node first. */
|
|
82
103
|
private buildChannels;
|
|
83
104
|
private dropChannels;
|
package/dist/native-drive.js
CHANGED
|
@@ -131,6 +131,71 @@ export class NativeScrollDriver {
|
|
|
131
131
|
},
|
|
132
132
|
};
|
|
133
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Play a view's opacity and transform by the clock: each channel an interpolation from a value
|
|
136
|
+
* native runs from nothing to `timing.toValue`, over the frames it is given, as many times as
|
|
137
|
+
* asked. Nothing runs in JavaScript while it plays. `ended` is told when native reaches the end
|
|
138
|
+
* of the last iteration; `stop` lets the view go, and stops an animation still playing.
|
|
139
|
+
*
|
|
140
|
+
* Null where the native module cannot start an animation, and the caller plays it itself.
|
|
141
|
+
*/
|
|
142
|
+
play(view, channels, timing, tagOf, ended) {
|
|
143
|
+
const { API } = this.native;
|
|
144
|
+
const start = API.startAnimatingNode;
|
|
145
|
+
if (!start || !API.stopAnimation || !this.native.generateNewAnimationId)
|
|
146
|
+
return null;
|
|
147
|
+
const state = {
|
|
148
|
+
viewTag: null,
|
|
149
|
+
nodes: null,
|
|
150
|
+
value: 0,
|
|
151
|
+
id: 0,
|
|
152
|
+
over: false,
|
|
153
|
+
};
|
|
154
|
+
const connect = () => {
|
|
155
|
+
if (state.over)
|
|
156
|
+
return true;
|
|
157
|
+
const viewTag = tagOf(view);
|
|
158
|
+
if (viewTag === null)
|
|
159
|
+
return false;
|
|
160
|
+
state.viewTag = viewTag;
|
|
161
|
+
state.value = this.native.generateNewNodeTag();
|
|
162
|
+
API.createAnimatedNode(state.value, { type: 'value', value: 0, offset: 0 });
|
|
163
|
+
state.nodes = this.buildChannels(state.value, viewTag, channels);
|
|
164
|
+
state.id = this.native.generateNewAnimationId();
|
|
165
|
+
const config = { type: 'frames', frames: [...timing.frames], toValue: timing.toValue };
|
|
166
|
+
start(state.id, state.value, { ...config, iterations: timing.iterations }, (result) => {
|
|
167
|
+
// Stopped rather than finished is the caller's own doing, and it knows.
|
|
168
|
+
if (!result.finished || state.over)
|
|
169
|
+
return;
|
|
170
|
+
state.id = 0;
|
|
171
|
+
// Written once more, to the view as it is now. A view is mounted when the task that
|
|
172
|
+
// made it is over, and an animation no longer than that task is over before there is a
|
|
173
|
+
// view to move: the view is then mounted at the frame the animation started from.
|
|
174
|
+
API.setAnimatedNodeValue(state.value, timing.toValue);
|
|
175
|
+
this.flush();
|
|
176
|
+
ended();
|
|
177
|
+
});
|
|
178
|
+
this.flush();
|
|
179
|
+
return true;
|
|
180
|
+
};
|
|
181
|
+
if (!connect())
|
|
182
|
+
this.pending.add(connect);
|
|
183
|
+
return {
|
|
184
|
+
stop: () => {
|
|
185
|
+
if (state.over)
|
|
186
|
+
return;
|
|
187
|
+
state.over = true;
|
|
188
|
+
this.pending.delete(connect);
|
|
189
|
+
if (!state.nodes || state.viewTag === null)
|
|
190
|
+
return;
|
|
191
|
+
if (state.id)
|
|
192
|
+
API.stopAnimation(state.id);
|
|
193
|
+
this.dropChannels(state.nodes, state.viewTag);
|
|
194
|
+
API.dropAnimatedNode(state.value);
|
|
195
|
+
this.flush();
|
|
196
|
+
},
|
|
197
|
+
};
|
|
198
|
+
}
|
|
134
199
|
/** The nodes for a set of channels, connected to the view; the props node first. */
|
|
135
200
|
buildChannels(value, viewTag, channels) {
|
|
136
201
|
const { API } = this.native;
|
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 readonly API: {\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 /** 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 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\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 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"]}
|