packages/core/src/lib/transitions/define-transition.ts
This is the source snapshot used to build these API details. View this revision on GitHub.
1 import { opacity } from '../../filters/native.js';
2 import { withSignalWriteForbidden } from '../signals/graph.js';
3 import { captureTransition, finite, type TransitionRegion } from './capture.js';
4 import { defineTransitionEffect, type PibblTransitionEffect } from './fade.js';
5
6 /**
7 * Progress, geometry, and drawing context supplied to a custom transition renderer.
8 *
9 * @see {@link PibblTransitionDefinition}
10 */
11 export interface PibblTransitionRenderFrame {
12 /** Borrowed for this synchronous callback only. Coordinates are receiver-local. */
13 readonly context: OffscreenCanvasRenderingContext2D;
14 /** Captured source pixels available during this synchronous rendering callback. See {@link PibblTransitionRenderFrame}. */
15 readonly source: OffscreenCanvas;
16 /** Bounds of the source pixels supplied to the transition. See {@link TransitionRegion}. */
17 readonly sourceBounds: Readonly<TransitionRegion>;
18 /**
19 * Normalized progress through the current animation or transition. See
20 * {@link PibblTransitionRenderFrame}.
21 */
22 readonly progress: number;
23 /** Selects `"enter"`, `"exit"` for phase. See {@link PibblTransitionRenderFrame}. */
24 readonly phase: 'enter' | 'exit';
25 /** Forward milliseconds since this run began, unaffected by reversals. */
26 readonly elapsed: number;
27 /**
28 * Material progress at an earlier time in this run (useful for particle births).
29 * @param elapsed - Elapsed transition time in milliseconds.
30 * @returns Transition progress at the requested time.
31 */
32 readonly progressAt: (elapsed: number) => number;
33 /**
34 * Draws the captured source into the transition's current rendering context. See
35 * {@link PibblTransitionRenderFrame}.
36 */
37 readonly drawSource: () => void;
38 }
39 /**
40 * Synchronous transition rendering callback and optional post-transition linger duration.
41 *
42 * @see {@link PibblTransitionRenderFrame}
43 * @see {@link defineTransition}
44 */
45 export interface PibblTransitionDefinition {
46 /**
47 * Renders the current data or resources using the supplied context. See
48 * {@link PibblTransitionRenderFrame}.
49 * @param frame - Captured source, presentation context, progress, and timing services. See
50 * {@link PibblTransitionRenderFrame} .
51 */
52 readonly render: (frame: Readonly<PibblTransitionRenderFrame>) => void;
53 /** Additional milliseconds after material reaches its target. Default zero. */
54 readonly linger?: number;
55 }
56 /**
57 * Inert custom definition. The callback may call synchronous JS or WASM kernels.
58 *
59 * @param definition - Renderer and metadata defining the effect. See
60 * {@link PibblTransitionDefinition} .
61 * @returns A transition effect usable by the visibility transition hook. See
62 * {@link PibblTransitionEffect} .
63 *
64 * @see {@link PibblTransitionDefinition}
65 * @see {@link PibblTransitionEffect}
66 */
67 export function defineTransition(definition: PibblTransitionDefinition): PibblTransitionEffect {
68 const render = definition.render, linger = finite(definition.linger ?? 0, 'linger', 0);
69 if (typeof render !== 'function') throw new TypeError('defineTransition requires a synchronous render callback.');
70 return defineTransitionEffect((progress, phase, frame) => {
71 if (!frame.active || !linger) {
72 if (progress === 1) return [];
73 if (progress === 0) return [opacity({ amount: 0 })];
74 }
75 return [captureTransition(({ context, source, windows, drawSource }) => {
76 const result: unknown = withSignalWriteForbidden('Transition render callbacks cannot write to signals.', () => render(Object.freeze({ context, source,
77 sourceBounds: Object.freeze({ ...windows.source.logicalBounds }), progress, phase,
78 elapsed: frame.elapsed, progressAt: frame.progressAt, drawSource,
79 })));
80 if (result && typeof (result as { then?: unknown }).then === 'function') throw new TypeError('Transition render callbacks must be synchronous.');
81 })];
82 }, linger);
83 }
84
Documentation version
Section titled “Documentation version”Documentation built with @pibbl/core 0.0.2, revision 2dccb19. ALPHA — NOT FOR PRODUCTION USE.