@jasonshimmy/custom-elements-runtime 2.8.2 → 3.1.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.
Files changed (99) hide show
  1. package/README.md +223 -73
  2. package/dist/css-utils-Cg4o1MqY.js +643 -0
  3. package/dist/css-utils-Cg4o1MqY.js.map +1 -0
  4. package/dist/css-utils-RqkyBWft.cjs +576 -0
  5. package/dist/css-utils-RqkyBWft.cjs.map +1 -0
  6. package/dist/custom-elements-runtime.cjs.js +3 -3
  7. package/dist/custom-elements-runtime.cjs.js.map +1 -1
  8. package/dist/custom-elements-runtime.dom-jit-css.cjs.js +7 -0
  9. package/dist/custom-elements-runtime.dom-jit-css.cjs.js.map +1 -0
  10. package/dist/custom-elements-runtime.dom-jit-css.es.js +136 -0
  11. package/dist/custom-elements-runtime.dom-jit-css.es.js.map +1 -0
  12. package/dist/custom-elements-runtime.es.js +105 -97
  13. package/dist/custom-elements-runtime.es.js.map +1 -1
  14. package/dist/custom-elements-runtime.event-bus.cjs.js +1 -1
  15. package/dist/custom-elements-runtime.event-bus.cjs.js.map +1 -1
  16. package/dist/custom-elements-runtime.event-bus.es.js +62 -46
  17. package/dist/custom-elements-runtime.event-bus.es.js.map +1 -1
  18. package/dist/custom-elements-runtime.jit-css.cjs.js +2 -0
  19. package/dist/custom-elements-runtime.jit-css.cjs.js.map +1 -0
  20. package/dist/custom-elements-runtime.jit-css.es.js +37 -0
  21. package/dist/custom-elements-runtime.jit-css.es.js.map +1 -0
  22. package/dist/custom-elements-runtime.router.cjs.js +20 -20
  23. package/dist/custom-elements-runtime.router.cjs.js.map +1 -1
  24. package/dist/custom-elements-runtime.router.es.js +472 -458
  25. package/dist/custom-elements-runtime.router.es.js.map +1 -1
  26. package/dist/custom-elements-runtime.ssr-middleware.cjs.js +2 -0
  27. package/dist/custom-elements-runtime.ssr-middleware.cjs.js.map +1 -0
  28. package/dist/custom-elements-runtime.ssr-middleware.es.js +63 -0
  29. package/dist/custom-elements-runtime.ssr-middleware.es.js.map +1 -0
  30. package/dist/custom-elements-runtime.ssr.cjs.js +3 -1
  31. package/dist/custom-elements-runtime.ssr.cjs.js.map +1 -1
  32. package/dist/custom-elements-runtime.ssr.es.js +137 -24
  33. package/dist/custom-elements-runtime.ssr.es.js.map +1 -1
  34. package/dist/custom-elements-runtime.store.cjs.js +1 -1
  35. package/dist/custom-elements-runtime.store.cjs.js.map +1 -1
  36. package/dist/custom-elements-runtime.store.es.js +21 -16
  37. package/dist/custom-elements-runtime.store.es.js.map +1 -1
  38. package/dist/custom-elements-runtime.transitions.cjs.js +1 -1
  39. package/dist/custom-elements-runtime.transitions.cjs.js.map +1 -1
  40. package/dist/custom-elements-runtime.transitions.es.js +279 -7
  41. package/dist/custom-elements-runtime.transitions.es.js.map +1 -1
  42. package/dist/custom-elements-runtime.vite-plugin.cjs.js +2 -0
  43. package/dist/custom-elements-runtime.vite-plugin.cjs.js.map +1 -0
  44. package/dist/custom-elements-runtime.vite-plugin.es.js +105 -0
  45. package/dist/custom-elements-runtime.vite-plugin.es.js.map +1 -0
  46. package/dist/dom-jit-css.d.ts +66 -0
  47. package/dist/event-bus.d.ts +3 -1
  48. package/dist/hooks-B50HhrHh.cjs +6 -0
  49. package/dist/hooks-B50HhrHh.cjs.map +1 -0
  50. package/dist/hooks-Cze3o-F7.js +1462 -0
  51. package/dist/hooks-Cze3o-F7.js.map +1 -0
  52. package/dist/index.d.ts +6 -3
  53. package/dist/jit-css.d.ts +30 -0
  54. package/dist/namespace-helpers-D4wC2-qA.js +61 -0
  55. package/dist/namespace-helpers-D4wC2-qA.js.map +1 -0
  56. package/dist/namespace-helpers-ckeEOxpR.cjs +2 -0
  57. package/dist/namespace-helpers-ckeEOxpR.cjs.map +1 -0
  58. package/dist/router/matcher.d.ts +14 -0
  59. package/dist/router/types.d.ts +4 -2
  60. package/dist/runtime/component/factory.d.ts +16 -2
  61. package/dist/runtime/css-utils.d.ts +33 -0
  62. package/dist/runtime/discovery-state.d.ts +3 -0
  63. package/dist/runtime/hooks.d.ts +78 -0
  64. package/dist/runtime/hydration.d.ts +33 -0
  65. package/dist/runtime/jit-hooks.d.ts +28 -0
  66. package/dist/runtime/render-bridge.d.ts +37 -0
  67. package/dist/runtime/scheduler.d.ts +3 -4
  68. package/dist/runtime/secure-expression-evaluator.d.ts +0 -1
  69. package/dist/runtime/ssr-context.d.ts +45 -0
  70. package/dist/runtime/style.d.ts +84 -26
  71. package/dist/runtime/template-compiler/lru-cache.d.ts +0 -3
  72. package/dist/runtime/types.d.ts +18 -0
  73. package/dist/runtime/vdom-helpers.d.ts +0 -1
  74. package/dist/runtime/vdom-ssr-dsd.d.ts +58 -0
  75. package/dist/ssr-middleware.d.ts +125 -0
  76. package/dist/ssr.d.ts +120 -16
  77. package/dist/{transitions-DMJXs_tY.js → style-BmyOIMcU.js} +904 -1344
  78. package/dist/style-BmyOIMcU.js.map +1 -0
  79. package/dist/style-D40DsIqJ.cjs +55 -0
  80. package/dist/style-D40DsIqJ.cjs.map +1 -0
  81. package/dist/style.css +1 -1
  82. package/dist/template-compiler-Cshhqxyd.cjs +23 -0
  83. package/dist/template-compiler-Cshhqxyd.cjs.map +1 -0
  84. package/dist/template-compiler-DtpNsqE-.js +3744 -0
  85. package/dist/template-compiler-DtpNsqE-.js.map +1 -0
  86. package/dist/variables.css +1 -1
  87. package/dist/vite-plugin.d.ts +142 -0
  88. package/package.json +60 -6
  89. package/dist/namespace-helpers-Ctd_h7j2.cjs +0 -5
  90. package/dist/namespace-helpers-Ctd_h7j2.cjs.map +0 -1
  91. package/dist/namespace-helpers-DhLBqt-7.js +0 -1009
  92. package/dist/namespace-helpers-DhLBqt-7.js.map +0 -1
  93. package/dist/template-compiler-Bvx02nAT.js +0 -4020
  94. package/dist/template-compiler-Bvx02nAT.js.map +0 -1
  95. package/dist/template-compiler-bj-MFC_Y.cjs +0 -23
  96. package/dist/template-compiler-bj-MFC_Y.cjs.map +0 -1
  97. package/dist/transitions-DMJXs_tY.js.map +0 -1
  98. package/dist/transitions-f4KfN29T.cjs +0 -330
  99. package/dist/transitions-f4KfN29T.cjs.map +0 -1
@@ -1,4 +1,4 @@
1
- import type { VNode } from '../types';
1
+ import type { HydrateStrategy, VNode } from '../types';
2
2
  /**
3
3
  * Streamlined functional component API with automatic reactive props and lifecycle hooks.
4
4
  *
@@ -36,4 +36,18 @@ import type { VNode } from '../types';
36
36
  * });
37
37
  * ```
38
38
  */
39
- export declare function component(tag: string, renderFn: () => VNode | VNode[] | Promise<VNode | VNode[]>): void;
39
+ /** Options for `component()`. */
40
+ export interface ComponentOptions {
41
+ /**
42
+ * Partial-hydration strategy when this component is server-rendered with
43
+ * Declarative Shadow DOM (`dsd: true`). Emitted as `data-cer-hydrate` on the
44
+ * host element so the client runtime can schedule hydration appropriately.
45
+ *
46
+ * - `'load'` — hydrate immediately on connection (default)
47
+ * - `'idle'` — defer to `requestIdleCallback`
48
+ * - `'visible'` — defer until the element enters the viewport
49
+ * - `'none'` — never hydrate (purely static, no JS runtime for this element)
50
+ */
51
+ hydrate?: HydrateStrategy;
52
+ }
53
+ export declare function component(tag: string, renderFn: () => VNode | VNode[] | Promise<VNode | VNode[]>, options?: ComponentOptions): void;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Pure CSS utility functions — no JIT dependencies, no module-level side effects.
3
+ *
4
+ * Extracted so that render.ts and hooks.ts can import lightweight CSS helpers
5
+ * without pulling the entire JIT CSS engine into every consumer's bundle.
6
+ */
7
+ /**
8
+ * CSS template literal tag
9
+ */
10
+ export declare function css(strings: TemplateStringsArray, ...values: unknown[]): string;
11
+ /**
12
+ * CSS minification utility (basic)
13
+ */
14
+ export declare function minifyCSS(input: string): string;
15
+ /**
16
+ * Sanitize CSS to prevent injection attacks (XSS, javascript: URLs, expression(), etc.)
17
+ */
18
+ export declare function sanitizeCSS(input: string): string;
19
+ /**
20
+ * Polyfill for CSS.escape() for SSR environments.
21
+ * Based on https://drafts.csswg.org/cssom/#serialize-an-identifier
22
+ */
23
+ export declare function cssEscape(value: string): string;
24
+ /** Escape a class name and prefix it with a dot for use in CSS selectors. */
25
+ export declare function escapeClassName(name: string): string;
26
+ /** Escape a string for use in a RegExp. */
27
+ export declare function escapeRegExp(str: string): string;
28
+ export declare const baseReset: string;
29
+ /** Default spacing unit used by the JIT spacing scale. */
30
+ export declare const spacing = "0.25rem";
31
+ export declare function getBaseResetSheet(): CSSStyleSheet;
32
+ /** Reset the base reset sheet singleton (for HMR). @internal */
33
+ export declare function _resetBaseResetSheet(): void;
@@ -19,6 +19,9 @@ export declare function isDiscoveryRender(): boolean;
19
19
  * Mark the start of a discovery render pass.
20
20
  * Call this immediately before invoking the render function for the first time
21
21
  * (before `useProps` prop-name collection).
22
+ *
23
+ * Emits a dev warning when called while a discovery render is already active
24
+ * so that nested or mismatched begin/end pairs are surfaced during development.
22
25
  * @internal
23
26
  */
24
27
  export declare function beginDiscoveryRender(): void;
@@ -2,6 +2,8 @@
2
2
  * Context-based hooks for functional components
3
3
  * Provides React-like hooks with perfect TypeScript inference
4
4
  */
5
+ import type { JITCSSOptions } from './style';
6
+ export type { JITCSSOptions };
5
7
  export { beginDiscoveryRender, endDiscoveryRender } from './discovery-state';
6
8
  /**
7
9
  * Returns true while a discovery render is in progress.
@@ -150,6 +152,82 @@ export declare function useProps<T extends Record<string, unknown>>(defaults: T)
150
152
  * ```
151
153
  */
152
154
  export declare function useStyle(callback: () => string): void;
155
+ /**
156
+ * Inject CSS into `document.adoptedStyleSheets`, escaping the Shadow DOM
157
+ * boundary. Suitable for `@font-face` declarations, `:root` variable overrides,
158
+ * and global scroll/scroll-bar styling. Deduplicated by CSS content so calling
159
+ * this in multiple component instances is safe.
160
+ *
161
+ * **Use sparingly** — this intentionally breaks Shadow DOM encapsulation.
162
+ * A dev-mode warning is emitted to make the escape hatch visible.
163
+ *
164
+ * @example
165
+ * ```ts
166
+ * component('app-root', () => {
167
+ * useGlobalStyle(() => css`
168
+ * @font-face {
169
+ * font-family: 'Inter';
170
+ * src: url('/fonts/inter.woff2') format('woff2');
171
+ * }
172
+ * :root {
173
+ * --app-font: 'Inter', sans-serif;
174
+ * }
175
+ * `);
176
+ * return html`<slot></slot>`;
177
+ * });
178
+ * ```
179
+ */
180
+ export declare function useGlobalStyle(styleFactory: () => string): void;
181
+ /**
182
+ * Design token definitions accepted by `useDesignTokens()`.
183
+ * Map high-level token names to CSS custom property overrides.
184
+ */
185
+ export interface DesignTokens {
186
+ /** Override the primary color scale root (sets --cer-color-primary-500) */
187
+ primary?: string;
188
+ /** Override the secondary color scale root */
189
+ secondary?: string;
190
+ /** Override the neutral color scale root */
191
+ neutral?: string;
192
+ /** Override the success color root */
193
+ success?: string;
194
+ /** Override the info color root */
195
+ info?: string;
196
+ /** Override the warning color root */
197
+ warning?: string;
198
+ /** Override the error color root */
199
+ error?: string;
200
+ /** Override the sans-serif font family */
201
+ fontSans?: string;
202
+ /** Override the serif font family */
203
+ fontSerif?: string;
204
+ /** Override the monospace font family */
205
+ fontMono?: string;
206
+ /** Additional arbitrary CSS custom property overrides */
207
+ [key: string]: string | undefined;
208
+ }
209
+ /**
210
+ * Apply design tokens to `:host` as CSS custom property overrides.
211
+ * Must be called during component render. This is a typed, validated
212
+ * alternative to writing `useStyle(() => css\`:host { ... }\`)` by hand.
213
+ *
214
+ * Semantic color tokens (e.g. `primary: '#6366f1'`) set the `*-500` shade
215
+ * for that scale. Use arbitrary `'--cer-color-primary-500'` keys to override
216
+ * individual shades.
217
+ *
218
+ * @example
219
+ * ```ts
220
+ * component('app-root', () => {
221
+ * useDesignTokens({
222
+ * primary: '#6366f1',
223
+ * fontSans: '"Inter", sans-serif',
224
+ * '--cer-color-neutral-900': '#0a0a0a',
225
+ * });
226
+ * return html`<slot></slot>`;
227
+ * });
228
+ * ```
229
+ */
230
+ export declare function useDesignTokens(tokens: DesignTokens): void;
153
231
  /**
154
232
  * Store a value under a key so that descendant components can retrieve it
155
233
  * with `inject()`. Must be called during component render.
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Client-side hydration helpers.
3
+ *
4
+ * When the server renders with `dsd: true`, each custom element's shadow DOM
5
+ * is already present in the HTML via a Declarative Shadow DOM template. The
6
+ * browser parses that template and attaches the shadow root before any
7
+ * JavaScript runs. When the JS bundle loads, the custom element constructors
8
+ * detect the existing shadow root and skip the `attachShadow()` call, then
9
+ * hydrate (attach reactivity to) the existing DOM on `connectedCallback`.
10
+ *
11
+ * `hydrateApp` is a signal/entry point for this process. In most cases custom
12
+ * elements self-hydrate automatically on connection — this function is useful
13
+ * when you need to explicitly trigger or defer the hydration of a subtree.
14
+ */
15
+ /**
16
+ * Trigger hydration for all registered custom elements within `root`.
17
+ *
18
+ * In practice, custom elements self-hydrate as soon as their class definition
19
+ * is registered and the element is connected to the DOM. Call `hydrateApp`
20
+ * after importing and calling `component()` for all your components to signal
21
+ * that the page is ready for reactive activation.
22
+ *
23
+ * @param root - The root element to hydrate. Defaults to `document`.
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * import { component, hydrateApp } from '@jasonshimmy/custom-elements-runtime';
28
+ * import './components'; // registers all components via component()
29
+ *
30
+ * hydrateApp(); // activate all DSD-rendered components on the page
31
+ * ```
32
+ */
33
+ export declare function hydrateApp(root?: Element | Document): void;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * JIT CSS hooks — lives in a separate module so that hooks.ts does not
3
+ * statically import style.ts. Consumers who never call `useJITCSS` will
4
+ * have the entire JIT engine tree-shaken out of their bundle.
5
+ */
6
+ import { type JITCSSOptions } from './style';
7
+ /**
8
+ * Configure the JIT CSS engine for the current session.
9
+ * This is a convenience wrapper around `enableJITCSS()` that can be called
10
+ * inside a component render function or at module initialisation time.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * component('my-component', () => {
15
+ * // Enable extended Tailwind colors so bg-blue-500, text-violet-700, etc. generate CSS
16
+ * useJITCSS({ extendedColors: true });
17
+ * return html`<div class="bg-blue-500 text-white">Hello</div>`;
18
+ * });
19
+ * ```
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * // At app entry – enable once for all components
24
+ * useJITCSS({ extendedColors: true, customColors: { brand: { '500': '#e63946' } } });
25
+ * ```
26
+ */
27
+ export declare function useJITCSS(options?: JITCSSOptions): void;
28
+ export type { JITCSSOptions };
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Lazy render bridge — populated by style.ts when the JIT engine is imported.
3
+ *
4
+ * render.ts always imports this module (so it is always bundled), but
5
+ * style.ts (the full JIT engine, ~24 KB gzip) is only bundled when the
6
+ * consumer explicitly imports JIT CSS symbols such as `enableJITCSS` or
7
+ * `useJITCSS`. When style.ts IS imported it registers itself here so that
8
+ * render.ts can call back into the JIT engine without a static dependency.
9
+ *
10
+ * Result: consumers that never use JIT CSS get zero JIT code in their bundle.
11
+ */
12
+ type JITChecker = (root: ShadowRoot) => boolean;
13
+ type JITProcessor = (html: string) => string;
14
+ type ProseSheetGetter = () => CSSStyleSheet | null;
15
+ /**
16
+ * Register the JIT CSS engine with the render pipeline.
17
+ * Called by style.ts at module load time so renders automatically get
18
+ * JIT processing without render.ts needing to import style.ts directly.
19
+ * @internal
20
+ */
21
+ export declare function _registerRenderBridge(checker: JITChecker, processor: JITProcessor, proseGetter: ProseSheetGetter): void;
22
+ /**
23
+ * Returns true when JIT CSS should run for the given shadow root.
24
+ * Returns false if the JIT engine is not loaded.
25
+ */
26
+ export declare function isJITCSSActiveFor(root: ShadowRoot): boolean;
27
+ /**
28
+ * Run JIT CSS processing over the aggregated HTML string.
29
+ * Returns empty string if the JIT engine is not loaded.
30
+ */
31
+ export declare function processJITCSS(html: string): string;
32
+ /**
33
+ * Get the prose stylesheet singleton.
34
+ * Returns null if the JIT engine is not loaded or no prose classes detected.
35
+ */
36
+ export declare function getProseStyleSheet(): CSSStyleSheet | null;
37
+ export {};
@@ -28,7 +28,6 @@ declare class UpdateScheduler {
28
28
  */
29
29
  private scheduleFlush;
30
30
  /**
31
- * Execute all pending updates with priority ordering
32
31
  * Execute all pending updates with priority ordering
33
32
  */
34
33
  private flush;
@@ -61,7 +60,8 @@ declare class UpdateScheduler {
61
60
  */
62
61
  private performPeriodicCleanup;
63
62
  /**
64
- * Emergency cleanup when pending updates exceed safe limits
63
+ * Emergency cleanup when pending updates exceed safe limits.
64
+ * @param queue - The specific map to trim; defaults to the normal queue.
65
65
  */
66
66
  private performEmergencyCleanup;
67
67
  /**
@@ -94,8 +94,7 @@ declare class UpdateScheduler {
94
94
  }
95
95
  export declare const updateScheduler: UpdateScheduler;
96
96
  /**
97
- * Schedule a DOM update to be batched with optional component identity and priority
98
- * Schedule a DOM update to be batched with optional component identity and priority
97
+ * Schedule a DOM update to be batched with optional component identity and priority.
99
98
  */
100
99
  export declare function scheduleDOMUpdate(update: () => void, componentId?: string): void;
101
100
  /**
@@ -7,7 +7,6 @@
7
7
  */
8
8
  declare class SecureExpressionEvaluator {
9
9
  private static cache;
10
- private static maxCacheSize;
11
10
  private static dangerousPatterns;
12
11
  static evaluate(expression: string, context: Record<string, unknown>): unknown;
13
12
  private static createEvaluator;
@@ -0,0 +1,45 @@
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
+ }
33
+ /**
34
+ * Run a component's render function in a minimal SSR context to capture its
35
+ * shadow DOM VNode tree and any useStyle() output.
36
+ *
37
+ * The component's render wrapper in factory.ts handles:
38
+ * - setCurrentComponentContext / clearCurrentComponentContext
39
+ * - _hookCallbacks reset
40
+ * - _computedStyle reset
41
+ * - reactiveSystem registration / cleanup
42
+ *
43
+ * We only need to build a context object that satisfies the hooks' expectations.
44
+ */
45
+ export declare function runComponentSSRRender(config: ComponentConfig<object, object, object>, attrs: Record<string, string | number | boolean | null | undefined>, tag?: string): SSRRenderResult;
@@ -1,24 +1,92 @@
1
- /**
2
- * Optimized JIT CSS implementation with reduced bloat and enhanced utilities
3
- */
4
- /**
5
- * CSS template literal
6
- */
7
- export declare function css(strings: TemplateStringsArray, ...values: unknown[]): string;
8
- /**
9
- * CSS minification utility (basic)
10
- */
11
- export declare function minifyCSS(css: string): string;
12
- export declare function getBaseResetSheet(): CSSStyleSheet;
13
1
  export declare function getProseSheet(): CSSStyleSheet | null;
14
2
  export declare function registerProseSize(size: string): void;
15
- export declare function sanitizeCSS(css: string): string;
16
- export declare const baseReset: string;
17
3
  export type CSSMap = Record<string, string>;
4
+ /**
5
+ * Options for configuring the JIT CSS engine.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { enableJITCSS } from '@jasonshimmy/custom-elements-runtime';
10
+ * enableJITCSS({ extendedColors: true });
11
+ * ```
12
+ */
13
+ export interface JITCSSOptions {
14
+ /**
15
+ * Include the extended Tailwind color palette (slate, gray, red, orange, blue, violet, rose, etc.).
16
+ * Pass `true` to include all 21 color families, or an array of specific family names to include only
17
+ * those (e.g. `['slate', 'blue', 'red']`). A targeted list reduces `_activeColors` size and improves
18
+ * JIT match performance when only a few extended families are needed.
19
+ */
20
+ extendedColors?: boolean | string[];
21
+ /** Custom color palette entries to add to the JIT engine */
22
+ customColors?: Record<string, Record<string, string>>;
23
+ /** Disable specific variant groups for smaller output */
24
+ disableVariants?: Array<'responsive' | 'dark' | 'motion' | 'print' | 'container'>;
25
+ }
18
26
  type SelectorVariantMap = Record<string, (selector: string, body: string) => string>;
19
27
  type MediaVariantMap = Record<string, string>;
20
28
  export declare const colors: Record<string, Record<string, string>>;
21
- export declare const spacing = "0.25rem";
29
+ /**
30
+ * Returns `true` when the JIT CSS engine is globally active.
31
+ * The render engine uses this to skip the JIT pass for projects that do not
32
+ * use utility classes.
33
+ */
34
+ export declare function isJITCSSEnabled(): boolean;
35
+ /**
36
+ * Returns `true` when JIT CSS should run for the given shadow root.
37
+ * JIT CSS is active if the global flag is set (`enableJITCSS()`) OR if the
38
+ * specific shadow root was registered via `registerJITCSSComponent()`
39
+ * (i.e. the component called `useJITCSS()` in its render function).
40
+ * @internal — used by render.ts
41
+ */
42
+ export declare function isJITCSSEnabledFor(root: ShadowRoot): boolean;
43
+ /**
44
+ * Register a shadow root for per-component JIT CSS opt-in.
45
+ * Called by `useJITCSS()` when invoked inside a component render function.
46
+ * Optionally processes colour / variant options for this render pass.
47
+ * @internal
48
+ */
49
+ export declare function registerJITCSSComponent(root: ShadowRoot, options?: JITCSSOptions): void;
50
+ /**
51
+ * Configure the JIT CSS engine globally.
52
+ * Call once at app startup to set options that apply to all components.
53
+ *
54
+ * Calling this function also activates the JIT CSS engine if it has been
55
+ * disabled (e.g. by `disableJITCSS()`).
56
+ *
57
+ * @example
58
+ * ```ts
59
+ * import { enableJITCSS } from '@jasonshimmy/custom-elements-runtime';
60
+ *
61
+ * // Enable extended Tailwind color palette (bg-blue-500, text-violet-700, etc.)
62
+ * enableJITCSS({ extendedColors: true });
63
+ *
64
+ * // Add custom colors
65
+ * enableJITCSS({ customColors: { brand: { '500': '#e63946', '600': '#c1121f' } } });
66
+ * ```
67
+ */
68
+ export declare function enableJITCSS(options?: JITCSSOptions): void;
69
+ /**
70
+ * Disable the JIT CSS engine globally. Útil for projects that use only
71
+ * `useStyle()` and want to avoid any JIT parsing overhead.
72
+ *
73
+ * @example
74
+ * ```ts
75
+ * import { disableJITCSS } from '@jasonshimmy/custom-elements-runtime';
76
+ * disableJITCSS(); // JIT CSS will not run for any component
77
+ * ```
78
+ */
79
+ export declare function disableJITCSS(): void;
80
+ /**
81
+ * Get the current global JIT CSS options.
82
+ * @internal
83
+ */
84
+ export declare function getJITCSSOptions(): JITCSSOptions;
85
+ /**
86
+ * Reset JIT CSS to default state (semantic colors only). Intended for tests.
87
+ * @internal
88
+ */
89
+ export declare function _resetJITCSS(): void;
22
90
  export declare const spacingProps: Record<string, string[]>;
23
91
  export declare const utilityMap: CSSMap;
24
92
  /**
@@ -52,18 +120,8 @@ export declare function parseGradientColorStop(className: string): string | null
52
120
  export declare function parseOpacity(className: string): string | null;
53
121
  export declare function parseArbitrary(className: string): string | null;
54
122
  export declare function parseArbitraryVariant(token: string): string | null;
55
- /**
56
- * Polyfill for CSS.escape() for SSR environments
57
- * Based on https://drafts.csswg.org/cssom/#serialize-an-identifier
58
- */
59
- export declare function cssEscape(value: string): string;
60
- export declare function escapeClassName(name: string): string;
61
- export declare function escapeRegExp(str: string): string;
62
123
  export declare function extractClassesFromHTML(html: string): string[];
63
- export declare const jitCssCache: Map<string, {
64
- css: string;
65
- timestamp: number;
66
- }>;
124
+ export declare const jitCssCache: Map<string, string>;
67
125
  export declare const JIT_CSS_THROTTLE_MS = 16;
68
126
  export declare function jitCSS(html: string): string;
69
127
  export {};
@@ -2,12 +2,9 @@ import type { VNode } from '../types';
2
2
  export declare class LRUCache<K, V> {
3
3
  private map;
4
4
  private maxSize;
5
- private accessOrder;
6
- private accessCounter;
7
5
  constructor(maxSize: number);
8
6
  get(key: K): V | undefined;
9
7
  set(key: K, value: V): void;
10
- private evictLRU;
11
8
  has(key: K): boolean;
12
9
  clear(): void;
13
10
  get size(): number;
@@ -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;
@@ -61,7 +61,6 @@ export interface VDomGlobal {
61
61
  };
62
62
  };
63
63
  __vitest__?: unknown;
64
- __VDOM_DISABLED_PROMOTIONS?: unknown[];
65
64
  }
66
65
  /**
67
66
  * Returns `true` when `val` is an object that exposes a `.value` property.
@@ -0,0 +1,58 @@
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 './vdom-ssr';
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
+ * Minified DSD polyfill for browsers without native Declarative Shadow DOM.
46
+ * Processes all `<template shadowrootmode>` elements synchronously.
47
+ */
48
+ export declare const DSD_POLYFILL_SCRIPT: string;
49
+ /**
50
+ * Render a VNode tree to an HTML string with Declarative Shadow DOM output
51
+ * for all registered custom elements encountered in the tree.
52
+ */
53
+ export declare function renderToDSD(vnode: VNode, opts: DSDRenderOptions): string;
54
+ /**
55
+ * Render a VNode tree to a DSD HTML string and optionally append the
56
+ * DSD polyfill script for older browsers.
57
+ */
58
+ export declare function renderToStringDSD(vnode: VNode, opts?: DSDRenderOptions): string;