@b9g/crank 0.7.6 → 0.7.7
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/README.md +15 -9
- package/_css.cjs.map +1 -1
- package/_css.d.ts +21 -0
- package/_css.js.map +1 -1
- package/_svg.cjs.map +1 -1
- package/_svg.d.ts +1 -0
- package/_svg.js.map +1 -1
- package/_utils.cjs.map +1 -1
- package/_utils.d.ts +14 -0
- package/_utils.js.map +1 -1
- package/async.cjs.map +1 -1
- package/async.d.ts +107 -0
- package/async.js.map +1 -1
- package/crank.cjs.map +1 -1
- package/crank.d.ts +733 -0
- package/crank.js.map +1 -1
- package/dom.cjs.map +1 -1
- package/dom.d.ts +14 -0
- package/dom.js.map +1 -1
- package/event-target.cjs.map +1 -1
- package/event-target.d.ts +26 -0
- package/event-target.js.map +1 -1
- package/html.cjs.map +1 -1
- package/html.d.ts +24 -0
- package/html.js.map +1 -1
- package/jsx-runtime.cjs.map +1 -1
- package/jsx-runtime.d.ts +6 -0
- package/jsx-runtime.js.map +1 -1
- package/jsx-tag.cjs.map +1 -1
- package/jsx-tag.d.ts +45 -0
- package/jsx-tag.js.map +1 -1
- package/package.json +1 -1
- package/standalone.d.ts +4 -0
- package/umd.d.ts +3 -0
- package/umd.js.map +1 -1
package/crank.d.ts
ADDED
|
@@ -0,0 +1,733 @@
|
|
|
1
|
+
import { CustomEventTarget } from "./event-target.js";
|
|
2
|
+
/**
|
|
3
|
+
* A type which represents all valid values for an element tag.
|
|
4
|
+
*/
|
|
5
|
+
export type Tag = string | symbol | Component;
|
|
6
|
+
/**
|
|
7
|
+
* A helper type to map the tag of an element to its expected props.
|
|
8
|
+
*
|
|
9
|
+
* @template TTag - The tag associated with the props. Can be a string, symbol
|
|
10
|
+
* or a component function.
|
|
11
|
+
*/
|
|
12
|
+
export type TagProps<TTag extends Tag> = TTag extends string ? JSX.IntrinsicElements[TTag] : TTag extends Component<infer TProps> ? TProps & JSX.IntrinsicAttributes : Record<string, unknown> & JSX.IntrinsicAttributes;
|
|
13
|
+
/**
|
|
14
|
+
* Describes all valid values of an element tree, excluding iterables.
|
|
15
|
+
*
|
|
16
|
+
* Arbitrary objects can also be safely rendered, but will be converted to a
|
|
17
|
+
* string using the toString() method. We exclude them from this type to catch
|
|
18
|
+
* potential mistakes.
|
|
19
|
+
*/
|
|
20
|
+
export type Child = Element | string | number | boolean | null | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* An arbitrarily nested iterable of Child values.
|
|
23
|
+
*
|
|
24
|
+
* We use a recursive interface here rather than making the Children type
|
|
25
|
+
* directly recursive because recursive type aliases were added in TypeScript
|
|
26
|
+
* 3.7.
|
|
27
|
+
*
|
|
28
|
+
* You should avoid referencing this type directly, as it is mainly exported to
|
|
29
|
+
* prevent TypeScript errors.
|
|
30
|
+
*/
|
|
31
|
+
export interface ChildIterable extends Iterable<Child | ChildIterable> {
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Describes all valid values for an element tree, including arbitrarily nested
|
|
35
|
+
* iterables of such values.
|
|
36
|
+
*
|
|
37
|
+
* This type can be used to represent the type of the children prop for an
|
|
38
|
+
* element or the return/yield type of a component.
|
|
39
|
+
*/
|
|
40
|
+
export type Children = Child | ChildIterable;
|
|
41
|
+
/**
|
|
42
|
+
* Represents all functions which can be used as a component.
|
|
43
|
+
*
|
|
44
|
+
* @template [TProps=*] - The expected props for the component.
|
|
45
|
+
*/
|
|
46
|
+
export type Component<TProps extends Record<string, unknown> = any> = (this: Context<TProps>, props: TProps, ctx: Context<TProps>) => Children | PromiseLike<Children> | Iterator<Children, Children | void, any> | AsyncIterator<Children, Children | void, any>;
|
|
47
|
+
/*** SPECIAL TAGS ***/
|
|
48
|
+
/**
|
|
49
|
+
* A special tag for grouping multiple children within the same parent.
|
|
50
|
+
*
|
|
51
|
+
* All non-string iterables which appear in the element tree are implicitly
|
|
52
|
+
* wrapped in a fragment element.
|
|
53
|
+
*
|
|
54
|
+
* This tag is just the empty string, and you can use the empty string in
|
|
55
|
+
* createElement calls or transpiler options directly to avoid having to
|
|
56
|
+
* reference this export.
|
|
57
|
+
*/
|
|
58
|
+
export declare const Fragment = "";
|
|
59
|
+
export type Fragment = typeof Fragment;
|
|
60
|
+
/**
|
|
61
|
+
* A special tag for rendering into a new root node via a root prop.
|
|
62
|
+
*
|
|
63
|
+
* This tag is useful for creating element trees with multiple roots, for
|
|
64
|
+
* things like modals or tooltips.
|
|
65
|
+
*
|
|
66
|
+
* Renderer.prototype.render() implicitly wraps top-level in a Portal element
|
|
67
|
+
* with the root set to the second argument passed in.
|
|
68
|
+
*/
|
|
69
|
+
export declare const Portal: Component<{
|
|
70
|
+
root?: object;
|
|
71
|
+
}> & symbol;
|
|
72
|
+
export type Portal = typeof Portal;
|
|
73
|
+
/**
|
|
74
|
+
* A special tag which preserves whatever was previously rendered in the
|
|
75
|
+
* element's position.
|
|
76
|
+
*
|
|
77
|
+
* Copy elements are useful for when you want to prevent a subtree from
|
|
78
|
+
* rerendering as a performance optimization. Copy elements can also be keyed,
|
|
79
|
+
* in which case the previously rendered keyed element will be copied.
|
|
80
|
+
*/
|
|
81
|
+
export declare const Copy: Component<{}> & symbol;
|
|
82
|
+
export type Copy = typeof Copy;
|
|
83
|
+
/**
|
|
84
|
+
* A special tag for rendering text nodes.
|
|
85
|
+
*
|
|
86
|
+
* Strings in the element tree are implicitly wrapped in a Text element with
|
|
87
|
+
* value set to the string.
|
|
88
|
+
*/
|
|
89
|
+
export declare const Text: Component<{
|
|
90
|
+
value: string;
|
|
91
|
+
}> & symbol;
|
|
92
|
+
export type Text = typeof Text;
|
|
93
|
+
/** A special tag for injecting raw nodes or strings via a value prop. */
|
|
94
|
+
export declare const Raw: Component<{
|
|
95
|
+
value: string | object;
|
|
96
|
+
}> & symbol;
|
|
97
|
+
export type Raw = typeof Raw;
|
|
98
|
+
type ChildrenIteratorResult = IteratorResult<Children, Children | void>;
|
|
99
|
+
declare const ElementSymbol: unique symbol;
|
|
100
|
+
export interface Element<TTag extends Tag = Tag> {
|
|
101
|
+
/**
|
|
102
|
+
* @internal
|
|
103
|
+
* A unique symbol to identify elements as elements across versions and
|
|
104
|
+
* realms, and to protect against basic injection attacks.
|
|
105
|
+
* https://overreacted.io/why-do-react-elements-have-typeof-property/
|
|
106
|
+
*
|
|
107
|
+
* This property is defined on the element prototype rather than per
|
|
108
|
+
* instance, because it is the same for every Element.
|
|
109
|
+
*/
|
|
110
|
+
$$typeof: typeof ElementSymbol;
|
|
111
|
+
/**
|
|
112
|
+
* The tag of the element. Can be a string, symbol or function.
|
|
113
|
+
*/
|
|
114
|
+
tag: TTag;
|
|
115
|
+
/**
|
|
116
|
+
* An object containing the "properties" of an element. These correspond to
|
|
117
|
+
* the attribute syntax from JSX.
|
|
118
|
+
*/
|
|
119
|
+
props: TagProps<TTag>;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Elements are the basic building blocks of Crank applications. They are
|
|
123
|
+
* JavaScript objects which are interpreted by special classes called renderers
|
|
124
|
+
* to produce and manage stateful nodes.
|
|
125
|
+
*
|
|
126
|
+
* @template {Tag} [TTag=Tag] - The type of the tag of the element.
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* // specific element types
|
|
130
|
+
* let div: Element<"div">;
|
|
131
|
+
* let portal: Element<Portal>;
|
|
132
|
+
* let myEl: Element<MyComponent>;
|
|
133
|
+
*
|
|
134
|
+
* // general element types
|
|
135
|
+
* let host: Element<string | symbol>;
|
|
136
|
+
* let component: Element<Component>;
|
|
137
|
+
*
|
|
138
|
+
* Typically, you use a helper function like createElement to create elements
|
|
139
|
+
* rather than instatiating this class directly.
|
|
140
|
+
*/
|
|
141
|
+
export declare class Element<TTag extends Tag = Tag> {
|
|
142
|
+
constructor(tag: TTag, props: TagProps<TTag>);
|
|
143
|
+
}
|
|
144
|
+
export declare function isElement(value: any): value is Element;
|
|
145
|
+
/**
|
|
146
|
+
* Creates an element with the specified tag, props and children.
|
|
147
|
+
*
|
|
148
|
+
* This function is usually used as a transpilation target for JSX transpilers,
|
|
149
|
+
* but it can also be called directly. It additionally extracts special props so
|
|
150
|
+
* they aren't accessible to renderer methods or components, and assigns the
|
|
151
|
+
* children prop according to any additional arguments passed to the function.
|
|
152
|
+
*/
|
|
153
|
+
export declare function createElement<TTag extends Tag>(tag: TTag, props?: TagProps<TTag> | null | undefined, ...children: Array<unknown>): Element<TTag>;
|
|
154
|
+
/** Clones a given element, shallowly copying the props object. */
|
|
155
|
+
export declare function cloneElement<TTag extends Tag>(el: Element<TTag>): Element<TTag>;
|
|
156
|
+
/**
|
|
157
|
+
* A helper type which repesents all possible rendered values of an element.
|
|
158
|
+
*
|
|
159
|
+
* @template TNode - The type of node produced by the associated renderer.
|
|
160
|
+
*
|
|
161
|
+
* When asking the question, what is the "value" of a specific element, the
|
|
162
|
+
* answer varies depending on the tag:
|
|
163
|
+
*
|
|
164
|
+
* For intrinsic elements, the value is the node created for the element, e.g.
|
|
165
|
+
* the DOM node in the case of the DOMRenderer.
|
|
166
|
+
*
|
|
167
|
+
* For portals, the value is undefined, because a Portal element's root and
|
|
168
|
+
* children are opaque to its parent.
|
|
169
|
+
*
|
|
170
|
+
* For component or fragment elements the value can be a node or an array of
|
|
171
|
+
* nodes, depending on how many children they have.
|
|
172
|
+
*/
|
|
173
|
+
export type ElementValue<TNode> = Array<TNode> | TNode | undefined;
|
|
174
|
+
/**
|
|
175
|
+
* @internal
|
|
176
|
+
* Retainers are objects which act as the internal representation of elements,
|
|
177
|
+
* mirroring the element tree.
|
|
178
|
+
*/
|
|
179
|
+
declare class Retainer<TNode, TScope = unknown> {
|
|
180
|
+
/** A bitmask. See RETAINER FLAGS above. */
|
|
181
|
+
f: number;
|
|
182
|
+
el: Element;
|
|
183
|
+
ctx: ContextState<TNode, TScope, any> | undefined;
|
|
184
|
+
children: Array<Retainer<TNode, TScope> | undefined> | Retainer<TNode, TScope> | undefined;
|
|
185
|
+
fallback: Retainer<TNode, TScope> | undefined;
|
|
186
|
+
value: ElementValue<TNode> | undefined;
|
|
187
|
+
scope: TScope | undefined;
|
|
188
|
+
oldProps: Record<string, any> | undefined;
|
|
189
|
+
pendingDiff: Promise<undefined> | undefined;
|
|
190
|
+
onNextDiff: Function | undefined;
|
|
191
|
+
graveyard: Array<Retainer<TNode, TScope>> | undefined;
|
|
192
|
+
lingerers: Array<Set<Retainer<TNode, TScope>> | undefined> | undefined;
|
|
193
|
+
constructor(el: Element);
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Interface for adapting the rendering process to a specific target environment.
|
|
197
|
+
*
|
|
198
|
+
* The RenderAdapter defines how Crank elements are mapped to nodes in your target
|
|
199
|
+
* rendering environment (DOM, Canvas, WebGL, Terminal, etc.). Each method handles
|
|
200
|
+
* a specific part of the element lifecycle, from creation to removal.
|
|
201
|
+
*
|
|
202
|
+
* @template TNode - The type representing a node in your target environment
|
|
203
|
+
* @template TScope - Additional context data passed down the component tree
|
|
204
|
+
* @template TRoot - The type of the root container (defaults to TNode)
|
|
205
|
+
* @template TResult - The type returned when reading element values (defaults to ElementValue<TNode>)
|
|
206
|
+
*
|
|
207
|
+
* @example
|
|
208
|
+
* ```typescript
|
|
209
|
+
* const adapter: RenderAdapter<MyNode, MyScope> = {
|
|
210
|
+
* create: ({ tag, props }) => new MyNode(tag, props),
|
|
211
|
+
* patch: ({ node, props }) => node.update(props),
|
|
212
|
+
* arrange: ({ node, children }) => node.replaceChildren(children),
|
|
213
|
+
* // ... other methods
|
|
214
|
+
* };
|
|
215
|
+
* ```
|
|
216
|
+
*/
|
|
217
|
+
export interface RenderAdapter<TNode, TScope, TRoot extends TNode | undefined = TNode, TResult = ElementValue<TNode>> {
|
|
218
|
+
/**
|
|
219
|
+
* Creates a new node for the given element tag and props.
|
|
220
|
+
*
|
|
221
|
+
* This method is called when Crank encounters a new element that needs to be
|
|
222
|
+
* rendered for the first time. You should create and return a node appropriate
|
|
223
|
+
* for your target environment.
|
|
224
|
+
*
|
|
225
|
+
* @param data.tag - The element tag (e.g., "div", "sprite", or a symbol)
|
|
226
|
+
* @param data.tagName - String representation of the tag for debugging
|
|
227
|
+
* @param data.props - The element's props object
|
|
228
|
+
* @param data.scope - Current scope context (can be undefined)
|
|
229
|
+
* @returns A new node instance
|
|
230
|
+
*
|
|
231
|
+
* @example
|
|
232
|
+
* ```typescript
|
|
233
|
+
* create: ({ tag, props, scope }) => {
|
|
234
|
+
* if (tag === "sprite") {
|
|
235
|
+
* return new PIXI.Sprite(props.texture);
|
|
236
|
+
* }
|
|
237
|
+
* throw new Error(`Unknown tag: ${tag}`);
|
|
238
|
+
* }
|
|
239
|
+
* ```
|
|
240
|
+
*/
|
|
241
|
+
create(data: {
|
|
242
|
+
tag: string | symbol;
|
|
243
|
+
tagName: string;
|
|
244
|
+
props: Record<string, any>;
|
|
245
|
+
scope: TScope | undefined;
|
|
246
|
+
root: TRoot | undefined;
|
|
247
|
+
}): TNode;
|
|
248
|
+
/**
|
|
249
|
+
* Adopts existing nodes during hydration.
|
|
250
|
+
*
|
|
251
|
+
* Called when hydrating server-rendered content or reusing existing nodes.
|
|
252
|
+
* Should return an array of child nodes if the provided node matches the
|
|
253
|
+
* expected tag, or undefined if hydration should fail.
|
|
254
|
+
*
|
|
255
|
+
* @param data.tag - The element tag being hydrated
|
|
256
|
+
* @param data.tagName - String representation of the tag
|
|
257
|
+
* @param data.props - The element's props
|
|
258
|
+
* @param data.node - The existing node to potentially adopt
|
|
259
|
+
* @param data.scope - Current scope context
|
|
260
|
+
* @returns Array of child nodes to hydrate, or undefined if adoption fails
|
|
261
|
+
*
|
|
262
|
+
* @example
|
|
263
|
+
* ```typescript
|
|
264
|
+
* adopt: ({ tag, node }) => {
|
|
265
|
+
* if (node && node.tagName.toLowerCase() === tag) {
|
|
266
|
+
* return Array.from(node.children);
|
|
267
|
+
* }
|
|
268
|
+
* return undefined; // Hydration mismatch
|
|
269
|
+
* }
|
|
270
|
+
* ```
|
|
271
|
+
*/
|
|
272
|
+
adopt(data: {
|
|
273
|
+
tag: string | symbol;
|
|
274
|
+
tagName: string;
|
|
275
|
+
props: Record<string, any>;
|
|
276
|
+
node: TNode | undefined;
|
|
277
|
+
scope: TScope | undefined;
|
|
278
|
+
root: TRoot | undefined;
|
|
279
|
+
}): Array<TNode> | undefined;
|
|
280
|
+
/**
|
|
281
|
+
* Creates or updates a text node.
|
|
282
|
+
*
|
|
283
|
+
* Called when rendering text content. Should create a new text node or
|
|
284
|
+
* update an existing one with the provided value.
|
|
285
|
+
*
|
|
286
|
+
* @param data.value - The text content to render
|
|
287
|
+
* @param data.scope - Current scope context
|
|
288
|
+
* @param data.oldNode - Previous text node to potentially reuse
|
|
289
|
+
* @param data.hydrationNodes - Nodes available during hydration
|
|
290
|
+
* @returns A text node containing the given value
|
|
291
|
+
*
|
|
292
|
+
* @example
|
|
293
|
+
* ```typescript
|
|
294
|
+
* text: ({ value, oldNode }) => {
|
|
295
|
+
* if (oldNode && oldNode.text !== value) {
|
|
296
|
+
* oldNode.text = value;
|
|
297
|
+
* return oldNode;
|
|
298
|
+
* }
|
|
299
|
+
* return new TextNode(value);
|
|
300
|
+
* }
|
|
301
|
+
* ```
|
|
302
|
+
*/
|
|
303
|
+
text(data: {
|
|
304
|
+
value: string;
|
|
305
|
+
scope: TScope | undefined;
|
|
306
|
+
oldNode: TNode | undefined;
|
|
307
|
+
hydrationNodes: Array<TNode> | undefined;
|
|
308
|
+
root: TRoot | undefined;
|
|
309
|
+
}): TNode;
|
|
310
|
+
/**
|
|
311
|
+
* Computes scope context for child elements.
|
|
312
|
+
*
|
|
313
|
+
* Called to determine what scope context should be passed to child elements.
|
|
314
|
+
* The scope can be used to pass rendering context like theme, coordinate systems,
|
|
315
|
+
* or namespaces down the component tree.
|
|
316
|
+
*
|
|
317
|
+
* @param data.tag - The element tag
|
|
318
|
+
* @param data.tagName - String representation of the tag
|
|
319
|
+
* @param data.props - The element's props
|
|
320
|
+
* @param data.scope - Current scope context
|
|
321
|
+
* @returns New scope for children, or undefined to inherit current scope
|
|
322
|
+
*
|
|
323
|
+
* @example
|
|
324
|
+
* ```typescript
|
|
325
|
+
* scope: ({ tag, props, scope }) => {
|
|
326
|
+
* if (tag === "svg") {
|
|
327
|
+
* return { ...scope, namespace: "http://www.w3.org/2000/svg" };
|
|
328
|
+
* }
|
|
329
|
+
* return scope;
|
|
330
|
+
* }
|
|
331
|
+
* ```
|
|
332
|
+
*/
|
|
333
|
+
scope(data: {
|
|
334
|
+
tag: string | symbol;
|
|
335
|
+
tagName: string;
|
|
336
|
+
props: Record<string, any>;
|
|
337
|
+
scope: TScope | undefined;
|
|
338
|
+
root: TRoot | undefined;
|
|
339
|
+
}): TScope | undefined;
|
|
340
|
+
/**
|
|
341
|
+
* Handles raw values (strings or nodes) that bypass normal element processing.
|
|
342
|
+
*
|
|
343
|
+
* Called when rendering Raw elements or other direct node insertions.
|
|
344
|
+
* Should convert string values to appropriate nodes for your environment.
|
|
345
|
+
*
|
|
346
|
+
* @param data.value - Raw string or node value to render
|
|
347
|
+
* @param data.scope - Current scope context
|
|
348
|
+
* @param data.hydrationNodes - Nodes available during hydration
|
|
349
|
+
* @returns ElementValue that can be handled by arrange()
|
|
350
|
+
*
|
|
351
|
+
* @example
|
|
352
|
+
* ```typescript
|
|
353
|
+
* raw: ({ value, scope }) => {
|
|
354
|
+
* if (typeof value === "string") {
|
|
355
|
+
* const container = new Container();
|
|
356
|
+
* container.innerHTML = value;
|
|
357
|
+
* return Array.from(container.children);
|
|
358
|
+
* }
|
|
359
|
+
* return value;
|
|
360
|
+
* }
|
|
361
|
+
* ```
|
|
362
|
+
*/
|
|
363
|
+
raw(data: {
|
|
364
|
+
value: string | TNode;
|
|
365
|
+
scope: TScope | undefined;
|
|
366
|
+
hydrationNodes: Array<TNode> | undefined;
|
|
367
|
+
root: TRoot | undefined;
|
|
368
|
+
}): ElementValue<TNode>;
|
|
369
|
+
/**
|
|
370
|
+
* Updates a node's properties.
|
|
371
|
+
*
|
|
372
|
+
* Called when element props change. Should efficiently update only the
|
|
373
|
+
* properties that have changed. This is where you implement prop-to-attribute
|
|
374
|
+
* mapping, event listener binding, and other property synchronization.
|
|
375
|
+
*
|
|
376
|
+
* @param data.tag - The element tag
|
|
377
|
+
* @param data.tagName - String representation of the tag
|
|
378
|
+
* @param data.node - The node to update
|
|
379
|
+
* @param data.props - New props object
|
|
380
|
+
* @param data.oldProps - Previous props object (undefined for initial render)
|
|
381
|
+
* @param data.scope - Current scope context
|
|
382
|
+
* @param data.copyProps - Props to skip (used for copying between renderers)
|
|
383
|
+
* @param data.isHydrating - Whether currently hydrating
|
|
384
|
+
* @param data.quietProps - Props to not warn about during hydration
|
|
385
|
+
*
|
|
386
|
+
* @example
|
|
387
|
+
* ```typescript
|
|
388
|
+
* patch: ({ node, props, oldProps }) => {
|
|
389
|
+
* for (const [key, value] of Object.entries(props)) {
|
|
390
|
+
* if (oldProps?.[key] !== value) {
|
|
391
|
+
* if (key.startsWith("on")) {
|
|
392
|
+
* node.addEventListener(key.slice(2), value);
|
|
393
|
+
* } else {
|
|
394
|
+
* node[key] = value;
|
|
395
|
+
* }
|
|
396
|
+
* }
|
|
397
|
+
* }
|
|
398
|
+
* }
|
|
399
|
+
* ```
|
|
400
|
+
*/
|
|
401
|
+
patch(data: {
|
|
402
|
+
tag: string | symbol;
|
|
403
|
+
tagName: string;
|
|
404
|
+
node: TNode;
|
|
405
|
+
props: Record<string, any>;
|
|
406
|
+
oldProps: Record<string, any> | undefined;
|
|
407
|
+
scope: TScope | undefined;
|
|
408
|
+
root: TRoot | undefined;
|
|
409
|
+
copyProps: Set<string> | undefined;
|
|
410
|
+
isHydrating: boolean;
|
|
411
|
+
quietProps: Set<string> | undefined;
|
|
412
|
+
}): void;
|
|
413
|
+
/**
|
|
414
|
+
* Arranges child nodes within their parent.
|
|
415
|
+
*
|
|
416
|
+
* Called after child elements are rendered to organize them within their
|
|
417
|
+
* parent node. Should efficiently insert, move, or remove child nodes to
|
|
418
|
+
* match the provided children array.
|
|
419
|
+
*
|
|
420
|
+
* @param data.tag - The parent element tag
|
|
421
|
+
* @param data.tagName - String representation of the tag
|
|
422
|
+
* @param data.node - The parent node
|
|
423
|
+
* @param data.props - The parent element's props
|
|
424
|
+
* @param data.children - Array of child nodes in correct order
|
|
425
|
+
* @param data.oldProps - Previous props (for reference)
|
|
426
|
+
*
|
|
427
|
+
* @example
|
|
428
|
+
* ```typescript
|
|
429
|
+
* arrange: ({ node, children }) => {
|
|
430
|
+
* // Remove existing children
|
|
431
|
+
* node.removeChildren();
|
|
432
|
+
* // Add new children in order
|
|
433
|
+
* for (const child of children) {
|
|
434
|
+
* node.addChild(child);
|
|
435
|
+
* }
|
|
436
|
+
* }
|
|
437
|
+
* ```
|
|
438
|
+
*/
|
|
439
|
+
arrange(data: {
|
|
440
|
+
tag: string | symbol;
|
|
441
|
+
tagName: string;
|
|
442
|
+
node: TNode;
|
|
443
|
+
props: Record<string, any>;
|
|
444
|
+
children: Array<TNode>;
|
|
445
|
+
oldProps: Record<string, any> | undefined;
|
|
446
|
+
scope: TScope | undefined;
|
|
447
|
+
root: TRoot | undefined;
|
|
448
|
+
}): void;
|
|
449
|
+
/**
|
|
450
|
+
* Removes a node from its parent.
|
|
451
|
+
*
|
|
452
|
+
* Called when an element is being unmounted. Should clean up the node
|
|
453
|
+
* and remove it from its parent if appropriate.
|
|
454
|
+
*
|
|
455
|
+
* @param data.node - The node to remove
|
|
456
|
+
* @param data.parentNode - The parent node
|
|
457
|
+
* @param data.isNested - Whether this is a nested removal (child of removed element)
|
|
458
|
+
*
|
|
459
|
+
* @example
|
|
460
|
+
* ```typescript
|
|
461
|
+
* remove: ({ node, parentNode, isNested }) => {
|
|
462
|
+
* // Clean up event listeners, resources, etc.
|
|
463
|
+
* node.cleanup?.();
|
|
464
|
+
* // Remove from parent unless it's a nested removal
|
|
465
|
+
* if (!isNested && parentNode.contains(node)) {
|
|
466
|
+
* parentNode.removeChild(node);
|
|
467
|
+
* }
|
|
468
|
+
* }
|
|
469
|
+
* ```
|
|
470
|
+
*/
|
|
471
|
+
remove(data: {
|
|
472
|
+
node: TNode;
|
|
473
|
+
parentNode: TNode;
|
|
474
|
+
isNested: boolean;
|
|
475
|
+
root: TRoot | undefined;
|
|
476
|
+
}): void;
|
|
477
|
+
/**
|
|
478
|
+
* Reads the final rendered value from an ElementValue.
|
|
479
|
+
*
|
|
480
|
+
* Called to extract the final result from rendered elements. This allows
|
|
481
|
+
* you to transform the internal node representation into the public API
|
|
482
|
+
* that users of your renderer will see.
|
|
483
|
+
*
|
|
484
|
+
* @param value - The ElementValue to read (array, single node, or undefined)
|
|
485
|
+
* @returns The public representation of the rendered value
|
|
486
|
+
*
|
|
487
|
+
* @example
|
|
488
|
+
* ```typescript
|
|
489
|
+
* read: (value) => {
|
|
490
|
+
* if (Array.isArray(value)) {
|
|
491
|
+
* return value.map(node => node.publicAPI);
|
|
492
|
+
* }
|
|
493
|
+
* return value?.publicAPI;
|
|
494
|
+
* }
|
|
495
|
+
* ```
|
|
496
|
+
*/
|
|
497
|
+
read(value: ElementValue<TNode>): TResult;
|
|
498
|
+
/**
|
|
499
|
+
* Performs final rendering to the root container.
|
|
500
|
+
*
|
|
501
|
+
* Called after the entire render cycle is complete. This is where you
|
|
502
|
+
* trigger the actual rendering/presentation in your target environment
|
|
503
|
+
* (e.g., calling render() on a canvas, flushing to the screen, etc.).
|
|
504
|
+
*
|
|
505
|
+
* @param root - The root container
|
|
506
|
+
*
|
|
507
|
+
* @example
|
|
508
|
+
* ```typescript
|
|
509
|
+
* finalize: (root) => {
|
|
510
|
+
* // Trigger actual rendering
|
|
511
|
+
* if (root instanceof PIXIApplication) {
|
|
512
|
+
* root.render();
|
|
513
|
+
* }
|
|
514
|
+
* }
|
|
515
|
+
* ```
|
|
516
|
+
*/
|
|
517
|
+
finalize(root: TRoot): void;
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* An abstract class which is subclassed to render to different target
|
|
521
|
+
* environments. Subclasses call super() with a custom RenderAdapter object.
|
|
522
|
+
* This class is responsible for kicking off the rendering process and caching
|
|
523
|
+
* previous trees by root.
|
|
524
|
+
*
|
|
525
|
+
* @template TNode - The type of the node for a rendering environment.
|
|
526
|
+
* @template TScope - Data which is passed down the tree.
|
|
527
|
+
* @template TRoot - The type of the root for a rendering environment.
|
|
528
|
+
* @template TResult - The type of exposed values.
|
|
529
|
+
*/
|
|
530
|
+
export declare class Renderer<TNode extends object, TScope, TRoot extends TNode | undefined = TNode, TResult = ElementValue<TNode>> {
|
|
531
|
+
/**
|
|
532
|
+
* @internal
|
|
533
|
+
* A weakmap which stores element trees by root.
|
|
534
|
+
*/
|
|
535
|
+
cache: WeakMap<object, Retainer<TNode, TScope>>;
|
|
536
|
+
adapter: RenderAdapter<TNode, TScope, TRoot, TResult>;
|
|
537
|
+
constructor(adapter: Partial<RenderAdapter<TNode, TScope, TRoot, TResult>>);
|
|
538
|
+
/**
|
|
539
|
+
* Renders an element tree into a specific root.
|
|
540
|
+
*
|
|
541
|
+
* @param children - An element tree. Rendering null deletes cached renders.
|
|
542
|
+
* @param root - The root to be rendered into. The renderer caches renders
|
|
543
|
+
* per root.
|
|
544
|
+
* @param bridge - An optional context that will be the ancestor context of
|
|
545
|
+
* all elements in the tree. Useful for connecting different renderers so
|
|
546
|
+
* that events/provisions/errors properly propagate. The context for a given
|
|
547
|
+
* root must be the same between renders.
|
|
548
|
+
*
|
|
549
|
+
* @returns The result of rendering the children, or a possible promise of
|
|
550
|
+
* the result if the element tree renders asynchronously.
|
|
551
|
+
*/
|
|
552
|
+
render(children: Children, root?: TRoot | undefined, bridge?: Context | undefined): Promise<TResult> | TResult;
|
|
553
|
+
hydrate(children: Children, root: TRoot, bridge?: Context | undefined): Promise<TResult> | TResult;
|
|
554
|
+
}
|
|
555
|
+
interface PullController {
|
|
556
|
+
iterationP: Promise<ChildrenIteratorResult> | undefined;
|
|
557
|
+
diff: Promise<undefined> | undefined;
|
|
558
|
+
onChildError: ((err: unknown) => void) | undefined;
|
|
559
|
+
}
|
|
560
|
+
interface ScheduleController {
|
|
561
|
+
promise: Promise<unknown>;
|
|
562
|
+
onAbort: () => void;
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* @internal
|
|
566
|
+
* The internal class which holds context data.
|
|
567
|
+
*/
|
|
568
|
+
declare class ContextState<TNode = unknown, TScope = unknown, TRoot extends TNode | undefined = TNode | undefined, TResult = unknown> {
|
|
569
|
+
/** The adapter of the renderer which created this context. */
|
|
570
|
+
adapter: RenderAdapter<TNode, TScope, TRoot, TResult>;
|
|
571
|
+
/** The root node as set by the nearest ancestor portal. */
|
|
572
|
+
root: TRoot | undefined;
|
|
573
|
+
/**
|
|
574
|
+
* The nearest ancestor host or portal retainer.
|
|
575
|
+
*
|
|
576
|
+
* When refresh is called, the host element will be arranged as the last step
|
|
577
|
+
* of the commit, to make sure the parent's children properly reflects the
|
|
578
|
+
* components's childrenk
|
|
579
|
+
*/
|
|
580
|
+
host: Retainer<TNode>;
|
|
581
|
+
/** The parent context state. */
|
|
582
|
+
parent: ContextState | undefined;
|
|
583
|
+
/** The actual context associated with this state. */
|
|
584
|
+
ctx: Context<unknown, TResult>;
|
|
585
|
+
/** The value of the scope at the point of element's creation. */
|
|
586
|
+
scope: TScope | undefined;
|
|
587
|
+
/** The internal node associated with this context. */
|
|
588
|
+
ret: Retainer<TNode>;
|
|
589
|
+
/**
|
|
590
|
+
* Any iterator returned by a component function.
|
|
591
|
+
*
|
|
592
|
+
* Existence of this property implies that the component is a generator
|
|
593
|
+
* component. It is deleted when a component is returned.
|
|
594
|
+
*/
|
|
595
|
+
iterator: Iterator<Children, Children | void, unknown> | AsyncIterator<Children, Children | void, unknown> | undefined;
|
|
596
|
+
inflight: [Promise<undefined>, Promise<undefined>] | undefined;
|
|
597
|
+
enqueued: [Promise<undefined>, Promise<undefined>] | undefined;
|
|
598
|
+
pull: PullController | undefined;
|
|
599
|
+
onPropsProvided: ((props: unknown) => unknown) | undefined;
|
|
600
|
+
onPropsRequested: (() => unknown) | undefined;
|
|
601
|
+
index: number;
|
|
602
|
+
schedule: ScheduleController | undefined;
|
|
603
|
+
constructor(adapter: RenderAdapter<TNode, TScope, TRoot, TResult>, root: TRoot, host: Retainer<TNode>, parent: ContextState | undefined, scope: TScope | undefined, ret: Retainer<TNode>);
|
|
604
|
+
}
|
|
605
|
+
export type ComponentProps<T> = T extends () => unknown ? {} : T extends (props: infer U) => unknown ? U : never;
|
|
606
|
+
export type ComponentPropsOrProps<T> = T extends Function ? ComponentProps<T> : T;
|
|
607
|
+
declare const _ContextState: unique symbol;
|
|
608
|
+
/**
|
|
609
|
+
* A class which is instantiated and passed to every component as its this
|
|
610
|
+
* value/second parameter. Contexts form a tree just like elements and all
|
|
611
|
+
* components in the element tree are connected via contexts. Components can
|
|
612
|
+
* use this tree to communicate data upwards via events and downwards via
|
|
613
|
+
* provisions.
|
|
614
|
+
*
|
|
615
|
+
* @template [T=*] - The expected shape of the props passed to the component,
|
|
616
|
+
* or a component function. Used to strongly type the Context iterator methods.
|
|
617
|
+
* @template [TResult=*] - The readable element value type. It is used in
|
|
618
|
+
* places such as the return value of refresh and the argument passed to
|
|
619
|
+
* schedule and cleanup callbacks.
|
|
620
|
+
*/
|
|
621
|
+
export declare class Context<T = any, TResult = any> extends CustomEventTarget<Context> {
|
|
622
|
+
/**
|
|
623
|
+
* @internal
|
|
624
|
+
* DO NOT USE READ THIS PROPERTY.
|
|
625
|
+
*/
|
|
626
|
+
[_ContextState]: ContextState<unknown, unknown, unknown, TResult>;
|
|
627
|
+
constructor(state: ContextState<unknown, unknown, unknown, TResult>);
|
|
628
|
+
/**
|
|
629
|
+
* The current props of the associated element.
|
|
630
|
+
*/
|
|
631
|
+
get props(): ComponentPropsOrProps<T>;
|
|
632
|
+
/**
|
|
633
|
+
* The current value of the associated element.
|
|
634
|
+
*
|
|
635
|
+
* @deprecated
|
|
636
|
+
*/
|
|
637
|
+
get value(): TResult;
|
|
638
|
+
get isExecuting(): boolean;
|
|
639
|
+
get isUnmounted(): boolean;
|
|
640
|
+
[Symbol.iterator](): Generator<ComponentPropsOrProps<T>, undefined>;
|
|
641
|
+
[Symbol.asyncIterator](): AsyncGenerator<ComponentPropsOrProps<T>, undefined>;
|
|
642
|
+
/**
|
|
643
|
+
* Re-executes a component.
|
|
644
|
+
*
|
|
645
|
+
* @param callback - Optional callback to execute before refresh
|
|
646
|
+
* @returns The rendered result of the component or a promise thereof if the
|
|
647
|
+
* component or its children execute asynchronously.
|
|
648
|
+
*/
|
|
649
|
+
refresh(callback?: () => unknown): Promise<TResult> | TResult;
|
|
650
|
+
/**
|
|
651
|
+
* Registers a callback which fires when the component's children are
|
|
652
|
+
* created. Will only fire once per callback and update.
|
|
653
|
+
*/
|
|
654
|
+
schedule(): Promise<TResult>;
|
|
655
|
+
schedule(callback: (value: TResult) => unknown): void;
|
|
656
|
+
/**
|
|
657
|
+
* Registers a callback which fires when the component's children are fully
|
|
658
|
+
* rendered. Will only fire once per callback and update.
|
|
659
|
+
*/
|
|
660
|
+
after(): Promise<TResult>;
|
|
661
|
+
after(callback: (value: TResult) => unknown): void;
|
|
662
|
+
/**
|
|
663
|
+
* @deprecated the flush() method has been renamed to after().
|
|
664
|
+
*/
|
|
665
|
+
flush(): Promise<TResult>;
|
|
666
|
+
flush(callback: (value: TResult) => unknown): void;
|
|
667
|
+
/**
|
|
668
|
+
* Registers a callback which fires when the component unmounts.
|
|
669
|
+
*
|
|
670
|
+
* The callback can be async to defer the unmounting of a component's children.
|
|
671
|
+
*/
|
|
672
|
+
cleanup(): Promise<TResult>;
|
|
673
|
+
cleanup(callback: (value: TResult) => unknown): void;
|
|
674
|
+
consume<TKey extends keyof ProvisionMap>(key: TKey): ProvisionMap[TKey];
|
|
675
|
+
consume(key: unknown): any;
|
|
676
|
+
provide<TKey extends keyof ProvisionMap>(key: TKey, value: ProvisionMap[TKey]): void;
|
|
677
|
+
provide(key: unknown, value: any): void;
|
|
678
|
+
[CustomEventTarget.dispatchEventOnSelf](ev: Event): void;
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* An interface which can be extended to provide strongly typed provisions.
|
|
682
|
+
* See Context.prototype.consume and Context.prototype.provide.
|
|
683
|
+
*/
|
|
684
|
+
export interface ProvisionMap extends Crank.ProvisionMap {
|
|
685
|
+
}
|
|
686
|
+
export interface EventMap extends Crank.EventMap {
|
|
687
|
+
}
|
|
688
|
+
type MappedEventListener<T extends string> = (ev: Crank.EventMap[T]) => unknown;
|
|
689
|
+
type MappedEventListenerOrEventListenerObject<T extends string> = MappedEventListener<T> | {
|
|
690
|
+
handleEvent: MappedEventListener<T>;
|
|
691
|
+
};
|
|
692
|
+
export interface Context extends Crank.Context {
|
|
693
|
+
addEventListener<T extends string>(type: T, listener: MappedEventListenerOrEventListenerObject<T> | null, options?: boolean | AddEventListenerOptions): void;
|
|
694
|
+
removeEventListener<T extends string>(type: T, listener: MappedEventListenerOrEventListenerObject<T> | null, options?: EventListenerOptions | boolean): void;
|
|
695
|
+
dispatchEvent<T extends string>(ev: EventMap[T] | Event): boolean;
|
|
696
|
+
}
|
|
697
|
+
declare global {
|
|
698
|
+
namespace Crank {
|
|
699
|
+
interface EventMap {
|
|
700
|
+
[tag: string]: Event;
|
|
701
|
+
}
|
|
702
|
+
interface ProvisionMap {
|
|
703
|
+
}
|
|
704
|
+
interface Context {
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
namespace JSX {
|
|
708
|
+
interface IntrinsicElements {
|
|
709
|
+
[tag: string]: any;
|
|
710
|
+
}
|
|
711
|
+
interface IntrinsicAttributes {
|
|
712
|
+
children?: unknown;
|
|
713
|
+
key?: unknown;
|
|
714
|
+
ref?: unknown;
|
|
715
|
+
copy?: unknown;
|
|
716
|
+
hydrate?: unknown;
|
|
717
|
+
}
|
|
718
|
+
interface ElementChildrenAttribute {
|
|
719
|
+
children: {};
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
/**
|
|
724
|
+
* A re-export of some Crank exports as the default export.
|
|
725
|
+
*
|
|
726
|
+
* Some JSX tools expect things like createElement/Fragment to be defined on
|
|
727
|
+
* the default export. Prefer using the named exports directly.
|
|
728
|
+
*/
|
|
729
|
+
declare const _default: {
|
|
730
|
+
createElement: typeof createElement;
|
|
731
|
+
Fragment: string;
|
|
732
|
+
};
|
|
733
|
+
export default _default;
|