packages/core/src/lib/render-layer/define-render-layer.ts
This is the source snapshot used to build these API details. View this revision on GitHub.
1 import { definePrimitive } from "../define-primitive.js";
2 import { GLOBAL_STATE } from "../global-state.js";
3 import { createLayerSurface } from "../surface/resolve-surface.js";
4 import {
5 resolveRequiredLength,
6 stripLayoutParticipation,
7 } from "../style/resolve-built-in.js";
8 import type {
9 PibblComponent,
10 PrimitiveCapabilities,
11 RenderingContext2D,
12 } from "../types.js";
13 import { PIBBL_EVENT_DEFINITIONS } from "../events/event-definitions.js";
14 import { wireStructuralEvents } from "../components/structural-events.js";
15 import { RenderLayerController } from "./controller.js";
16 import type {
17 PibblRenderLayerDefinition,
18 PibblRenderLayerProps,
19 PibblRenderLayerSize,
20 PibblRenderLayerStyle,
21 } from "./types.js";
22
23 type ResolvedRenderLayerStyle = PibblRenderLayerStyle & {
24 readonly width: number;
25 readonly height: number;
26 };
27
28 /**
29 * Defines a Pibbl component backed by a persistent external-renderer surface and resource lifetime.
30 * Pibbl schedules frames and commits the bitmap and interaction snapshot together; the definition
31 * owns application-resource cleanup.
32 *
33 * @param definition - Synchronous resource lifecycle, rendering, and interaction implementation.
34 * See {@link PibblRenderLayerDefinition} .
35 * @returns A Pibbl component that owns one external-renderer boundary per mounted identity. See
36 * {@link PibblComponent} , {@link PibblRenderLayerProps} .
37 *
38 * @see {@link PibblRenderLayerDefinition}
39 * @see {@link PibblComponent}
40 * @see {@link PibblRenderLayerProps}
41 */
42 export function defineRenderLayer<
43 Props,
44 Resources,
45 Target extends object = object,
46 >(
47 definition: PibblRenderLayerDefinition<Props, Resources, Target>,
48 ): PibblComponent<PibblRenderLayerProps<Props>> {
49 const immutableDefinition = snapshotDefinition(definition);
50 const primitive = (definePrimitive as any)(
51 function renderDefinedRenderLayer(
52 props: Readonly<PibblRenderLayerProps<Props>>,
53 style: Readonly<ResolvedRenderLayerStyle>,
54 ctx: RenderingContext2D,
55 ) {
56 wireStructuralEvents(props);
57 const refs = GLOBAL_STATE.componentRefs!;
58 let controller = refs.refs[0] as
59 RenderLayerController<Props, Resources, Target> | undefined;
60 if (!controller) {
61 controller = new RenderLayerController(immutableDefinition, refs);
62 refs.refs[0] = controller;
63 }
64 const surface = GLOBAL_STATE.currentPibblInstance!.surface.snapshot!;
65 const layerSurface = createLayerSurface(
66 style.width,
67 style.height,
68 surface.backingPixelsPerLogicalUnitX,
69 surface.backingPixelsPerLogicalUnitY,
70 );
71 const size: PibblRenderLayerSize = Object.freeze({
72 width: style.width,
73 height: style.height,
74 backingWidth: layerSurface.backingWidth,
75 backingHeight: layerSurface.backingHeight,
76 pixelRatioX: layerSurface.backingPixelsPerLogicalUnitX,
77 pixelRatioY: layerSurface.backingPixelsPerLogicalUnitY,
78 });
79 controller.render(customProps(props) as Props, size, ctx, {
80 missBehavior: props.missBehavior ?? "pass-through",
81 pointerEvents: props.pointerEvents,
82 keyboardFocusable: props.keyboardFocusable,
83 keyboardNavigationBounds: props.keyboardNavigationBounds,
84 });
85 },
86 { resolveStyle },
87 );
88 return primitive as PibblComponent<PibblRenderLayerProps<Props>>;
89 }
90
91 const resolveStyle: NonNullable<
92 PrimitiveCapabilities<
93 PibblRenderLayerProps<any>,
94 PibblRenderLayerStyle,
95 PibblRenderLayerStyle,
96 ResolvedRenderLayerStyle
97 >["resolveStyle"]
98 > = (style, context) =>
99 ({
100 ...stripLayoutParticipation(style),
101 width: resolveRequiredLength(
102 style.width ?? context.allocation.width,
103 context.percentageBasis.width,
104 "width",
105 context,
106 ),
107 height: resolveRequiredLength(
108 style.height ?? context.allocation.height,
109 context.percentageBasis.height,
110 "height",
111 context,
112 ),
113 }) as ResolvedRenderLayerStyle;
114
115 function customProps<Props>(
116 props: Readonly<PibblRenderLayerProps<Props>>,
117 ): Props {
118 const custom = { ...props } as Record<PropertyKey, unknown>;
119 delete custom.missBehavior;
120 delete custom.pointerEvents;
121 delete custom.keyboardFocusable;
122 delete custom.keyboardNavigationBounds;
123 for (const definition of PIBBL_EVENT_DEFINITIONS) {
124 delete custom[definition.prop];
125 delete custom[definition.captureProp];
126 }
127 return custom as Props;
128 }
129
130 function snapshotDefinition<Props, Resources, Target extends object>(
131 definition: PibblRenderLayerDefinition<Props, Resources, Target>,
132 ): PibblRenderLayerDefinition<Props, Resources, Target> {
133 return Object.freeze({
134 create: definition.create,
135 update: definition.update,
136 resize: definition.resize,
137 render: definition.render,
138 dispose: definition.dispose,
139 interaction: definition.interaction
140 ? Object.freeze({
141 settle: definition.interaction.settle,
142 })
143 : undefined,
144 });
145 }
146
Documentation version
Section titled “Documentation version”Documentation built with @pibbl/core 0.0.2, revision 272a94a. ALPHA — NOT FOR PRODUCTION USE.