streetui 1.8.0 → 2.0.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/bin.cjs +1 -1
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/bin.js.map +1 -1
- package/dist/create-bin.cjs +1 -1
- package/dist/create-bin.cjs.map +1 -1
- package/dist/create-bin.js +1 -1
- package/dist/create-bin.js.map +1 -1
- package/dist/{compile-CJJQYi71.d.cts → hydration-diagnostics-CFYDXBlm.d.cts} +471 -5
- package/dist/{compile-CJJQYi71.d.ts → hydration-diagnostics-CFYDXBlm.d.ts} +471 -5
- package/dist/index.cjs +1401 -47
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +598 -147
- package/dist/index.d.ts +598 -147
- package/dist/index.js +1379 -47
- package/dist/index.js.map +1 -1
- package/dist/renderer-interface-BUhHV7ja.d.cts +26 -0
- package/dist/renderer-interface-B_-hWnKk.d.ts +26 -0
- package/dist/{server-CnLEnlYU.d.cts → server-C0PvFBzD.d.ts} +181 -2
- package/dist/{server-DNlg7ou2.d.ts → server-DnAOFpMP.d.cts} +181 -2
- package/dist/server.cjs +482 -32
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +2 -2
- package/dist/server.d.ts +2 -2
- package/dist/server.js +481 -32
- package/dist/server.js.map +1 -1
- package/dist/testing.cjs +754 -41
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +42 -4
- package/dist/testing.d.ts +42 -4
- package/dist/testing.js +746 -40
- package/dist/testing.js.map +1 -1
- package/package.json +1 -1
- package/dist/hydration-diagnostics-BQeehq3i.d.cts +0 -89
- package/dist/hydration-diagnostics-DNAJumYF.d.ts +0 -89
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { C as CompiledApplication } from './hydration-diagnostics-CFYDXBlm.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The interface the runtime uses to communicate with the renderer.
|
|
5
|
+
*
|
|
6
|
+
* The runtime never knows how DOM nodes are created — it delegates to this
|
|
7
|
+
* interface. This keeps the runtime/renderer boundary clean.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
interface RenderHandle {
|
|
11
|
+
/** Force a synchronous flush of pending updates. */
|
|
12
|
+
flush(): void;
|
|
13
|
+
/** Unmount and dispose all resources. */
|
|
14
|
+
unmount(): void;
|
|
15
|
+
}
|
|
16
|
+
interface StreetRenderer {
|
|
17
|
+
mount(application: CompiledApplication, container: Element): RenderHandle;
|
|
18
|
+
/**
|
|
19
|
+
* Optional: attach behavior to server-rendered HTML already present in
|
|
20
|
+
* `container` instead of recreating it. Renderers that cannot hydrate may
|
|
21
|
+
* omit this; callers fall back to `mount`.
|
|
22
|
+
*/
|
|
23
|
+
hydrate?(application: CompiledApplication, container: Element): RenderHandle;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export type { RenderHandle as R, StreetRenderer as S };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { C as CompiledApplication } from './hydration-diagnostics-CFYDXBlm.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The interface the runtime uses to communicate with the renderer.
|
|
5
|
+
*
|
|
6
|
+
* The runtime never knows how DOM nodes are created — it delegates to this
|
|
7
|
+
* interface. This keeps the runtime/renderer boundary clean.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
interface RenderHandle {
|
|
11
|
+
/** Force a synchronous flush of pending updates. */
|
|
12
|
+
flush(): void;
|
|
13
|
+
/** Unmount and dispose all resources. */
|
|
14
|
+
unmount(): void;
|
|
15
|
+
}
|
|
16
|
+
interface StreetRenderer {
|
|
17
|
+
mount(application: CompiledApplication, container: Element): RenderHandle;
|
|
18
|
+
/**
|
|
19
|
+
* Optional: attach behavior to server-rendered HTML already present in
|
|
20
|
+
* `container` instead of recreating it. Renderers that cannot hydrate may
|
|
21
|
+
* omit this; callers fall back to `mount`.
|
|
22
|
+
*/
|
|
23
|
+
hydrate?(application: CompiledApplication, container: Element): RenderHandle;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export type { RenderHandle as R, StreetRenderer as S };
|
|
@@ -1,4 +1,31 @@
|
|
|
1
|
-
import { C as CompiledApplication } from './
|
|
1
|
+
import { G as GraphNode, R as ReadonlySignal, C as CompiledApplication, i as ApplicationGraph, j as HydrationDiagnosticSink } from './hydration-diagnostics-CFYDXBlm.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Application and component lifecycle primitives.
|
|
5
|
+
*
|
|
6
|
+
* Lifecycle phases:
|
|
7
|
+
* created → mounted → active ⇄ updating → unmounting → destroyed
|
|
8
|
+
*/
|
|
9
|
+
type LifecyclePhase = 'created' | 'mounted' | 'active' | 'updating' | 'unmounting' | 'destroyed';
|
|
10
|
+
type LifecycleHook = () => void | Promise<void>;
|
|
11
|
+
declare class Lifecycle {
|
|
12
|
+
private _phase;
|
|
13
|
+
private readonly _hooks;
|
|
14
|
+
get phase(): LifecyclePhase;
|
|
15
|
+
get isMounted(): boolean;
|
|
16
|
+
get isDestroyed(): boolean;
|
|
17
|
+
on(phase: LifecyclePhase, hook: LifecycleHook): () => void;
|
|
18
|
+
transition(to: LifecyclePhase): Promise<void>;
|
|
19
|
+
onMount(hook: LifecycleHook): () => void;
|
|
20
|
+
onUnmount(hook: LifecycleHook): () => void;
|
|
21
|
+
onDestroy(hook: LifecycleHook): () => void;
|
|
22
|
+
}
|
|
23
|
+
/** A simple cleanup registry — collect teardown functions and run them all at once. */
|
|
24
|
+
declare class CleanupRegistry {
|
|
25
|
+
private readonly _fns;
|
|
26
|
+
add(fn: () => void): void;
|
|
27
|
+
run(): void;
|
|
28
|
+
}
|
|
2
29
|
|
|
3
30
|
/**
|
|
4
31
|
* DOMAdapter — framework-owned abstraction over DOM operations.
|
|
@@ -44,6 +71,13 @@ interface DOMAdapter {
|
|
|
44
71
|
* inline rendering and focus management degrade to a no-op.
|
|
45
72
|
*/
|
|
46
73
|
body(): Element | null;
|
|
74
|
+
/**
|
|
75
|
+
* The document head — the mount target for `head()` metadata (title/meta/
|
|
76
|
+
* link/etc.). Returns null on the server (no document), which is what makes
|
|
77
|
+
* the head platform degrade to server-side string emission (`renderHead`) and
|
|
78
|
+
* the browser `wireHeadBehavior` a no-op on the server render pass.
|
|
79
|
+
*/
|
|
80
|
+
head(): Element | null;
|
|
47
81
|
/** The currently focused element, or null on the server / when none is focused. */
|
|
48
82
|
activeElement(): Element | null;
|
|
49
83
|
/** True if `ancestor` contains `node` (inclusive). Always false on the server. */
|
|
@@ -106,6 +140,7 @@ declare class ServerDOMAdapter implements DOMAdapter {
|
|
|
106
140
|
getElementById(): Element | null;
|
|
107
141
|
focus(): void;
|
|
108
142
|
body(): Element | null;
|
|
143
|
+
head(): Element | null;
|
|
109
144
|
activeElement(): Element | null;
|
|
110
145
|
contains(_ancestor: Element, _node: Node): boolean;
|
|
111
146
|
matches(_element: Element, _selector: string): boolean;
|
|
@@ -123,6 +158,150 @@ declare class ServerDOMAdapter implements DOMAdapter {
|
|
|
123
158
|
}
|
|
124
159
|
declare const serverDOMAdapter: ServerDOMAdapter;
|
|
125
160
|
|
|
161
|
+
/**
|
|
162
|
+
* NodeInstance — the renderer's live counterpart to a GraphNode.
|
|
163
|
+
*
|
|
164
|
+
* Tracks the actual DOM node(s), all signal subscriptions that drive
|
|
165
|
+
* targeted DOM updates, and DOM event listener teardowns.
|
|
166
|
+
*/
|
|
167
|
+
|
|
168
|
+
declare class NodeInstance {
|
|
169
|
+
readonly graphNode: GraphNode;
|
|
170
|
+
/** The primary DOM node for this instance (element or text node). */
|
|
171
|
+
domNode: Node;
|
|
172
|
+
readonly children: NodeInstance[];
|
|
173
|
+
readonly cleanup: CleanupRegistry;
|
|
174
|
+
constructor(graphNode: GraphNode, domNode: Node);
|
|
175
|
+
addChild(child: NodeInstance): void;
|
|
176
|
+
/** Subscribe to a signal; auto-cleanup on unmount. */
|
|
177
|
+
trackSignal<T>(sig: ReadonlySignal<T>, handler: (v: T) => void): void;
|
|
178
|
+
/** Register a raw cleanup fn (DOM event removal, etc.). */
|
|
179
|
+
trackCleanup(fn: () => void): void;
|
|
180
|
+
dispose(): void;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Document head / metadata runtime (2.0 §1–§3).
|
|
185
|
+
*
|
|
186
|
+
* Two entry points, sharing the normalized {@link HeadEntry} model the DSL's
|
|
187
|
+
* `head()` produces (mirrored here as a local structural type so the renderer
|
|
188
|
+
* takes no compile-time dependency on the DSL package — the same convention as
|
|
189
|
+
* the overlay/component descriptors):
|
|
190
|
+
*
|
|
191
|
+
* • `wireHeadBehavior(ctx, node, instance)` — BROWSER. Reads the
|
|
192
|
+
* `__head__<id>` descriptor, registers this node's contribution with a
|
|
193
|
+
* per-render {@link HeadManager} (created lazily on `ctx`), subscribes to any
|
|
194
|
+
* reactive attr/text signals, and tracks cleanup on the NodeInstance so the
|
|
195
|
+
* contribution is withdrawn (and the manager re-applies the merged result)
|
|
196
|
+
* when the node unmounts or the route changes. Server-safe: when
|
|
197
|
+
* `dom.head()` is null (SSR) it is a no-op.
|
|
198
|
+
*
|
|
199
|
+
* • `renderHead(compiled)` — SERVER. Walks the compiled graph in document
|
|
200
|
+
* order, merges every live `head()` contribution (last-in-document-order
|
|
201
|
+
* wins per dedup key — §3), and serializes the effective tags to an HTML
|
|
202
|
+
* string for the caller to place inside `<head>`. Only the active graph is
|
|
203
|
+
* walked, so only active-route metadata is emitted (§2). Each tag carries
|
|
204
|
+
* `data-streetui-head` + `data-streetui-head-key="…"` so the browser adopts
|
|
205
|
+
* it on hydration instead of creating a duplicate.
|
|
206
|
+
*/
|
|
207
|
+
|
|
208
|
+
interface HeadEntryLike {
|
|
209
|
+
readonly tag: 'title' | 'meta' | 'link' | 'base';
|
|
210
|
+
readonly dedupKey: string;
|
|
211
|
+
readonly attrs: Readonly<Record<string, unknown>>;
|
|
212
|
+
readonly text?: unknown;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Coordinates every live `head()` node's contribution into a single
|
|
216
|
+
* `document.head`. One instance per render (lazily created on `ctx`). Merges by
|
|
217
|
+
* dedup key with last-in-document-order winning, and applies the minimal diff to
|
|
218
|
+
* the DOM on every register/unregister/signal change. Adopts server-emitted tags
|
|
219
|
+
* on the first apply so hydration produces no duplicates.
|
|
220
|
+
*/
|
|
221
|
+
declare class HeadManager {
|
|
222
|
+
private readonly _dom;
|
|
223
|
+
private readonly _head;
|
|
224
|
+
private readonly _contributions;
|
|
225
|
+
private readonly _applied;
|
|
226
|
+
private _order;
|
|
227
|
+
private _adopted;
|
|
228
|
+
constructor(dom: DOMAdapter, head: Element);
|
|
229
|
+
/** Register (or replace) a node's contribution and re-apply the merged result. */
|
|
230
|
+
register(nodeId: string, entries: readonly HeadEntryLike[]): void;
|
|
231
|
+
/** Withdraw a node's contribution (unmount / route change) and re-apply. */
|
|
232
|
+
unregister(nodeId: string): void;
|
|
233
|
+
/** Recompute the merged head and patch `document.head` to match. */
|
|
234
|
+
apply(): void;
|
|
235
|
+
private _createTag;
|
|
236
|
+
private _reconcileAttrs;
|
|
237
|
+
/**
|
|
238
|
+
* Seed `_applied` from server-emitted `[data-streetui-head-key]` tags already
|
|
239
|
+
* in `document.head`. The subsequent diff reuses these elements when the
|
|
240
|
+
* client desires the same key (no duplicate), rewrites them if the value
|
|
241
|
+
* changed, or removes them if the client graph no longer wants them.
|
|
242
|
+
*/
|
|
243
|
+
private _adoptServerTags;
|
|
244
|
+
/** The framework-managed attribute names currently on a server tag. */
|
|
245
|
+
private _attrNames;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Wire a mounted/hydrated `head` node's contribution into `document.head`.
|
|
249
|
+
* Server-safe (no-op when there is no document). Shared by the mount and hydrate
|
|
250
|
+
* paths so both establish identical ownership + cleanup.
|
|
251
|
+
*/
|
|
252
|
+
declare function wireHeadBehavior(ctx: RenderContext, graphNode: GraphNode, instance: NodeInstance): void;
|
|
253
|
+
/**
|
|
254
|
+
* Render the active graph's merged document metadata to an HTML string suitable
|
|
255
|
+
* for placing inside `<head>`. Walks the graph in document order, merges every
|
|
256
|
+
* `head()` contribution (last-in-document-order wins per dedup key), and
|
|
257
|
+
* serializes each effective tag with the `data-streetui-head` marker so the
|
|
258
|
+
* browser adopts it on hydration. Returns `''` when the app declares no metadata
|
|
259
|
+
* — so apps that never call `head()` emit nothing extra and existing SSR output
|
|
260
|
+
* is unchanged.
|
|
261
|
+
*/
|
|
262
|
+
declare function renderHead(compiled: CompiledApplication): string;
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* RenderContext — shared state for a single mount operation.
|
|
266
|
+
*
|
|
267
|
+
* Passed through the render pipeline so every sub-function has access
|
|
268
|
+
* to the DOM adapter, graph, and instance map without prop-drilling.
|
|
269
|
+
*/
|
|
270
|
+
|
|
271
|
+
interface RenderContext {
|
|
272
|
+
readonly dom: DOMAdapter;
|
|
273
|
+
readonly graph: ApplicationGraph;
|
|
274
|
+
/** Maps GraphNode.id → its live NodeInstance */
|
|
275
|
+
readonly instances: Map<string, NodeInstance>;
|
|
276
|
+
/** The root container element. */
|
|
277
|
+
readonly container: Element;
|
|
278
|
+
/**
|
|
279
|
+
* Optional dev-only sink that observes hydration mismatch repairs. When
|
|
280
|
+
* absent (the default) the hydration path does no extra work — this is how
|
|
281
|
+
* DevTools/diagnostics stay off the production runtime path.
|
|
282
|
+
*/
|
|
283
|
+
readonly hydrationDiagnostics?: HydrationDiagnosticSink;
|
|
284
|
+
/**
|
|
285
|
+
* Optional SSR-only static-subtree plan (v1.7). Maps a maximal
|
|
286
|
+
* static-subtree root GraphNode.id → its precomputed, verbatim HTML string.
|
|
287
|
+
* Present only on the server render path when a plan has been built; on the
|
|
288
|
+
* browser mount path it is always `undefined`, so the client hot path is
|
|
289
|
+
* unaffected (a single `=== undefined` check short-circuits). When a mounted
|
|
290
|
+
* node's id is in this map, the renderer emits the precomputed HTML via
|
|
291
|
+
* `dom.createRawHTML` instead of recursively constructing the subtree.
|
|
292
|
+
*/
|
|
293
|
+
readonly staticHTML?: ReadonlyMap<string, string>;
|
|
294
|
+
/**
|
|
295
|
+
* Lazily-created coordinator for `head()` metadata nodes (2.0 §1). Created on
|
|
296
|
+
* first `wireHeadBehavior` call on the browser (never on the server, where
|
|
297
|
+
* `dom.head()` is null and `renderHead` emits the metadata instead). Mutable
|
|
298
|
+
* because it is attached on demand; a render with no `head()` nodes never
|
|
299
|
+
* allocates one.
|
|
300
|
+
*/
|
|
301
|
+
head?: HeadManager;
|
|
302
|
+
}
|
|
303
|
+
declare function createRenderContext(dom: DOMAdapter, graph: ApplicationGraph, container: Element, hydrationDiagnostics?: HydrationDiagnosticSink, staticHTML?: ReadonlyMap<string, string>): RenderContext;
|
|
304
|
+
|
|
126
305
|
/**
|
|
127
306
|
* SSR state transfer (dehydration) — move server-resolved data to the client.
|
|
128
307
|
*
|
|
@@ -204,4 +383,4 @@ interface RenderToStringOptions {
|
|
|
204
383
|
*/
|
|
205
384
|
declare function renderToString(compiled: CompiledApplication, options?: RenderToStringOptions): string;
|
|
206
385
|
|
|
207
|
-
export { type DOMAdapter as D, type
|
|
386
|
+
export { CleanupRegistry as C, type DOMAdapter as D, HeadManager as H, Lifecycle as L, NodeInstance as N, type RenderContext as R, STATE_MARKER_ATTR as S, type LifecycleHook as a, type LifecyclePhase as b, type RenderToStringOptions as c, ServerDOMAdapter as d, createRenderContext as e, renderHead as f, renderToString as g, serverDOMAdapter as h, readState as r, serializeState as s, wireHeadBehavior as w };
|
|
@@ -1,4 +1,31 @@
|
|
|
1
|
-
import { C as CompiledApplication } from './
|
|
1
|
+
import { G as GraphNode, R as ReadonlySignal, C as CompiledApplication, i as ApplicationGraph, j as HydrationDiagnosticSink } from './hydration-diagnostics-CFYDXBlm.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Application and component lifecycle primitives.
|
|
5
|
+
*
|
|
6
|
+
* Lifecycle phases:
|
|
7
|
+
* created → mounted → active ⇄ updating → unmounting → destroyed
|
|
8
|
+
*/
|
|
9
|
+
type LifecyclePhase = 'created' | 'mounted' | 'active' | 'updating' | 'unmounting' | 'destroyed';
|
|
10
|
+
type LifecycleHook = () => void | Promise<void>;
|
|
11
|
+
declare class Lifecycle {
|
|
12
|
+
private _phase;
|
|
13
|
+
private readonly _hooks;
|
|
14
|
+
get phase(): LifecyclePhase;
|
|
15
|
+
get isMounted(): boolean;
|
|
16
|
+
get isDestroyed(): boolean;
|
|
17
|
+
on(phase: LifecyclePhase, hook: LifecycleHook): () => void;
|
|
18
|
+
transition(to: LifecyclePhase): Promise<void>;
|
|
19
|
+
onMount(hook: LifecycleHook): () => void;
|
|
20
|
+
onUnmount(hook: LifecycleHook): () => void;
|
|
21
|
+
onDestroy(hook: LifecycleHook): () => void;
|
|
22
|
+
}
|
|
23
|
+
/** A simple cleanup registry — collect teardown functions and run them all at once. */
|
|
24
|
+
declare class CleanupRegistry {
|
|
25
|
+
private readonly _fns;
|
|
26
|
+
add(fn: () => void): void;
|
|
27
|
+
run(): void;
|
|
28
|
+
}
|
|
2
29
|
|
|
3
30
|
/**
|
|
4
31
|
* DOMAdapter — framework-owned abstraction over DOM operations.
|
|
@@ -44,6 +71,13 @@ interface DOMAdapter {
|
|
|
44
71
|
* inline rendering and focus management degrade to a no-op.
|
|
45
72
|
*/
|
|
46
73
|
body(): Element | null;
|
|
74
|
+
/**
|
|
75
|
+
* The document head — the mount target for `head()` metadata (title/meta/
|
|
76
|
+
* link/etc.). Returns null on the server (no document), which is what makes
|
|
77
|
+
* the head platform degrade to server-side string emission (`renderHead`) and
|
|
78
|
+
* the browser `wireHeadBehavior` a no-op on the server render pass.
|
|
79
|
+
*/
|
|
80
|
+
head(): Element | null;
|
|
47
81
|
/** The currently focused element, or null on the server / when none is focused. */
|
|
48
82
|
activeElement(): Element | null;
|
|
49
83
|
/** True if `ancestor` contains `node` (inclusive). Always false on the server. */
|
|
@@ -106,6 +140,7 @@ declare class ServerDOMAdapter implements DOMAdapter {
|
|
|
106
140
|
getElementById(): Element | null;
|
|
107
141
|
focus(): void;
|
|
108
142
|
body(): Element | null;
|
|
143
|
+
head(): Element | null;
|
|
109
144
|
activeElement(): Element | null;
|
|
110
145
|
contains(_ancestor: Element, _node: Node): boolean;
|
|
111
146
|
matches(_element: Element, _selector: string): boolean;
|
|
@@ -123,6 +158,150 @@ declare class ServerDOMAdapter implements DOMAdapter {
|
|
|
123
158
|
}
|
|
124
159
|
declare const serverDOMAdapter: ServerDOMAdapter;
|
|
125
160
|
|
|
161
|
+
/**
|
|
162
|
+
* NodeInstance — the renderer's live counterpart to a GraphNode.
|
|
163
|
+
*
|
|
164
|
+
* Tracks the actual DOM node(s), all signal subscriptions that drive
|
|
165
|
+
* targeted DOM updates, and DOM event listener teardowns.
|
|
166
|
+
*/
|
|
167
|
+
|
|
168
|
+
declare class NodeInstance {
|
|
169
|
+
readonly graphNode: GraphNode;
|
|
170
|
+
/** The primary DOM node for this instance (element or text node). */
|
|
171
|
+
domNode: Node;
|
|
172
|
+
readonly children: NodeInstance[];
|
|
173
|
+
readonly cleanup: CleanupRegistry;
|
|
174
|
+
constructor(graphNode: GraphNode, domNode: Node);
|
|
175
|
+
addChild(child: NodeInstance): void;
|
|
176
|
+
/** Subscribe to a signal; auto-cleanup on unmount. */
|
|
177
|
+
trackSignal<T>(sig: ReadonlySignal<T>, handler: (v: T) => void): void;
|
|
178
|
+
/** Register a raw cleanup fn (DOM event removal, etc.). */
|
|
179
|
+
trackCleanup(fn: () => void): void;
|
|
180
|
+
dispose(): void;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Document head / metadata runtime (2.0 §1–§3).
|
|
185
|
+
*
|
|
186
|
+
* Two entry points, sharing the normalized {@link HeadEntry} model the DSL's
|
|
187
|
+
* `head()` produces (mirrored here as a local structural type so the renderer
|
|
188
|
+
* takes no compile-time dependency on the DSL package — the same convention as
|
|
189
|
+
* the overlay/component descriptors):
|
|
190
|
+
*
|
|
191
|
+
* • `wireHeadBehavior(ctx, node, instance)` — BROWSER. Reads the
|
|
192
|
+
* `__head__<id>` descriptor, registers this node's contribution with a
|
|
193
|
+
* per-render {@link HeadManager} (created lazily on `ctx`), subscribes to any
|
|
194
|
+
* reactive attr/text signals, and tracks cleanup on the NodeInstance so the
|
|
195
|
+
* contribution is withdrawn (and the manager re-applies the merged result)
|
|
196
|
+
* when the node unmounts or the route changes. Server-safe: when
|
|
197
|
+
* `dom.head()` is null (SSR) it is a no-op.
|
|
198
|
+
*
|
|
199
|
+
* • `renderHead(compiled)` — SERVER. Walks the compiled graph in document
|
|
200
|
+
* order, merges every live `head()` contribution (last-in-document-order
|
|
201
|
+
* wins per dedup key — §3), and serializes the effective tags to an HTML
|
|
202
|
+
* string for the caller to place inside `<head>`. Only the active graph is
|
|
203
|
+
* walked, so only active-route metadata is emitted (§2). Each tag carries
|
|
204
|
+
* `data-streetui-head` + `data-streetui-head-key="…"` so the browser adopts
|
|
205
|
+
* it on hydration instead of creating a duplicate.
|
|
206
|
+
*/
|
|
207
|
+
|
|
208
|
+
interface HeadEntryLike {
|
|
209
|
+
readonly tag: 'title' | 'meta' | 'link' | 'base';
|
|
210
|
+
readonly dedupKey: string;
|
|
211
|
+
readonly attrs: Readonly<Record<string, unknown>>;
|
|
212
|
+
readonly text?: unknown;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Coordinates every live `head()` node's contribution into a single
|
|
216
|
+
* `document.head`. One instance per render (lazily created on `ctx`). Merges by
|
|
217
|
+
* dedup key with last-in-document-order winning, and applies the minimal diff to
|
|
218
|
+
* the DOM on every register/unregister/signal change. Adopts server-emitted tags
|
|
219
|
+
* on the first apply so hydration produces no duplicates.
|
|
220
|
+
*/
|
|
221
|
+
declare class HeadManager {
|
|
222
|
+
private readonly _dom;
|
|
223
|
+
private readonly _head;
|
|
224
|
+
private readonly _contributions;
|
|
225
|
+
private readonly _applied;
|
|
226
|
+
private _order;
|
|
227
|
+
private _adopted;
|
|
228
|
+
constructor(dom: DOMAdapter, head: Element);
|
|
229
|
+
/** Register (or replace) a node's contribution and re-apply the merged result. */
|
|
230
|
+
register(nodeId: string, entries: readonly HeadEntryLike[]): void;
|
|
231
|
+
/** Withdraw a node's contribution (unmount / route change) and re-apply. */
|
|
232
|
+
unregister(nodeId: string): void;
|
|
233
|
+
/** Recompute the merged head and patch `document.head` to match. */
|
|
234
|
+
apply(): void;
|
|
235
|
+
private _createTag;
|
|
236
|
+
private _reconcileAttrs;
|
|
237
|
+
/**
|
|
238
|
+
* Seed `_applied` from server-emitted `[data-streetui-head-key]` tags already
|
|
239
|
+
* in `document.head`. The subsequent diff reuses these elements when the
|
|
240
|
+
* client desires the same key (no duplicate), rewrites them if the value
|
|
241
|
+
* changed, or removes them if the client graph no longer wants them.
|
|
242
|
+
*/
|
|
243
|
+
private _adoptServerTags;
|
|
244
|
+
/** The framework-managed attribute names currently on a server tag. */
|
|
245
|
+
private _attrNames;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Wire a mounted/hydrated `head` node's contribution into `document.head`.
|
|
249
|
+
* Server-safe (no-op when there is no document). Shared by the mount and hydrate
|
|
250
|
+
* paths so both establish identical ownership + cleanup.
|
|
251
|
+
*/
|
|
252
|
+
declare function wireHeadBehavior(ctx: RenderContext, graphNode: GraphNode, instance: NodeInstance): void;
|
|
253
|
+
/**
|
|
254
|
+
* Render the active graph's merged document metadata to an HTML string suitable
|
|
255
|
+
* for placing inside `<head>`. Walks the graph in document order, merges every
|
|
256
|
+
* `head()` contribution (last-in-document-order wins per dedup key), and
|
|
257
|
+
* serializes each effective tag with the `data-streetui-head` marker so the
|
|
258
|
+
* browser adopts it on hydration. Returns `''` when the app declares no metadata
|
|
259
|
+
* — so apps that never call `head()` emit nothing extra and existing SSR output
|
|
260
|
+
* is unchanged.
|
|
261
|
+
*/
|
|
262
|
+
declare function renderHead(compiled: CompiledApplication): string;
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* RenderContext — shared state for a single mount operation.
|
|
266
|
+
*
|
|
267
|
+
* Passed through the render pipeline so every sub-function has access
|
|
268
|
+
* to the DOM adapter, graph, and instance map without prop-drilling.
|
|
269
|
+
*/
|
|
270
|
+
|
|
271
|
+
interface RenderContext {
|
|
272
|
+
readonly dom: DOMAdapter;
|
|
273
|
+
readonly graph: ApplicationGraph;
|
|
274
|
+
/** Maps GraphNode.id → its live NodeInstance */
|
|
275
|
+
readonly instances: Map<string, NodeInstance>;
|
|
276
|
+
/** The root container element. */
|
|
277
|
+
readonly container: Element;
|
|
278
|
+
/**
|
|
279
|
+
* Optional dev-only sink that observes hydration mismatch repairs. When
|
|
280
|
+
* absent (the default) the hydration path does no extra work — this is how
|
|
281
|
+
* DevTools/diagnostics stay off the production runtime path.
|
|
282
|
+
*/
|
|
283
|
+
readonly hydrationDiagnostics?: HydrationDiagnosticSink;
|
|
284
|
+
/**
|
|
285
|
+
* Optional SSR-only static-subtree plan (v1.7). Maps a maximal
|
|
286
|
+
* static-subtree root GraphNode.id → its precomputed, verbatim HTML string.
|
|
287
|
+
* Present only on the server render path when a plan has been built; on the
|
|
288
|
+
* browser mount path it is always `undefined`, so the client hot path is
|
|
289
|
+
* unaffected (a single `=== undefined` check short-circuits). When a mounted
|
|
290
|
+
* node's id is in this map, the renderer emits the precomputed HTML via
|
|
291
|
+
* `dom.createRawHTML` instead of recursively constructing the subtree.
|
|
292
|
+
*/
|
|
293
|
+
readonly staticHTML?: ReadonlyMap<string, string>;
|
|
294
|
+
/**
|
|
295
|
+
* Lazily-created coordinator for `head()` metadata nodes (2.0 §1). Created on
|
|
296
|
+
* first `wireHeadBehavior` call on the browser (never on the server, where
|
|
297
|
+
* `dom.head()` is null and `renderHead` emits the metadata instead). Mutable
|
|
298
|
+
* because it is attached on demand; a render with no `head()` nodes never
|
|
299
|
+
* allocates one.
|
|
300
|
+
*/
|
|
301
|
+
head?: HeadManager;
|
|
302
|
+
}
|
|
303
|
+
declare function createRenderContext(dom: DOMAdapter, graph: ApplicationGraph, container: Element, hydrationDiagnostics?: HydrationDiagnosticSink, staticHTML?: ReadonlyMap<string, string>): RenderContext;
|
|
304
|
+
|
|
126
305
|
/**
|
|
127
306
|
* SSR state transfer (dehydration) — move server-resolved data to the client.
|
|
128
307
|
*
|
|
@@ -204,4 +383,4 @@ interface RenderToStringOptions {
|
|
|
204
383
|
*/
|
|
205
384
|
declare function renderToString(compiled: CompiledApplication, options?: RenderToStringOptions): string;
|
|
206
385
|
|
|
207
|
-
export { type DOMAdapter as D, type
|
|
386
|
+
export { CleanupRegistry as C, type DOMAdapter as D, HeadManager as H, Lifecycle as L, NodeInstance as N, type RenderContext as R, STATE_MARKER_ATTR as S, type LifecycleHook as a, type LifecyclePhase as b, type RenderToStringOptions as c, ServerDOMAdapter as d, createRenderContext as e, renderHead as f, renderToString as g, serverDOMAdapter as h, readState as r, serializeState as s, wireHeadBehavior as w };
|