@ng-native/fabric 0.5.0 → 0.7.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.
@@ -1 +1 @@
1
- {"version":3,"file":"scroll-animation.js","sourceRoot":"","sources":["../src/scroll-animation.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A `@keyframes` animation played by a scroll view's offset: `animation-timeline: scroll()`.\n *\n * Native interpolates linearly between the points it is given and clamps past both ends, which is\n * all a scroll-driven animation needs from it once its keyframes are laid along the offset: each\n * keyframe sits at its share of the range, a segment's timing function is sampled into points\n * along it, and an unfilled end falls back to the resting value just outside the range. What\n * native can animate this way is opacity and the transforms; anything else holds its first frame.\n */\nimport type { ScrollRange } from './native-drive.ts';\nimport { at, type AnimationSpec, type TrackPoint } from './transition.ts';\n\ntype Track = readonly { offset: number; value: unknown }[];\n\n/** The channels a scroll-driven animation drives natively, in the order native applies them. */\nexport interface DrivenChannels {\n readonly opacity?: ScrollRange;\n /** Every transform entry the view paints: driven by the scroll, or held as it is. */\n readonly transform: readonly TransformChannel[];\n}\n\nexport type TransformChannel =\n | { readonly property: string; readonly range: ScrollRange }\n | { readonly property: string; readonly value: number };\n\n/** What a range with no end, or a percentage of one, stands in for until the scroll view says. */\nconst UNKNOWN_EXTENT = 1e6;\n\n/** Points per eased segment: enough that the curve between them reads as the curve. */\nconst SAMPLES = 12;\n\n/** The transform groups in the order CSS applies them, as the engine composes them. */\nconst GROUPS = ['__translate', '__rotate', '__scale', 'transform'] as const;\n\n/** Where the range starts and ends on the scroll view's offset. */\nexport function rangeOf(spec: AnimationSpec, extent: number | null): [number, number] {\n const end = (value: number | string | undefined, otherwise: number): number => {\n if (value === undefined) return otherwise;\n if (typeof value === 'number') return value;\n return (parseFloat(value) / 100) * (extent ?? UNKNOWN_EXTENT);\n };\n return [end(spec.range?.start, 0), end(spec.range?.end, extent ?? UNKNOWN_EXTENT)];\n}\n\n/**\n * The channels for an animation's tracks over a range, and the properties it cannot drive\n * natively, which the caller holds at their first frame.\n */\nexport function scrollChannels(\n tracks: ReadonlyMap<string, Track>,\n spec: AnimationSpec,\n resting: Readonly<Record<string, unknown>>,\n range: readonly [number, number],\n): { channels: DrivenChannels; held: string[] } {\n const along = (track: Track, pick: (value: unknown) => number | null, rest: number) =>\n laid(track, pick, rest, spec, range);\n const held: string[] = [];\n let opacity: ScrollRange | undefined;\n const transform: TransformChannel[] = [];\n for (const [property, track] of tracks) {\n if (property === 'opacity') {\n opacity =\n along(\n track,\n (value) => (typeof value === 'number' ? value : null),\n numberOr(resting['opacity'], 1),\n ) ?? undefined;\n if (!opacity) held.push(property);\n } else if (!(GROUPS as readonly string[]).includes(property)) {\n held.push(property);\n }\n }\n for (const group of GROUPS) {\n const track = tracks.get(group);\n const channels = track ? drivenGroup(track, resting[group], along) : heldGroup(resting[group]);\n if (channels === null) held.push(group);\n else transform.push(...channels);\n }\n const anyDriven = transform.some((channel) => 'range' in channel);\n return {\n channels: { ...(opacity ? { opacity } : {}), transform: anyDriven ? transform : [] },\n held,\n };\n}\n\n/**\n * The channels for an animation played by the clock, along a value native runs from nothing to\n * `span`: one iteration along 0 to 1, and for `alternate` the way back along 1 to 2, so that\n * native repeats there and back as one animation. Both ends are the frames' own: what the\n * element rests at is committed when the animation ends, and not played.\n */\nexport function clockChannels(\n tracks: ReadonlyMap<string, Track>,\n spec: AnimationSpec,\n resting: Readonly<Record<string, unknown>>,\n): { channels: DrivenChannels; held: string[]; span: number } {\n const way = (direction: AnimationSpec['direction'], range: readonly [number, number]) =>\n scrollChannels(tracks, { ...spec, fill: 'both', direction }, resting, range);\n if (spec.direction !== 'alternate' && spec.direction !== 'alternate-reverse') {\n return { ...way(spec.direction, [0, 1]), span: 1 };\n }\n const reversed = spec.direction === 'alternate-reverse';\n const out = way(reversed ? 'reverse' : undefined, [0, 1]);\n const back = way(reversed ? undefined : 'reverse', [1, 2]);\n const join = (a: ScrollRange, b: ScrollRange): ScrollRange => ({\n input: [...a.input, ...b.input.slice(1)],\n output: [...a.output, ...b.output.slice(1)],\n });\n const transform = out.channels.transform.map((channel, i) => {\n const other = back.channels.transform[i];\n return 'range' in channel && other && 'range' in other\n ? { property: channel.property, range: join(channel.range, other.range) }\n : channel;\n });\n const opacity =\n out.channels.opacity && back.channels.opacity\n ? { opacity: join(out.channels.opacity, back.channels.opacity) }\n : {};\n return { channels: { ...opacity, transform }, held: out.held, span: 2 };\n}\n\n/** One transform group's entries, each driven along the scroll; null if their shapes differ. */\nfunction drivenGroup(\n track: Track,\n resting: unknown,\n along: (\n track: Track,\n pick: (value: unknown) => number | null,\n rest: number,\n ) => ScrollRange | null,\n): TransformChannel[] | null {\n const shapes = track.map((point) => (Array.isArray(point.value) ? point.value : null));\n const shape = shapes.find((entries) => entries?.length) ?? [];\n const keys = shape.map((entry) => Object.keys(entry as object)[0]!);\n const channels: TransformChannel[] = [];\n for (const [index, key] of keys.entries()) {\n const identity = key.startsWith('scale') ? 1 : 0;\n const pick = (value: unknown) => {\n const entries = Array.isArray(value) ? value : null;\n if (!entries?.length) return identity;\n const entry = entries[index] as Record<string, unknown> | undefined;\n return entry && key in entry ? amount(key, entry[key]) : null;\n };\n const range = along(track, pick, restingAmount(resting, index, key, identity));\n if (!range) return null;\n channels.push({ property: key, range });\n }\n return channels;\n}\n\n/** A transform group no keyframe touches, held as the element has it. */\nfunction heldGroup(resting: unknown): TransformChannel[] | null {\n if (!Array.isArray(resting)) return [];\n const channels: TransformChannel[] = [];\n for (const entry of resting as Record<string, unknown>[]) {\n const [key, value] = Object.entries(entry)[0] ?? [];\n const number = key === undefined ? null : amount(key, value);\n if (key === undefined || number === null) return null;\n channels.push({ property: key, value: number });\n }\n return channels;\n}\n\nfunction restingAmount(resting: unknown, index: number, key: string, identity: number): number {\n const entry = Array.isArray(resting) ? (resting[index] as Record<string, unknown>) : undefined;\n return (entry && key in entry ? amount(key, entry[key]) : null) ?? identity;\n}\n\nconst numberOr = (value: unknown, otherwise: number) =>\n typeof value === 'number' ? value : otherwise;\n\nconst RADIANS: Record<string, number> = {\n deg: Math.PI / 180,\n rad: 1,\n grad: Math.PI / 200,\n turn: 2 * Math.PI,\n};\n\n/**\n * A transform entry's amount as native's transform node takes it: points, a factor, or an angle\n * in radians. Null for what it cannot take, a percentage translate.\n */\nfunction amount(key: string, value: unknown): number | null {\n if (typeof value === 'number') return value;\n if (typeof value !== 'string') return null;\n const angle = /^(-?[\\d.]+)(deg|rad|grad|turn)$/.exec(value);\n if (angle && (key.startsWith('rotate') || key.startsWith('skew'))) {\n return Number(angle[1]) * RADIANS[angle[2]!]!;\n }\n return null;\n}\n\n/**\n * One property's frames laid along the scroll: each keyframe at its share of the range, eased\n * segments sampled, and the resting value just past an end the animation does not fill.\n */\nfunction laid(\n track: Track,\n pick: (value: unknown) => number | null,\n rest: number,\n spec: AnimationSpec,\n [start, end]: readonly [number, number],\n): ScrollRange | null {\n const values = track.map((point) => pick(point.value));\n if (values.some((value) => value === null)) return null;\n // Each point keeps its own timing function, which eases the stretch it starts.\n const numeric = track.map((point, i) => ({ ...point, value: values[i]! }));\n const points = sampled(numeric, spec, start, Math.max(end - start, 1e-3));\n const fills = spec.fill;\n const backwards = fills === 'backwards' || fills === 'both';\n const forwards = fills === 'forwards' || fills === 'both';\n if (!backwards) points.unshift([points[0]![0] - 1e-3, rest]);\n if (!forwards) points.push([points.at(-1)![0] + 1e-3, rest]);\n return { input: points.map(([x]) => x), output: points.map(([, y]) => round(y)) };\n}\n\n/** A numeric track's points along the scroll, each eased segment sampled, in offset order. */\nfunction sampled(\n numeric: readonly (TrackPoint & { value: number })[],\n spec: AnimationSpec,\n start: number,\n span: number,\n): [number, number][] {\n const reversed = spec.direction === 'reverse' || spec.direction === 'alternate-reverse';\n const points: [number, number][] = [];\n for (let i = 0; i < numeric.length - 1; i++) {\n const from = numeric[i]!;\n const to = numeric[i + 1]!;\n const steps = isLinear(from.easing ?? spec.easing) ? 1 : SAMPLES;\n for (let s = i === 0 ? 0 : 1; s <= steps; s++) {\n const offset = from.offset + ((to.offset - from.offset) * s) / steps;\n const value = at(numeric, offset, spec.easing) as number;\n points.push([start + (reversed ? 1 - offset : offset) * span, value]);\n }\n }\n if (points.length === 1) points.push([start + span, points[0]![1]]);\n return points.sort((a, b) => a[0] - b[0]);\n}\n\nconst isLinear = (easing: readonly number[]) =>\n easing[0] === 0 && easing[1] === 0 && easing[2] === 1 && easing[3] === 1;\n\nconst round = (value: number) => Math.round(value * 1e6) / 1e6;\n\n/** The values a scroll-driven animation commits: its frame at the offset the view starts at. */\nexport function firstFrame(\n tracks: ReadonlyMap<string, Track>,\n spec: AnimationSpec,\n range: readonly [number, number],\n): Record<string, unknown> {\n const [start, end] = range;\n const reversed = spec.direction === 'reverse' || spec.direction === 'alternate-reverse';\n const before = 0 < start;\n if (before && spec.fill !== 'backwards' && spec.fill !== 'both') return {};\n const through = Math.min(1, Math.max(0, (0 - start) / Math.max(end - start, 1e-3)));\n const local = reversed ? 1 - through : through;\n const values: Record<string, unknown> = {};\n for (const [property, track] of tracks) values[property] = at(track, local, spec.easing);\n return values;\n}\n"]}
1
+ {"version":3,"file":"scroll-animation.js","sourceRoot":"","sources":["../src/scroll-animation.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A `@keyframes` animation played by a scroll view's offset: `animation-timeline: scroll()`.\n *\n * Native interpolates linearly between the points it is given and clamps past both ends, which is\n * all a scroll-driven animation needs from it once its keyframes are laid along the offset: each\n * keyframe sits at its share of the range, a segment's timing function is sampled into points\n * along it, and an unfilled end falls back to the resting value just outside the range. What\n * native can animate this way is opacity and the transforms; anything else holds its first frame.\n */\nimport type { ScrollRange } from './native-drive.ts';\nimport { at, type AnimationSpec, type TrackPoint } from './transition.ts';\n\ntype Track = readonly { offset: number; value: unknown }[];\n\n/** The channels a scroll-driven animation drives natively, in the order native applies them. */\nexport interface DrivenChannels {\n readonly opacity?: ScrollRange;\n /** Every transform entry the view paints: driven by the scroll, or held as it is. */\n readonly transform: readonly TransformChannel[];\n}\n\nexport type TransformChannel =\n | { readonly property: string; readonly range: ScrollRange }\n | { readonly property: string; readonly value: number };\n\n/** What a range with no end, or a percentage of one, stands in for until the scroll view says. */\nconst UNKNOWN_EXTENT = 1e6;\n\n/** Points per eased segment: enough that the curve between them reads as the curve. */\nconst SAMPLES = 12;\n\n/** The transform groups in the order CSS applies them, as the engine composes them. */\nconst GROUPS = ['__translate', '__rotate', '__scale', 'transform'] as const;\n\n/** Where the range starts and ends on the scroll view's offset. */\nexport function rangeOf(spec: AnimationSpec, extent: number | null): [number, number] {\n const end = (value: number | string | undefined, otherwise: number): number => {\n if (value === undefined) return otherwise;\n if (typeof value === 'number') return value;\n return (parseFloat(value) / 100) * (extent ?? UNKNOWN_EXTENT);\n };\n return [end(spec.range?.start, 0), end(spec.range?.end, extent ?? UNKNOWN_EXTENT)];\n}\n\n/**\n * The channels for an animation's tracks over a range, and the properties it cannot drive\n * natively, which the caller holds at their first frame.\n */\nexport function scrollChannels(\n tracks: ReadonlyMap<string, Track>,\n spec: AnimationSpec,\n resting: Readonly<Record<string, unknown>>,\n range: readonly [number, number],\n): { channels: DrivenChannels; held: string[] } {\n const along = (track: Track, pick: (value: unknown) => number | null, rest: number) =>\n laid(track, pick, rest, spec, range);\n const held: string[] = [];\n let opacity: ScrollRange | undefined;\n const transform: TransformChannel[] = [];\n for (const [property, track] of tracks) {\n if (property === 'opacity') {\n opacity =\n along(\n track,\n (value) => (typeof value === 'number' ? value : null),\n numberOr(resting['opacity'], 1),\n ) ?? undefined;\n if (!opacity) held.push(property);\n } else if (!(GROUPS as readonly string[]).includes(property)) {\n held.push(property);\n }\n }\n for (const group of GROUPS) {\n const track = tracks.get(group);\n const channels = track ? drivenGroup(track, resting[group], along) : heldGroup(resting[group]);\n if (channels === null) held.push(group);\n else transform.push(...channels);\n }\n const anyDriven = transform.some((channel) => 'range' in channel);\n return {\n channels: { ...(opacity ? { opacity } : {}), transform: anyDriven ? transform : [] },\n held,\n };\n}\n\n/**\n * The channels for an animation played by the clock, along a value native runs from nothing to\n * `span`: one iteration along 0 to 1, and for `alternate` the way back along 1 to 2, so that\n * native repeats there and back as one animation. Both ends are the frames' own: what the\n * element rests at is committed when the animation ends, and not played.\n */\nexport function clockChannels(\n tracks: ReadonlyMap<string, Track>,\n spec: AnimationSpec,\n resting: Readonly<Record<string, unknown>>,\n): { channels: DrivenChannels; held: string[]; span: number } {\n const way = (direction: AnimationSpec['direction'], range: readonly [number, number]) =>\n scrollChannels(tracks, { ...spec, fill: 'both', direction }, resting, range);\n if (spec.direction !== 'alternate' && spec.direction !== 'alternate-reverse') {\n return { ...way(spec.direction, [0, 1]), span: 1 };\n }\n const reversed = spec.direction === 'alternate-reverse';\n const out = way(reversed ? 'reverse' : undefined, [0, 1]);\n const back = way(reversed ? undefined : 'reverse', [1, 2]);\n const join = (a: ScrollRange, b: ScrollRange): ScrollRange => ({\n input: [...a.input, ...b.input.slice(1)],\n output: [...a.output, ...b.output.slice(1)],\n });\n const transform = out.channels.transform.map((channel, i) => {\n const other = back.channels.transform[i];\n return 'range' in channel && other && 'range' in other\n ? { property: channel.property, range: join(channel.range, other.range) }\n : channel;\n });\n const opacity =\n out.channels.opacity && back.channels.opacity\n ? { opacity: join(out.channels.opacity, back.channels.opacity) }\n : {};\n return { channels: { ...opacity, transform }, held: out.held, span: 2 };\n}\n\n/**\n * One transform group's entries, each driven along the scroll; null if their shapes differ. A\n * frame, or the element at rest, with fewer functions than the longest is that list with the\n * rest at their identity, which is how CSS eases a list into a longer one that starts the same.\n */\nfunction drivenGroup(\n track: Track,\n resting: unknown,\n along: (\n track: Track,\n pick: (value: unknown) => number | null,\n rest: number,\n ) => ScrollRange | null,\n): TransformChannel[] | null {\n const shapes = track.map((point) => (Array.isArray(point.value) ? point.value : []));\n if (Array.isArray(resting)) shapes.push(resting);\n const shape = shapes.reduce((longest, entries) =>\n entries.length > longest.length ? entries : longest,\n );\n const keys = shape.map((entry) => Object.keys(entry as object)[0]!);\n const channels: TransformChannel[] = [];\n for (const [index, key] of keys.entries()) {\n const identity = key.startsWith('scale') ? 1 : 0;\n const pick = (value: unknown) => {\n const entries = Array.isArray(value) ? value : null;\n if (!entries?.length) return identity;\n const entry = entries[index] as Record<string, unknown> | undefined;\n // Past the end of a shorter list. Where it differs before its end, an earlier entry says.\n if (!entry) return identity;\n return key in entry ? amount(key, entry[key]) : null;\n };\n const range = along(track, pick, restingAmount(resting, index, key, identity));\n if (!range) return null;\n channels.push({ property: key, range });\n }\n return channels;\n}\n\n/** A transform group no keyframe touches, held as the element has it. */\nfunction heldGroup(resting: unknown): TransformChannel[] | null {\n if (!Array.isArray(resting)) return [];\n const channels: TransformChannel[] = [];\n for (const entry of resting as Record<string, unknown>[]) {\n const [key, value] = Object.entries(entry)[0] ?? [];\n const number = key === undefined ? null : amount(key, value);\n if (key === undefined || number === null) return null;\n channels.push({ property: key, value: number });\n }\n return channels;\n}\n\nfunction restingAmount(resting: unknown, index: number, key: string, identity: number): number {\n const entry = Array.isArray(resting) ? (resting[index] as Record<string, unknown>) : undefined;\n return (entry && key in entry ? amount(key, entry[key]) : null) ?? identity;\n}\n\nconst numberOr = (value: unknown, otherwise: number) =>\n typeof value === 'number' ? value : otherwise;\n\nconst RADIANS: Record<string, number> = {\n deg: Math.PI / 180,\n rad: 1,\n grad: Math.PI / 200,\n turn: 2 * Math.PI,\n};\n\n/** The side of a box each move by a share is a share of. */\nconst SHARED: Readonly<Record<string, 'width' | 'height'>> = {\n translateX: 'width',\n translateY: 'height',\n};\n\nconst isShare = (value: unknown): value is string =>\n typeof value === 'string' && value.endsWith('%');\n\nconst sharesIn = (value: unknown): boolean =>\n Array.isArray(value) &&\n value.some((entry) =>\n Object.entries(entry as object).some(([key, to]) => key in SHARED && isShare(to)),\n );\n\n/** Whether an animation moves a box by a share of its own size, in a frame or at rest. */\nexport function movesByShare(\n tracks: ReadonlyMap<string, Track>,\n resting: Readonly<Record<string, unknown>>,\n): boolean {\n return GROUPS.some(\n (group) =>\n sharesIn(resting[group]) ||\n tracks.get(group)?.some((point) => sharesIn(point.value)) === true,\n );\n}\n\n/** A transform list with each move by a share as the points it is of a box of `size`. */\nfunction inPoints(value: unknown, size: { width: number; height: number }): unknown {\n if (!sharesIn(value)) return value;\n return (value as Record<string, unknown>[]).map((entry) => {\n const [key, to] = Object.entries(entry)[0]!;\n const side = SHARED[key];\n return side && isShare(to) ? { [key]: (size[side] * Number.parseFloat(to)) / 100 } : entry;\n });\n}\n\n/**\n * An animation's tracks and resting style with every move by a share of the box as points, which\n * is what native interpolates: `translateX(200%)` of a box 300 wide is 600.\n */\nexport function sharesAsPoints<T extends Track>(\n tracks: ReadonlyMap<string, T>,\n resting: Readonly<Record<string, unknown>>,\n size: { width: number; height: number },\n): { tracks: Map<string, T>; resting: Record<string, unknown> } {\n const sized = new Map(tracks);\n const rest = { ...resting };\n for (const group of GROUPS) {\n const track = tracks.get(group);\n if (track) {\n sized.set(\n group,\n track.map((point) => ({ ...point, value: inPoints(point.value, size) })) as never,\n );\n }\n if (group in rest) rest[group] = inPoints(rest[group], size);\n }\n return { tracks: sized, resting: rest };\n}\n\n/**\n * A transform entry's amount as native's transform node takes it: points, a factor, or an angle\n * in radians. Null for what it cannot take, a percentage translate.\n */\nfunction amount(key: string, value: unknown): number | null {\n if (typeof value === 'number') return value;\n if (typeof value !== 'string') return null;\n const angle = /^(-?[\\d.]+)(deg|rad|grad|turn)$/.exec(value);\n if (angle && (key.startsWith('rotate') || key.startsWith('skew'))) {\n return Number(angle[1]) * RADIANS[angle[2]!]!;\n }\n return null;\n}\n\n/**\n * One property's frames laid along the scroll: each keyframe at its share of the range, eased\n * segments sampled, and the resting value just past an end the animation does not fill.\n */\nfunction laid(\n track: Track,\n pick: (value: unknown) => number | null,\n rest: number,\n spec: AnimationSpec,\n [start, end]: readonly [number, number],\n): ScrollRange | null {\n const values = track.map((point) => pick(point.value));\n if (values.some((value) => value === null)) return null;\n // Each point keeps its own timing function, which eases the stretch it starts.\n const numeric = track.map((point, i) => ({ ...point, value: values[i]! }));\n const points = sampled(numeric, spec, start, Math.max(end - start, 1e-3));\n const fills = spec.fill;\n const backwards = fills === 'backwards' || fills === 'both';\n const forwards = fills === 'forwards' || fills === 'both';\n if (!backwards) points.unshift([points[0]![0] - 1e-3, rest]);\n if (!forwards) points.push([points.at(-1)![0] + 1e-3, rest]);\n return { input: points.map(([x]) => x), output: points.map(([, y]) => round(y)) };\n}\n\n/** A numeric track's points along the scroll, each eased segment sampled, in offset order. */\nfunction sampled(\n numeric: readonly (TrackPoint & { value: number })[],\n spec: AnimationSpec,\n start: number,\n span: number,\n): [number, number][] {\n const reversed = spec.direction === 'reverse' || spec.direction === 'alternate-reverse';\n const points: [number, number][] = [];\n for (let i = 0; i < numeric.length - 1; i++) {\n const from = numeric[i]!;\n const to = numeric[i + 1]!;\n const steps = isLinear(from.easing ?? spec.easing) ? 1 : SAMPLES;\n for (let s = i === 0 ? 0 : 1; s <= steps; s++) {\n const offset = from.offset + ((to.offset - from.offset) * s) / steps;\n const value = at(numeric, offset, spec.easing) as number;\n points.push([start + (reversed ? 1 - offset : offset) * span, value]);\n }\n }\n if (points.length === 1) points.push([start + span, points[0]![1]]);\n return points.sort((a, b) => a[0] - b[0]);\n}\n\nconst isLinear = (easing: readonly number[]) =>\n easing[0] === 0 && easing[1] === 0 && easing[2] === 1 && easing[3] === 1;\n\nconst round = (value: number) => Math.round(value * 1e6) / 1e6;\n\n/** The values a scroll-driven animation commits: its frame at the offset the view starts at. */\nexport function firstFrame(\n tracks: ReadonlyMap<string, Track>,\n spec: AnimationSpec,\n range: readonly [number, number],\n): Record<string, unknown> {\n const [start, end] = range;\n const reversed = spec.direction === 'reverse' || spec.direction === 'alternate-reverse';\n const before = 0 < start;\n if (before && spec.fill !== 'backwards' && spec.fill !== 'both') return {};\n const through = Math.min(1, Math.max(0, (0 - start) / Math.max(end - start, 1e-3)));\n const local = reversed ? 1 - through : through;\n const values: Record<string, unknown> = {};\n for (const [property, track] of tracks) values[property] = at(track, local, spec.easing);\n return values;\n}\n"]}
@@ -27,6 +27,12 @@ export interface Transition {
27
27
  /** What the node paints right now. Also the value a redirected transition starts from. */
28
28
  current: unknown;
29
29
  done: boolean;
30
+ /**
31
+ * The value a change back is a reversal to, and the share of the full duration this one takes:
32
+ * CSS's reversing-adjusted start value and reversing shortening factor. See `redirect`.
33
+ */
34
+ reversingFrom: unknown;
35
+ shortening: number;
30
36
  }
31
37
  export declare function bezier(points: readonly number[], x: number): number;
32
38
  /** How many degrees one of each hue unit is. */
@@ -59,7 +65,15 @@ export declare function interpolate(from: unknown, to: unknown, t: number): unkn
59
65
  export declare function step(state: Map<string, Transition>, key: string, props: Record<string, unknown>, rule: TransitionSpec | undefined, now: number): boolean;
60
66
  /** A property seen for the first time: recorded so the next change has something to aim from. */
61
67
  export declare function settled(value: unknown, rule: TransitionSpec): Transition;
62
- /** Aim an existing transition at a new value, starting from wherever it had got to. */
68
+ /**
69
+ * Aim an existing transition at a new value, starting from wherever it had got to.
70
+ *
71
+ * One turned back to where it came from before it got there takes as long as it had been going,
72
+ * as CSS has it: half way out, the way back is half the distance and half the duration. The
73
+ * factor is how far the old one had eased, of the share it was itself, plus the share it left
74
+ * out, so a transition turned round twice comes back by the same rule. A negative delay is
75
+ * shortened with it; a positive one is waited out in full.
76
+ */
63
77
  export declare function redirect(transition: Transition, target: unknown, rule: TransitionSpec, now: number): void;
64
78
  /** What the CSS compiler emits for `animation:`. Times are milliseconds. */
65
79
  export interface AnimationSpec {
@@ -133,6 +147,16 @@ export declare function tracksOf(frames: readonly Keyframe[], resting: Record<st
133
147
  * differs from one element to the next. Kept per set of frames, as it is asked on every frame.
134
148
  */
135
149
  export declare function readsInheritedColour(frames: readonly Keyframe[]): boolean;
150
+ /**
151
+ * The properties to step for an element: the ones it has, and the ones its transition *names*,
152
+ * even where the element has none yet. A property is only transitioned once it has been seen
153
+ * settling, and one that does not exist is never seen - so `transition: transform` with no
154
+ * transform until a class adds one would arrive instantly, which is the commonest way to write
155
+ * one. `all` names none of them, but it does cover the ones with an initial value to ease from:
156
+ * an opacity nothing set is still 1. And the ones already in `state`, so one whose rule and value
157
+ * both went away is forgotten rather than left running.
158
+ */
159
+ export declare function steppedKeys(props: Record<string, unknown>, spec: Record<string, TransitionSpec> | undefined, state: ReadonlyMap<string, Transition>): Set<string>;
136
160
  /**
137
161
  * Where an animation has got to, as the properties to paint.
138
162
  *
@@ -308,8 +308,9 @@ export function tween(from, to, t) {
308
308
  return null;
309
309
  const a = UNIT.exec(from);
310
310
  const b = UNIT.exec(to);
311
- // Matching units only. Converting between them needs a table, and for the pairs anybody
312
- // actually writes - `0deg` to `1turn`, `0%` to `10px` - the answer would be a guess.
311
+ // Matching units only. Converting between them needs a table, and for a pair anybody actually
312
+ // writes, `0deg` to `1turn`, the answer would be a guess. A translate by a percentage and by a
313
+ // length is the pair with an answer, and `interpolateTransform` gives it: see `summed`.
313
314
  if (!a || !b || a[2] !== b[2])
314
315
  return null;
315
316
  const value = Number(a[1]) + (Number(b[1]) - Number(a[1])) * t;
@@ -337,6 +338,78 @@ function operation(entry) {
337
338
  const keys = Object.keys(entry);
338
339
  return keys.length === 1 ? keys[0] : null;
339
340
  }
341
+ /**
342
+ * Two lists as lists of one length: the shorter with the operations the longer goes on to, each
343
+ * at rest, which is how CSS blends `translateY(4px)` into `translateY(8px) scale(0.5)`. Where the
344
+ * two start differently the caller finds nothing between them.
345
+ */
346
+ function sameLength(a, b) {
347
+ if (a.length === b.length)
348
+ return [a, b];
349
+ const [short, long] = a.length < b.length ? [a, b] : [b, a];
350
+ const padded = [...short, ...atRest(long.slice(short.length))];
351
+ return a.length < b.length ? [padded, b] : [a, padded];
352
+ }
353
+ /** The translates: the operations whose amount may be a share of the box, a length, or both. */
354
+ const TRANSLATES = new Set(['translateX', 'translateY']);
355
+ function sumOf(value) {
356
+ if (Array.isArray(value))
357
+ return value;
358
+ if (typeof value === 'number')
359
+ return [0, value];
360
+ const percent = typeof value === 'string' ? PERCENTAGE.exec(value) : null;
361
+ return percent ? [Number(percent[1]), 0] : null;
362
+ }
363
+ /** Whether a translate by a percentage is followed at once by one by points along the same axis. */
364
+ function isSum(before, entry) {
365
+ const name = operation(entry);
366
+ if (name === null || !TRANSLATES.has(name) || operation(before) !== name)
367
+ return false;
368
+ const percent = before[name];
369
+ const points = entry[name];
370
+ return typeof points === 'number' && typeof percent === 'string' && PERCENTAGE.test(percent);
371
+ }
372
+ /**
373
+ * A list with each such pair read as the one translate it comes to, its amount a `Sum`.
374
+ *
375
+ * `translateY(-25%) translateY(-17px)` is how a frame between `translateY(-50%)` and
376
+ * `translateY(-34px)` is written: CSS eases the two as `calc(-25% - 17px)`, and two translates
377
+ * along one axis add up to that whatever size the box is, which nothing here knows. A transition
378
+ * turned round part way starts from such a frame, so the pair has to pair with one translate.
379
+ */
380
+ function summed(list) {
381
+ if (!list.some((entry, i) => i > 0 && isSum(list[i - 1], entry)))
382
+ return list;
383
+ const out = [];
384
+ for (const entry of list) {
385
+ const before = out.at(-1);
386
+ if (!isSum(before, entry)) {
387
+ out.push(entry);
388
+ continue;
389
+ }
390
+ const name = operation(entry);
391
+ const percent = before[name];
392
+ out[out.length - 1] = {
393
+ [name]: [parseFloat(percent), entry[name]],
394
+ };
395
+ }
396
+ return out;
397
+ }
398
+ /** A translate part way between two amounts `tween` cannot blend, as its pair; null if not one. */
399
+ function tweenSum(name, from, to, t) {
400
+ const a = TRANSLATES.has(name) ? sumOf(from) : null;
401
+ const b = a && sumOf(to);
402
+ if (!a || !b)
403
+ return null;
404
+ const percent = Math.round((a[0] + (b[0] - a[0]) * t) * 1000) / 1000;
405
+ const points = a[1] + (b[1] - a[1]) * t;
406
+ // At an end one of the two is nothing, and the frame is the one translate that was written.
407
+ if (percent === 0)
408
+ return [{ [name]: points }];
409
+ return points === 0
410
+ ? [{ [name]: `${percent}%` }]
411
+ : [{ [name]: `${percent}%` }, { [name]: points }];
412
+ }
340
413
  /**
341
414
  * Two transform lists blended operation by operation.
342
415
  *
@@ -344,6 +417,9 @@ function operation(entry) {
344
417
  * matrix, which is a great deal of arithmetic for a case an author can always write out. Anything
345
418
  * that does not line up returns null and steps instead, which is what CSS falls back to.
346
419
  *
420
+ * A translate by a share of the box and one by a length do line up, and the frame between them is
421
+ * two translates: see `summed`.
422
+ *
347
423
  * A missing side is the ordinary case rather than the exception - `.slider` to
348
424
  * `.slider-end { transform: translateX(180px) }`, and the same again when the class comes off -
349
425
  * so whichever side is absent is read as each operation at rest, which is CSS's `none`.
@@ -352,19 +428,19 @@ function interpolateTransform(from, to, t) {
352
428
  const shape = hasOperations(to) ? to : hasOperations(from) ? from : null;
353
429
  if (!shape)
354
430
  return null;
355
- const start = hasOperations(from) ? from : atRest(shape);
356
- const end = hasOperations(to) ? to : atRest(shape);
357
- if (start.length !== end.length)
358
- return null;
431
+ const [start, end] = sameLength(summed(hasOperations(from) ? from : atRest(shape)), summed(hasOperations(to) ? to : atRest(shape)));
359
432
  const out = [];
360
433
  for (let i = 0; i < end.length; i++) {
361
434
  const name = operation(end[i]);
362
435
  if (name === null || name !== operation(start[i]))
363
436
  return null;
364
- const value = tween(start[i][name], end[i][name], t);
365
- if (value === null)
437
+ const a = start[i][name];
438
+ const b = end[i][name];
439
+ const value = tween(a, b, t);
440
+ const entries = value === null ? tweenSum(name, a, b, t) : [{ [name]: value }];
441
+ if (entries === null)
366
442
  return null;
367
- out.push({ [name]: value });
443
+ out.push(...entries);
368
444
  }
369
445
  return out;
370
446
  }
@@ -380,11 +456,8 @@ export function interpolate(from, to, t) {
380
456
  return from + (to - from) * t;
381
457
  const a = parseColor(from);
382
458
  const b = parseColor(to);
383
- if (a && b) {
384
- const mix = (i) => Math.round(a[i] + (b[i] - a[i]) * t);
385
- const alpha = Math.round((a[3] + (b[3] - a[3]) * t) * 1000) / 1000;
386
- return `rgba(${mix(0)}, ${mix(1)}, ${mix(2)}, ${alpha})`;
387
- }
459
+ if (a && b)
460
+ return mixColours(a, b, t);
388
461
  const percent = interpolatePercentage(from, to, t);
389
462
  if (percent !== null)
390
463
  return percent;
@@ -393,6 +466,19 @@ export function interpolate(from, to, t) {
393
466
  return transform;
394
467
  return t >= 1 ? to : from;
395
468
  }
469
+ /**
470
+ * Two colours part way, in premultiplied alpha as CSS mixes them: each channel weighted by its
471
+ * own alpha, so a colour at no opacity adds no colour at all. Halfway from `transparent`, which
472
+ * is black at no opacity, to red is red at half opacity rather than a dark red, and a colour at
473
+ * part opacity pulls the mix less than an opaque one does.
474
+ */
475
+ function mixColours(a, b, t) {
476
+ const alpha = a[3] + (b[3] - a[3]) * t;
477
+ if (alpha <= 0)
478
+ return 'rgba(0, 0, 0, 0)';
479
+ const mix = (i) => Math.round((a[i] * a[3] + (b[i] * b[3] - a[i] * a[3]) * t) / alpha);
480
+ return `rgba(${mix(0)}, ${mix(1)}, ${mix(2)}, ${Math.round(alpha * 1000) / 1000})`;
481
+ }
396
482
  /** `50%` -> `75%`. Both sides have to be percentages; a percentage and a length are not a scale. */
397
483
  const PERCENTAGE = /^(-?[\d.]+)%$/;
398
484
  function interpolatePercentage(from, to, t) {
@@ -412,36 +498,46 @@ function interpolatePercentage(from, to, t) {
412
498
  * value it has reached rather than the one it is heading for.
413
499
  */
414
500
  export function step(state, key, props, rule, now) {
415
- if (!rule || rule.duration <= 0) {
501
+ if (!rule) {
416
502
  // No longer transitioning: forget it, so re-adding the rule later starts fresh.
417
503
  state.delete(key);
418
504
  return false;
419
505
  }
506
+ // A property nothing sets still has a value to ease from or to: `opacity` is 1. Only the
507
+ // painted value is read this way, so one the element never writes is still not sent.
508
+ const target = props[key] ?? INITIAL[key];
509
+ if (rule.duration <= 0) {
510
+ // Named, with no time to take: it arrives at once, and where it is stays known. A change
511
+ // that comes with a duration, as a ripple's style sets both in one go, starts from here.
512
+ state.set(key, settled(target, rule));
513
+ return false;
514
+ }
420
515
  const seen = state.get(key);
421
516
  if (seen === undefined) {
422
517
  // First sight of the property. CSS does not animate one of these either; without the rule
423
518
  // every element would animate in from whatever the previous value happened to be.
424
- state.set(key, settled(props[key], rule));
519
+ state.set(key, settled(target, rule));
425
520
  return false;
426
521
  }
427
522
  // Nothing to interpolate when one end is missing: `null` here is `auto`, or a property the
428
- // element no longer sets at all, and there is no value halfway between a number and "whatever
429
- // this works out to be". CSS refuses the same transition. Interpolating anyway held the old
430
- // value for the whole duration, which is how a section that opened to a height nothing had
431
- // measured stayed shut - and clearing a height is also what stops the layout that would have
432
- // corrected it, so it stayed shut rather than catching up a frame later.
523
+ // element no longer sets at all and that has no initial value worth easing to, and there is no
524
+ // value halfway between a number and "whatever this works out to be". CSS refuses the same
525
+ // transition. Interpolating anyway held the old value for the whole duration, which is how a
526
+ // section that opened to a height nothing had measured stayed shut - and clearing a height is
527
+ // also what stops the layout that would have corrected it, so it stayed shut rather than
528
+ // catching up a frame later.
433
529
  //
434
530
  // The same goes for a pair with nothing between them at all, a keyword such as `display` or
435
531
  // `flex-direction`: CSS changes it at once rather than transitioning it, and `transition: all`
436
532
  // covers it. Holding the old one for the duration kept a `display: none` on screen until the
437
533
  // end and then made it vanish.
438
- const started = !Object.is(seen.to, props[key]);
439
- if (started && !interpolable(seen.current, props[key])) {
440
- state.set(key, settled(props[key], rule));
534
+ const started = !sameValue(seen.to, target);
535
+ if (started && !interpolable(seen.current, target)) {
536
+ state.set(key, settled(target, rule));
441
537
  return false;
442
538
  }
443
539
  if (started)
444
- redirect(seen, props[key], rule, now);
540
+ redirect(seen, target, rule, now);
445
541
  if (!seen.done)
446
542
  props[key] = seen.current;
447
543
  return started;
@@ -472,14 +568,42 @@ export function settled(value, rule) {
472
568
  easing: rule.easing,
473
569
  current: value,
474
570
  done: true,
571
+ reversingFrom: value,
572
+ shortening: 1,
475
573
  };
476
574
  }
477
- /** Aim an existing transition at a new value, starting from wherever it had got to. */
575
+ /** Whether two values are the same, a transform list by what is in it rather than by identity. */
576
+ function sameValue(a, b) {
577
+ if (Object.is(a, b))
578
+ return true;
579
+ if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null)
580
+ return false;
581
+ return JSON.stringify(a) === JSON.stringify(b);
582
+ }
583
+ /**
584
+ * Aim an existing transition at a new value, starting from wherever it had got to.
585
+ *
586
+ * One turned back to where it came from before it got there takes as long as it had been going,
587
+ * as CSS has it: half way out, the way back is half the distance and half the duration. The
588
+ * factor is how far the old one had eased, of the share it was itself, plus the share it left
589
+ * out, so a transition turned round twice comes back by the same rule. A negative delay is
590
+ * shortened with it; a positive one is waited out in full.
591
+ */
478
592
  export function redirect(transition, target, rule, now) {
593
+ const reversing = !transition.done && sameValue(target, transition.reversingFrom);
594
+ let shortening = 1;
595
+ if (reversing) {
596
+ const elapsed = transition.duration <= 0 ? 1 : (now - transition.start) / transition.duration;
597
+ const eased = bezier(transition.easing, elapsed);
598
+ const factor = eased * transition.shortening + 1 - transition.shortening;
599
+ shortening = Math.min(1, Math.abs(factor));
600
+ }
601
+ transition.reversingFrom = reversing ? transition.to : transition.current;
602
+ transition.shortening = shortening;
479
603
  transition.from = transition.current;
480
604
  transition.to = target;
481
- transition.start = now + rule.delay;
482
- transition.duration = rule.duration;
605
+ transition.start = now + (rule.delay < 0 ? rule.delay * shortening : rule.delay);
606
+ transition.duration = rule.duration * shortening;
483
607
  transition.easing = rule.easing;
484
608
  transition.done = false;
485
609
  }
@@ -539,15 +663,40 @@ const isCurrentColour = (value) => value?.__colour?.color === 'currentcolor';
539
663
  * skeleton that declares no opacity of its own - so both of its implicit frames were empty and the
540
664
  * pulse did not fade, in every skeleton in the library.
541
665
  *
666
+ * A transition reads it too, for an end the element does not set: `.closed { opacity: 0 }`
667
+ * fades out from 1 and back in to it, and a background colour nothing set eases from
668
+ * `transparent`, as in a browser.
669
+ *
542
670
  * Only the properties that appear in an animation and have a meaningful resting value. A length
543
- * defaulting to zero is the same as absent for anything here, and a colour has no initial worth
544
- * animating from.
671
+ * defaulting to zero is the same as absent for anything here.
545
672
  */
546
673
  const INITIAL = {
547
674
  opacity: 1,
548
675
  scale: 1,
549
676
  rotate: '0deg',
677
+ backgroundColor: 'transparent',
550
678
  };
679
+ /**
680
+ * The properties to step for an element: the ones it has, and the ones its transition *names*,
681
+ * even where the element has none yet. A property is only transitioned once it has been seen
682
+ * settling, and one that does not exist is never seen - so `transition: transform` with no
683
+ * transform until a class adds one would arrive instantly, which is the commonest way to write
684
+ * one. `all` names none of them, but it does cover the ones with an initial value to ease from:
685
+ * an opacity nothing set is still 1. And the ones already in `state`, so one whose rule and value
686
+ * both went away is forgotten rather than left running.
687
+ */
688
+ export function steppedKeys(props, spec, state) {
689
+ const keys = new Set([...Object.keys(props), ...state.keys()]);
690
+ if (!spec)
691
+ return keys;
692
+ for (const key of Object.keys(spec))
693
+ if (key !== 'all')
694
+ keys.add(key);
695
+ if (spec['all'])
696
+ for (const key of Object.keys(INITIAL))
697
+ keys.add(key);
698
+ return keys;
699
+ }
551
700
  /**
552
701
  * Where an animation has got to, as the properties to paint.
553
702
  *