@jasonshimmy/custom-elements-runtime 3.0.0 → 3.1.1

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.
Files changed (68) hide show
  1. package/README.md +118 -81
  2. package/dist/custom-elements-runtime.cjs.js +3 -3
  3. package/dist/custom-elements-runtime.cjs.js.map +1 -1
  4. package/dist/custom-elements-runtime.es.js +77 -72
  5. package/dist/custom-elements-runtime.es.js.map +1 -1
  6. package/dist/custom-elements-runtime.jit-css.cjs.js +1 -1
  7. package/dist/custom-elements-runtime.jit-css.cjs.js.map +1 -1
  8. package/dist/custom-elements-runtime.jit-css.es.js +25 -26
  9. package/dist/custom-elements-runtime.jit-css.es.js.map +1 -1
  10. package/dist/custom-elements-runtime.router.cjs.js +8 -8
  11. package/dist/custom-elements-runtime.router.cjs.js.map +1 -1
  12. package/dist/custom-elements-runtime.router.es.js +134 -134
  13. package/dist/custom-elements-runtime.router.es.js.map +1 -1
  14. package/dist/custom-elements-runtime.ssr-middleware.cjs.js +2 -0
  15. package/dist/custom-elements-runtime.ssr-middleware.cjs.js.map +1 -0
  16. package/dist/custom-elements-runtime.ssr-middleware.es.js +69 -0
  17. package/dist/custom-elements-runtime.ssr-middleware.es.js.map +1 -0
  18. package/dist/custom-elements-runtime.ssr.cjs.js +3 -1
  19. package/dist/custom-elements-runtime.ssr.cjs.js.map +1 -1
  20. package/dist/custom-elements-runtime.ssr.es.js +158 -39
  21. package/dist/custom-elements-runtime.ssr.es.js.map +1 -1
  22. package/dist/custom-elements-runtime.vite-plugin.cjs.js +1 -1
  23. package/dist/custom-elements-runtime.vite-plugin.cjs.js.map +1 -1
  24. package/dist/custom-elements-runtime.vite-plugin.es.js +81 -49
  25. package/dist/custom-elements-runtime.vite-plugin.es.js.map +1 -1
  26. package/dist/hooks-x8M4knLc.cjs +6 -0
  27. package/dist/hooks-x8M4knLc.cjs.map +1 -0
  28. package/dist/hooks-xWZhQHco.js +1465 -0
  29. package/dist/hooks-xWZhQHco.js.map +1 -0
  30. package/dist/index.d.ts +3 -0
  31. package/dist/namespace-helpers-D4wC2-qA.js +61 -0
  32. package/dist/namespace-helpers-D4wC2-qA.js.map +1 -0
  33. package/dist/namespace-helpers-ckeEOxpR.cjs +2 -0
  34. package/dist/namespace-helpers-ckeEOxpR.cjs.map +1 -0
  35. package/dist/router/matcher.d.ts +14 -0
  36. package/dist/runtime/component/factory.d.ts +16 -2
  37. package/dist/runtime/hydration.d.ts +33 -0
  38. package/dist/runtime/render.d.ts +0 -11
  39. package/dist/runtime/scheduler.d.ts +12 -0
  40. package/dist/runtime/ssr-context.d.ts +47 -0
  41. package/dist/runtime/ssr-utils.d.ts +9 -0
  42. package/dist/runtime/types.d.ts +18 -0
  43. package/dist/runtime/vdom-ssr-dsd.d.ts +82 -0
  44. package/dist/runtime/vdom-ssr.d.ts +2 -6
  45. package/dist/ssr-middleware.d.ts +125 -0
  46. package/dist/ssr.d.ts +95 -33
  47. package/dist/template-compiler-CTUhEHr8.cjs +22 -0
  48. package/dist/template-compiler-CTUhEHr8.cjs.map +1 -0
  49. package/dist/template-compiler-ZhSg1yPh.js +3724 -0
  50. package/dist/template-compiler-ZhSg1yPh.js.map +1 -0
  51. package/dist/vite-plugin.d.ts +94 -4
  52. package/package.json +6 -1
  53. package/dist/helpers-CweFZFWU.js +0 -987
  54. package/dist/helpers-CweFZFWU.js.map +0 -1
  55. package/dist/helpers-DeWjSmOl.cjs +0 -5
  56. package/dist/helpers-DeWjSmOl.cjs.map +0 -1
  57. package/dist/hooks-BrrLKSub.cjs +0 -3
  58. package/dist/hooks-BrrLKSub.cjs.map +0 -1
  59. package/dist/hooks-DyShDHKo.js +0 -403
  60. package/dist/hooks-DyShDHKo.js.map +0 -1
  61. package/dist/namespace-helpers-CnpZ5__p.js +0 -45
  62. package/dist/namespace-helpers-CnpZ5__p.js.map +0 -1
  63. package/dist/namespace-helpers-CyIDtI97.cjs +0 -2
  64. package/dist/namespace-helpers-CyIDtI97.cjs.map +0 -1
  65. package/dist/template-compiler-B5uN1EQw.js +0 -3731
  66. package/dist/template-compiler-B5uN1EQw.js.map +0 -1
  67. package/dist/template-compiler-Cx623BSB.cjs +0 -23
  68. package/dist/template-compiler-Cx623BSB.cjs.map +0 -1
@@ -7,6 +7,18 @@
7
7
  * (time-sliced, non-blocking rendering for low-priority work).
8
8
  */
9
9
  export type UpdatePriority = 'immediate' | 'normal' | 'idle';
10
+ /**
11
+ * Environment detection utilities
12
+ */
13
+ export interface TestEnvironment {
14
+ isTest: boolean;
15
+ isVitest: boolean;
16
+ isCypress: boolean;
17
+ }
18
+ /**
19
+ * Detect test environment with improved reliability
20
+ */
21
+ export declare function detectTestEnvironment(): TestEnvironment;
10
22
  declare class UpdateScheduler {
11
23
  private pendingUpdates;
12
24
  private isFlushScheduled;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * SSR execution context for running component render functions server-side.
3
+ *
4
+ * When generating Declarative Shadow DOM (DSD) output, the SSR renderer must
5
+ * call each custom element's render function to obtain its shadow DOM VNode
6
+ * tree and capture any useStyle() / useGlobalStyle() output. This module
7
+ * provides the minimal execution environment that makes that safe.
8
+ *
9
+ * Guarantees:
10
+ * - useStyle() callbacks are executed and their output is captured.
11
+ * - useGlobalStyle() callbacks are captured (not injected into document).
12
+ * - Lifecycle hooks (useOnConnected, watch, …) register harmlessly to arrays
13
+ * that are never invoked.
14
+ * - The reactive system is never permanently mutated — component registration
15
+ * is cleaned up by the render wrapper in factory.ts after each call.
16
+ */
17
+ import type { ComponentConfig, VNode } from './types';
18
+ /** Start collecting useGlobalStyle() output from the current render pass. */
19
+ export declare function beginSSRGlobalStyleCollection(): void;
20
+ /** Stop collecting and return everything gathered so far. */
21
+ export declare function endSSRGlobalStyleCollection(): string[];
22
+ /**
23
+ * Called by useGlobalStyle() when an SSR collection pass is active.
24
+ * Returns true if the CSS was captured (caller should skip DOM injection).
25
+ */
26
+ export declare function captureGlobalStyleForSSR(css: string): boolean;
27
+ export interface SSRRenderResult {
28
+ /** VNode tree from the component's render function (shadow DOM content). */
29
+ shadowVNode: VNode | VNode[] | null;
30
+ /** CSS string captured from useStyle() calls during this render. */
31
+ useStyleCSS: string;
32
+ /** Present when the component's render function returned a Promise. */
33
+ asyncPromise?: Promise<VNode | VNode[]>;
34
+ }
35
+ /**
36
+ * Run a component's render function in a minimal SSR context to capture its
37
+ * shadow DOM VNode tree and any useStyle() output.
38
+ *
39
+ * The component's render wrapper in factory.ts handles:
40
+ * - setCurrentComponentContext / clearCurrentComponentContext
41
+ * - _hookCallbacks reset
42
+ * - _computedStyle reset
43
+ * - reactiveSystem registration / cleanup
44
+ *
45
+ * We only need to build a context object that satisfies the hooks' expectations.
46
+ */
47
+ export declare function runComponentSSRRender(config: ComponentConfig<object, object, object, object>, attrs: Record<string, string | number | boolean | null | undefined>, tag?: string): SSRRenderResult;
@@ -0,0 +1,9 @@
1
+ export type RenderOptions = {
2
+ /** Backwards-compatible: whether to inject the SVG namespace on <svg> nodes (default true) */
3
+ injectSvgNamespace?: boolean;
4
+ /** Inject known well-known namespaces for tags like <math> when missing (default follows injectSvgNamespace) */
5
+ injectKnownNamespaces?: boolean;
6
+ };
7
+ export declare const VOID_ELEMENTS: Set<string>;
8
+ export declare function buildAttrs(attrs: Record<string, unknown>, tag: string, opts: RenderOptions): string;
9
+ export declare function buildRawAttrs(attrs: Record<string, unknown>): string;
@@ -86,11 +86,29 @@ export type ComponentContext<S extends object, C extends object, P extends objec
86
86
  } & {
87
87
  [key: string]: unknown;
88
88
  };
89
+ /**
90
+ * Controls when (and whether) a server-rendered custom element is hydrated
91
+ * on the client after the JavaScript bundle loads.
92
+ *
93
+ * | Value | Behaviour |
94
+ * |-----------|-----------|
95
+ * | `'load'` | Hydrate immediately when the element connects (default). |
96
+ * | `'idle'` | Defer until `requestIdleCallback` fires. |
97
+ * | `'visible'` | Defer until the element enters the viewport (`IntersectionObserver`). |
98
+ * | `'none'` | Never hydrate — element stays as static server-rendered HTML. |
99
+ */
100
+ export type HydrateStrategy = 'load' | 'idle' | 'visible' | 'none';
89
101
  export type ComponentConfig<S extends object, C extends object = object, P extends object = object, T extends object = object> = {
90
102
  props?: Record<string, {
91
103
  type: StringConstructor | NumberConstructor | BooleanConstructor | FunctionConstructor;
92
104
  default?: string | number | boolean;
93
105
  }>;
106
+ /**
107
+ * Partial-hydration strategy for this component when SSR DSD output is used.
108
+ * Emitted as `data-cer-hydrate` on the host element in DSD HTML.
109
+ * @default 'load'
110
+ */
111
+ hydrate?: HydrateStrategy;
94
112
  render: (context: ComponentContext<S, C, P, T>) => VNode | VNode[] | Promise<VNode | VNode[]>;
95
113
  onConnected?: (context: ComponentContext<S, C, P, T>) => void;
96
114
  onDisconnected?: (context: ComponentContext<S, C, P, T>) => void;
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Declarative Shadow DOM (DSD) SSR renderer.
3
+ *
4
+ * When `dsd: true` is passed to the render options, registered custom elements
5
+ * are serialised as:
6
+ *
7
+ * ```html
8
+ * <my-element attr="val">
9
+ * <template shadowrootmode="open">
10
+ * <style>
11
+ * /* baseReset + useStyle() output + JIT utility CSS *\/
12
+ * </style>
13
+ * <!-- shadow DOM from component render function -->
14
+ * </template>
15
+ * <!-- light DOM / slotted children from vnode.children -->
16
+ * </my-element>
17
+ * ```
18
+ *
19
+ * The browser parses the `<template shadowrootmode="open">` block and attaches
20
+ * a real shadow root before any JavaScript executes. All CSS layers are present
21
+ * at first paint — eliminating both FOUC and layout shift.
22
+ *
23
+ * Non-custom-element VNodes are rendered identically to renderToString() but
24
+ * with DSD recursion active for any custom elements nested inside them.
25
+ */
26
+ import type { VNode } from './types';
27
+ import { type RenderOptions } from './ssr-utils';
28
+ export type DSDRenderOptions = RenderOptions & {
29
+ /**
30
+ * Emit Declarative Shadow DOM output for registered custom elements.
31
+ * Shadow content is serialised inside `<template shadowrootmode="open">`,
32
+ * with a complete CSS layer stack (`baseReset` + `useStyle` + JIT CSS)
33
+ * injected as a `<style>` block so styles are available at first paint.
34
+ * @default false
35
+ */
36
+ dsd?: boolean;
37
+ /**
38
+ * Append the DSD polyfill `<script>` for browsers without native support
39
+ * (Firefox < 123). Only meaningful when `dsd` is true.
40
+ * @default true
41
+ */
42
+ dsdPolyfill?: boolean;
43
+ };
44
+ /**
45
+ * @internal
46
+ * Minified DSD polyfill for browsers without native Declarative Shadow DOM.
47
+ * Processes all `<template shadowrootmode>` elements synchronously.
48
+ */
49
+ export declare const DSD_POLYFILL_SCRIPT: string;
50
+ /**
51
+ * Build the combined `<style>` block for a shadow root.
52
+ *
53
+ * Layer order (matches the runtime adoptedStyleSheets order):
54
+ * 1. baseReset — global reset + CSS custom properties
55
+ * 2. useStyle() output — component-defined rules (:host, ::slotted, etc.)
56
+ * 3. JIT CSS — utility classes extracted from the shadow HTML
57
+ */
58
+ export declare function buildShadowStyleBlock(useStyleCSS: string, shadowHTML: string): string;
59
+ export interface AsyncStreamEntry {
60
+ id: string;
61
+ tag: string;
62
+ attrsString: string;
63
+ hydrateAttr: string;
64
+ useStyleCSS: string;
65
+ lightDOM: string;
66
+ opts: DSDRenderOptions;
67
+ promise: Promise<VNode | VNode[]>;
68
+ }
69
+ /** @internal Called by renderToStream() before the sync render pass. */
70
+ export declare function beginStreamingCollection(collector: AsyncStreamEntry[]): void;
71
+ /** @internal Called by renderToStream() after the sync render pass. */
72
+ export declare function endStreamingCollection(): void;
73
+ /**
74
+ * Render a VNode tree to an HTML string with Declarative Shadow DOM output
75
+ * for all registered custom elements encountered in the tree.
76
+ */
77
+ export declare function renderToDSD(vnode: VNode, opts: DSDRenderOptions): string;
78
+ /**
79
+ * Render a VNode tree to a DSD HTML string and optionally append the
80
+ * DSD polyfill script for older browsers.
81
+ */
82
+ export declare function renderToStringDSD(vnode: VNode, opts?: DSDRenderOptions): string;
@@ -1,4 +1,5 @@
1
1
  import type { VNode } from './types';
2
+ import { type RenderOptions } from './ssr-utils';
2
3
  /**
3
4
  * Render a VNode to a string (SSR).
4
5
  * Kept intentionally minimal: only serializes attributes under `props.attrs`
@@ -6,10 +7,5 @@ import type { VNode } from './types';
6
7
  * @param vnode The virtual node to render.
7
8
  * @returns The rendered HTML string.
8
9
  */
9
- export type RenderOptions = {
10
- /** Backwards-compatible: whether to inject the SVG namespace on <svg> nodes (default true) */
11
- injectSvgNamespace?: boolean;
12
- /** Inject known well-known namespaces for tags like <math> when missing (default follows injectSvgNamespace) */
13
- injectKnownNamespaces?: boolean;
14
- };
10
+ export type { RenderOptions } from './ssr-utils';
15
11
  export declare function renderToString(vnode: VNode, opts?: RenderOptions): string;
@@ -0,0 +1,125 @@
1
+ /**
2
+ * SSR middleware helpers for Express, Fastify, Hono, and other Node.js HTTP frameworks.
3
+ *
4
+ * Provides two handler factories that wrap the SSR rendering pipeline and
5
+ * emit a complete HTML document response. Both accept a static VNode **or**
6
+ * a per-request factory function so route-specific data can be threaded into
7
+ * the render tree.
8
+ *
9
+ * @example Express — static VNode
10
+ * ```ts
11
+ * import express from 'express';
12
+ * import { createSSRHandler } from '@jasonshimmy/custom-elements-runtime/ssr-middleware';
13
+ * import { html } from '@jasonshimmy/custom-elements-runtime';
14
+ *
15
+ * const app = express();
16
+ * app.get('/', createSSRHandler(html`<my-app />`, {
17
+ * render: { dsd: true, jit: { extendedColors: true } },
18
+ * }));
19
+ * ```
20
+ *
21
+ * @example Express — per-request factory
22
+ * ```ts
23
+ * app.get('*', createSSRHandler(
24
+ * (req) => html`<my-app url="${req.url}" />`,
25
+ * { render: { dsd: true }, head: '<link rel="stylesheet" href="/app.css">' },
26
+ * ));
27
+ * ```
28
+ *
29
+ * @example Streaming variant
30
+ * ```ts
31
+ * app.get('*', createStreamingSSRHandler(
32
+ * (req) => html`<my-app url="${req.url}" />`,
33
+ * ));
34
+ * ```
35
+ */
36
+ import type { VNode } from './runtime/types';
37
+ import type { RenderOptions } from './runtime/vdom-ssr';
38
+ import type { DSDRenderOptions } from './runtime/vdom-ssr-dsd';
39
+ import type { JITCSSOptions } from './runtime/style';
40
+ /**
41
+ * Minimal request interface compatible with Express, Fastify, Hono, and the
42
+ * raw Node.js `IncomingMessage`. Extend or replace with your framework's
43
+ * request type via the generic parameter on `createSSRHandler`.
44
+ */
45
+ export interface MinimalRequest {
46
+ url?: string;
47
+ method?: string;
48
+ headers?: Record<string, string | string[] | undefined>;
49
+ }
50
+ /**
51
+ * Minimal response interface compatible with Express, Fastify, Hono, and the
52
+ * raw Node.js `ServerResponse`. `write` is optional — handlers fall back to
53
+ * buffering when it is absent.
54
+ */
55
+ export interface MinimalResponse {
56
+ setHeader(name: string, value: string): void;
57
+ write?(chunk: string): boolean | void;
58
+ end(data?: string): void;
59
+ }
60
+ /**
61
+ * Options for {@link createSSRHandler} and {@link createStreamingSSRHandler}.
62
+ */
63
+ export interface SSRMiddlewareOptions {
64
+ /**
65
+ * Render options forwarded to `renderToStringWithJITCSS`.
66
+ * Defaults to `{ dsd: true }` so DSD output is on by default.
67
+ */
68
+ render?: RenderOptions & DSDRenderOptions & {
69
+ jit?: JITCSSOptions;
70
+ };
71
+ /**
72
+ * Additional HTML inserted at the end of the `<head>` tag.
73
+ * Use this to inject `<link>`, `<script>`, `<meta>`, or `<title>` tags.
74
+ */
75
+ head?: string;
76
+ /**
77
+ * When `true` (default), the response is wrapped in a complete
78
+ * `<!DOCTYPE html>` document shell. Set to `false` if you want to
79
+ * assemble the document yourself and only need the rendered fragment.
80
+ */
81
+ document?: boolean;
82
+ }
83
+ /**
84
+ * Create a request handler that SSR-renders a VNode tree and sends the full
85
+ * HTML document as the response.
86
+ *
87
+ * Compatible with Express, Fastify, Hono, and any framework that uses an
88
+ * `(req, res)` handler signature. The generic `Req` parameter lets you use
89
+ * your framework's typed request object.
90
+ *
91
+ * @param vnodeOrFactory - A static {@link VNode} **or** a (possibly async)
92
+ * factory function that receives the request and returns the VNode to render.
93
+ * @param options - Render and document-shell options.
94
+ *
95
+ * @example
96
+ * ```ts
97
+ * app.get('*', createSSRHandler(
98
+ * (req) => html`<my-app url="${req.url}" />`,
99
+ * { render: { dsd: true, jit: { extendedColors: true } } },
100
+ * ));
101
+ * ```
102
+ */
103
+ export declare function createSSRHandler<Req extends MinimalRequest = MinimalRequest>(vnodeOrFactory: VNode | ((req: Req) => VNode | Promise<VNode>), options?: SSRMiddlewareOptions): (req: Req, res: MinimalResponse) => Promise<void>;
104
+ /**
105
+ * Create a request handler that SSR-renders a VNode tree and streams the HTML
106
+ * response using chunked transfer encoding.
107
+ *
108
+ * Each chunk produced by the underlying {@link renderToStream} call is written
109
+ * to the response as it becomes available, minimising Time-to-First-Byte.
110
+ * The document shell preamble (`<!DOCTYPE html>…<body>`) is sent in the first
111
+ * write so the browser can begin parsing immediately.
112
+ *
113
+ * @param vnodeOrFactory - A static {@link VNode} **or** a (possibly async)
114
+ * factory function that receives the request and returns the VNode to render.
115
+ * @param options - Render and document-shell options.
116
+ *
117
+ * @example
118
+ * ```ts
119
+ * app.get('*', createStreamingSSRHandler(
120
+ * (req) => html`<my-app url="${req.url}" />`,
121
+ * { render: { dsd: true } },
122
+ * ));
123
+ * ```
124
+ */
125
+ export declare function createStreamingSSRHandler<Req extends MinimalRequest = MinimalRequest>(vnodeOrFactory: VNode | ((req: Req) => VNode | Promise<VNode>), options?: SSRMiddlewareOptions): (req: Req, res: MinimalResponse) => Promise<void>;
package/dist/ssr.d.ts CHANGED
@@ -1,70 +1,132 @@
1
1
  /**
2
- * SSR entrypointsmall re-export so consumers can import SSR-only helpers
3
- * without pulling them into the main client runtime bundle.
2
+ * SSR entry point import from `@jasonshimmy/custom-elements-runtime/ssr`.
4
3
  *
5
- * renderToString accepts an optional second argument to control SSR behavior:
4
+ * Provides four rendering modes:
6
5
  *
7
- * renderToString(vnode, { injectSvgNamespace?: boolean })
6
+ * 1. **renderToString** — baseline HTML serialisation (no shadow DOM content).
7
+ * Backwards-compatible with the original API.
8
8
  *
9
- * - injectSvgNamespace (default: true): when true, the SSR renderer will
10
- * inject the standard SVG namespace attribute (xmlns="http://www.w3.org/2000/svg")
11
- * onto `<svg>` elements that do not already provide an explicit `xmlns`.
12
- * This matches the client runtime behavior (createElementNS) and avoids
13
- * hydration/namespace mismatches. Set to `false` to opt out and keep SSR
14
- * output minimal.
9
+ * 2. **renderToStringWithJITCSS** HTML + pre-generated JIT CSS injected into
10
+ * `<head>` to prevent FOUC. Supports `dsd: true` for DSD output.
15
11
  *
16
- * Examples
12
+ * 3. **renderToStringWithJITCSSDSD** — convenience alias for DSD mode.
13
+ * Full Declarative Shadow DOM output with per-shadow-root CSS layer stack
14
+ * (baseReset + useStyle() + JIT CSS). Enables true hydration, zero FOUC.
17
15
  *
18
- * // Default (injects xmlns for <svg> if missing)
19
- * import { renderToString } from '@jasonshimmy/custom-elements-runtime/ssr';
20
- * const html = renderToString(vnodeTree);
16
+ * 4. **renderToStream** ReadableStream variant for streaming SSR.
21
17
  *
22
- * // Opt-out
23
- * const htmlNoNs = renderToString(vnodeTree, { injectSvgNamespace: false });
18
+ * Entity map utilities are also exported for full HTML5 named-entity support.
19
+ *
20
+ * @example DSD usage (recommended)
21
+ * ```ts
22
+ * import { renderToStringWithJITCSSDSD } from '@jasonshimmy/custom-elements-runtime/ssr';
23
+ *
24
+ * const { htmlWithStyles } = renderToStringWithJITCSSDSD(appVNode, {
25
+ * jit: { extendedColors: true },
26
+ * });
27
+ * res.send(`<!DOCTYPE html><html><head>${head}</head><body>${htmlWithStyles}</body></html>`);
28
+ * ```
24
29
  */
25
30
  export { renderToString } from './runtime/vdom-ssr';
26
31
  export type { VNode } from './runtime/types';
27
32
  export type { RenderOptions } from './runtime/vdom-ssr';
28
33
  export { registerEntityMap, loadEntityMap, clearRegisteredEntityMap, } from './runtime/helpers';
34
+ export { renderToStringDSD, DSD_POLYFILL_SCRIPT, } from './runtime/vdom-ssr-dsd';
35
+ export type { DSDRenderOptions } from './runtime/vdom-ssr-dsd';
29
36
  import { type JITCSSOptions } from './runtime/style';
30
37
  import type { VNode } from './runtime/types';
31
38
  import type { RenderOptions } from './runtime/vdom-ssr';
39
+ import type { DSDRenderOptions } from './runtime/vdom-ssr-dsd';
32
40
  /**
33
- * Result of `renderToStringWithJITCSS()`.
41
+ * Result of `renderToStringWithJITCSS()` and `renderToStringWithJITCSSDSD()`.
34
42
  */
35
43
  export interface SSRJITResult {
36
- /** The rendered HTML string. */
44
+ /** The rendered HTML string (styles not yet injected). */
37
45
  html: string;
38
46
  /**
39
- * Pre-generated JIT CSS extracted from the rendered HTML.
40
- * Embed this in a `<style>` element in your document `<head>` to eliminate
41
- * Flash of Unstyled Content (FOUC) on hydration.
47
+ * Global JIT CSS extracted from the rendered HTML.
48
+ * For DSD renders, each shadow root embeds its own scoped styles; this field
49
+ * holds any residual light-DOM utility CSS.
42
50
  */
43
51
  css: string;
44
52
  /**
45
- * Convenience: the HTML with a `<style>` element injected before `</head>`.
46
- * If no `</head>` tag is found, the `<style>` is prepended to the HTML.
53
+ * CSS captured from `useGlobalStyle()` calls during this render pass
54
+ * (e.g. `@font-face`, `:root` custom properties).
55
+ * Inject in a `<style id="cer-ssr-global">` in `<head>`.
56
+ */
57
+ globalStyles: string;
58
+ /**
59
+ * Convenience: `html` with both `<style>` tags injected before `</head>`.
60
+ * If no `</head>` is found, the styles are prepended.
47
61
  */
48
62
  htmlWithStyles: string;
49
63
  }
50
64
  /**
51
- * Server-side render a VNode tree and simultaneously pre-generate JIT CSS for
52
- * all utility classes present in the rendered output.
65
+ * Server-side render a VNode tree and simultaneously pre-generate JIT CSS.
53
66
  *
54
- * Embed the returned `css` in a `<style>` element in your document `<head>`
55
- * to ensure correct styles are present before the client runtime hydrates,
56
- * eliminating Flash of Unstyled Content (FOUC).
67
+ * Pass `dsd: true` to enable Declarative Shadow DOM output with full per-shadow-
68
+ * root CSS layer extraction (recommended for new apps).
57
69
  *
58
- * @example
70
+ * @example Standard (no DSD)
59
71
  * ```ts
60
- * import { renderToStringWithJITCSS } from '@jasonshimmy/custom-elements-runtime/ssr';
72
+ * const { htmlWithStyles } = renderToStringWithJITCSS(appVNode);
73
+ * ```
61
74
  *
62
- * const { htmlWithStyles } = await renderToStringWithJITCSS(appVNode, {
75
+ * @example With DSD
76
+ * ```ts
77
+ * const { htmlWithStyles } = renderToStringWithJITCSS(appVNode, {
78
+ * dsd: true,
63
79
  * jit: { extendedColors: true },
64
80
  * });
65
- * res.send(`<!DOCTYPE html><html><head>${headTags}</head><body>${htmlWithStyles}</body></html>`);
66
81
  * ```
67
82
  */
68
- export declare function renderToStringWithJITCSS(vnode: VNode, options?: RenderOptions & {
83
+ export declare function renderToStringWithJITCSS(vnode: VNode, options?: RenderOptions & DSDRenderOptions & {
69
84
  jit?: JITCSSOptions;
70
85
  }): SSRJITResult;
86
+ /**
87
+ * Convenience alias: `renderToStringWithJITCSS(vnode, { dsd: true, ...options })`.
88
+ *
89
+ * Renders with Declarative Shadow DOM output, full per-shadow-root CSS layer
90
+ * extraction, and the DSD browser polyfill. This is the recommended function
91
+ * for all new server-rendered applications.
92
+ *
93
+ * @example
94
+ * ```ts
95
+ * import { renderToStringWithJITCSSDSD } from '@jasonshimmy/custom-elements-runtime/ssr';
96
+ *
97
+ * const { htmlWithStyles } = renderToStringWithJITCSSDSD(appVNode, {
98
+ * jit: { extendedColors: true },
99
+ * });
100
+ * ```
101
+ */
102
+ export declare function renderToStringWithJITCSSDSD(vnode: VNode, options?: Omit<RenderOptions & DSDRenderOptions & {
103
+ jit?: JITCSSOptions;
104
+ }, 'dsd'>): SSRJITResult;
105
+ /**
106
+ * Render a VNode tree to a `ReadableStream<string>`.
107
+ *
108
+ * The current implementation flushes the complete rendered output as a single
109
+ * chunk, providing the streaming API surface for framework adapters. True
110
+ * incremental streaming (flush shell immediately, resolve async components
111
+ * progressively) is planned for a future release.
112
+ *
113
+ * @example Node.js
114
+ * ```ts
115
+ * import { renderToStream } from '@jasonshimmy/custom-elements-runtime/ssr';
116
+ *
117
+ * app.get('/', (req, res) => {
118
+ * const stream = renderToStream(appVNode, { dsd: true });
119
+ * const reader = stream.getReader();
120
+ * const pump = () =>
121
+ * reader.read().then(({ value, done }) => {
122
+ * if (done) { res.end(); return; }
123
+ * res.write(value);
124
+ * pump();
125
+ * });
126
+ * pump();
127
+ * });
128
+ * ```
129
+ */
130
+ export declare function renderToStream(vnode: VNode, options?: RenderOptions & DSDRenderOptions & {
131
+ jit?: JITCSSOptions;
132
+ }): ReadableStream<string>;