@jasonshimmy/custom-elements-runtime 3.3.0 → 3.5.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 (106) hide show
  1. package/README.md +28 -7
  2. package/dist/css-utils-Bn-dO44e.js +203 -0
  3. package/dist/{css-utils-CC43BbEy.js.map → css-utils-Bn-dO44e.js.map} +1 -1
  4. package/dist/{css-utils-CC43BbEy.js → css-utils-CFeP8SK1.cjs} +5 -71
  5. package/dist/{css-utils-mgjmH8qX.cjs.map → css-utils-CFeP8SK1.cjs.map} +1 -1
  6. package/dist/custom-elements-runtime.cjs.js +3 -4
  7. package/dist/custom-elements-runtime.cjs.js.map +1 -1
  8. package/dist/custom-elements-runtime.colors.cjs.js +1 -2
  9. package/dist/custom-elements-runtime.colors.cjs.js.map +1 -1
  10. package/dist/custom-elements-runtime.colors.es.js +277 -277
  11. package/dist/custom-elements-runtime.colors.es.js.map +1 -1
  12. package/dist/custom-elements-runtime.directive-enhancements.cjs.js +1 -2
  13. package/dist/custom-elements-runtime.directive-enhancements.cjs.js.map +1 -1
  14. package/dist/custom-elements-runtime.directive-enhancements.es.js +106 -122
  15. package/dist/custom-elements-runtime.directive-enhancements.es.js.map +1 -1
  16. package/dist/custom-elements-runtime.directives.cjs.js +1 -2
  17. package/dist/custom-elements-runtime.directives.cjs.js.map +1 -1
  18. package/dist/custom-elements-runtime.directives.es.js +60 -65
  19. package/dist/custom-elements-runtime.directives.es.js.map +1 -1
  20. package/dist/custom-elements-runtime.dom-jit-css.cjs.js +1 -7
  21. package/dist/custom-elements-runtime.dom-jit-css.cjs.js.map +1 -1
  22. package/dist/custom-elements-runtime.dom-jit-css.es.js +103 -115
  23. package/dist/custom-elements-runtime.dom-jit-css.es.js.map +1 -1
  24. package/dist/custom-elements-runtime.es.js +206 -253
  25. package/dist/custom-elements-runtime.es.js.map +1 -1
  26. package/dist/custom-elements-runtime.event-bus.cjs.js +1 -2
  27. package/dist/custom-elements-runtime.event-bus.cjs.js.map +1 -1
  28. package/dist/custom-elements-runtime.event-bus.es.js +102 -108
  29. package/dist/custom-elements-runtime.event-bus.es.js.map +1 -1
  30. package/dist/custom-elements-runtime.jit-css.cjs.js +1 -2
  31. package/dist/custom-elements-runtime.jit-css.cjs.js.map +1 -1
  32. package/dist/custom-elements-runtime.jit-css.es.js +14 -32
  33. package/dist/custom-elements-runtime.jit-css.es.js.map +1 -1
  34. package/dist/custom-elements-runtime.router.cjs.js +20 -21
  35. package/dist/custom-elements-runtime.router.cjs.js.map +1 -1
  36. package/dist/custom-elements-runtime.router.es.js +866 -926
  37. package/dist/custom-elements-runtime.router.es.js.map +1 -1
  38. package/dist/custom-elements-runtime.ssr-middleware.cjs.js +3 -4
  39. package/dist/custom-elements-runtime.ssr-middleware.cjs.js.map +1 -1
  40. package/dist/custom-elements-runtime.ssr-middleware.es.js +67 -73
  41. package/dist/custom-elements-runtime.ssr-middleware.es.js.map +1 -1
  42. package/dist/custom-elements-runtime.ssr.cjs.js +1 -1
  43. package/dist/custom-elements-runtime.ssr.es.js +3 -13
  44. package/dist/custom-elements-runtime.store.cjs.js +1 -2
  45. package/dist/custom-elements-runtime.store.cjs.js.map +1 -1
  46. package/dist/custom-elements-runtime.store.es.js +32 -33
  47. package/dist/custom-elements-runtime.store.es.js.map +1 -1
  48. package/dist/custom-elements-runtime.transitions.cjs.js +1 -2
  49. package/dist/custom-elements-runtime.transitions.cjs.js.map +1 -1
  50. package/dist/custom-elements-runtime.transitions.es.js +200 -210
  51. package/dist/custom-elements-runtime.transitions.es.js.map +1 -1
  52. package/dist/custom-elements-runtime.vite-plugin.cjs.js +4 -2
  53. package/dist/custom-elements-runtime.vite-plugin.cjs.js.map +1 -1
  54. package/dist/custom-elements-runtime.vite-plugin.es.js +155 -78
  55. package/dist/custom-elements-runtime.vite-plugin.es.js.map +1 -1
  56. package/dist/helpers-DcEpRwq5.cjs +5 -0
  57. package/dist/helpers-DcEpRwq5.cjs.map +1 -0
  58. package/dist/helpers-tJgb4Qve.js +693 -0
  59. package/dist/helpers-tJgb4Qve.js.map +1 -0
  60. package/dist/hooks-CEUnvtsA.js +407 -0
  61. package/dist/hooks-CEUnvtsA.js.map +1 -0
  62. package/dist/hooks-CNfugc95.cjs +2 -0
  63. package/dist/hooks-CNfugc95.cjs.map +1 -0
  64. package/dist/logger-DIJ0UH3R.js +36 -0
  65. package/dist/{logger-L25axmB-.js.map → logger-DIJ0UH3R.js.map} +1 -1
  66. package/dist/logger-Dkht1dCX.cjs +2 -0
  67. package/dist/{logger-BYIN7ysT.cjs.map → logger-Dkht1dCX.cjs.map} +1 -1
  68. package/dist/namespace-helpers-CIUkG8Mn.js +56 -0
  69. package/dist/{namespace-helpers-BucDdgz_.js.map → namespace-helpers-CIUkG8Mn.js.map} +1 -1
  70. package/dist/namespace-helpers-yYIb7INq.cjs +2 -0
  71. package/dist/{namespace-helpers-Bf7rm9JV.cjs.map → namespace-helpers-yYIb7INq.cjs.map} +1 -1
  72. package/dist/runtime/tag-utils.d.ts +11 -0
  73. package/dist/ssr-BpYy9XlW.js +170 -0
  74. package/dist/{ssr-B3lxl1vr.js.map → ssr-BpYy9XlW.js.map} +1 -1
  75. package/dist/ssr-CFabTOyi.cjs +4 -0
  76. package/dist/{ssr-DtD9e5iA.cjs.map → ssr-CFabTOyi.cjs.map} +1 -1
  77. package/dist/ssr.d.ts +33 -0
  78. package/dist/style-A8l3aQ52.cjs +55 -0
  79. package/dist/{style-Bjn8zDiZ.cjs.map → style-A8l3aQ52.cjs.map} +1 -1
  80. package/dist/style-DSSoCbC9.js +1877 -0
  81. package/dist/{style-DuDoj_xK.js.map → style-DSSoCbC9.js.map} +1 -1
  82. package/dist/tag-utils-CoSXTr1F.js +10 -0
  83. package/dist/tag-utils-CoSXTr1F.js.map +1 -0
  84. package/dist/tag-utils-XJ3dkcPQ.cjs +2 -0
  85. package/dist/tag-utils-XJ3dkcPQ.cjs.map +1 -0
  86. package/dist/template-compiler-B4B_jAPN.cjs +19 -0
  87. package/dist/{template-compiler-BB4JJdqk.cjs.map → template-compiler-B4B_jAPN.cjs.map} +1 -1
  88. package/dist/template-compiler-C3h8_vbE.js +3044 -0
  89. package/dist/{template-compiler-Cs5axmn4.js.map → template-compiler-C3h8_vbE.js.map} +1 -1
  90. package/dist/vite-plugin.d.ts +96 -2
  91. package/package.json +8 -8
  92. package/dist/css-utils-mgjmH8qX.cjs +0 -577
  93. package/dist/hooks-_3xP4G2N.js +0 -1189
  94. package/dist/hooks-_3xP4G2N.js.map +0 -1
  95. package/dist/hooks-fYQgZk2g.cjs +0 -7
  96. package/dist/hooks-fYQgZk2g.cjs.map +0 -1
  97. package/dist/logger-BYIN7ysT.cjs +0 -3
  98. package/dist/logger-L25axmB-.js +0 -41
  99. package/dist/namespace-helpers-Bf7rm9JV.cjs +0 -3
  100. package/dist/namespace-helpers-BucDdgz_.js +0 -61
  101. package/dist/ssr-B3lxl1vr.js +0 -165
  102. package/dist/ssr-DtD9e5iA.cjs +0 -5
  103. package/dist/style-Bjn8zDiZ.cjs +0 -56
  104. package/dist/style-DuDoj_xK.js +0 -1972
  105. package/dist/template-compiler-BB4JJdqk.cjs +0 -23
  106. package/dist/template-compiler-Cs5axmn4.js +0 -3236
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks-CEUnvtsA.js","names":[],"sources":["../src/lib/runtime/ssr-context.ts","../src/lib/runtime/hooks.ts"],"sourcesContent":["/**\n * SSR execution context for running component render functions server-side.\n *\n * When generating Declarative Shadow DOM (DSD) output, the SSR renderer must\n * call each custom element's render function to obtain its shadow DOM VNode\n * tree and capture any useStyle() / useGlobalStyle() output. This module\n * provides the minimal execution environment that makes that safe.\n *\n * Guarantees:\n * - useStyle() callbacks are executed and their output is captured.\n * - useGlobalStyle() callbacks are captured (not injected into document).\n * - Lifecycle hooks (useOnConnected, watch, …) register harmlessly to arrays\n * that are never invoked.\n * - The reactive system is never permanently mutated — component registration\n * is cleaned up by the render wrapper in factory.ts after each call.\n */\n\nimport type { ComponentConfig, ComponentContext, VNode } from './types';\nimport { toCamel } from './helpers';\nimport {\n setCurrentComponentContext,\n clearCurrentComponentContext,\n} from './hooks';\nimport { devWarn } from './logger';\n\n// ---------------------------------------------------------------------------\n// Global-style SSR collector\n// ---------------------------------------------------------------------------\n\n/**\n * When set, useGlobalStyle() factories write here instead of touching\n * document.adoptedStyleSheets (which doesn't exist in SSR environments).\n */\nlet _ssrGlobalStyleCollector: string[] | null = null;\n\n/** Start collecting useGlobalStyle() output from the current render pass. */\nexport function beginSSRGlobalStyleCollection(): void {\n if (_ssrGlobalStyleCollector !== null) {\n throw new Error(\n '[CER] Concurrent SSR render detected: beginSSRGlobalStyleCollection() called ' +\n 'while a collection is already active. For concurrent request handling, use ' +\n 'worker threads or multiple Node.js processes.',\n );\n }\n _ssrGlobalStyleCollector = [];\n}\n\n/** Stop collecting and return everything gathered so far. */\nexport function endSSRGlobalStyleCollection(): string[] {\n const collected = _ssrGlobalStyleCollector ?? [];\n _ssrGlobalStyleCollector = null;\n return collected;\n}\n\n/**\n * Called by useGlobalStyle() when an SSR collection pass is active.\n * Returns true if the CSS was captured (caller should skip DOM injection).\n */\nexport function captureGlobalStyleForSSR(css: string): boolean {\n if (_ssrGlobalStyleCollector !== null) {\n if (css && !_ssrGlobalStyleCollector.includes(css)) {\n _ssrGlobalStyleCollector.push(css);\n }\n return true;\n }\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// SSR render pass\n// ---------------------------------------------------------------------------\n\nexport interface SSRRenderResult {\n /** VNode tree from the component's render function (shadow DOM content). */\n shadowVNode: VNode | VNode[] | null;\n /** CSS string captured from useStyle() calls during this render. */\n useStyleCSS: string;\n /** Present when the component's render function returned a Promise. */\n asyncPromise?: Promise<VNode | VNode[]>;\n}\n\n/**\n * Run a component's render function in a minimal SSR context to capture its\n * shadow DOM VNode tree and any useStyle() output.\n *\n * The component's render wrapper in factory.ts handles:\n * - setCurrentComponentContext / clearCurrentComponentContext\n * - _hookCallbacks reset\n * - _computedStyle reset\n * - reactiveSystem registration / cleanup\n *\n * We only need to build a context object that satisfies the hooks' expectations.\n */\n// Monotonic counter ensures each SSR render context gets a unique component ID,\n// preventing the reactive system's stateStorage from returning stale cached\n// ref/computed values from a previous request.\nlet _ssrRenderCounter = 0;\n\nexport function runComponentSSRRender(\n config: ComponentConfig<object, object, object, object>,\n attrs: Record<string, string | number | boolean | null | undefined>,\n tag = 'unknown',\n ssrRouter?: unknown,\n): SSRRenderResult {\n // Build camelCase prop map from serialised attribute names.\n const propsFromAttrs: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(attrs ?? {})) {\n propsFromAttrs[toCamel(k)] = v;\n }\n\n // Fake host element: satisfies useProps()'s attribute reads without a real DOM node.\n const fakeHost = {\n getAttribute(name: string): string | null {\n const camel = toCamel(name);\n if (\n propsFromAttrs[camel] !== undefined &&\n propsFromAttrs[camel] !== null\n ) {\n return String(propsFromAttrs[camel]);\n }\n const raw = (attrs ?? {})[name];\n return raw !== undefined && raw !== null ? String(raw) : null;\n },\n hasAttribute(name: string): boolean {\n return this.getAttribute(name) !== null;\n },\n // shadowRoot must be null so useJITCSS() doesn't try to registerJITCSSComponent\n shadowRoot: null as null,\n tagName: '',\n parentElement: null as null,\n };\n\n // Minimal context object — the factory render wrapper will add _hookCallbacks\n // and _computedStyle via Object.defineProperty before calling renderFn().\n const ssrContext: Record<string, unknown> = {\n ...propsFromAttrs,\n // Unique ID per SSR render prevents the reactive system's stateStorage from\n // returning cached ref/computed values from a previous request. Using a\n // monotonic counter is cheaper than crypto.randomUUID() and avoids the\n // Node.js version compatibility concern noted in the original comment.\n _componentId: `cer-ssr-${Object.keys(propsFromAttrs).join('-') || 'root'}-${++_ssrRenderCounter}`,\n requestRender: () => undefined,\n _requestRender: () => undefined,\n emit: () => true,\n refs: {},\n };\n\n // Set _host as non-enumerable to avoid triggering the reactive proxy trap.\n Object.defineProperty(ssrContext, '_host', {\n value: fakeHost,\n writable: true,\n enumerable: false,\n configurable: true,\n });\n\n // Thread the per-request router instance so router-view (and any component\n // that calls getCurrentComponentContext()._router) reads from the correct\n // router rather than the module-level activeRouterProxy singleton.\n // Non-enumerable keeps it out of prop serialisation / Object.keys iteration.\n if (ssrRouter !== undefined) {\n Object.defineProperty(ssrContext, '_router', {\n value: ssrRouter,\n writable: false,\n enumerable: false,\n configurable: true,\n });\n }\n\n // Pre-set the component context so hooks (useStyle, useProps, etc.) work even\n // when config.render is a raw function rather than the factory.ts wrapper.\n // If config.render IS the factory wrapper, it will call setCurrentComponentContext\n // again with the same object — that is harmless.\n setCurrentComponentContext(ssrContext);\n\n let shadowVNode: VNode | VNode[] | null = null;\n let asyncPromise: Promise<VNode | VNode[]> | undefined;\n try {\n const result = config.render(\n ssrContext as ComponentContext<object, object, object, object>,\n );\n // Async render functions cannot be awaited in the synchronous SSR pass.\n // The DSD renderer will emit a streaming placeholder if active; otherwise\n // the shadow DOM will be empty. The caller emits the appropriate warning.\n if (result instanceof Promise) {\n asyncPromise = result;\n } else {\n shadowVNode = result as VNode | VNode[];\n }\n } catch (err) {\n // Best-effort — a render error during SSR should not crash the server.\n // The component will still get a DSD wrapper, just without shadow content.\n devWarn(\n `[SSR] Component \"${tag}\" threw during SSR render. ` +\n `The shadow DOM will be empty. Error:`,\n err,\n );\n } finally {\n // Clear context. The factory wrapper clears it too, but calling clearCurrentComponentContext()\n // twice (null → null) is harmless and ensures clean state if config.render was a raw function.\n clearCurrentComponentContext();\n }\n\n const useStyleCSS = String(\n (ssrContext as { _computedStyle?: string })._computedStyle ?? '',\n );\n\n return { shadowVNode, useStyleCSS, asyncPromise };\n}\n","/**\n * Context-based hooks for functional components\n * Provides React-like hooks with perfect TypeScript inference\n */\n\nimport { isReactiveState } from './reactive';\nimport { toKebab } from './helpers';\nimport { devWarn, devError } from './logger';\nimport { isDiscoveryRender as _isDiscoveryRenderFn } from './discovery-state';\nimport { sanitizeCSS, minifyCSS } from './css-utils';\nimport type { JITCSSOptions } from './style';\nimport { captureGlobalStyleForSSR } from './ssr-context';\n\n// Re-export JITCSSOptions as a type-only re-export so consumers can still\n// import it from './runtime/hooks' without creating a runtime dependency on style.ts.\nexport type { JITCSSOptions };\n\n// Re-export discovery helpers so consumers continue to use the same import path.\nexport { beginDiscoveryRender, endDiscoveryRender } from './discovery-state';\n\n/**\n * Returns true while a discovery render is in progress.\n * Used by `html` and other primitives to short-circuit side effects.\n * @internal\n */\nexport function isDiscoveryRender(): boolean {\n return _isDiscoveryRenderFn();\n}\n\n// Global state to track current component context during render\n// Narrowed internal type for currentComponentContext to expose _hookCallbacks\ninterface InternalHookCallbacks {\n onConnected?: Array<(context?: unknown) => void>;\n onDisconnected?: Array<(context?: unknown) => void>;\n onAttributeChanged?: Array<\n (name: string, oldValue: string | null, newValue: string | null) => void\n >;\n onError?: Array<(err: unknown) => void>;\n props?: Record<string, unknown>;\n style?: () => string;\n expose?: Record<string, unknown>;\n}\n\ntype InternalComponentContext = Record<string, unknown> & {\n _hookCallbacks?: InternalHookCallbacks;\n _computedStyle?: string;\n};\n\nlet currentComponentContext: InternalComponentContext | null = null;\n\n/** Symbol key used to store provides map on a component's context object. */\nconst PROVIDES_KEY = Symbol('cer:provides');\n\n/**\n * Set the current component context (called internally during render)\n * @internal\n */\nexport function setCurrentComponentContext(\n context: Record<string, unknown>,\n): void {\n currentComponentContext = context;\n}\n\n/**\n * Clear the current component context (called internally after render)\n * @internal\n */\nexport function clearCurrentComponentContext(): void {\n currentComponentContext = null;\n}\n\n// ---------- Discovery render probe ----------\n// The actual state and helpers live in discovery-state.ts to avoid\n// circular dependencies with reactive.ts. The re-exports above forward\n// beginDiscoveryRender / endDiscoveryRender / isDiscoveryRender from that\n// module so all existing import sites remain unchanged.\n\n/**\n * Get the current component context. Useful for advanced composable patterns\n * that need to access or pass the context explicitly.\n * @internal\n */\nexport function getCurrentComponentContext(): Record<string, unknown> | null {\n return currentComponentContext;\n}\n\n/**\n * Get the emit function for the current component\n * Must be called during component render\n *\n * @example\n * ```ts\n * component('my-button', () => {\n * const { label } = useProps({ label: 'Click me' });\n * const emit = useEmit();\n *\n * return html`\n * <button @click=\"${() => emit('button-click', { label })}\">\n * ${label}\n * </button>\n * `;\n * });\n * ```\n */\nexport function useEmit(): (\n eventName: string,\n detail?: unknown,\n options?: CustomEventInit,\n) => boolean {\n if (!currentComponentContext) {\n throw new Error('useEmit must be called during component render');\n }\n\n // During discovery render, return a no-op function — no real host exists.\n if (_isDiscoveryRenderFn()) {\n return () => false;\n }\n\n // Capture and validate the emit function from the current context\n const emitCandidate = (currentComponentContext as { emit?: unknown }).emit;\n if (typeof emitCandidate !== 'function') {\n throw new Error(\n 'useEmit requires an emit function on the component context',\n );\n }\n const emitFn = emitCandidate as (\n eventName: string,\n detail?: unknown,\n options?: CustomEventInit,\n ) => boolean;\n\n return (eventName: string, detail?: unknown, options?: CustomEventInit) => {\n return emitFn(eventName, detail, options);\n };\n}\n\n/**\n * Initialize hook callbacks storage on context if not exists\n * Uses Object.defineProperty to avoid triggering reactive updates\n */\nfunction ensureHookCallbacks(context: Record<string, unknown>): void {\n if (!context._hookCallbacks) {\n Object.defineProperty(context, '_hookCallbacks', {\n value: {},\n writable: true,\n enumerable: false,\n configurable: true,\n });\n }\n}\n\n/**\n * Register a callback to be called when component is connected to DOM\n *\n * @example\n * ```ts\n * component('my-component', () => {\n * useOnConnected(() => {\n * console.log('Component mounted!');\n * });\n *\n * return html`<div>Hello World</div>`;\n * });\n * ```\n */\nexport function useOnConnected(callback: () => void): void {\n if (!currentComponentContext) {\n throw new Error('useOnConnected must be called during component render');\n }\n\n // During discovery render, skip registering lifecycle callbacks — the\n // discoveryContext is ephemeral and its hooks are never invoked.\n if (_isDiscoveryRenderFn()) return;\n\n ensureHookCallbacks(currentComponentContext as InternalComponentContext);\n const hooks = currentComponentContext._hookCallbacks as InternalHookCallbacks;\n if (!hooks.onConnected) hooks.onConnected = [];\n hooks.onConnected.push(callback);\n}\n\n/**\n * Register a callback to be called when component is disconnected from DOM\n *\n * @example\n * ```ts\n * component('my-component', () => {\n * useOnDisconnected(() => {\n * console.log('Component unmounted!');\n * });\n *\n * return html`<div>Goodbye World</div>`;\n * });\n * ```\n */\nexport function useOnDisconnected(callback: () => void): void {\n if (!currentComponentContext) {\n throw new Error('useOnDisconnected must be called during component render');\n }\n\n // During discovery render, skip registering lifecycle callbacks.\n if (_isDiscoveryRenderFn()) return;\n\n ensureHookCallbacks(currentComponentContext as InternalComponentContext);\n const hooks = currentComponentContext._hookCallbacks as InternalHookCallbacks;\n if (!hooks.onDisconnected) hooks.onDisconnected = [];\n hooks.onDisconnected.push(callback);\n}\n\n/**\n * Register a callback to be called when an attribute changes\n *\n * @example\n * ```ts\n * component('my-component', () => {\n * useOnAttributeChanged((name, oldValue, newValue) => {\n * console.log(`Attribute ${name} changed from ${oldValue} to ${newValue}`);\n * });\n *\n * return html`<div>Attribute watcher</div>`;\n * });\n * ```\n */\nexport function useOnAttributeChanged(\n callback: (\n name: string,\n oldValue: string | null,\n newValue: string | null,\n ) => void,\n): void {\n if (!currentComponentContext) {\n throw new Error(\n 'useOnAttributeChanged must be called during component render',\n );\n }\n\n // During discovery render, skip registering lifecycle callbacks.\n if (_isDiscoveryRenderFn()) return;\n\n ensureHookCallbacks(currentComponentContext as InternalComponentContext);\n const hooks = currentComponentContext._hookCallbacks as InternalHookCallbacks;\n if (!hooks.onAttributeChanged) hooks.onAttributeChanged = [];\n hooks.onAttributeChanged.push(callback);\n}\n\n/**\n * Register a callback to be called when an error occurs\n *\n * @example\n * ```ts\n * component('my-component', () => {\n * useOnError((error) => {\n * console.error('Component error:', error);\n * });\n *\n * return html`<div>Error handler</div>`;\n * });\n * ```\n */\nexport function useOnError(callback: (error: Error) => void): void {\n if (!currentComponentContext) {\n throw new Error('useOnError must be called during component render');\n }\n\n // During discovery render, skip registering lifecycle callbacks.\n if (_isDiscoveryRenderFn()) return;\n\n ensureHookCallbacks(currentComponentContext as InternalComponentContext);\n const hooks = currentComponentContext._hookCallbacks as InternalHookCallbacks;\n if (!hooks.onError) hooks.onError = [];\n // Wrap to normalize to Error. If the user's handler itself throws, log it in\n // dev mode so it doesn't vanish silently — the original error is already handled.\n hooks.onError.push((err: unknown) => {\n try {\n if (err instanceof Error) callback(err);\n else callback(new Error(String(err)));\n } catch (handlerErr) {\n devError('[useOnError] The error handler itself threw an exception:', handlerErr);\n }\n });\n}\n\n/**\n * Register prop defaults for the component. Can be called during render.\n * Stores the prop defaults on `context._hookCallbacks.props` so the runtime\n * can pick them up when building the component config.\n *\n * Example:\n * ```ts\n * component('my-comp', () => {\n * useProps({ modelValue: false, label: 'Hello' });\n * return html`<div/>`;\n * });\n * ```\n */\nexport function useProps<T extends Record<string, unknown>>(defaults: T): T {\n if (!currentComponentContext) {\n throw new Error('useProps must be called during component render');\n }\n\n ensureHookCallbacks(currentComponentContext as InternalComponentContext);\n const hooks = currentComponentContext._hookCallbacks as InternalHookCallbacks;\n hooks.props = {\n ...(hooks.props || {}),\n ...defaults,\n };\n\n const ctx = currentComponentContext;\n // Define dynamic getters for declared props so the context property\n // always reflects the host element's property (or reactive ref.value)\n try {\n const declaredKeys = Object.keys(defaults || {});\n for (const key of declaredKeys) {\n if (typeof key !== 'string' || key.startsWith('_')) continue;\n const existing = Object.getOwnPropertyDescriptor(ctx, key);\n // Only define if not present or configurable (allow overriding)\n if (existing && !existing.configurable) continue;\n try {\n // Preserve any existing concrete value on the context in a closure.\n // This avoids recursive getters when we later reference ctx[key].\n const hasOwn = Object.prototype.hasOwnProperty.call(ctx, key);\n let localValue: unknown = hasOwn\n ? (ctx as Record<string, unknown>)[key]\n : undefined;\n\n Object.defineProperty(ctx, key, {\n configurable: true,\n enumerable: true,\n get() {\n try {\n const host = (ctx && (ctx as { _host?: HTMLElement })._host) as\n | HTMLElement\n | undefined;\n if (host) {\n // First, check for attribute value (attributes should take precedence)\n const kebabKey = toKebab(key);\n const attrValue = host.getAttribute(kebabKey);\n if (attrValue !== null) {\n const defaultType = typeof defaults[key];\n if (defaultType === 'boolean') {\n // Standalone boolean attributes have empty string value\n return attrValue === '' || attrValue === 'true';\n }\n if (defaultType === 'number') {\n return Number(attrValue);\n }\n return attrValue;\n }\n\n // If no attribute, check if host has a property value set\n if (\n typeof (host as unknown as Record<string, unknown>)[key] !==\n 'undefined'\n ) {\n const fromHost = (host as unknown as Record<string, unknown>)[\n key\n ];\n // prefer host value when present\n // If the host provided a ReactiveState instance or a wrapper\n // with a .value, unwrap it here so destructured props and\n // useProps return the primitive/current value consistently.\n if (isReactiveState(fromHost)) {\n return (fromHost as { value: unknown }).value;\n }\n if (\n fromHost &&\n typeof fromHost === 'object' &&\n 'value' in fromHost &&\n !(typeof Node !== 'undefined' && fromHost instanceof Node)\n ) {\n return (fromHost as { value?: unknown }).value;\n }\n // For string-typed declared props, avoid returning host\n // object-like properties (for example `element.style` which\n // is a CSSStyleDeclaration). Prefer attribute value or the\n // local default instead of returning a non-primitive host\n // property into templates which expect primitives.\n const defaultType = typeof defaults[key];\n if (\n defaultType === 'string' &&\n fromHost &&\n typeof fromHost === 'object'\n ) {\n // fallthrough to localValue\n } else {\n // For boolean defaults, treat empty string (standalone attribute) or 'true' as true.\n if (\n defaultType === 'boolean' &&\n typeof fromHost === 'string'\n ) {\n return fromHost === '' || fromHost === 'true';\n }\n return fromHost;\n }\n }\n }\n } catch {\n // ignore host read failures and fall back to context\n }\n return localValue;\n },\n set(v: unknown) {\n // allow test/runtime code to set context props during render/init\n localValue = v;\n },\n });\n } catch {\n // ignore\n }\n }\n } catch {\n // ignore\n }\n // Return a Proxy that always reads the latest value from the component\n // context so accesses are reactive. Also unwrap functional refs ({ value })\n // and coerce string attribute values to boolean/number when defaults\n // indicate such types.\n const result = new Proxy({} as Record<string, unknown>, {\n get(_target, prop: string) {\n if (typeof prop !== 'string') return undefined;\n const def = (defaults as Record<string, unknown>)[prop];\n\n // If a host element is available, prefer reading from attributes first,\n // then from properties. This ensures that HTML attributes take precedence\n // over default property values (like the standard \"title\" attribute).\n try {\n const host = (ctx && (ctx as { _host?: HTMLElement })._host) as\n | HTMLElement\n | undefined;\n if (host) {\n // Check attribute first (only if host is an actual HTMLElement)\n if (\n (typeof HTMLElement !== 'undefined' && host instanceof HTMLElement) ||\n (typeof (host as { getAttribute?: (name: string) => string | null })\n .getAttribute === 'function' &&\n typeof (host as { hasAttribute?: (name: string) => boolean })\n .hasAttribute === 'function')\n ) {\n const kebabKey = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\n const attrValue = (\n host as { getAttribute: (name: string) => string | null }\n ).getAttribute(kebabKey);\n if (attrValue !== null) {\n // Attribute exists - convert based on default type\n if (typeof def === 'boolean') {\n return attrValue === '' || attrValue === 'true';\n }\n if (typeof def === 'number') {\n return Number(attrValue);\n }\n return attrValue;\n }\n }\n\n // No attribute - check property value\n const hostValue = (host as unknown as Record<string, unknown>)[prop];\n // Only use host value if it's explicitly set (not undefined AND not empty string for string defaults)\n // Empty strings on standard HTML properties (like 'title') should fall through to defaults\n if (typeof hostValue !== 'undefined' && hostValue !== '') {\n // If the declared default is a string, avoid returning raw DOM\n // object-like properties (such as element.style which is a CSSStyleDeclaration)\n // since templates expect primitives and serializing objects can\n // cause DOMExceptions. However, wrapper-like objects that expose\n // a `.value` property (or ReactiveState instances) should be\n // unwrapped and returned even for string defaults.\n const isWrapperLike =\n hostValue &&\n typeof hostValue === 'object' &&\n 'value' in hostValue &&\n !(typeof Node !== 'undefined' && hostValue instanceof Node);\n if (\n typeof def === 'string' &&\n hostValue &&\n typeof hostValue === 'object' &&\n !isWrapperLike &&\n !isReactiveState(hostValue)\n ) {\n // treat as not present and fall through to ctx/default\n } else {\n // Special handling for boolean props: if default is false and hostValue is empty string,\n // treat it as if the property wasn't set (use default false)\n if (\n typeof def === 'boolean' &&\n def === false &&\n hostValue === ''\n ) {\n return def;\n }\n\n // Unwrap ReactiveState instances and wrapper-like objects coming\n // from the host so useProps mirrors applyProps/destructured props\n // behavior and returns primitive/current values.\n if (isReactiveState(hostValue)) {\n return (hostValue as { value: unknown }).value;\n }\n if (isWrapperLike) {\n return (hostValue as { value: unknown }).value;\n }\n\n // Primitive on host - return directly (but coerce strings if default provided).\n // Use the same rule as the attribute path: empty string (standalone attribute\n // presence) or the literal string 'true' coerce to true; everything else is false.\n if (typeof def === 'boolean' && typeof hostValue === 'string') {\n return hostValue === '' || hostValue === 'true';\n }\n if (\n typeof def === 'number' &&\n typeof hostValue === 'string' &&\n !Number.isNaN(Number(hostValue))\n )\n return Number(hostValue);\n return hostValue;\n }\n }\n }\n } catch {\n // ignore host read failures and fall back to context\n }\n\n // Fall back to reading from the component context itself.\n const raw = ctx[prop];\n // Treat empty-string on context as boolean true (attribute presence)\n // EXCEPT when the default is false - in that case, empty string means \"not set\"\n if (typeof def === 'boolean' && raw === '') {\n if (def === false) {\n // For boolean props with default false, empty string means use the default\n return def;\n }\n // For boolean props with default true, empty string means attribute presence = true\n return true;\n }\n // If the context stores a ReactiveState or wrapper, unwrap it here\n // so components using useProps receive the primitive/current value\n // when the source is the component context itself. Host-provided\n // ReactiveState instances are preserved above; this path is only\n // for ctx values and defaults.\n if (isReactiveState(raw)) return (raw as { value: unknown }).value;\n if (\n raw &&\n typeof raw === 'object' &&\n 'value' in raw &&\n !(typeof Node !== 'undefined' && raw instanceof Node)\n )\n return (raw as { value: unknown }).value;\n if (raw != null && raw !== '') {\n if (typeof def === 'boolean' && typeof raw === 'string') {\n return raw === 'true';\n }\n if (\n typeof def === 'number' &&\n typeof raw === 'string' &&\n !Number.isNaN(Number(raw))\n )\n return Number(raw);\n return raw;\n }\n return def;\n },\n has(_target, prop: string) {\n return typeof prop === 'string' && (prop in ctx || prop in defaults);\n },\n ownKeys() {\n return Array.from(\n new Set([...Object.keys(defaults), ...Object.keys(ctx || {})]),\n );\n },\n getOwnPropertyDescriptor() {\n return { configurable: true, enumerable: true } as PropertyDescriptor;\n },\n });\n\n return result as T;\n}\n\n/**\n * Register prop defaults and return a stable props object for use inside render.\n * The returned object reads values from the current component context at render\n * time and falls back to the provided defaults. This keeps prop access stable\n * in production builds and avoids reliance on parsing the render function.\n *\n * Must be called during render. Example:\n * const props = useProps({ modelValue: false });\n */\n// (useProps now returns the props object directly)\n\n/**\n * Register a style function that will be called during each render\n * to provide reactive styles for the component\n *\n * @example\n * ```ts\n * import { css } from '@lib/style';\n *\n * component('my-component', () => {\n * const { theme } = useProps({ theme: 'light' });\n *\n * useStyle(() => css`\n * :host {\n * background: ${theme === 'light' ? 'white' : 'black'};\n * color: ${theme === 'light' ? 'black' : 'white'};\n * }\n * `);\n *\n * return html`<div>Styled component</div>`;\n * });\n * ```\n */\nexport function useStyle(callback: () => string): void {\n if (!currentComponentContext) {\n throw new Error('useStyle must be called during component render');\n }\n\n // During discovery render, skip style computation — no real DOM to style.\n if (_isDiscoveryRenderFn()) return;\n\n ensureHookCallbacks(currentComponentContext);\n\n // Execute the callback immediately during render to capture the current style\n // This ensures reactive state is read during the render phase, not during style application\n try {\n const computedStyle = callback();\n\n // Store the computed style using Object.defineProperty to avoid triggering reactive updates\n Object.defineProperty(currentComponentContext, '_computedStyle', {\n value: computedStyle,\n writable: true,\n enumerable: false,\n configurable: true,\n });\n } catch (error) {\n devWarn('Error in useStyle callback:', error);\n Object.defineProperty(currentComponentContext, '_computedStyle', {\n value: '',\n writable: true,\n enumerable: false,\n configurable: true,\n });\n }\n}\n\n/**\n * Cache of globally-injected stylesheets keyed by their CSS content.\n * Prevents duplicate `<style>` injections when the same `useGlobalStyle()`\n * factory runs across multiple component instances.\n */\nconst _globalStyleSheets = new Map<string, CSSStyleSheet>();\n\n/**\n * Inject CSS into `document.adoptedStyleSheets`, escaping the Shadow DOM\n * boundary. Suitable for `@font-face` declarations, `:root` variable overrides,\n * and global scroll/scroll-bar styling. Deduplicated by CSS content so calling\n * this in multiple component instances is safe.\n *\n * **Use sparingly** — this intentionally breaks Shadow DOM encapsulation.\n * A dev-mode warning is emitted to make the escape hatch visible.\n *\n * @example\n * ```ts\n * component('app-root', () => {\n * useGlobalStyle(() => css`\n * @font-face {\n * font-family: 'Inter';\n * src: url('/fonts/inter.woff2') format('woff2');\n * }\n * :root {\n * --app-font: 'Inter', sans-serif;\n * }\n * `);\n * return html`<slot></slot>`;\n * });\n * ```\n */\nexport function useGlobalStyle(styleFactory: () => string): void {\n let raw: string;\n try {\n raw = styleFactory();\n } catch {\n return;\n }\n\n // SSR collection pass: when an active collector exists (set up by\n // beginSSRGlobalStyleCollection in ssr.ts), capture here and skip DOM\n // injection regardless of whether document is available. This correctly\n // handles both Node.js SSR (no document) and test environments (document\n // present via happy-dom/jsdom) that call renderToStringWithJITCSS.\n if (captureGlobalStyleForSSR(raw)) return;\n\n if (typeof document === 'undefined' || typeof CSSStyleSheet === 'undefined') {\n // SSR without an active collector — nothing to do.\n return;\n }\n devWarn(\n '[useGlobalStyle] Injecting global styles from a component. ' +\n 'This escapes Shadow DOM encapsulation — use sparingly.',\n );\n const style = minifyCSS(sanitizeCSS(raw!));\n if (!style || _globalStyleSheets.has(style)) return;\n try {\n const sheet = new CSSStyleSheet();\n sheet.replaceSync(style);\n document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];\n _globalStyleSheets.set(style, sheet);\n } catch {\n // Fallback: inject a <style> element in <head>\n const el = document.createElement('style');\n el.textContent = style;\n (document.head ?? document.documentElement).appendChild(el);\n }\n}\n\n/**\n * Design token definitions accepted by `useDesignTokens()`.\n * Map high-level token names to CSS custom property overrides.\n */\nexport interface DesignTokens {\n /** Override the primary color scale root (sets --cer-color-primary-500) */\n primary?: string;\n /** Override the secondary color scale root */\n secondary?: string;\n /** Override the neutral color scale root */\n neutral?: string;\n /** Override the success color root */\n success?: string;\n /** Override the info color root */\n info?: string;\n /** Override the warning color root */\n warning?: string;\n /** Override the error color root */\n error?: string;\n /** Override the sans-serif font family */\n fontSans?: string;\n /** Override the serif font family */\n fontSerif?: string;\n /** Override the monospace font family */\n fontMono?: string;\n /** Additional arbitrary CSS custom property overrides */\n [key: string]: string | undefined;\n}\n\n/**\n * Apply design tokens to `:host` as CSS custom property overrides.\n * Must be called during component render. This is a typed, validated\n * alternative to writing `useStyle(() => css\\`:host { ... }\\`)` by hand.\n *\n * Semantic color tokens (e.g. `primary: '#6366f1'`) set the `*-500` shade\n * for that scale. Use arbitrary `'--cer-color-primary-500'` keys to override\n * individual shades.\n *\n * @example\n * ```ts\n * component('app-root', () => {\n * useDesignTokens({\n * primary: '#6366f1',\n * fontSans: '\"Inter\", sans-serif',\n * '--cer-color-neutral-900': '#0a0a0a',\n * });\n * return html`<slot></slot>`;\n * });\n * ```\n */\nexport function useDesignTokens(tokens: DesignTokens): void {\n if (!currentComponentContext) {\n throw new Error('useDesignTokens must be called during component render');\n }\n\n if (_isDiscoveryRenderFn()) return;\n\n const declarations: string[] = [];\n const semanticColorMap: Record<string, string> = {\n primary: '--cer-color-primary-500',\n secondary: '--cer-color-secondary-500',\n neutral: '--cer-color-neutral-500',\n success: '--cer-color-success-500',\n info: '--cer-color-info-500',\n warning: '--cer-color-warning-500',\n error: '--cer-color-error-500',\n };\n const fontMap: Record<string, string> = {\n fontSans: '--cer-font-sans',\n fontSerif: '--cer-font-serif',\n fontMono: '--cer-font-mono',\n };\n\n for (const [key, value] of Object.entries(tokens)) {\n if (value === undefined) continue;\n if (key in semanticColorMap) {\n declarations.push(`${semanticColorMap[key]}:${value}`);\n } else if (key in fontMap) {\n declarations.push(`${fontMap[key]}:${value}`);\n } else if (key.startsWith('--')) {\n declarations.push(`${key}:${value}`);\n }\n }\n\n if (declarations.length === 0) return;\n\n const cssText = `:host{${declarations.join(';')}}`;\n\n // Append to any existing computed style\n const ctx = currentComponentContext as { _computedStyle?: string };\n const existing = ctx._computedStyle ?? '';\n const combined = existing ? `${existing}\\n${cssText}` : cssText;\n\n Object.defineProperty(currentComponentContext, '_computedStyle', {\n value: combined,\n writable: true,\n enumerable: false,\n configurable: true,\n });\n}\n\n// ---------- provide / inject ----------\n\n/**\n * Store a value under a key so that descendant components can retrieve it\n * with `inject()`. Must be called during component render.\n *\n * @example\n * ```ts\n * component('theme-provider', () => {\n * provide('theme', 'dark');\n * return html`<slot></slot>`;\n * });\n * ```\n */\nexport function provide<T>(key: string | symbol, value: T): void {\n if (!currentComponentContext) {\n throw new Error('provide must be called during component render');\n }\n\n // During discovery render, skip provide — the ephemeral context is discarded.\n if (_isDiscoveryRenderFn()) return;\n\n const ctx = currentComponentContext as Record<string | symbol, unknown>;\n if (!ctx[PROVIDES_KEY]) {\n Object.defineProperty(ctx, PROVIDES_KEY, {\n value: new Map<string | symbol, unknown>(),\n writable: false,\n enumerable: false,\n configurable: true,\n });\n }\n (ctx[PROVIDES_KEY] as Map<string | symbol, unknown>).set(key, value);\n}\n\n/**\n * Retrieve a value provided by an ancestor component. Traverses the shadow\n * DOM tree upward through ShadowRoot host elements looking for the nearest\n * `provide()` call with the matching key. Returns `defaultValue` (or\n * `undefined`) when no provider is found. Must be called during render.\n *\n * @example\n * ```ts\n * component('themed-button', () => {\n * const theme = inject<string>('theme', 'light');\n * return html`<button class=\"btn-${theme}\">Click</button>`;\n * });\n * ```\n */\nexport function inject<T>(\n key: string | symbol,\n defaultValue?: T,\n): T | undefined {\n if (!currentComponentContext) {\n throw new Error('inject must be called during component render');\n }\n\n // During discovery render, the host tree is not yet mounted — return the\n // default value to allow prop detection to continue without DOM traversal.\n if (_isDiscoveryRenderFn()) return defaultValue;\n\n try {\n const host = (currentComponentContext as { _host?: HTMLElement })._host;\n if (host) {\n let node: Node | null = host.parentNode as Node | null;\n if (!node) node = host.getRootNode() as Node | null;\n\n // Depth counter prevents infinite loops in detached subtrees where\n // getRootNode() may return a subtree root instead of `document`.\n let depth = 0;\n const MAX_DEPTH = 50;\n\n while (node && depth < MAX_DEPTH) {\n depth++;\n if (typeof ShadowRoot !== 'undefined' && node instanceof ShadowRoot) {\n const shadowHost = node.host;\n const hostCtx = (\n shadowHost as unknown as {\n context?: Record<string | symbol, unknown>;\n }\n ).context;\n if (hostCtx) {\n const provides = hostCtx[PROVIDES_KEY] as\n | Map<string | symbol, unknown>\n | undefined;\n if (provides?.has(key)) {\n return provides.get(key) as T;\n }\n }\n const next: Node | null = shadowHost.parentNode as Node | null;\n node = next ?? (shadowHost.getRootNode() as Node | null);\n if (node === document || node === shadowHost) break;\n } else {\n // Also check light-DOM ancestor elements that may be custom components\n // with provides (e.g. a consumer that is a slotted child of a provider).\n if (typeof Element !== 'undefined' && node instanceof Element) {\n const elCtx = (\n node as unknown as {\n context?: Record<string | symbol, unknown>;\n }\n ).context;\n if (elCtx) {\n const provides = elCtx[PROVIDES_KEY] as\n | Map<string | symbol, unknown>\n | undefined;\n if (provides?.has(key)) {\n return provides.get(key) as T;\n }\n }\n }\n const prevNode = node;\n const next: Node | null = (node as Node).parentNode as Node | null;\n node = next ?? ((node as Node).getRootNode?.() as Node | null);\n // Guard against infinite loops: if getRootNode() returns the same\n // node (disconnected element with no ancestors), stop traversal.\n if (node === document || node === prevNode) break;\n }\n }\n }\n } catch {\n // ignore traversal errors - fall through to default\n }\n\n return defaultValue;\n}\n\n// ---------- createComposable ----------\n\n/**\n * Execute a function that calls hooks (useOnConnected, useOnDisconnected, etc.)\n * using an explicit component context rather than requiring the call to happen\n * directly inside a render function. This enables composable utility functions\n * that register lifecycle callbacks from outside the render body.\n *\n * @example\n * ```ts\n * function useLogger(label: string) {\n * return createComposable(() => {\n * useOnConnected(() => console.log(`${label} connected`));\n * useOnDisconnected(() => console.log(`${label} disconnected`));\n * });\n * }\n *\n * component('my-comp', () => {\n * const stopLogger = useLogger('my-comp');\n * stopLogger(context); // pass the component context explicitly\n * return html`<div>Hello</div>`;\n * });\n * ```\n *\n * More commonly, use it as a direct wrapper inside render:\n * ```ts\n * component('my-comp', () => {\n * // Accepts context automatically from getCurrentComponentContext()\n * createComposable(() => {\n * useOnConnected(() => console.log('connected from composable'));\n * })();\n * return html`<div>Hello</div>`;\n * });\n * ```\n */\nexport function createComposable<T>(\n fn: () => T,\n): (ctx?: Record<string, unknown>) => T {\n return (ctx?: Record<string, unknown>) => {\n const targetCtx = ctx ?? currentComponentContext;\n if (!targetCtx) {\n throw new Error(\n 'createComposable: no component context available. Pass a context explicitly or call inside a render function.',\n );\n }\n\n const prev = currentComponentContext;\n setCurrentComponentContext(targetCtx);\n try {\n return fn();\n } finally {\n // Restore the previous context (supports nested composables)\n if (prev) {\n setCurrentComponentContext(prev);\n } else {\n clearCurrentComponentContext();\n }\n }\n };\n}\n\n/**\n * Expose a public interface from the current component so that parent\n * components holding a template ref to this element can call its methods\n * or read its properties. Must be called during component render.\n *\n * @example\n * ```ts\n * component('my-counter', () => {\n * const count = ref(0);\n * useExpose({ increment: () => count.value++, get count() { return count.value; } });\n * return html`<div>${count.value}</div>`;\n * });\n *\n * // Parent: counterRef.value.increment()\n * ```\n */\nexport function useExpose<T extends Record<string, unknown>>(exposed: T): void {\n if (!currentComponentContext) {\n throw new Error('useExpose must be called during component render');\n }\n\n // During discovery render, skip — no real host to expose properties on\n if (_isDiscoveryRenderFn()) return;\n\n ensureHookCallbacks(currentComponentContext);\n const hooks = currentComponentContext._hookCallbacks as InternalHookCallbacks;\n hooks.expose = { ...(hooks.expose ?? {}), ...exposed };\n\n // Apply exposed properties onto the host element immediately if available\n const host = (currentComponentContext as { _host?: HTMLElement })._host;\n if (host) {\n for (const [key, value] of Object.entries(exposed)) {\n try {\n (host as unknown as Record<string, unknown>)[key] = value;\n } catch {\n // ignore non-writable properties\n }\n }\n }\n}\n\n/**\n * Access named slots provided to the current component. Returns helpers to\n * check slot presence and retrieve slotted elements. Must be called during\n * component render.\n *\n * @example\n * ```ts\n * component('my-card', () => {\n * const slots = useSlots();\n * return html`\n * <div class=\"card\">\n * <slot></slot>\n * ${slots.has('footer') ? html`<footer><slot name=\"footer\"></slot></footer>` : ''}\n * </div>\n * `;\n * });\n * ```\n */\nexport function useSlots(): {\n has(name?: string): boolean;\n getNodes(name?: string): Element[];\n names(): string[];\n} {\n if (!currentComponentContext) {\n throw new Error('useSlots must be called during component render');\n }\n\n // During discovery render, return empty no-op slot object\n if (_isDiscoveryRenderFn()) {\n return { has: () => false, getNodes: () => [], names: () => [] };\n }\n\n const host = (currentComponentContext as { _host?: HTMLElement })._host;\n\n // Single-pass collection: group children by slot name once, reuse for all methods.\n const getSlotMap = (): Map<string, Element[]> => {\n const map = new Map<string, Element[]>();\n if (!host) return map;\n for (const child of host.children) {\n const key = child.getAttribute('slot') ?? 'default';\n const bucket = map.get(key);\n if (bucket) {\n bucket.push(child);\n } else {\n map.set(key, [child]);\n }\n }\n return map;\n };\n\n return {\n /**\n * Returns true if the named slot (or the default slot when name is\n * omitted) has at least one slotted child element.\n */\n has(name?: string): boolean {\n if (!host) return false;\n const slotName = !name || name === 'default' ? 'default' : name;\n const bucket = getSlotMap().get(slotName);\n return bucket !== undefined && bucket.length > 0;\n },\n /**\n * Returns all child elements assigned to the named slot (or the default\n * slot when name is omitted).\n */\n getNodes(name?: string): Element[] {\n if (!host) return [];\n const slotName = !name || name === 'default' ? 'default' : name;\n return getSlotMap().get(slotName) ?? [];\n },\n /** Returns the names of all slots that have content, including 'default'. */\n names(): string[] {\n if (!host) return [];\n return Array.from(getSlotMap().keys());\n },\n };\n}\n\n/**\n * A writable ref that reads from a component prop and emits `update:<propName>`\n * when its value is set, enabling two-way binding with a parent's `:model` or\n * `:model:<propName>` directive.\n *\n * Also recognised by the vdom `:model` directive as a reactive value so it can\n * be passed directly to native inputs inside the child template.\n */\nexport interface ModelRef<T> {\n /** The current prop value. Reactive — reads trigger re-renders. */\n value: T;\n}\n\n/**\n * Define a two-way binding model for a component prop, similar to Vue's\n * `defineModel()`. It combines `useProps` + `useEmit` into a single ergonomic\n * API so child components don't need to wire the plumbing manually.\n *\n * The returned `ModelRef` object:\n * - **reads** `.value` → returns the current prop value (reactive)\n * - **writes** `.value = x` → emits `update:<propName>` so the parent's\n * `:model` / `:model:<propName>` directive can update its reactive state\n *\n * The object is also recognised by the vdom `:model` directive, so you can\n * pass it directly to a native input's `:model` binding inside the child\n * template and the two-way sync is wired up automatically.\n *\n * @example\n * ```ts\n * // Default model — maps to the parent's :model=\"...\"\n * component('my-input', () => {\n * const model = defineModel('');\n *\n * return html`\n * <input :model=\"${model}\" />\n * `;\n * });\n *\n * // Named model — maps to the parent's :model:title=\"...\"\n * component('my-field', () => {\n * const title = defineModel('title', '');\n * const count = defineModel('count', 0);\n *\n * return html`\n * <input :model=\"${title}\" />\n * <input type=\"number\" :model=\"${count}\" />\n * `;\n * });\n * ```\n *\n * @param args - Either:\n * - No arguments → `modelValue` prop, no default.\n * - One argument → treated as the **default value** for the `modelValue` prop;\n * type is inferred from the value.\n * - Two arguments → first is the **prop name**, second is the **default value**;\n * type is inferred from the default value.\n */\nexport function defineModel<T = unknown>(): ModelRef<T | undefined>;\nexport function defineModel<T>(defaultValue: T): ModelRef<T>;\nexport function defineModel<T>(propName: string, defaultValue: T): ModelRef<T>;\nexport function defineModel<T = unknown>(\n ...args: [] | [T] | [string, T]\n): ModelRef<T | undefined> {\n if (!currentComponentContext) {\n throw new Error('defineModel must be called during component render');\n }\n\n const propName = args.length === 2 ? (args[0] as string) : 'modelValue';\n const initialDefault =\n args.length === 2\n ? (args[1] as T)\n : args.length === 1\n ? (args[0] as T)\n : undefined;\n\n // Register the prop so the runtime discovers it during the discovery render\n // and includes it in the component's observed attributes / prop definitions.\n const props = useProps({\n [propName]: initialDefault,\n } as Record<string, unknown>);\n\n // Capture the emit function once — during a discovery render this is a no-op.\n const isDiscovery = _isDiscoveryRenderFn();\n const emitFn = isDiscovery\n ? null\n : (() => {\n const candidate = (currentComponentContext as { emit?: unknown }).emit;\n if (typeof candidate !== 'function') return null;\n return candidate as (\n eventName: string,\n detail?: unknown,\n options?: CustomEventInit,\n ) => boolean;\n })();\n\n // The model ref is marked with the ReactiveState symbol so that\n // processModelDirective treats it as a reactive value and wires up\n // `:model` on native inputs inside the child template correctly.\n const modelRef: ModelRef<T> = {\n get value(): T {\n return props[propName] as T;\n },\n set value(newValue: T) {\n if (emitFn) {\n emitFn(`update:${propName}`, newValue);\n }\n },\n };\n\n try {\n const key = Symbol.for('@cer/ReactiveState');\n Object.defineProperty(modelRef, key, {\n value: true,\n enumerable: false,\n configurable: false,\n });\n } catch {\n // ignore exotic runtimes\n }\n\n return modelRef;\n}\n"],"mappings":";;;;AAiCA,IAAI,IAA4C;AAGhD,SAAgB,IAAsC;AACpD,KAAI,MAA6B,KAC/B,OAAU,MACR,wMAGD;AAEH,KAA2B,EAAE;;AAI/B,SAAgB,IAAwC;CACtD,IAAM,IAAY,KAA4B,EAAE;AAEhD,QADA,IAA2B,MACpB;;AAOT,SAAgB,EAAyB,GAAsB;AAO7D,QANI,MAA6B,OAM1B,MALD,KAAO,CAAC,EAAyB,SAAS,EAAI,IAChD,EAAyB,KAAK,EAAI,EAE7B;;AAiCX,IAAI,IAAoB;AAExB,SAAgB,EACd,GACA,GACA,IAAM,WACN,GACiB;CAEjB,IAAM,IAA0C,EAAE;AAClD,MAAK,IAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,KAAS,EAAE,CAAC,CAC9C,GAAe,EAAQ,EAAE,IAAI;CAI/B,IAAM,IAAW;EACf,aAAa,GAA6B;GACxC,IAAM,IAAQ,EAAQ,EAAK;AAC3B,OACE,EAAe,OAAW,KAAA,KAC1B,EAAe,OAAW,KAE1B,QAAO,OAAO,EAAe,GAAO;GAEtC,IAAM,KAAO,KAAS,EAAE,EAAE;AAC1B,UAAO,KAA6B,OAAqB,OAAd,OAAO,EAAI;;EAExD,aAAa,GAAuB;AAClC,UAAO,KAAK,aAAa,EAAK,KAAK;;EAGrC,YAAY;EACZ,SAAS;EACT,eAAe;EAChB,EAIK,IAAsC;EAC1C,GAAG;EAKH,cAAc,WAAW,OAAO,KAAK,EAAe,CAAC,KAAK,IAAI,IAAI,OAAO,GAAG,EAAE;EAC9E,qBAAqB,KAAA;EACrB,sBAAsB,KAAA;EACtB,YAAY;EACZ,MAAM,EAAE;EACT;AA2BD,CAxBA,OAAO,eAAe,GAAY,SAAS;EACzC,OAAO;EACP,UAAU;EACV,YAAY;EACZ,cAAc;EACf,CAAC,EAME,MAAc,KAAA,KAChB,OAAO,eAAe,GAAY,WAAW;EAC3C,OAAO;EACP,UAAU;EACV,YAAY;EACZ,cAAc;EACf,CAAC,EAOJ,EAA2B,EAAW;CAEtC,IAAI,IAAsC,MACtC;AACJ,KAAI;EACF,IAAM,IAAS,EAAO,OACpB,EACD;AAID,EAAI,aAAkB,UACpB,IAAe,IAEf,IAAc;UAET,GAAK;AAGZ,IACE,oBAAoB,EAAI,kEAExB,EACD;WACO;AAGR,KAA8B;;CAGhC,IAAM,IAAc,OACjB,EAA2C,kBAAkB,GAC/D;AAED,QAAO;EAAE;EAAa;EAAa;EAAc;;;;ACrLnD,SAAgB,IAA6B;AAC3C,QAAO,GAAsB;;AAsB/B,IAAI,IAA2D,MAGzD,IAAe,OAAO,eAAe;AAM3C,SAAgB,EACd,GACM;AACN,KAA0B;;AAO5B,SAAgB,IAAqC;AACnD,KAA0B;;AAc5B,SAAgB,IAA6D;AAC3E,QAAO;;AAqBT,SAAgB,IAIH;AACX,KAAI,CAAC,EACH,OAAU,MAAM,iDAAiD;AAInE,KAAI,GAAsB,CACxB,cAAa;CAIf,IAAM,IAAiB,EAA+C;AACtE,KAAI,OAAO,KAAkB,WAC3B,OAAU,MACR,6DACD;CAEH,IAAM,IAAS;AAMf,SAAQ,GAAmB,GAAkB,MACpC,EAAO,GAAW,GAAQ,EAAQ;;AAQ7C,SAAS,EAAoB,GAAwC;AACnE,CAAK,EAAQ,kBACX,OAAO,eAAe,GAAS,kBAAkB;EAC/C,OAAO,EAAE;EACT,UAAU;EACV,YAAY;EACZ,cAAc;EACf,CAAC;;AAkBN,SAAgB,EAAe,GAA4B;AACzD,KAAI,CAAC,EACH,OAAU,MAAM,wDAAwD;AAK1E,KAAI,GAAsB,CAAE;AAE5B,GAAoB,EAAoD;CACxE,IAAM,IAAQ,EAAwB;AAEtC,CADA,AAAwB,EAAM,gBAAc,EAAE,EAC9C,EAAM,YAAY,KAAK,EAAS;;AAiBlC,SAAgB,EAAkB,GAA4B;AAC5D,KAAI,CAAC,EACH,OAAU,MAAM,2DAA2D;AAI7E,KAAI,GAAsB,CAAE;AAE5B,GAAoB,EAAoD;CACxE,IAAM,IAAQ,EAAwB;AAEtC,CADA,AAA2B,EAAM,mBAAiB,EAAE,EACpD,EAAM,eAAe,KAAK,EAAS;;AAiBrC,SAAgB,EACd,GAKM;AACN,KAAI,CAAC,EACH,OAAU,MACR,+DACD;AAIH,KAAI,GAAsB,CAAE;AAE5B,GAAoB,EAAoD;CACxE,IAAM,IAAQ,EAAwB;AAEtC,CADA,AAA+B,EAAM,uBAAqB,EAAE,EAC5D,EAAM,mBAAmB,KAAK,EAAS;;AAiBzC,SAAgB,EAAW,GAAwC;AACjE,KAAI,CAAC,EACH,OAAU,MAAM,oDAAoD;AAItE,KAAI,GAAsB,CAAE;AAE5B,GAAoB,EAAoD;CACxE,IAAM,IAAQ,EAAwB;AAItC,CAHA,AAAoB,EAAM,YAAU,EAAE,EAGtC,EAAM,QAAQ,MAAM,MAAiB;AACnC,MAAI;AACF,GAAI,aAAe,QAAO,EAAS,EAAI,GAClC,EAAa,MAAM,OAAO,EAAI,CAAC,CAAC;WAC9B,GAAY;AACnB,KAAS,6DAA6D,EAAW;;GAEnF;;AAgBJ,SAAgB,EAA4C,GAAgB;AAC1E,KAAI,CAAC,EACH,OAAU,MAAM,kDAAkD;AAGpE,GAAoB,EAAoD;CACxE,IAAM,IAAQ,EAAwB;AACtC,GAAM,QAAQ;EACZ,GAAI,EAAM,SAAS,EAAE;EACrB,GAAG;EACJ;CAED,IAAM,IAAM;AAGZ,KAAI;EACF,IAAM,IAAe,OAAO,KAAK,KAAY,EAAE,CAAC;AAChD,OAAK,IAAM,KAAO,GAAc;AAC9B,OAAI,OAAO,KAAQ,YAAY,EAAI,WAAW,IAAI,CAAE;GACpD,IAAM,IAAW,OAAO,yBAAyB,GAAK,EAAI;AAEtD,cAAY,CAAC,EAAS,cAC1B,KAAI;IAIF,IAAI,IADW,OAAO,UAAU,eAAe,KAAK,GAAK,EAAI,GAExD,EAAgC,KACjC,KAAA;AAEJ,WAAO,eAAe,GAAK,GAAK;KAC9B,cAAc;KACd,YAAY;KACZ,MAAM;AACJ,UAAI;OACF,IAAM,IAAQ,KAAQ,EAAgC;AAGtD,WAAI,GAAM;QAER,IAAM,IAAW,EAAQ,EAAI,EACvB,IAAY,EAAK,aAAa,EAAS;AAC7C,YAAI,MAAc,MAAM;SACtB,IAAM,IAAc,OAAO,EAAS;AAQpC,gBAPI,MAAgB,YAEX,MAAc,MAAM,MAAc,SAEvC,MAAgB,WACX,OAAO,EAAU,GAEnB;;AAIT,YACU,EAA4C,OACpD,QACA;SACA,IAAM,IAAY,EAChB;AASF,aAHI,EAAgB,EAAS,IAI3B,KACA,OAAO,KAAa,YACpB,WAAW,KACX,EAAE,OAAO,OAAS,OAAe,aAAoB,MAErD,QAAQ,EAAiC;SAO3C,IAAM,IAAc,OAAO,EAAS;AACpC,aACE,QAAgB,YAChB,KACA,OAAO,KAAa,UAWpB,QALE,MAAgB,aAChB,OAAO,KAAa,WAEb,MAAa,MAAM,MAAa,SAElC;;;cAIP;AAGR,aAAO;;KAET,IAAI,GAAY;AAEd,UAAa;;KAEhB,CAAC;WACI;;SAIJ;AAiKR,QA1Je,IAAI,MAAM,EAAE,EAA6B;EACtD,IAAI,GAAS,GAAc;AACzB,OAAI,OAAO,KAAS,SAAU;GAC9B,IAAM,IAAO,EAAqC;AAKlD,OAAI;IACF,IAAM,IAAQ,KAAQ,EAAgC;AAGtD,QAAI,GAAM;AAER,SACG,OAAO,cAAgB,OAAe,aAAgB,eACtD,OAAQ,EACN,gBAAiB,cAClB,OAAQ,EACL,gBAAiB,YACtB;MACA,IAAM,IAAW,EAAK,QAAQ,YAAY,MAAM,CAAC,aAAa,EACxD,IACJ,EACA,aAAa,EAAS;AACxB,UAAI,MAAc,KAQhB,QANI,OAAO,KAAQ,YACV,MAAc,MAAM,MAAc,SAEvC,OAAO,KAAQ,WACV,OAAO,EAAU,GAEnB;;KAKX,IAAM,IAAa,EAA4C;AAG/D,SAAW,MAAc,UAAe,MAAc,IAAI;MAOxD,IAAM,IACJ,KACA,OAAO,KAAc,YACrB,WAAW,KACX,EAAE,OAAO,OAAS,OAAe,aAAqB;AACxD,UACE,SAAO,KAAQ,YACf,KACA,OAAO,KAAc,YACrB,CAAC,KACD,CAAC,EAAgB,EAAU,EAoC3B,QA7BE,OAAO,KAAQ,aACf,MAAQ,MACR,MAAc,KAEP,IAML,EAAgB,EAAU,IAG1B,IACM,EAAiC,QAMvC,OAAO,KAAQ,aAAa,OAAO,KAAc,WAC5C,MAAc,MAAM,MAAc,SAGzC,OAAO,KAAQ,YACf,OAAO,KAAc,YACrB,CAAC,OAAO,MAAM,OAAO,EAAU,CAAC,GAEzB,OAAO,EAAU,GACnB;;;WAIP;GAKR,IAAM,IAAM,EAAI;AAoChB,UAjCI,OAAO,KAAQ,aAAa,MAAQ,KAClC,MAAQ,KAEH,IAGF,KAOL,EAAgB,EAAI,IAEtB,KACA,OAAO,KAAQ,YACf,WAAW,KACX,EAAE,OAAO,OAAS,OAAe,aAAe,QAExC,EAA2B,QACjC,KAAO,QAAQ,MAAQ,KACrB,OAAO,KAAQ,aAAa,OAAO,KAAQ,WACtC,MAAQ,SAGf,OAAO,KAAQ,YACf,OAAO,KAAQ,YACf,CAAC,OAAO,MAAM,OAAO,EAAI,CAAC,GAEnB,OAAO,EAAI,GACb,IAEF;;EAET,IAAI,GAAS,GAAc;AACzB,UAAO,OAAO,KAAS,aAAa,KAAQ,KAAO,KAAQ;;EAE7D,UAAU;AACR,UAAO,MAAM,KACX,IAAI,IAAI,CAAC,GAAG,OAAO,KAAK,EAAS,EAAE,GAAG,OAAO,KAAK,KAAO,EAAE,CAAC,CAAC,CAAC,CAC/D;;EAEH,2BAA2B;AACzB,UAAO;IAAE,cAAc;IAAM,YAAY;IAAM;;EAElD,CAAC;;AAsCJ,SAAgB,EAAS,GAA8B;AACrD,KAAI,CAAC,EACH,OAAU,MAAM,kDAAkD;AAIhE,SAAsB,EAE1B;IAAoB,EAAwB;AAI5C,MAAI;GACF,IAAM,IAAgB,GAAU;AAGhC,UAAO,eAAe,GAAyB,kBAAkB;IAC/D,OAAO;IACP,UAAU;IACV,YAAY;IACZ,cAAc;IACf,CAAC;WACK,GAAO;AAEd,GADA,EAAQ,+BAA+B,EAAM,EAC7C,OAAO,eAAe,GAAyB,kBAAkB;IAC/D,OAAO;IACP,UAAU;IACV,YAAY;IACZ,cAAc;IACf,CAAC;;;;AASN,IAAM,oBAAqB,IAAI,KAA4B;AA2B3D,SAAgB,EAAe,GAAkC;CAC/D,IAAI;AACJ,KAAI;AACF,MAAM,GAAc;SACd;AACN;;AAUF,KAFI,EAAyB,EAAI,IAE7B,OAAO,WAAa,OAAe,OAAO,gBAAkB,IAE9D;AAEF,GACE,oHAED;CACD,IAAM,IAAQ,EAAU,EAAY,EAAK,CAAC;AACtC,QAAC,KAAS,EAAmB,IAAI,EAAM,EAC3C,KAAI;EACF,IAAM,IAAQ,IAAI,eAAe;AAGjC,EAFA,EAAM,YAAY,EAAM,EACxB,SAAS,qBAAqB,CAAC,GAAG,SAAS,oBAAoB,EAAM,EACrE,EAAmB,IAAI,GAAO,EAAM;SAC9B;EAEN,IAAM,IAAK,SAAS,cAAc,QAAQ;AAE1C,EADA,EAAG,cAAc,IAChB,SAAS,QAAQ,SAAS,iBAAiB,YAAY,EAAG;;;AAsD/D,SAAgB,EAAgB,GAA4B;AAC1D,KAAI,CAAC,EACH,OAAU,MAAM,yDAAyD;AAG3E,KAAI,GAAsB,CAAE;CAE5B,IAAM,IAAyB,EAAE,EAC3B,IAA2C;EAC/C,SAAS;EACT,WAAW;EACX,SAAS;EACT,SAAS;EACT,MAAM;EACN,SAAS;EACT,OAAO;EACR,EACK,IAAkC;EACtC,UAAU;EACV,WAAW;EACX,UAAU;EACX;AAED,MAAK,IAAM,CAAC,GAAK,MAAU,OAAO,QAAQ,EAAO,CAC3C,OAAU,KAAA,MACV,KAAO,IACT,EAAa,KAAK,GAAG,EAAiB,GAAK,GAAG,IAAQ,GAC7C,KAAO,IAChB,EAAa,KAAK,GAAG,EAAQ,GAAK,GAAG,IAAQ,GACpC,EAAI,WAAW,KAAK,IAC7B,EAAa,KAAK,GAAG,EAAI,GAAG,IAAQ;AAIxC,KAAI,EAAa,WAAW,EAAG;CAE/B,IAAM,IAAU,SAAS,EAAa,KAAK,IAAI,CAAC,IAI1C,IADM,EACS,kBAAkB,IACjC,IAAW,IAAW,GAAG,EAAS,IAAI,MAAY;AAExD,QAAO,eAAe,GAAyB,kBAAkB;EAC/D,OAAO;EACP,UAAU;EACV,YAAY;EACZ,cAAc;EACf,CAAC;;AAiBJ,SAAgB,EAAW,GAAsB,GAAgB;AAC/D,KAAI,CAAC,EACH,OAAU,MAAM,iDAAiD;AAInE,KAAI,GAAsB,CAAE;CAE5B,IAAM,IAAM;AASX,CARI,EAAI,MACP,OAAO,eAAe,GAAK,GAAc;EACvC,uBAAO,IAAI,KAA+B;EAC1C,UAAU;EACV,YAAY;EACZ,cAAc;EACf,CAAC,EAEH,EAAI,GAAgD,IAAI,GAAK,EAAM;;AAiBtE,SAAgB,EACd,GACA,GACe;AACf,KAAI,CAAC,EACH,OAAU,MAAM,gDAAgD;AAKlE,KAAI,GAAsB,CAAE,QAAO;AAEnC,KAAI;EACF,IAAM,IAAQ,EAAoD;AAClE,MAAI,GAAM;GACR,IAAI,IAAoB,EAAK;AAC7B,GAAW,MAAO,EAAK,aAAa;GAIpC,IAAI,IAAQ;AAGZ,UAAO,KAAQ,IAAQ,IAErB,KADA,KACI,OAAO,aAAe,OAAe,aAAgB,YAAY;IACnE,IAAM,IAAa,EAAK,MAClB,IACJ,EAGA;AACF,QAAI,GAAS;KACX,IAAM,IAAW,EAAQ;AAGzB,SAAI,GAAU,IAAI,EAAI,CACpB,QAAO,EAAS,IAAI,EAAI;;AAK5B,QADA,IAD0B,EAAW,cACrB,EAAW,aAAa,EACpC,MAAS,YAAY,MAAS,EAAY;UACzC;AAGL,QAAI,OAAO,UAAY,OAAe,aAAgB,SAAS;KAC7D,IAAM,IACJ,EAGA;AACF,SAAI,GAAO;MACT,IAAM,IAAW,EAAM;AAGvB,UAAI,GAAU,IAAI,EAAI,CACpB,QAAO,EAAS,IAAI,EAAI;;;IAI9B,IAAM,IAAW;AAKjB,QAHA,IAD2B,EAAc,cACxB,EAAc,eAAe,EAG1C,MAAS,YAAY,MAAS,EAAU;;;SAI5C;AAIR,QAAO;;AAsCT,SAAgB,EACd,GACsC;AACtC,SAAQ,MAAkC;EACxC,IAAM,IAAY,KAAO;AACzB,MAAI,CAAC,EACH,OAAU,MACR,gHACD;EAGH,IAAM,IAAO;AACb,IAA2B,EAAU;AACrC,MAAI;AACF,UAAO,GAAI;YACH;AAER,GAAI,IACF,EAA2B,EAAK,GAEhC,GAA8B;;;;AAsBtC,SAAgB,EAA6C,GAAkB;AAC7E,KAAI,CAAC,EACH,OAAU,MAAM,mDAAmD;AAIrE,KAAI,GAAsB,CAAE;AAE5B,GAAoB,EAAwB;CAC5C,IAAM,IAAQ,EAAwB;AACtC,GAAM,SAAS;EAAE,GAAI,EAAM,UAAU,EAAE;EAAG,GAAG;EAAS;CAGtD,IAAM,IAAQ,EAAoD;AAClE,KAAI,EACF,MAAK,IAAM,CAAC,GAAK,MAAU,OAAO,QAAQ,EAAQ,CAChD,KAAI;AACD,IAA4C,KAAO;SAC9C;;AAyBd,SAAgB,IAId;AACA,KAAI,CAAC,EACH,OAAU,MAAM,kDAAkD;AAIpE,KAAI,GAAsB,CACxB,QAAO;EAAE,WAAW;EAAO,gBAAgB,EAAE;EAAE,aAAa,EAAE;EAAE;CAGlE,IAAM,IAAQ,EAAoD,OAG5D,UAA2C;EAC/C,IAAM,oBAAM,IAAI,KAAwB;AACxC,MAAI,CAAC,EAAM,QAAO;AAClB,OAAK,IAAM,KAAS,EAAK,UAAU;GACjC,IAAM,IAAM,EAAM,aAAa,OAAO,IAAI,WACpC,IAAS,EAAI,IAAI,EAAI;AAC3B,GAAI,IACF,EAAO,KAAK,EAAM,GAElB,EAAI,IAAI,GAAK,CAAC,EAAM,CAAC;;AAGzB,SAAO;;AAGT,QAAO;EAKL,IAAI,GAAwB;AAC1B,OAAI,CAAC,EAAM,QAAO;GAClB,IAAM,IAAW,CAAC,KAAQ,MAAS,YAAY,YAAY,GACrD,IAAS,GAAY,CAAC,IAAI,EAAS;AACzC,UAAO,MAAW,KAAA,KAAa,EAAO,SAAS;;EAMjD,SAAS,GAA0B;AACjC,OAAI,CAAC,EAAM,QAAO,EAAE;GACpB,IAAM,IAAW,CAAC,KAAQ,MAAS,YAAY,YAAY;AAC3D,UAAO,GAAY,CAAC,IAAI,EAAS,IAAI,EAAE;;EAGzC,QAAkB;AAEhB,UADK,IACE,MAAM,KAAK,GAAY,CAAC,MAAM,CAAC,GADpB,EAAE;;EAGvB;;AA+DH,SAAgB,EACd,GAAG,GACsB;AACzB,KAAI,CAAC,EACH,OAAU,MAAM,qDAAqD;CAGvE,IAAM,IAAW,EAAK,WAAW,IAAK,EAAK,KAAgB,cACrD,IACJ,EAAK,WAAW,IACX,EAAK,KACN,EAAK,WAAW,IACb,EAAK,KACN,KAAA,GAIF,IAAQ,EAAS,GACpB,IAAW,GACb,CAA4B,EAIvB,IADc,GAAsB,GAEtC,cACO;EACL,IAAM,IAAa,EAA+C;AAElE,SADI,OAAO,KAAc,aAClB,IADqC;KAM1C,EAKF,IAAwB;EAC5B,IAAI,QAAW;AACb,UAAO,EAAM;;EAEf,IAAI,MAAM,GAAa;AACrB,GAAI,KACF,EAAO,UAAU,KAAY,EAAS;;EAG3C;AAED,KAAI;AAEF,SAAO,eAAe,GADV,OAAO,IAAI,qBAAqB,EACP;GACnC,OAAO;GACP,YAAY;GACZ,cAAc;GACf,CAAC;SACI;AAIR,QAAO"}
@@ -0,0 +1,2 @@
1
+ const e=require(`./logger-Dkht1dCX.cjs`),t=require(`./helpers-DcEpRwq5.cjs`),n=require(`./css-utils-CFeP8SK1.cjs`);var r=null;function i(){if(r!==null)throw Error(`[CER] Concurrent SSR render detected: beginSSRGlobalStyleCollection() called while a collection is already active. For concurrent request handling, use worker threads or multiple Node.js processes.`);r=[]}function a(){let e=r??[];return r=null,e}function o(e){return r===null?!1:(e&&!r.includes(e)&&r.push(e),!0)}var s=0;function c(n,r,i=`unknown`,a){let o={};for(let[e,n]of Object.entries(r??{}))o[t.f(e)]=n;let c={getAttribute(e){let n=t.f(e);if(o[n]!==void 0&&o[n]!==null)return String(o[n]);let i=(r??{})[e];return i==null?null:String(i)},hasAttribute(e){return this.getAttribute(e)!==null},shadowRoot:null,tagName:``,parentElement:null},l={...o,_componentId:`cer-ssr-${Object.keys(o).join(`-`)||`root`}-${++s}`,requestRender:()=>void 0,_requestRender:()=>void 0,emit:()=>!0,refs:{}};Object.defineProperty(l,`_host`,{value:c,writable:!0,enumerable:!1,configurable:!0}),a!==void 0&&Object.defineProperty(l,`_router`,{value:a,writable:!1,enumerable:!1,configurable:!0}),f(l);let u=null,d;try{let e=n.render(l);e instanceof Promise?d=e:u=e}catch(t){e.r(`[SSR] Component "${i}" threw during SSR render. The shadow DOM will be empty. Error:`,t)}finally{p()}let m=String(l._computedStyle??``);return{shadowVNode:u,useStyleCSS:m,asyncPromise:d}}function l(){return t.w()}var u=null,d=Symbol(`cer:provides`);function f(e){u=e}function p(){u=null}function m(){return u}function h(){if(!u)throw Error(`useEmit must be called during component render`);if(t.w())return()=>!1;let e=u.emit;if(typeof e!=`function`)throw Error(`useEmit requires an emit function on the component context`);let n=e;return(e,t,r)=>n(e,t,r)}function g(e){e._hookCallbacks||Object.defineProperty(e,`_hookCallbacks`,{value:{},writable:!0,enumerable:!1,configurable:!0})}function _(e){if(!u)throw Error(`useOnConnected must be called during component render`);if(t.w())return;g(u);let n=u._hookCallbacks;n.onConnected||=[],n.onConnected.push(e)}function v(e){if(!u)throw Error(`useOnDisconnected must be called during component render`);if(t.w())return;g(u);let n=u._hookCallbacks;n.onDisconnected||=[],n.onDisconnected.push(e)}function y(e){if(!u)throw Error(`useOnAttributeChanged must be called during component render`);if(t.w())return;g(u);let n=u._hookCallbacks;n.onAttributeChanged||=[],n.onAttributeChanged.push(e)}function b(n){if(!u)throw Error(`useOnError must be called during component render`);if(t.w())return;g(u);let r=u._hookCallbacks;r.onError||=[],r.onError.push(t=>{try{t instanceof Error?n(t):n(Error(String(t)))}catch(t){e.t(`[useOnError] The error handler itself threw an exception:`,t)}})}function x(e){if(!u)throw Error(`useProps must be called during component render`);g(u);let n=u._hookCallbacks;n.props={...n.props||{},...e};let r=u;try{let n=Object.keys(e||{});for(let i of n){if(typeof i!=`string`||i.startsWith(`_`))continue;let n=Object.getOwnPropertyDescriptor(r,i);if(!(n&&!n.configurable))try{let n=Object.prototype.hasOwnProperty.call(r,i)?r[i]:void 0;Object.defineProperty(r,i,{configurable:!0,enumerable:!0,get(){try{let n=r&&r._host;if(n){let r=t.p(i),a=n.getAttribute(r);if(a!==null){let t=typeof e[i];return t===`boolean`?a===``||a===`true`:t===`number`?Number(a):a}if(n[i]!==void 0){let r=n[i];if(t._(r)||r&&typeof r==`object`&&`value`in r&&!(typeof Node<`u`&&r instanceof Node))return r.value;let a=typeof e[i];if(!(a===`string`&&r&&typeof r==`object`))return a===`boolean`&&typeof r==`string`?r===``||r===`true`:r}}}catch{}return n},set(e){n=e}})}catch{}}}catch{}return new Proxy({},{get(n,i){if(typeof i!=`string`)return;let a=e[i];try{let e=r&&r._host;if(e){if(typeof HTMLElement<`u`&&e instanceof HTMLElement||typeof e.getAttribute==`function`&&typeof e.hasAttribute==`function`){let t=i.replace(/([A-Z])/g,`-$1`).toLowerCase(),n=e.getAttribute(t);if(n!==null)return typeof a==`boolean`?n===``||n===`true`:typeof a==`number`?Number(n):n}let n=e[i];if(n!==void 0&&n!==``){let e=n&&typeof n==`object`&&`value`in n&&!(typeof Node<`u`&&n instanceof Node);if(!(typeof a==`string`&&n&&typeof n==`object`&&!e&&!t._(n)))return typeof a==`boolean`&&a===!1&&n===``?a:t._(n)||e?n.value:typeof a==`boolean`&&typeof n==`string`?n===``||n===`true`:typeof a==`number`&&typeof n==`string`&&!Number.isNaN(Number(n))?Number(n):n}}}catch{}let o=r[i];return typeof a==`boolean`&&o===``?a===!1?a:!0:t._(o)||o&&typeof o==`object`&&`value`in o&&!(typeof Node<`u`&&o instanceof Node)?o.value:o!=null&&o!==``?typeof a==`boolean`&&typeof o==`string`?o===`true`:typeof a==`number`&&typeof o==`string`&&!Number.isNaN(Number(o))?Number(o):o:a},has(t,n){return typeof n==`string`&&(n in r||n in e)},ownKeys(){return Array.from(new Set([...Object.keys(e),...Object.keys(r||{})]))},getOwnPropertyDescriptor(){return{configurable:!0,enumerable:!0}}})}function S(n){if(!u)throw Error(`useStyle must be called during component render`);if(!t.w()){g(u);try{let e=n();Object.defineProperty(u,`_computedStyle`,{value:e,writable:!0,enumerable:!1,configurable:!0})}catch(t){e.r(`Error in useStyle callback:`,t),Object.defineProperty(u,`_computedStyle`,{value:``,writable:!0,enumerable:!1,configurable:!0})}}}var C=new Map;function w(t){let r;try{r=t()}catch{return}if(o(r)||typeof document>`u`||typeof CSSStyleSheet>`u`)return;e.r(`[useGlobalStyle] Injecting global styles from a component. This escapes Shadow DOM encapsulation — use sparingly.`);let i=n.d(n.f(r));if(!(!i||C.has(i)))try{let e=new CSSStyleSheet;e.replaceSync(i),document.adoptedStyleSheets=[...document.adoptedStyleSheets,e],C.set(i,e)}catch{let e=document.createElement(`style`);e.textContent=i,(document.head??document.documentElement).appendChild(e)}}function T(e){if(!u)throw Error(`useDesignTokens must be called during component render`);if(t.w())return;let n=[],r={primary:`--cer-color-primary-500`,secondary:`--cer-color-secondary-500`,neutral:`--cer-color-neutral-500`,success:`--cer-color-success-500`,info:`--cer-color-info-500`,warning:`--cer-color-warning-500`,error:`--cer-color-error-500`},i={fontSans:`--cer-font-sans`,fontSerif:`--cer-font-serif`,fontMono:`--cer-font-mono`};for(let[t,a]of Object.entries(e))a!==void 0&&(t in r?n.push(`${r[t]}:${a}`):t in i?n.push(`${i[t]}:${a}`):t.startsWith(`--`)&&n.push(`${t}:${a}`));if(n.length===0)return;let a=`:host{${n.join(`;`)}}`,o=u._computedStyle??``,s=o?`${o}\n${a}`:a;Object.defineProperty(u,`_computedStyle`,{value:s,writable:!0,enumerable:!1,configurable:!0})}function E(e,n){if(!u)throw Error(`provide must be called during component render`);if(t.w())return;let r=u;r[d]||Object.defineProperty(r,d,{value:new Map,writable:!1,enumerable:!1,configurable:!0}),r[d].set(e,n)}function D(e,n){if(!u)throw Error(`inject must be called during component render`);if(t.w())return n;try{let t=u._host;if(t){let n=t.parentNode;n||=t.getRootNode();let r=0;for(;n&&r<50;)if(r++,typeof ShadowRoot<`u`&&n instanceof ShadowRoot){let t=n.host,r=t.context;if(r){let t=r[d];if(t?.has(e))return t.get(e)}if(n=t.parentNode??t.getRootNode(),n===document||n===t)break}else{if(typeof Element<`u`&&n instanceof Element){let t=n.context;if(t){let n=t[d];if(n?.has(e))return n.get(e)}}let t=n;if(n=n.parentNode??n.getRootNode?.(),n===document||n===t)break}}}catch{}return n}function O(e){return t=>{let n=t??u;if(!n)throw Error(`createComposable: no component context available. Pass a context explicitly or call inside a render function.`);let r=u;f(n);try{return e()}finally{r?f(r):p()}}}function k(e){if(!u)throw Error(`useExpose must be called during component render`);if(t.w())return;g(u);let n=u._hookCallbacks;n.expose={...n.expose??{},...e};let r=u._host;if(r)for(let[t,n]of Object.entries(e))try{r[t]=n}catch{}}function A(){if(!u)throw Error(`useSlots must be called during component render`);if(t.w())return{has:()=>!1,getNodes:()=>[],names:()=>[]};let e=u._host,n=()=>{let t=new Map;if(!e)return t;for(let n of e.children){let e=n.getAttribute(`slot`)??`default`,r=t.get(e);r?r.push(n):t.set(e,[n])}return t};return{has(t){if(!e)return!1;let r=!t||t===`default`?`default`:t,i=n().get(r);return i!==void 0&&i.length>0},getNodes(t){if(!e)return[];let r=!t||t===`default`?`default`:t;return n().get(r)??[]},names(){return e?Array.from(n().keys()):[]}}}function j(...e){if(!u)throw Error(`defineModel must be called during component render`);let n=e.length===2?e[0]:`modelValue`,r=e.length===2?e[1]:e.length===1?e[0]:void 0,i=x({[n]:r}),a=t.w()?null:(()=>{let e=u.emit;return typeof e==`function`?e:null})(),o={get value(){return i[n]},set value(e){a&&a(`update:${n}`,e)}};try{Object.defineProperty(o,Symbol.for(`@cer/ReactiveState`),{value:!0,enumerable:!1,configurable:!1})}catch{}return o}Object.defineProperty(exports,`S`,{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,`_`,{enumerable:!0,get:function(){return x}}),Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return D}}),Object.defineProperty(exports,`b`,{enumerable:!0,get:function(){return i}}),Object.defineProperty(exports,`c`,{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,`d`,{enumerable:!0,get:function(){return k}}),Object.defineProperty(exports,`f`,{enumerable:!0,get:function(){return w}}),Object.defineProperty(exports,`g`,{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,`h`,{enumerable:!0,get:function(){return v}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return m}}),Object.defineProperty(exports,`l`,{enumerable:!0,get:function(){return T}}),Object.defineProperty(exports,`m`,{enumerable:!0,get:function(){return _}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return O}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,`p`,{enumerable:!0,get:function(){return y}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return j}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return E}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,`u`,{enumerable:!0,get:function(){return h}}),Object.defineProperty(exports,`v`,{enumerable:!0,get:function(){return A}}),Object.defineProperty(exports,`x`,{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,`y`,{enumerable:!0,get:function(){return S}});
2
+ //# sourceMappingURL=hooks-CNfugc95.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks-CNfugc95.cjs","names":[],"sources":["../src/lib/runtime/ssr-context.ts","../src/lib/runtime/hooks.ts"],"sourcesContent":["/**\n * SSR execution context for running component render functions server-side.\n *\n * When generating Declarative Shadow DOM (DSD) output, the SSR renderer must\n * call each custom element's render function to obtain its shadow DOM VNode\n * tree and capture any useStyle() / useGlobalStyle() output. This module\n * provides the minimal execution environment that makes that safe.\n *\n * Guarantees:\n * - useStyle() callbacks are executed and their output is captured.\n * - useGlobalStyle() callbacks are captured (not injected into document).\n * - Lifecycle hooks (useOnConnected, watch, …) register harmlessly to arrays\n * that are never invoked.\n * - The reactive system is never permanently mutated — component registration\n * is cleaned up by the render wrapper in factory.ts after each call.\n */\n\nimport type { ComponentConfig, ComponentContext, VNode } from './types';\nimport { toCamel } from './helpers';\nimport {\n setCurrentComponentContext,\n clearCurrentComponentContext,\n} from './hooks';\nimport { devWarn } from './logger';\n\n// ---------------------------------------------------------------------------\n// Global-style SSR collector\n// ---------------------------------------------------------------------------\n\n/**\n * When set, useGlobalStyle() factories write here instead of touching\n * document.adoptedStyleSheets (which doesn't exist in SSR environments).\n */\nlet _ssrGlobalStyleCollector: string[] | null = null;\n\n/** Start collecting useGlobalStyle() output from the current render pass. */\nexport function beginSSRGlobalStyleCollection(): void {\n if (_ssrGlobalStyleCollector !== null) {\n throw new Error(\n '[CER] Concurrent SSR render detected: beginSSRGlobalStyleCollection() called ' +\n 'while a collection is already active. For concurrent request handling, use ' +\n 'worker threads or multiple Node.js processes.',\n );\n }\n _ssrGlobalStyleCollector = [];\n}\n\n/** Stop collecting and return everything gathered so far. */\nexport function endSSRGlobalStyleCollection(): string[] {\n const collected = _ssrGlobalStyleCollector ?? [];\n _ssrGlobalStyleCollector = null;\n return collected;\n}\n\n/**\n * Called by useGlobalStyle() when an SSR collection pass is active.\n * Returns true if the CSS was captured (caller should skip DOM injection).\n */\nexport function captureGlobalStyleForSSR(css: string): boolean {\n if (_ssrGlobalStyleCollector !== null) {\n if (css && !_ssrGlobalStyleCollector.includes(css)) {\n _ssrGlobalStyleCollector.push(css);\n }\n return true;\n }\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// SSR render pass\n// ---------------------------------------------------------------------------\n\nexport interface SSRRenderResult {\n /** VNode tree from the component's render function (shadow DOM content). */\n shadowVNode: VNode | VNode[] | null;\n /** CSS string captured from useStyle() calls during this render. */\n useStyleCSS: string;\n /** Present when the component's render function returned a Promise. */\n asyncPromise?: Promise<VNode | VNode[]>;\n}\n\n/**\n * Run a component's render function in a minimal SSR context to capture its\n * shadow DOM VNode tree and any useStyle() output.\n *\n * The component's render wrapper in factory.ts handles:\n * - setCurrentComponentContext / clearCurrentComponentContext\n * - _hookCallbacks reset\n * - _computedStyle reset\n * - reactiveSystem registration / cleanup\n *\n * We only need to build a context object that satisfies the hooks' expectations.\n */\n// Monotonic counter ensures each SSR render context gets a unique component ID,\n// preventing the reactive system's stateStorage from returning stale cached\n// ref/computed values from a previous request.\nlet _ssrRenderCounter = 0;\n\nexport function runComponentSSRRender(\n config: ComponentConfig<object, object, object, object>,\n attrs: Record<string, string | number | boolean | null | undefined>,\n tag = 'unknown',\n ssrRouter?: unknown,\n): SSRRenderResult {\n // Build camelCase prop map from serialised attribute names.\n const propsFromAttrs: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(attrs ?? {})) {\n propsFromAttrs[toCamel(k)] = v;\n }\n\n // Fake host element: satisfies useProps()'s attribute reads without a real DOM node.\n const fakeHost = {\n getAttribute(name: string): string | null {\n const camel = toCamel(name);\n if (\n propsFromAttrs[camel] !== undefined &&\n propsFromAttrs[camel] !== null\n ) {\n return String(propsFromAttrs[camel]);\n }\n const raw = (attrs ?? {})[name];\n return raw !== undefined && raw !== null ? String(raw) : null;\n },\n hasAttribute(name: string): boolean {\n return this.getAttribute(name) !== null;\n },\n // shadowRoot must be null so useJITCSS() doesn't try to registerJITCSSComponent\n shadowRoot: null as null,\n tagName: '',\n parentElement: null as null,\n };\n\n // Minimal context object — the factory render wrapper will add _hookCallbacks\n // and _computedStyle via Object.defineProperty before calling renderFn().\n const ssrContext: Record<string, unknown> = {\n ...propsFromAttrs,\n // Unique ID per SSR render prevents the reactive system's stateStorage from\n // returning cached ref/computed values from a previous request. Using a\n // monotonic counter is cheaper than crypto.randomUUID() and avoids the\n // Node.js version compatibility concern noted in the original comment.\n _componentId: `cer-ssr-${Object.keys(propsFromAttrs).join('-') || 'root'}-${++_ssrRenderCounter}`,\n requestRender: () => undefined,\n _requestRender: () => undefined,\n emit: () => true,\n refs: {},\n };\n\n // Set _host as non-enumerable to avoid triggering the reactive proxy trap.\n Object.defineProperty(ssrContext, '_host', {\n value: fakeHost,\n writable: true,\n enumerable: false,\n configurable: true,\n });\n\n // Thread the per-request router instance so router-view (and any component\n // that calls getCurrentComponentContext()._router) reads from the correct\n // router rather than the module-level activeRouterProxy singleton.\n // Non-enumerable keeps it out of prop serialisation / Object.keys iteration.\n if (ssrRouter !== undefined) {\n Object.defineProperty(ssrContext, '_router', {\n value: ssrRouter,\n writable: false,\n enumerable: false,\n configurable: true,\n });\n }\n\n // Pre-set the component context so hooks (useStyle, useProps, etc.) work even\n // when config.render is a raw function rather than the factory.ts wrapper.\n // If config.render IS the factory wrapper, it will call setCurrentComponentContext\n // again with the same object — that is harmless.\n setCurrentComponentContext(ssrContext);\n\n let shadowVNode: VNode | VNode[] | null = null;\n let asyncPromise: Promise<VNode | VNode[]> | undefined;\n try {\n const result = config.render(\n ssrContext as ComponentContext<object, object, object, object>,\n );\n // Async render functions cannot be awaited in the synchronous SSR pass.\n // The DSD renderer will emit a streaming placeholder if active; otherwise\n // the shadow DOM will be empty. The caller emits the appropriate warning.\n if (result instanceof Promise) {\n asyncPromise = result;\n } else {\n shadowVNode = result as VNode | VNode[];\n }\n } catch (err) {\n // Best-effort — a render error during SSR should not crash the server.\n // The component will still get a DSD wrapper, just without shadow content.\n devWarn(\n `[SSR] Component \"${tag}\" threw during SSR render. ` +\n `The shadow DOM will be empty. Error:`,\n err,\n );\n } finally {\n // Clear context. The factory wrapper clears it too, but calling clearCurrentComponentContext()\n // twice (null → null) is harmless and ensures clean state if config.render was a raw function.\n clearCurrentComponentContext();\n }\n\n const useStyleCSS = String(\n (ssrContext as { _computedStyle?: string })._computedStyle ?? '',\n );\n\n return { shadowVNode, useStyleCSS, asyncPromise };\n}\n","/**\n * Context-based hooks for functional components\n * Provides React-like hooks with perfect TypeScript inference\n */\n\nimport { isReactiveState } from './reactive';\nimport { toKebab } from './helpers';\nimport { devWarn, devError } from './logger';\nimport { isDiscoveryRender as _isDiscoveryRenderFn } from './discovery-state';\nimport { sanitizeCSS, minifyCSS } from './css-utils';\nimport type { JITCSSOptions } from './style';\nimport { captureGlobalStyleForSSR } from './ssr-context';\n\n// Re-export JITCSSOptions as a type-only re-export so consumers can still\n// import it from './runtime/hooks' without creating a runtime dependency on style.ts.\nexport type { JITCSSOptions };\n\n// Re-export discovery helpers so consumers continue to use the same import path.\nexport { beginDiscoveryRender, endDiscoveryRender } from './discovery-state';\n\n/**\n * Returns true while a discovery render is in progress.\n * Used by `html` and other primitives to short-circuit side effects.\n * @internal\n */\nexport function isDiscoveryRender(): boolean {\n return _isDiscoveryRenderFn();\n}\n\n// Global state to track current component context during render\n// Narrowed internal type for currentComponentContext to expose _hookCallbacks\ninterface InternalHookCallbacks {\n onConnected?: Array<(context?: unknown) => void>;\n onDisconnected?: Array<(context?: unknown) => void>;\n onAttributeChanged?: Array<\n (name: string, oldValue: string | null, newValue: string | null) => void\n >;\n onError?: Array<(err: unknown) => void>;\n props?: Record<string, unknown>;\n style?: () => string;\n expose?: Record<string, unknown>;\n}\n\ntype InternalComponentContext = Record<string, unknown> & {\n _hookCallbacks?: InternalHookCallbacks;\n _computedStyle?: string;\n};\n\nlet currentComponentContext: InternalComponentContext | null = null;\n\n/** Symbol key used to store provides map on a component's context object. */\nconst PROVIDES_KEY = Symbol('cer:provides');\n\n/**\n * Set the current component context (called internally during render)\n * @internal\n */\nexport function setCurrentComponentContext(\n context: Record<string, unknown>,\n): void {\n currentComponentContext = context;\n}\n\n/**\n * Clear the current component context (called internally after render)\n * @internal\n */\nexport function clearCurrentComponentContext(): void {\n currentComponentContext = null;\n}\n\n// ---------- Discovery render probe ----------\n// The actual state and helpers live in discovery-state.ts to avoid\n// circular dependencies with reactive.ts. The re-exports above forward\n// beginDiscoveryRender / endDiscoveryRender / isDiscoveryRender from that\n// module so all existing import sites remain unchanged.\n\n/**\n * Get the current component context. Useful for advanced composable patterns\n * that need to access or pass the context explicitly.\n * @internal\n */\nexport function getCurrentComponentContext(): Record<string, unknown> | null {\n return currentComponentContext;\n}\n\n/**\n * Get the emit function for the current component\n * Must be called during component render\n *\n * @example\n * ```ts\n * component('my-button', () => {\n * const { label } = useProps({ label: 'Click me' });\n * const emit = useEmit();\n *\n * return html`\n * <button @click=\"${() => emit('button-click', { label })}\">\n * ${label}\n * </button>\n * `;\n * });\n * ```\n */\nexport function useEmit(): (\n eventName: string,\n detail?: unknown,\n options?: CustomEventInit,\n) => boolean {\n if (!currentComponentContext) {\n throw new Error('useEmit must be called during component render');\n }\n\n // During discovery render, return a no-op function — no real host exists.\n if (_isDiscoveryRenderFn()) {\n return () => false;\n }\n\n // Capture and validate the emit function from the current context\n const emitCandidate = (currentComponentContext as { emit?: unknown }).emit;\n if (typeof emitCandidate !== 'function') {\n throw new Error(\n 'useEmit requires an emit function on the component context',\n );\n }\n const emitFn = emitCandidate as (\n eventName: string,\n detail?: unknown,\n options?: CustomEventInit,\n ) => boolean;\n\n return (eventName: string, detail?: unknown, options?: CustomEventInit) => {\n return emitFn(eventName, detail, options);\n };\n}\n\n/**\n * Initialize hook callbacks storage on context if not exists\n * Uses Object.defineProperty to avoid triggering reactive updates\n */\nfunction ensureHookCallbacks(context: Record<string, unknown>): void {\n if (!context._hookCallbacks) {\n Object.defineProperty(context, '_hookCallbacks', {\n value: {},\n writable: true,\n enumerable: false,\n configurable: true,\n });\n }\n}\n\n/**\n * Register a callback to be called when component is connected to DOM\n *\n * @example\n * ```ts\n * component('my-component', () => {\n * useOnConnected(() => {\n * console.log('Component mounted!');\n * });\n *\n * return html`<div>Hello World</div>`;\n * });\n * ```\n */\nexport function useOnConnected(callback: () => void): void {\n if (!currentComponentContext) {\n throw new Error('useOnConnected must be called during component render');\n }\n\n // During discovery render, skip registering lifecycle callbacks — the\n // discoveryContext is ephemeral and its hooks are never invoked.\n if (_isDiscoveryRenderFn()) return;\n\n ensureHookCallbacks(currentComponentContext as InternalComponentContext);\n const hooks = currentComponentContext._hookCallbacks as InternalHookCallbacks;\n if (!hooks.onConnected) hooks.onConnected = [];\n hooks.onConnected.push(callback);\n}\n\n/**\n * Register a callback to be called when component is disconnected from DOM\n *\n * @example\n * ```ts\n * component('my-component', () => {\n * useOnDisconnected(() => {\n * console.log('Component unmounted!');\n * });\n *\n * return html`<div>Goodbye World</div>`;\n * });\n * ```\n */\nexport function useOnDisconnected(callback: () => void): void {\n if (!currentComponentContext) {\n throw new Error('useOnDisconnected must be called during component render');\n }\n\n // During discovery render, skip registering lifecycle callbacks.\n if (_isDiscoveryRenderFn()) return;\n\n ensureHookCallbacks(currentComponentContext as InternalComponentContext);\n const hooks = currentComponentContext._hookCallbacks as InternalHookCallbacks;\n if (!hooks.onDisconnected) hooks.onDisconnected = [];\n hooks.onDisconnected.push(callback);\n}\n\n/**\n * Register a callback to be called when an attribute changes\n *\n * @example\n * ```ts\n * component('my-component', () => {\n * useOnAttributeChanged((name, oldValue, newValue) => {\n * console.log(`Attribute ${name} changed from ${oldValue} to ${newValue}`);\n * });\n *\n * return html`<div>Attribute watcher</div>`;\n * });\n * ```\n */\nexport function useOnAttributeChanged(\n callback: (\n name: string,\n oldValue: string | null,\n newValue: string | null,\n ) => void,\n): void {\n if (!currentComponentContext) {\n throw new Error(\n 'useOnAttributeChanged must be called during component render',\n );\n }\n\n // During discovery render, skip registering lifecycle callbacks.\n if (_isDiscoveryRenderFn()) return;\n\n ensureHookCallbacks(currentComponentContext as InternalComponentContext);\n const hooks = currentComponentContext._hookCallbacks as InternalHookCallbacks;\n if (!hooks.onAttributeChanged) hooks.onAttributeChanged = [];\n hooks.onAttributeChanged.push(callback);\n}\n\n/**\n * Register a callback to be called when an error occurs\n *\n * @example\n * ```ts\n * component('my-component', () => {\n * useOnError((error) => {\n * console.error('Component error:', error);\n * });\n *\n * return html`<div>Error handler</div>`;\n * });\n * ```\n */\nexport function useOnError(callback: (error: Error) => void): void {\n if (!currentComponentContext) {\n throw new Error('useOnError must be called during component render');\n }\n\n // During discovery render, skip registering lifecycle callbacks.\n if (_isDiscoveryRenderFn()) return;\n\n ensureHookCallbacks(currentComponentContext as InternalComponentContext);\n const hooks = currentComponentContext._hookCallbacks as InternalHookCallbacks;\n if (!hooks.onError) hooks.onError = [];\n // Wrap to normalize to Error. If the user's handler itself throws, log it in\n // dev mode so it doesn't vanish silently — the original error is already handled.\n hooks.onError.push((err: unknown) => {\n try {\n if (err instanceof Error) callback(err);\n else callback(new Error(String(err)));\n } catch (handlerErr) {\n devError('[useOnError] The error handler itself threw an exception:', handlerErr);\n }\n });\n}\n\n/**\n * Register prop defaults for the component. Can be called during render.\n * Stores the prop defaults on `context._hookCallbacks.props` so the runtime\n * can pick them up when building the component config.\n *\n * Example:\n * ```ts\n * component('my-comp', () => {\n * useProps({ modelValue: false, label: 'Hello' });\n * return html`<div/>`;\n * });\n * ```\n */\nexport function useProps<T extends Record<string, unknown>>(defaults: T): T {\n if (!currentComponentContext) {\n throw new Error('useProps must be called during component render');\n }\n\n ensureHookCallbacks(currentComponentContext as InternalComponentContext);\n const hooks = currentComponentContext._hookCallbacks as InternalHookCallbacks;\n hooks.props = {\n ...(hooks.props || {}),\n ...defaults,\n };\n\n const ctx = currentComponentContext;\n // Define dynamic getters for declared props so the context property\n // always reflects the host element's property (or reactive ref.value)\n try {\n const declaredKeys = Object.keys(defaults || {});\n for (const key of declaredKeys) {\n if (typeof key !== 'string' || key.startsWith('_')) continue;\n const existing = Object.getOwnPropertyDescriptor(ctx, key);\n // Only define if not present or configurable (allow overriding)\n if (existing && !existing.configurable) continue;\n try {\n // Preserve any existing concrete value on the context in a closure.\n // This avoids recursive getters when we later reference ctx[key].\n const hasOwn = Object.prototype.hasOwnProperty.call(ctx, key);\n let localValue: unknown = hasOwn\n ? (ctx as Record<string, unknown>)[key]\n : undefined;\n\n Object.defineProperty(ctx, key, {\n configurable: true,\n enumerable: true,\n get() {\n try {\n const host = (ctx && (ctx as { _host?: HTMLElement })._host) as\n | HTMLElement\n | undefined;\n if (host) {\n // First, check for attribute value (attributes should take precedence)\n const kebabKey = toKebab(key);\n const attrValue = host.getAttribute(kebabKey);\n if (attrValue !== null) {\n const defaultType = typeof defaults[key];\n if (defaultType === 'boolean') {\n // Standalone boolean attributes have empty string value\n return attrValue === '' || attrValue === 'true';\n }\n if (defaultType === 'number') {\n return Number(attrValue);\n }\n return attrValue;\n }\n\n // If no attribute, check if host has a property value set\n if (\n typeof (host as unknown as Record<string, unknown>)[key] !==\n 'undefined'\n ) {\n const fromHost = (host as unknown as Record<string, unknown>)[\n key\n ];\n // prefer host value when present\n // If the host provided a ReactiveState instance or a wrapper\n // with a .value, unwrap it here so destructured props and\n // useProps return the primitive/current value consistently.\n if (isReactiveState(fromHost)) {\n return (fromHost as { value: unknown }).value;\n }\n if (\n fromHost &&\n typeof fromHost === 'object' &&\n 'value' in fromHost &&\n !(typeof Node !== 'undefined' && fromHost instanceof Node)\n ) {\n return (fromHost as { value?: unknown }).value;\n }\n // For string-typed declared props, avoid returning host\n // object-like properties (for example `element.style` which\n // is a CSSStyleDeclaration). Prefer attribute value or the\n // local default instead of returning a non-primitive host\n // property into templates which expect primitives.\n const defaultType = typeof defaults[key];\n if (\n defaultType === 'string' &&\n fromHost &&\n typeof fromHost === 'object'\n ) {\n // fallthrough to localValue\n } else {\n // For boolean defaults, treat empty string (standalone attribute) or 'true' as true.\n if (\n defaultType === 'boolean' &&\n typeof fromHost === 'string'\n ) {\n return fromHost === '' || fromHost === 'true';\n }\n return fromHost;\n }\n }\n }\n } catch {\n // ignore host read failures and fall back to context\n }\n return localValue;\n },\n set(v: unknown) {\n // allow test/runtime code to set context props during render/init\n localValue = v;\n },\n });\n } catch {\n // ignore\n }\n }\n } catch {\n // ignore\n }\n // Return a Proxy that always reads the latest value from the component\n // context so accesses are reactive. Also unwrap functional refs ({ value })\n // and coerce string attribute values to boolean/number when defaults\n // indicate such types.\n const result = new Proxy({} as Record<string, unknown>, {\n get(_target, prop: string) {\n if (typeof prop !== 'string') return undefined;\n const def = (defaults as Record<string, unknown>)[prop];\n\n // If a host element is available, prefer reading from attributes first,\n // then from properties. This ensures that HTML attributes take precedence\n // over default property values (like the standard \"title\" attribute).\n try {\n const host = (ctx && (ctx as { _host?: HTMLElement })._host) as\n | HTMLElement\n | undefined;\n if (host) {\n // Check attribute first (only if host is an actual HTMLElement)\n if (\n (typeof HTMLElement !== 'undefined' && host instanceof HTMLElement) ||\n (typeof (host as { getAttribute?: (name: string) => string | null })\n .getAttribute === 'function' &&\n typeof (host as { hasAttribute?: (name: string) => boolean })\n .hasAttribute === 'function')\n ) {\n const kebabKey = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\n const attrValue = (\n host as { getAttribute: (name: string) => string | null }\n ).getAttribute(kebabKey);\n if (attrValue !== null) {\n // Attribute exists - convert based on default type\n if (typeof def === 'boolean') {\n return attrValue === '' || attrValue === 'true';\n }\n if (typeof def === 'number') {\n return Number(attrValue);\n }\n return attrValue;\n }\n }\n\n // No attribute - check property value\n const hostValue = (host as unknown as Record<string, unknown>)[prop];\n // Only use host value if it's explicitly set (not undefined AND not empty string for string defaults)\n // Empty strings on standard HTML properties (like 'title') should fall through to defaults\n if (typeof hostValue !== 'undefined' && hostValue !== '') {\n // If the declared default is a string, avoid returning raw DOM\n // object-like properties (such as element.style which is a CSSStyleDeclaration)\n // since templates expect primitives and serializing objects can\n // cause DOMExceptions. However, wrapper-like objects that expose\n // a `.value` property (or ReactiveState instances) should be\n // unwrapped and returned even for string defaults.\n const isWrapperLike =\n hostValue &&\n typeof hostValue === 'object' &&\n 'value' in hostValue &&\n !(typeof Node !== 'undefined' && hostValue instanceof Node);\n if (\n typeof def === 'string' &&\n hostValue &&\n typeof hostValue === 'object' &&\n !isWrapperLike &&\n !isReactiveState(hostValue)\n ) {\n // treat as not present and fall through to ctx/default\n } else {\n // Special handling for boolean props: if default is false and hostValue is empty string,\n // treat it as if the property wasn't set (use default false)\n if (\n typeof def === 'boolean' &&\n def === false &&\n hostValue === ''\n ) {\n return def;\n }\n\n // Unwrap ReactiveState instances and wrapper-like objects coming\n // from the host so useProps mirrors applyProps/destructured props\n // behavior and returns primitive/current values.\n if (isReactiveState(hostValue)) {\n return (hostValue as { value: unknown }).value;\n }\n if (isWrapperLike) {\n return (hostValue as { value: unknown }).value;\n }\n\n // Primitive on host - return directly (but coerce strings if default provided).\n // Use the same rule as the attribute path: empty string (standalone attribute\n // presence) or the literal string 'true' coerce to true; everything else is false.\n if (typeof def === 'boolean' && typeof hostValue === 'string') {\n return hostValue === '' || hostValue === 'true';\n }\n if (\n typeof def === 'number' &&\n typeof hostValue === 'string' &&\n !Number.isNaN(Number(hostValue))\n )\n return Number(hostValue);\n return hostValue;\n }\n }\n }\n } catch {\n // ignore host read failures and fall back to context\n }\n\n // Fall back to reading from the component context itself.\n const raw = ctx[prop];\n // Treat empty-string on context as boolean true (attribute presence)\n // EXCEPT when the default is false - in that case, empty string means \"not set\"\n if (typeof def === 'boolean' && raw === '') {\n if (def === false) {\n // For boolean props with default false, empty string means use the default\n return def;\n }\n // For boolean props with default true, empty string means attribute presence = true\n return true;\n }\n // If the context stores a ReactiveState or wrapper, unwrap it here\n // so components using useProps receive the primitive/current value\n // when the source is the component context itself. Host-provided\n // ReactiveState instances are preserved above; this path is only\n // for ctx values and defaults.\n if (isReactiveState(raw)) return (raw as { value: unknown }).value;\n if (\n raw &&\n typeof raw === 'object' &&\n 'value' in raw &&\n !(typeof Node !== 'undefined' && raw instanceof Node)\n )\n return (raw as { value: unknown }).value;\n if (raw != null && raw !== '') {\n if (typeof def === 'boolean' && typeof raw === 'string') {\n return raw === 'true';\n }\n if (\n typeof def === 'number' &&\n typeof raw === 'string' &&\n !Number.isNaN(Number(raw))\n )\n return Number(raw);\n return raw;\n }\n return def;\n },\n has(_target, prop: string) {\n return typeof prop === 'string' && (prop in ctx || prop in defaults);\n },\n ownKeys() {\n return Array.from(\n new Set([...Object.keys(defaults), ...Object.keys(ctx || {})]),\n );\n },\n getOwnPropertyDescriptor() {\n return { configurable: true, enumerable: true } as PropertyDescriptor;\n },\n });\n\n return result as T;\n}\n\n/**\n * Register prop defaults and return a stable props object for use inside render.\n * The returned object reads values from the current component context at render\n * time and falls back to the provided defaults. This keeps prop access stable\n * in production builds and avoids reliance on parsing the render function.\n *\n * Must be called during render. Example:\n * const props = useProps({ modelValue: false });\n */\n// (useProps now returns the props object directly)\n\n/**\n * Register a style function that will be called during each render\n * to provide reactive styles for the component\n *\n * @example\n * ```ts\n * import { css } from '@lib/style';\n *\n * component('my-component', () => {\n * const { theme } = useProps({ theme: 'light' });\n *\n * useStyle(() => css`\n * :host {\n * background: ${theme === 'light' ? 'white' : 'black'};\n * color: ${theme === 'light' ? 'black' : 'white'};\n * }\n * `);\n *\n * return html`<div>Styled component</div>`;\n * });\n * ```\n */\nexport function useStyle(callback: () => string): void {\n if (!currentComponentContext) {\n throw new Error('useStyle must be called during component render');\n }\n\n // During discovery render, skip style computation — no real DOM to style.\n if (_isDiscoveryRenderFn()) return;\n\n ensureHookCallbacks(currentComponentContext);\n\n // Execute the callback immediately during render to capture the current style\n // This ensures reactive state is read during the render phase, not during style application\n try {\n const computedStyle = callback();\n\n // Store the computed style using Object.defineProperty to avoid triggering reactive updates\n Object.defineProperty(currentComponentContext, '_computedStyle', {\n value: computedStyle,\n writable: true,\n enumerable: false,\n configurable: true,\n });\n } catch (error) {\n devWarn('Error in useStyle callback:', error);\n Object.defineProperty(currentComponentContext, '_computedStyle', {\n value: '',\n writable: true,\n enumerable: false,\n configurable: true,\n });\n }\n}\n\n/**\n * Cache of globally-injected stylesheets keyed by their CSS content.\n * Prevents duplicate `<style>` injections when the same `useGlobalStyle()`\n * factory runs across multiple component instances.\n */\nconst _globalStyleSheets = new Map<string, CSSStyleSheet>();\n\n/**\n * Inject CSS into `document.adoptedStyleSheets`, escaping the Shadow DOM\n * boundary. Suitable for `@font-face` declarations, `:root` variable overrides,\n * and global scroll/scroll-bar styling. Deduplicated by CSS content so calling\n * this in multiple component instances is safe.\n *\n * **Use sparingly** — this intentionally breaks Shadow DOM encapsulation.\n * A dev-mode warning is emitted to make the escape hatch visible.\n *\n * @example\n * ```ts\n * component('app-root', () => {\n * useGlobalStyle(() => css`\n * @font-face {\n * font-family: 'Inter';\n * src: url('/fonts/inter.woff2') format('woff2');\n * }\n * :root {\n * --app-font: 'Inter', sans-serif;\n * }\n * `);\n * return html`<slot></slot>`;\n * });\n * ```\n */\nexport function useGlobalStyle(styleFactory: () => string): void {\n let raw: string;\n try {\n raw = styleFactory();\n } catch {\n return;\n }\n\n // SSR collection pass: when an active collector exists (set up by\n // beginSSRGlobalStyleCollection in ssr.ts), capture here and skip DOM\n // injection regardless of whether document is available. This correctly\n // handles both Node.js SSR (no document) and test environments (document\n // present via happy-dom/jsdom) that call renderToStringWithJITCSS.\n if (captureGlobalStyleForSSR(raw)) return;\n\n if (typeof document === 'undefined' || typeof CSSStyleSheet === 'undefined') {\n // SSR without an active collector — nothing to do.\n return;\n }\n devWarn(\n '[useGlobalStyle] Injecting global styles from a component. ' +\n 'This escapes Shadow DOM encapsulation — use sparingly.',\n );\n const style = minifyCSS(sanitizeCSS(raw!));\n if (!style || _globalStyleSheets.has(style)) return;\n try {\n const sheet = new CSSStyleSheet();\n sheet.replaceSync(style);\n document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];\n _globalStyleSheets.set(style, sheet);\n } catch {\n // Fallback: inject a <style> element in <head>\n const el = document.createElement('style');\n el.textContent = style;\n (document.head ?? document.documentElement).appendChild(el);\n }\n}\n\n/**\n * Design token definitions accepted by `useDesignTokens()`.\n * Map high-level token names to CSS custom property overrides.\n */\nexport interface DesignTokens {\n /** Override the primary color scale root (sets --cer-color-primary-500) */\n primary?: string;\n /** Override the secondary color scale root */\n secondary?: string;\n /** Override the neutral color scale root */\n neutral?: string;\n /** Override the success color root */\n success?: string;\n /** Override the info color root */\n info?: string;\n /** Override the warning color root */\n warning?: string;\n /** Override the error color root */\n error?: string;\n /** Override the sans-serif font family */\n fontSans?: string;\n /** Override the serif font family */\n fontSerif?: string;\n /** Override the monospace font family */\n fontMono?: string;\n /** Additional arbitrary CSS custom property overrides */\n [key: string]: string | undefined;\n}\n\n/**\n * Apply design tokens to `:host` as CSS custom property overrides.\n * Must be called during component render. This is a typed, validated\n * alternative to writing `useStyle(() => css\\`:host { ... }\\`)` by hand.\n *\n * Semantic color tokens (e.g. `primary: '#6366f1'`) set the `*-500` shade\n * for that scale. Use arbitrary `'--cer-color-primary-500'` keys to override\n * individual shades.\n *\n * @example\n * ```ts\n * component('app-root', () => {\n * useDesignTokens({\n * primary: '#6366f1',\n * fontSans: '\"Inter\", sans-serif',\n * '--cer-color-neutral-900': '#0a0a0a',\n * });\n * return html`<slot></slot>`;\n * });\n * ```\n */\nexport function useDesignTokens(tokens: DesignTokens): void {\n if (!currentComponentContext) {\n throw new Error('useDesignTokens must be called during component render');\n }\n\n if (_isDiscoveryRenderFn()) return;\n\n const declarations: string[] = [];\n const semanticColorMap: Record<string, string> = {\n primary: '--cer-color-primary-500',\n secondary: '--cer-color-secondary-500',\n neutral: '--cer-color-neutral-500',\n success: '--cer-color-success-500',\n info: '--cer-color-info-500',\n warning: '--cer-color-warning-500',\n error: '--cer-color-error-500',\n };\n const fontMap: Record<string, string> = {\n fontSans: '--cer-font-sans',\n fontSerif: '--cer-font-serif',\n fontMono: '--cer-font-mono',\n };\n\n for (const [key, value] of Object.entries(tokens)) {\n if (value === undefined) continue;\n if (key in semanticColorMap) {\n declarations.push(`${semanticColorMap[key]}:${value}`);\n } else if (key in fontMap) {\n declarations.push(`${fontMap[key]}:${value}`);\n } else if (key.startsWith('--')) {\n declarations.push(`${key}:${value}`);\n }\n }\n\n if (declarations.length === 0) return;\n\n const cssText = `:host{${declarations.join(';')}}`;\n\n // Append to any existing computed style\n const ctx = currentComponentContext as { _computedStyle?: string };\n const existing = ctx._computedStyle ?? '';\n const combined = existing ? `${existing}\\n${cssText}` : cssText;\n\n Object.defineProperty(currentComponentContext, '_computedStyle', {\n value: combined,\n writable: true,\n enumerable: false,\n configurable: true,\n });\n}\n\n// ---------- provide / inject ----------\n\n/**\n * Store a value under a key so that descendant components can retrieve it\n * with `inject()`. Must be called during component render.\n *\n * @example\n * ```ts\n * component('theme-provider', () => {\n * provide('theme', 'dark');\n * return html`<slot></slot>`;\n * });\n * ```\n */\nexport function provide<T>(key: string | symbol, value: T): void {\n if (!currentComponentContext) {\n throw new Error('provide must be called during component render');\n }\n\n // During discovery render, skip provide — the ephemeral context is discarded.\n if (_isDiscoveryRenderFn()) return;\n\n const ctx = currentComponentContext as Record<string | symbol, unknown>;\n if (!ctx[PROVIDES_KEY]) {\n Object.defineProperty(ctx, PROVIDES_KEY, {\n value: new Map<string | symbol, unknown>(),\n writable: false,\n enumerable: false,\n configurable: true,\n });\n }\n (ctx[PROVIDES_KEY] as Map<string | symbol, unknown>).set(key, value);\n}\n\n/**\n * Retrieve a value provided by an ancestor component. Traverses the shadow\n * DOM tree upward through ShadowRoot host elements looking for the nearest\n * `provide()` call with the matching key. Returns `defaultValue` (or\n * `undefined`) when no provider is found. Must be called during render.\n *\n * @example\n * ```ts\n * component('themed-button', () => {\n * const theme = inject<string>('theme', 'light');\n * return html`<button class=\"btn-${theme}\">Click</button>`;\n * });\n * ```\n */\nexport function inject<T>(\n key: string | symbol,\n defaultValue?: T,\n): T | undefined {\n if (!currentComponentContext) {\n throw new Error('inject must be called during component render');\n }\n\n // During discovery render, the host tree is not yet mounted — return the\n // default value to allow prop detection to continue without DOM traversal.\n if (_isDiscoveryRenderFn()) return defaultValue;\n\n try {\n const host = (currentComponentContext as { _host?: HTMLElement })._host;\n if (host) {\n let node: Node | null = host.parentNode as Node | null;\n if (!node) node = host.getRootNode() as Node | null;\n\n // Depth counter prevents infinite loops in detached subtrees where\n // getRootNode() may return a subtree root instead of `document`.\n let depth = 0;\n const MAX_DEPTH = 50;\n\n while (node && depth < MAX_DEPTH) {\n depth++;\n if (typeof ShadowRoot !== 'undefined' && node instanceof ShadowRoot) {\n const shadowHost = node.host;\n const hostCtx = (\n shadowHost as unknown as {\n context?: Record<string | symbol, unknown>;\n }\n ).context;\n if (hostCtx) {\n const provides = hostCtx[PROVIDES_KEY] as\n | Map<string | symbol, unknown>\n | undefined;\n if (provides?.has(key)) {\n return provides.get(key) as T;\n }\n }\n const next: Node | null = shadowHost.parentNode as Node | null;\n node = next ?? (shadowHost.getRootNode() as Node | null);\n if (node === document || node === shadowHost) break;\n } else {\n // Also check light-DOM ancestor elements that may be custom components\n // with provides (e.g. a consumer that is a slotted child of a provider).\n if (typeof Element !== 'undefined' && node instanceof Element) {\n const elCtx = (\n node as unknown as {\n context?: Record<string | symbol, unknown>;\n }\n ).context;\n if (elCtx) {\n const provides = elCtx[PROVIDES_KEY] as\n | Map<string | symbol, unknown>\n | undefined;\n if (provides?.has(key)) {\n return provides.get(key) as T;\n }\n }\n }\n const prevNode = node;\n const next: Node | null = (node as Node).parentNode as Node | null;\n node = next ?? ((node as Node).getRootNode?.() as Node | null);\n // Guard against infinite loops: if getRootNode() returns the same\n // node (disconnected element with no ancestors), stop traversal.\n if (node === document || node === prevNode) break;\n }\n }\n }\n } catch {\n // ignore traversal errors - fall through to default\n }\n\n return defaultValue;\n}\n\n// ---------- createComposable ----------\n\n/**\n * Execute a function that calls hooks (useOnConnected, useOnDisconnected, etc.)\n * using an explicit component context rather than requiring the call to happen\n * directly inside a render function. This enables composable utility functions\n * that register lifecycle callbacks from outside the render body.\n *\n * @example\n * ```ts\n * function useLogger(label: string) {\n * return createComposable(() => {\n * useOnConnected(() => console.log(`${label} connected`));\n * useOnDisconnected(() => console.log(`${label} disconnected`));\n * });\n * }\n *\n * component('my-comp', () => {\n * const stopLogger = useLogger('my-comp');\n * stopLogger(context); // pass the component context explicitly\n * return html`<div>Hello</div>`;\n * });\n * ```\n *\n * More commonly, use it as a direct wrapper inside render:\n * ```ts\n * component('my-comp', () => {\n * // Accepts context automatically from getCurrentComponentContext()\n * createComposable(() => {\n * useOnConnected(() => console.log('connected from composable'));\n * })();\n * return html`<div>Hello</div>`;\n * });\n * ```\n */\nexport function createComposable<T>(\n fn: () => T,\n): (ctx?: Record<string, unknown>) => T {\n return (ctx?: Record<string, unknown>) => {\n const targetCtx = ctx ?? currentComponentContext;\n if (!targetCtx) {\n throw new Error(\n 'createComposable: no component context available. Pass a context explicitly or call inside a render function.',\n );\n }\n\n const prev = currentComponentContext;\n setCurrentComponentContext(targetCtx);\n try {\n return fn();\n } finally {\n // Restore the previous context (supports nested composables)\n if (prev) {\n setCurrentComponentContext(prev);\n } else {\n clearCurrentComponentContext();\n }\n }\n };\n}\n\n/**\n * Expose a public interface from the current component so that parent\n * components holding a template ref to this element can call its methods\n * or read its properties. Must be called during component render.\n *\n * @example\n * ```ts\n * component('my-counter', () => {\n * const count = ref(0);\n * useExpose({ increment: () => count.value++, get count() { return count.value; } });\n * return html`<div>${count.value}</div>`;\n * });\n *\n * // Parent: counterRef.value.increment()\n * ```\n */\nexport function useExpose<T extends Record<string, unknown>>(exposed: T): void {\n if (!currentComponentContext) {\n throw new Error('useExpose must be called during component render');\n }\n\n // During discovery render, skip — no real host to expose properties on\n if (_isDiscoveryRenderFn()) return;\n\n ensureHookCallbacks(currentComponentContext);\n const hooks = currentComponentContext._hookCallbacks as InternalHookCallbacks;\n hooks.expose = { ...(hooks.expose ?? {}), ...exposed };\n\n // Apply exposed properties onto the host element immediately if available\n const host = (currentComponentContext as { _host?: HTMLElement })._host;\n if (host) {\n for (const [key, value] of Object.entries(exposed)) {\n try {\n (host as unknown as Record<string, unknown>)[key] = value;\n } catch {\n // ignore non-writable properties\n }\n }\n }\n}\n\n/**\n * Access named slots provided to the current component. Returns helpers to\n * check slot presence and retrieve slotted elements. Must be called during\n * component render.\n *\n * @example\n * ```ts\n * component('my-card', () => {\n * const slots = useSlots();\n * return html`\n * <div class=\"card\">\n * <slot></slot>\n * ${slots.has('footer') ? html`<footer><slot name=\"footer\"></slot></footer>` : ''}\n * </div>\n * `;\n * });\n * ```\n */\nexport function useSlots(): {\n has(name?: string): boolean;\n getNodes(name?: string): Element[];\n names(): string[];\n} {\n if (!currentComponentContext) {\n throw new Error('useSlots must be called during component render');\n }\n\n // During discovery render, return empty no-op slot object\n if (_isDiscoveryRenderFn()) {\n return { has: () => false, getNodes: () => [], names: () => [] };\n }\n\n const host = (currentComponentContext as { _host?: HTMLElement })._host;\n\n // Single-pass collection: group children by slot name once, reuse for all methods.\n const getSlotMap = (): Map<string, Element[]> => {\n const map = new Map<string, Element[]>();\n if (!host) return map;\n for (const child of host.children) {\n const key = child.getAttribute('slot') ?? 'default';\n const bucket = map.get(key);\n if (bucket) {\n bucket.push(child);\n } else {\n map.set(key, [child]);\n }\n }\n return map;\n };\n\n return {\n /**\n * Returns true if the named slot (or the default slot when name is\n * omitted) has at least one slotted child element.\n */\n has(name?: string): boolean {\n if (!host) return false;\n const slotName = !name || name === 'default' ? 'default' : name;\n const bucket = getSlotMap().get(slotName);\n return bucket !== undefined && bucket.length > 0;\n },\n /**\n * Returns all child elements assigned to the named slot (or the default\n * slot when name is omitted).\n */\n getNodes(name?: string): Element[] {\n if (!host) return [];\n const slotName = !name || name === 'default' ? 'default' : name;\n return getSlotMap().get(slotName) ?? [];\n },\n /** Returns the names of all slots that have content, including 'default'. */\n names(): string[] {\n if (!host) return [];\n return Array.from(getSlotMap().keys());\n },\n };\n}\n\n/**\n * A writable ref that reads from a component prop and emits `update:<propName>`\n * when its value is set, enabling two-way binding with a parent's `:model` or\n * `:model:<propName>` directive.\n *\n * Also recognised by the vdom `:model` directive as a reactive value so it can\n * be passed directly to native inputs inside the child template.\n */\nexport interface ModelRef<T> {\n /** The current prop value. Reactive — reads trigger re-renders. */\n value: T;\n}\n\n/**\n * Define a two-way binding model for a component prop, similar to Vue's\n * `defineModel()`. It combines `useProps` + `useEmit` into a single ergonomic\n * API so child components don't need to wire the plumbing manually.\n *\n * The returned `ModelRef` object:\n * - **reads** `.value` → returns the current prop value (reactive)\n * - **writes** `.value = x` → emits `update:<propName>` so the parent's\n * `:model` / `:model:<propName>` directive can update its reactive state\n *\n * The object is also recognised by the vdom `:model` directive, so you can\n * pass it directly to a native input's `:model` binding inside the child\n * template and the two-way sync is wired up automatically.\n *\n * @example\n * ```ts\n * // Default model — maps to the parent's :model=\"...\"\n * component('my-input', () => {\n * const model = defineModel('');\n *\n * return html`\n * <input :model=\"${model}\" />\n * `;\n * });\n *\n * // Named model — maps to the parent's :model:title=\"...\"\n * component('my-field', () => {\n * const title = defineModel('title', '');\n * const count = defineModel('count', 0);\n *\n * return html`\n * <input :model=\"${title}\" />\n * <input type=\"number\" :model=\"${count}\" />\n * `;\n * });\n * ```\n *\n * @param args - Either:\n * - No arguments → `modelValue` prop, no default.\n * - One argument → treated as the **default value** for the `modelValue` prop;\n * type is inferred from the value.\n * - Two arguments → first is the **prop name**, second is the **default value**;\n * type is inferred from the default value.\n */\nexport function defineModel<T = unknown>(): ModelRef<T | undefined>;\nexport function defineModel<T>(defaultValue: T): ModelRef<T>;\nexport function defineModel<T>(propName: string, defaultValue: T): ModelRef<T>;\nexport function defineModel<T = unknown>(\n ...args: [] | [T] | [string, T]\n): ModelRef<T | undefined> {\n if (!currentComponentContext) {\n throw new Error('defineModel must be called during component render');\n }\n\n const propName = args.length === 2 ? (args[0] as string) : 'modelValue';\n const initialDefault =\n args.length === 2\n ? (args[1] as T)\n : args.length === 1\n ? (args[0] as T)\n : undefined;\n\n // Register the prop so the runtime discovers it during the discovery render\n // and includes it in the component's observed attributes / prop definitions.\n const props = useProps({\n [propName]: initialDefault,\n } as Record<string, unknown>);\n\n // Capture the emit function once — during a discovery render this is a no-op.\n const isDiscovery = _isDiscoveryRenderFn();\n const emitFn = isDiscovery\n ? null\n : (() => {\n const candidate = (currentComponentContext as { emit?: unknown }).emit;\n if (typeof candidate !== 'function') return null;\n return candidate as (\n eventName: string,\n detail?: unknown,\n options?: CustomEventInit,\n ) => boolean;\n })();\n\n // The model ref is marked with the ReactiveState symbol so that\n // processModelDirective treats it as a reactive value and wires up\n // `:model` on native inputs inside the child template correctly.\n const modelRef: ModelRef<T> = {\n get value(): T {\n return props[propName] as T;\n },\n set value(newValue: T) {\n if (emitFn) {\n emitFn(`update:${propName}`, newValue);\n }\n },\n };\n\n try {\n const key = Symbol.for('@cer/ReactiveState');\n Object.defineProperty(modelRef, key, {\n value: true,\n enumerable: false,\n configurable: false,\n });\n } catch {\n // ignore exotic runtimes\n }\n\n return modelRef;\n}\n"],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ //#region src/lib/runtime/logger.ts
2
+ var e = !1;
3
+ try {
4
+ let t = globalThis.process;
5
+ e = t?.env ? (t.env.NODE_ENV ?? t.env.MODE) !== "production" : typeof window < "u" && typeof document < "u";
6
+ } catch {
7
+ e = !0;
8
+ }
9
+ var t;
10
+ function n(e) {
11
+ t = !!e;
12
+ try {
13
+ let e = globalThis;
14
+ e.__CE_RUNTIME_DEV__ = t;
15
+ } catch {}
16
+ }
17
+ function r() {
18
+ try {
19
+ let e = globalThis;
20
+ if (e.__CE_RUNTIME_DEV__ !== void 0) return !!e.__CE_RUNTIME_DEV__;
21
+ } catch {}
22
+ return t === !0 || e;
23
+ }
24
+ function i(e, ...t) {
25
+ r() && console.error(e, ...t);
26
+ }
27
+ function a(e, ...t) {
28
+ r() && console.warn(e, ...t);
29
+ }
30
+ function o(e, ...t) {
31
+ r() && console.log(e, ...t);
32
+ }
33
+ //#endregion
34
+ export { n as i, o as n, a as r, i as t };
35
+
36
+ //# sourceMappingURL=logger-DIJ0UH3R.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"logger-L25axmB-.js","names":[],"sources":["../src/lib/runtime/logger.ts"],"sourcesContent":["/**\n * Development-only logging utilities\n * These are stripped out in production builds via bundler configuration\n */\n\n// Robust dev-mode detection across environments (Node tests, Vite dev server, browser)\nlet isDev = false;\ntry {\n const maybeProcess = (\n globalThis as { process?: { env?: Record<string, string> } }\n ).process;\n\n if (maybeProcess?.env) {\n const env = maybeProcess.env.NODE_ENV ?? maybeProcess.env.MODE;\n isDev = env !== 'production';\n } else {\n // Browser fallback\n isDev = typeof window !== 'undefined' && typeof document !== 'undefined';\n }\n} catch {\n isDev = true;\n}\n\n// Runtime-overridable flag. Consumers can set `globalThis.__CE_RUNTIME_DEV__ = true`\n// before importing the library, or call `setDevMode(true)` at runtime to enable\n// dev logging. We keep `isDev` for build-time detection but consult the\n// runtime flag at each call so bundlers cannot safely remove the console calls\n// if consumers rely on runtime toggling.\nlet runtimeFlag: boolean | undefined;\n\n/**\n * Programmatically toggle dev-mode logging at runtime.\n * Prefer setting `globalThis.__CE_RUNTIME_DEV__ = true` before importing\n * the runtime so logs are enabled as early as possible.\n *\n * @param v - `true` to enable dev logging, `false` to disable it.\n *\n * @example\n * ```ts\n * import { setDevMode } from '@jasonshimmy/custom-elements-runtime';\n * setDevMode(true); // enable verbose dev logs\n * ```\n */\nexport function setDevMode(v: boolean): void {\n runtimeFlag = !!v;\n try {\n const g = globalThis as unknown as { __CE_RUNTIME_DEV__?: unknown };\n g.__CE_RUNTIME_DEV__ = runtimeFlag;\n } catch (_err: unknown) {\n void _err;\n }\n}\n\nfunction runtimeDevEnabled(): boolean {\n try {\n const g = globalThis as unknown as { __CE_RUNTIME_DEV__?: unknown };\n if (typeof g.__CE_RUNTIME_DEV__ !== 'undefined')\n return Boolean(g.__CE_RUNTIME_DEV__);\n } catch {\n // ignore\n }\n // fall back to build-time detection\n return runtimeFlag === true || isDev;\n}\n\n/**\n * Log error only in development mode\n */\nexport function devError(message: string, ...args: unknown[]): void {\n if (runtimeDevEnabled()) {\n console.error(message, ...args);\n }\n}\n\n/**\n * Log warning only in development mode\n */\nexport function devWarn(message: string, ...args: unknown[]): void {\n if (runtimeDevEnabled()) {\n console.warn(message, ...args);\n }\n}\n\n/**\n * Log an informational message only in development mode.\n * No-ops in production builds or when dev mode is disabled.\n *\n * @param message - Message to log.\n * @param args - Additional values to pass to `console.log`.\n *\n * @example\n * ```ts\n * import { devLog } from '@jasonshimmy/custom-elements-runtime';\n * devLog('[my-component] mounted', { props });\n * ```\n */\nexport function devLog(message: string, ...args: unknown[]): void {\n if (runtimeDevEnabled()) {\n console.log(message, ...args);\n }\n}\n"],"mappings":"AAMA,IAAI,IAAQ;AACZ,IAAI;AACF,QAAM,IACJ,WACA;AAEF,EAAI,GAAc,MAEhB,KADY,EAAa,IAAI,YAAY,EAAa,IAAI,UAC1C,eAGhB,IAAQ,OAAO,SAAW,OAAe,OAAO,WAAa;QAEzD;AACN,EAAA,IAAQ;;AAQV,IAAI;AAeJ,SAAgB,EAAW,GAAkB;AAC3C,EAAA,IAAc,CAAC,CAAC;AAChB,MAAI;AACF,UAAM,IAAI;AACV,IAAA,EAAE,qBAAqB;AAAA,UACD;AAAA,EAAA;;AAK1B,SAAS,IAA6B;AACpC,MAAI;AACF,UAAM,IAAI;AACV,QAAI,OAAO,EAAE,qBAAuB,IAClC,QAAO,EAAQ,EAAE;AAAA,UACb;AAAA,EAAA;AAIR,SAAO,MAAgB,MAAQ;;AAMjC,SAAgB,EAAS,MAAoB,GAAuB;AAClE,EAAI,EAAA,KACF,QAAQ,MAAM,GAAS,GAAG,CAAA;;AAO9B,SAAgB,EAAQ,MAAoB,GAAuB;AACjE,EAAI,EAAA,KACF,QAAQ,KAAK,GAAS,GAAG,CAAA;;AAiB7B,SAAgB,EAAO,MAAoB,GAAuB;AAChE,EAAI,EAAA,KACF,QAAQ,IAAI,GAAS,GAAG,CAAA"}
1
+ {"version":3,"file":"logger-DIJ0UH3R.js","names":[],"sources":["../src/lib/runtime/logger.ts"],"sourcesContent":["/**\n * Development-only logging utilities\n * These are stripped out in production builds via bundler configuration\n */\n\n// Robust dev-mode detection across environments (Node tests, Vite dev server, browser)\nlet isDev = false;\ntry {\n const maybeProcess = (\n globalThis as { process?: { env?: Record<string, string> } }\n ).process;\n\n if (maybeProcess?.env) {\n const env = maybeProcess.env.NODE_ENV ?? maybeProcess.env.MODE;\n isDev = env !== 'production';\n } else {\n // Browser fallback\n isDev = typeof window !== 'undefined' && typeof document !== 'undefined';\n }\n} catch {\n isDev = true;\n}\n\n// Runtime-overridable flag. Consumers can set `globalThis.__CE_RUNTIME_DEV__ = true`\n// before importing the library, or call `setDevMode(true)` at runtime to enable\n// dev logging. We keep `isDev` for build-time detection but consult the\n// runtime flag at each call so bundlers cannot safely remove the console calls\n// if consumers rely on runtime toggling.\nlet runtimeFlag: boolean | undefined;\n\n/**\n * Programmatically toggle dev-mode logging at runtime.\n * Prefer setting `globalThis.__CE_RUNTIME_DEV__ = true` before importing\n * the runtime so logs are enabled as early as possible.\n *\n * @param v - `true` to enable dev logging, `false` to disable it.\n *\n * @example\n * ```ts\n * import { setDevMode } from '@jasonshimmy/custom-elements-runtime';\n * setDevMode(true); // enable verbose dev logs\n * ```\n */\nexport function setDevMode(v: boolean): void {\n runtimeFlag = !!v;\n try {\n const g = globalThis as unknown as { __CE_RUNTIME_DEV__?: unknown };\n g.__CE_RUNTIME_DEV__ = runtimeFlag;\n } catch (_err: unknown) {\n void _err;\n }\n}\n\nfunction runtimeDevEnabled(): boolean {\n try {\n const g = globalThis as unknown as { __CE_RUNTIME_DEV__?: unknown };\n if (typeof g.__CE_RUNTIME_DEV__ !== 'undefined')\n return Boolean(g.__CE_RUNTIME_DEV__);\n } catch {\n // ignore\n }\n // fall back to build-time detection\n return runtimeFlag === true || isDev;\n}\n\n/**\n * Log error only in development mode\n */\nexport function devError(message: string, ...args: unknown[]): void {\n if (runtimeDevEnabled()) {\n console.error(message, ...args);\n }\n}\n\n/**\n * Log warning only in development mode\n */\nexport function devWarn(message: string, ...args: unknown[]): void {\n if (runtimeDevEnabled()) {\n console.warn(message, ...args);\n }\n}\n\n/**\n * Log an informational message only in development mode.\n * No-ops in production builds or when dev mode is disabled.\n *\n * @param message - Message to log.\n * @param args - Additional values to pass to `console.log`.\n *\n * @example\n * ```ts\n * import { devLog } from '@jasonshimmy/custom-elements-runtime';\n * devLog('[my-component] mounted', { props });\n * ```\n */\nexport function devLog(message: string, ...args: unknown[]): void {\n if (runtimeDevEnabled()) {\n console.log(message, ...args);\n }\n}\n"],"mappings":";AAMA,IAAI,IAAQ;AACZ,IAAI;CACF,IAAM,IACJ,WACA;AAEF,CAKE,IALE,GAAc,OACJ,EAAa,IAAI,YAAY,EAAa,IAAI,UAC1C,eAGR,OAAO,SAAW,OAAe,OAAO,WAAa;QAEzD;AACN,KAAQ;;AAQV,IAAI;AAeJ,SAAgB,EAAW,GAAkB;AAC3C,KAAc,CAAC,CAAC;AAChB,KAAI;EACF,IAAM,IAAI;AACV,IAAE,qBAAqB;SACD;;AAK1B,SAAS,IAA6B;AACpC,KAAI;EACF,IAAM,IAAI;AACV,MAAW,EAAE,uBAAuB,OAClC,QAAO,EAAQ,EAAE;SACb;AAIR,QAAO,MAAgB,MAAQ;;AAMjC,SAAgB,EAAS,GAAiB,GAAG,GAAuB;AAClE,CAAI,GAAmB,IACrB,QAAQ,MAAM,GAAS,GAAG,EAAK;;AAOnC,SAAgB,EAAQ,GAAiB,GAAG,GAAuB;AACjE,CAAI,GAAmB,IACrB,QAAQ,KAAK,GAAS,GAAG,EAAK;;AAiBlC,SAAgB,EAAO,GAAiB,GAAG,GAAuB;AAChE,CAAI,GAAmB,IACrB,QAAQ,IAAI,GAAS,GAAG,EAAK"}
@@ -0,0 +1,2 @@
1
+ var e=!1;try{let t=globalThis.process;e=t?.env?(t.env.NODE_ENV??t.env.MODE)!==`production`:typeof window<`u`&&typeof document<`u`}catch{e=!0}var t;function n(e){t=!!e;try{let e=globalThis;e.__CE_RUNTIME_DEV__=t}catch{}}function r(){try{let e=globalThis;if(e.__CE_RUNTIME_DEV__!==void 0)return!!e.__CE_RUNTIME_DEV__}catch{}return t===!0||e}function i(e,...t){r()&&console.error(e,...t)}function a(e,...t){r()&&console.warn(e,...t)}function o(e,...t){r()&&console.log(e,...t)}Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return n}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return i}});
2
+ //# sourceMappingURL=logger-Dkht1dCX.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"logger-BYIN7ysT.cjs","names":[],"sources":["../src/lib/runtime/logger.ts"],"sourcesContent":["/**\n * Development-only logging utilities\n * These are stripped out in production builds via bundler configuration\n */\n\n// Robust dev-mode detection across environments (Node tests, Vite dev server, browser)\nlet isDev = false;\ntry {\n const maybeProcess = (\n globalThis as { process?: { env?: Record<string, string> } }\n ).process;\n\n if (maybeProcess?.env) {\n const env = maybeProcess.env.NODE_ENV ?? maybeProcess.env.MODE;\n isDev = env !== 'production';\n } else {\n // Browser fallback\n isDev = typeof window !== 'undefined' && typeof document !== 'undefined';\n }\n} catch {\n isDev = true;\n}\n\n// Runtime-overridable flag. Consumers can set `globalThis.__CE_RUNTIME_DEV__ = true`\n// before importing the library, or call `setDevMode(true)` at runtime to enable\n// dev logging. We keep `isDev` for build-time detection but consult the\n// runtime flag at each call so bundlers cannot safely remove the console calls\n// if consumers rely on runtime toggling.\nlet runtimeFlag: boolean | undefined;\n\n/**\n * Programmatically toggle dev-mode logging at runtime.\n * Prefer setting `globalThis.__CE_RUNTIME_DEV__ = true` before importing\n * the runtime so logs are enabled as early as possible.\n *\n * @param v - `true` to enable dev logging, `false` to disable it.\n *\n * @example\n * ```ts\n * import { setDevMode } from '@jasonshimmy/custom-elements-runtime';\n * setDevMode(true); // enable verbose dev logs\n * ```\n */\nexport function setDevMode(v: boolean): void {\n runtimeFlag = !!v;\n try {\n const g = globalThis as unknown as { __CE_RUNTIME_DEV__?: unknown };\n g.__CE_RUNTIME_DEV__ = runtimeFlag;\n } catch (_err: unknown) {\n void _err;\n }\n}\n\nfunction runtimeDevEnabled(): boolean {\n try {\n const g = globalThis as unknown as { __CE_RUNTIME_DEV__?: unknown };\n if (typeof g.__CE_RUNTIME_DEV__ !== 'undefined')\n return Boolean(g.__CE_RUNTIME_DEV__);\n } catch {\n // ignore\n }\n // fall back to build-time detection\n return runtimeFlag === true || isDev;\n}\n\n/**\n * Log error only in development mode\n */\nexport function devError(message: string, ...args: unknown[]): void {\n if (runtimeDevEnabled()) {\n console.error(message, ...args);\n }\n}\n\n/**\n * Log warning only in development mode\n */\nexport function devWarn(message: string, ...args: unknown[]): void {\n if (runtimeDevEnabled()) {\n console.warn(message, ...args);\n }\n}\n\n/**\n * Log an informational message only in development mode.\n * No-ops in production builds or when dev mode is disabled.\n *\n * @param message - Message to log.\n * @param args - Additional values to pass to `console.log`.\n *\n * @example\n * ```ts\n * import { devLog } from '@jasonshimmy/custom-elements-runtime';\n * devLog('[my-component] mounted', { props });\n * ```\n */\nexport function devLog(message: string, ...args: unknown[]): void {\n if (runtimeDevEnabled()) {\n console.log(message, ...args);\n }\n}\n"],"mappings":"AAMA,IAAI,EAAQ,GACZ,GAAI,CACF,MAAM,EACJ,WACA,QAEE,GAAc,IAEhB,GADY,EAAa,IAAI,UAAY,EAAa,IAAI,QAC1C,aAGhB,EAAQ,OAAO,OAAW,KAAe,OAAO,SAAa,SAEzD,CACN,EAAQ,GAQV,IAAI,EAeJ,SAAgB,EAAW,EAAkB,CAC3C,EAAc,CAAC,CAAC,EAChB,GAAI,CACF,MAAM,EAAI,WACV,EAAE,mBAAqB,OACD,CAAA,EAK1B,SAAS,GAA6B,CACpC,GAAI,CACF,MAAM,EAAI,WACV,GAAI,OAAO,EAAE,mBAAuB,IAClC,MAAO,EAAQ,EAAE,wBACb,CAAA,CAIR,OAAO,IAAgB,IAAQ,EAMjC,SAAgB,EAAS,KAAoB,EAAuB,CAC9D,EAAA,GACF,QAAQ,MAAM,EAAS,GAAG,CAAA,EAO9B,SAAgB,EAAQ,KAAoB,EAAuB,CAC7D,EAAA,GACF,QAAQ,KAAK,EAAS,GAAG,CAAA,EAiB7B,SAAgB,EAAO,KAAoB,EAAuB,CAC5D,EAAA,GACF,QAAQ,IAAI,EAAS,GAAG,CAAA"}
1
+ {"version":3,"file":"logger-Dkht1dCX.cjs","names":[],"sources":["../src/lib/runtime/logger.ts"],"sourcesContent":["/**\n * Development-only logging utilities\n * These are stripped out in production builds via bundler configuration\n */\n\n// Robust dev-mode detection across environments (Node tests, Vite dev server, browser)\nlet isDev = false;\ntry {\n const maybeProcess = (\n globalThis as { process?: { env?: Record<string, string> } }\n ).process;\n\n if (maybeProcess?.env) {\n const env = maybeProcess.env.NODE_ENV ?? maybeProcess.env.MODE;\n isDev = env !== 'production';\n } else {\n // Browser fallback\n isDev = typeof window !== 'undefined' && typeof document !== 'undefined';\n }\n} catch {\n isDev = true;\n}\n\n// Runtime-overridable flag. Consumers can set `globalThis.__CE_RUNTIME_DEV__ = true`\n// before importing the library, or call `setDevMode(true)` at runtime to enable\n// dev logging. We keep `isDev` for build-time detection but consult the\n// runtime flag at each call so bundlers cannot safely remove the console calls\n// if consumers rely on runtime toggling.\nlet runtimeFlag: boolean | undefined;\n\n/**\n * Programmatically toggle dev-mode logging at runtime.\n * Prefer setting `globalThis.__CE_RUNTIME_DEV__ = true` before importing\n * the runtime so logs are enabled as early as possible.\n *\n * @param v - `true` to enable dev logging, `false` to disable it.\n *\n * @example\n * ```ts\n * import { setDevMode } from '@jasonshimmy/custom-elements-runtime';\n * setDevMode(true); // enable verbose dev logs\n * ```\n */\nexport function setDevMode(v: boolean): void {\n runtimeFlag = !!v;\n try {\n const g = globalThis as unknown as { __CE_RUNTIME_DEV__?: unknown };\n g.__CE_RUNTIME_DEV__ = runtimeFlag;\n } catch (_err: unknown) {\n void _err;\n }\n}\n\nfunction runtimeDevEnabled(): boolean {\n try {\n const g = globalThis as unknown as { __CE_RUNTIME_DEV__?: unknown };\n if (typeof g.__CE_RUNTIME_DEV__ !== 'undefined')\n return Boolean(g.__CE_RUNTIME_DEV__);\n } catch {\n // ignore\n }\n // fall back to build-time detection\n return runtimeFlag === true || isDev;\n}\n\n/**\n * Log error only in development mode\n */\nexport function devError(message: string, ...args: unknown[]): void {\n if (runtimeDevEnabled()) {\n console.error(message, ...args);\n }\n}\n\n/**\n * Log warning only in development mode\n */\nexport function devWarn(message: string, ...args: unknown[]): void {\n if (runtimeDevEnabled()) {\n console.warn(message, ...args);\n }\n}\n\n/**\n * Log an informational message only in development mode.\n * No-ops in production builds or when dev mode is disabled.\n *\n * @param message - Message to log.\n * @param args - Additional values to pass to `console.log`.\n *\n * @example\n * ```ts\n * import { devLog } from '@jasonshimmy/custom-elements-runtime';\n * devLog('[my-component] mounted', { props });\n * ```\n */\nexport function devLog(message: string, ...args: unknown[]): void {\n if (runtimeDevEnabled()) {\n console.log(message, ...args);\n }\n}\n"],"mappings":"AAMA,IAAI,EAAQ,GACZ,GAAI,CACF,IAAM,EACJ,WACA,QAEF,AAKE,EALE,GAAc,KACJ,EAAa,IAAI,UAAY,EAAa,IAAI,QAC1C,aAGR,OAAO,OAAW,KAAe,OAAO,SAAa,SAEzD,CACN,EAAQ,GAQV,IAAI,EAeJ,SAAgB,EAAW,EAAkB,CAC3C,EAAc,CAAC,CAAC,EAChB,GAAI,CACF,IAAM,EAAI,WACV,EAAE,mBAAqB,OACD,GAK1B,SAAS,GAA6B,CACpC,GAAI,CACF,IAAM,EAAI,WACV,GAAW,EAAE,qBAAuB,OAClC,MAAO,EAAQ,EAAE,wBACb,EAIR,OAAO,IAAgB,IAAQ,EAMjC,SAAgB,EAAS,EAAiB,GAAG,EAAuB,CAC9D,GAAmB,EACrB,QAAQ,MAAM,EAAS,GAAG,EAAK,CAOnC,SAAgB,EAAQ,EAAiB,GAAG,EAAuB,CAC7D,GAAmB,EACrB,QAAQ,KAAK,EAAS,GAAG,EAAK,CAiBlC,SAAgB,EAAO,EAAiB,GAAG,EAAuB,CAC5D,GAAmB,EACrB,QAAQ,IAAI,EAAS,GAAG,EAAK"}
@@ -0,0 +1,56 @@
1
+ import { r as e } from "./logger-DIJ0UH3R.js";
2
+ //#region src/lib/runtime/component/registry.ts
3
+ var t = /* @__PURE__ */ new Map(), n = Symbol.for("cer.registry");
4
+ function r() {
5
+ if (!(typeof window > "u" && typeof document > "u" && typeof navigator > "u")) try {
6
+ let e = globalThis;
7
+ if (!e[n]) {
8
+ let r = crypto.randomUUID();
9
+ e[n] = new Map([...t.entries()]), e[n].__realmId = r;
10
+ }
11
+ } catch (t) {
12
+ e("Could not initialize global registry:", t);
13
+ }
14
+ }
15
+ //#endregion
16
+ //#region src/lib/runtime/namespace-helpers.ts
17
+ var i = {
18
+ xlink: "http://www.w3.org/1999/xlink",
19
+ xml: "http://www.w3.org/XML/1998/namespace"
20
+ };
21
+ function a(e, t, n) {
22
+ try {
23
+ if (!t || !t.includes(":")) {
24
+ e.setAttribute(t, n);
25
+ return;
26
+ }
27
+ let r = t.indexOf(":"), a = t.substring(0, r), o = t.substring(r + 1), s = i[a];
28
+ s ? e.setAttributeNS(s, o, n) : e.setAttribute(t, n);
29
+ } catch {
30
+ try {
31
+ e.setAttribute(t, n);
32
+ } catch {}
33
+ }
34
+ }
35
+ function o(e, t) {
36
+ try {
37
+ if (!t || !t.includes(":")) {
38
+ e.removeAttribute(t);
39
+ return;
40
+ }
41
+ let n = t.indexOf(":"), r = t.substring(0, n), a = t.substring(n + 1), o = i[r];
42
+ o ? e.removeAttributeNS(o, a) : e.removeAttribute(t);
43
+ } catch {
44
+ try {
45
+ e.removeAttribute(t);
46
+ } catch {}
47
+ }
48
+ }
49
+ var s = "http://www.w3.org/2000/svg", c = {
50
+ svg: s,
51
+ math: "http://www.w3.org/1998/Math/MathML"
52
+ };
53
+ //#endregion
54
+ export { r as a, a as i, c as n, t as o, o as r, s as t };
55
+
56
+ //# sourceMappingURL=namespace-helpers-CIUkG8Mn.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"namespace-helpers-BucDdgz_.js","names":[],"sources":["../src/lib/runtime/component/registry.ts","../src/lib/runtime/namespace-helpers.ts"],"sourcesContent":["import type { ComponentConfig } from '../types';\nimport { devWarn } from '../logger';\n\n// Interface for custom element with framework-specific properties\ninterface CustomElement extends HTMLElement {\n _cfg?: ComponentConfig<object, object, object>;\n _render?: (config: ComponentConfig<object, object, object>) => void;\n onLoadingStateChange?: (loading: boolean) => void;\n onErrorStateChange?: (error: Error | null) => void;\n}\n\n/**\n * @internal\n * Runtime registry of component configs.\n * NOTE: This is an internal implementation detail. Do not import from the\n * published package in consumer code — it is intended for runtime/HMR and\n * internal tests only. Consumers should use the public `component` API.\n */\nexport const registry = new Map<\n string,\n ComponentConfig<object, object, object>\n>();\n\n// Expose the registry for browser/HMR use without overwriting existing globals\n// (avoid cross-request mutation in SSR and preserve HMR behavior).\nconst GLOBAL_REG_KEY = Symbol.for('cer.registry');\n\n/**\n * Lazily initialize the global registry slot with SSR safety.\n * This avoids performing a write to globalThis at module-import time\n * (which is a side-effect that prevents bundlers from tree-shaking).\n * Enhanced with SSR detection and multi-tenant safety.\n */\nexport function initGlobalRegistryIfNeeded(): void {\n // Enhanced SSR detection\n const isSSR =\n typeof window === 'undefined' &&\n typeof document === 'undefined' &&\n typeof navigator === 'undefined';\n\n if (!isSSR) {\n try {\n const g = globalThis as Record<string | symbol, unknown>;\n if (!g[GLOBAL_REG_KEY]) {\n // Use a unique registry per realm to avoid cross-contamination\n const realmId = crypto.randomUUID();\n g[GLOBAL_REG_KEY] = new Map([...registry.entries()]);\n // Store realm identifier for debugging\n (\n g[GLOBAL_REG_KEY] as Record<string, unknown> & { __realmId?: string }\n ).__realmId = realmId;\n }\n } catch (error) {\n // Gracefully handle cases where globalThis access is restricted\n devWarn('Could not initialize global registry:', error);\n }\n }\n}\n\n// --- Hot Module Replacement (HMR) ---\n{\n type HMRImportMeta = {\n hot?: { accept: (fn: (newModule?: unknown) => void) => void };\n };\n const hmrHot = (import.meta as HMRImportMeta).hot;\n if (hmrHot) {\n hmrHot.accept((newModule: unknown) => {\n // Update registry with new configs from the hot module (SSR-safe)\n const mod = newModule as\n | { registry?: Map<string, ComponentConfig<object, object, object>> }\n | undefined;\n if (mod && mod.registry) {\n for (const [tag, newConfig] of mod.registry.entries()) {\n registry.set(tag, newConfig);\n // Update all instances to use new config (browser only)\n if (typeof document !== 'undefined' && document.querySelectorAll) {\n try {\n document.querySelectorAll(tag).forEach((el) => {\n const customEl = el as CustomElement;\n if (typeof customEl._cfg !== 'undefined') {\n customEl._cfg = newConfig;\n }\n // HMR: Preserve existing state by keeping the context object intact.\n // Instead of re-executing the component function (which would create new refs),\n // we just update the config and re-render with the existing context.\n // This ensures refs and other reactive state are preserved across HMR updates.\n if (typeof customEl._render === 'function') {\n customEl._render(newConfig);\n }\n });\n } catch (error) {\n devWarn('HMR update failed:', error);\n }\n }\n }\n }\n });\n }\n}\n","/**\n * Namespace-aware attribute helpers.\n * Provides small, fast utilities to set/remove attributes using the\n * appropriate namespace when an attribute uses a known prefix (e.g. xlink:href).\n */\n\nconst ATTR_NAMESPACE_MAP: Record<string, string> = {\n xlink: 'http://www.w3.org/1999/xlink',\n xml: 'http://www.w3.org/XML/1998/namespace',\n};\n\n/**\n * Set attribute using namespace when the key contains a known prefix.\n */\nexport function setAttributeSmart(\n el: Element,\n key: string,\n value: string,\n): void {\n try {\n if (!key || !key.includes(':')) {\n el.setAttribute(key, value);\n return;\n }\n const idx = key.indexOf(':');\n const prefix = key.substring(0, idx);\n const local = key.substring(idx + 1);\n const ns = ATTR_NAMESPACE_MAP[prefix];\n if (ns) el.setAttributeNS(ns, local, value);\n else el.setAttribute(key, value);\n } catch {\n try {\n // Fallback to un-namespaced setAttribute on error\n el.setAttribute(key, value);\n } catch {\n /* swallow */\n }\n }\n}\n\n/**\n * Remove attribute using namespace when the key contains a known prefix.\n */\nexport function removeAttributeSmart(el: Element, key: string): void {\n try {\n if (!key || !key.includes(':')) {\n el.removeAttribute(key);\n return;\n }\n const idx = key.indexOf(':');\n const prefix = key.substring(0, idx);\n const local = key.substring(idx + 1);\n const ns = ATTR_NAMESPACE_MAP[prefix];\n if (ns) el.removeAttributeNS(ns, local);\n else el.removeAttribute(key);\n } catch {\n try {\n el.removeAttribute(key);\n } catch {\n /* swallow */\n }\n }\n}\n\nexport const __TEST_ONLY_ATTR_NS_MAP = ATTR_NAMESPACE_MAP;\n\n// Common element namespace URIs and a small tag->namespace map used by\n// both the client renderer and the SSR serializer. Exporting these from\n// this module keeps namespace knowledge centralized and prevents\n// accidental duplication between runtime and SSR code.\nexport const SVG_NS = 'http://www.w3.org/2000/svg';\nexport const MATHML_NS = 'http://www.w3.org/1998/Math/MathML';\n\nexport const TAG_NAMESPACE_MAP: Record<string, string> = {\n svg: SVG_NS,\n math: MATHML_NS,\n};\n"],"mappings":";AAkBA,IAAa,IAAW,oBAAI,IAAA,GAOtB,IAAiB,uBAAO,IAAI,cAAA;AAQlC,SAAgB,IAAmC;AAOjD,MAAI,EAJF,OAAO,SAAW,OAClB,OAAO,WAAa,OACpB,OAAO,YAAc,KAGrB,KAAI;AACF,UAAM,IAAI;AACV,QAAI,CAAC,EAAE,CAAA,GAAiB;AAEtB,YAAM,IAAU,OAAO,WAAA;AACvB,MAAA,EAAE,CAAA,IAAkB,IAAI,IAAI,CAAC,GAAG,EAAS,QAAA,CAAS,CAAC,GAGjD,EAAE,CAAA,EACF,YAAY;AAAA;WAET,GAAO;AAEd,IAAA,EAAQ,yCAAyC,CAAA;AAAA;;AChDvD,IAAM,IAA6C;AAAA,EACjD,OAAO;AAAA,EACP,KAAK;;AAMP,SAAgB,EACd,GACA,GACA,GACM;AACN,MAAI;AACF,QAAI,CAAC,KAAO,CAAC,EAAI,SAAS,GAAA,GAAM;AAC9B,MAAA,EAAG,aAAa,GAAK,CAAA;AACrB;AAAA;AAEF,UAAM,IAAM,EAAI,QAAQ,GAAA,GAClB,IAAS,EAAI,UAAU,GAAG,CAAA,GAC1B,IAAQ,EAAI,UAAU,IAAM,CAAA,GAC5B,IAAK,EAAmB,CAAA;AAC9B,IAAI,IAAI,EAAG,eAAe,GAAI,GAAO,CAAA,IAChC,EAAG,aAAa,GAAK,CAAA;AAAA,UACpB;AACN,QAAI;AAEF,MAAA,EAAG,aAAa,GAAK,CAAA;AAAA,YACf;AAAA,IAAA;AAAA;;AASZ,SAAgB,EAAqB,GAAa,GAAmB;AACnE,MAAI;AACF,QAAI,CAAC,KAAO,CAAC,EAAI,SAAS,GAAA,GAAM;AAC9B,MAAA,EAAG,gBAAgB,CAAA;AACnB;AAAA;AAEF,UAAM,IAAM,EAAI,QAAQ,GAAA,GAClB,IAAS,EAAI,UAAU,GAAG,CAAA,GAC1B,IAAQ,EAAI,UAAU,IAAM,CAAA,GAC5B,IAAK,EAAmB,CAAA;AAC9B,IAAI,IAAI,EAAG,kBAAkB,GAAI,CAAA,IAC5B,EAAG,gBAAgB,CAAA;AAAA,UAClB;AACN,QAAI;AACF,MAAA,EAAG,gBAAgB,CAAA;AAAA,YACb;AAAA,IAAA;AAAA;;AAYZ,IAAa,IAAS,8BACT,IAAY,sCAEZ,IAA4C;AAAA,EACvD,KAAK;AAAA,EACL,MAAM"}
1
+ {"version":3,"file":"namespace-helpers-CIUkG8Mn.js","names":[],"sources":["../src/lib/runtime/component/registry.ts","../src/lib/runtime/namespace-helpers.ts"],"sourcesContent":["import type { ComponentConfig } from '../types';\nimport { devWarn } from '../logger';\n\n// Interface for custom element with framework-specific properties\ninterface CustomElement extends HTMLElement {\n _cfg?: ComponentConfig<object, object, object>;\n _render?: (config: ComponentConfig<object, object, object>) => void;\n onLoadingStateChange?: (loading: boolean) => void;\n onErrorStateChange?: (error: Error | null) => void;\n}\n\n/**\n * @internal\n * Runtime registry of component configs.\n * NOTE: This is an internal implementation detail. Do not import from the\n * published package in consumer code — it is intended for runtime/HMR and\n * internal tests only. Consumers should use the public `component` API.\n */\nexport const registry = new Map<\n string,\n ComponentConfig<object, object, object>\n>();\n\n// Expose the registry for browser/HMR use without overwriting existing globals\n// (avoid cross-request mutation in SSR and preserve HMR behavior).\nconst GLOBAL_REG_KEY = Symbol.for('cer.registry');\n\n/**\n * Lazily initialize the global registry slot with SSR safety.\n * This avoids performing a write to globalThis at module-import time\n * (which is a side-effect that prevents bundlers from tree-shaking).\n * Enhanced with SSR detection and multi-tenant safety.\n */\nexport function initGlobalRegistryIfNeeded(): void {\n // Enhanced SSR detection\n const isSSR =\n typeof window === 'undefined' &&\n typeof document === 'undefined' &&\n typeof navigator === 'undefined';\n\n if (!isSSR) {\n try {\n const g = globalThis as Record<string | symbol, unknown>;\n if (!g[GLOBAL_REG_KEY]) {\n // Use a unique registry per realm to avoid cross-contamination\n const realmId = crypto.randomUUID();\n g[GLOBAL_REG_KEY] = new Map([...registry.entries()]);\n // Store realm identifier for debugging\n (\n g[GLOBAL_REG_KEY] as Record<string, unknown> & { __realmId?: string }\n ).__realmId = realmId;\n }\n } catch (error) {\n // Gracefully handle cases where globalThis access is restricted\n devWarn('Could not initialize global registry:', error);\n }\n }\n}\n\n// --- Hot Module Replacement (HMR) ---\n{\n type HMRImportMeta = {\n hot?: { accept: (fn: (newModule?: unknown) => void) => void };\n };\n const hmrHot = (import.meta as HMRImportMeta).hot;\n if (hmrHot) {\n hmrHot.accept((newModule: unknown) => {\n // Update registry with new configs from the hot module (SSR-safe)\n const mod = newModule as\n | { registry?: Map<string, ComponentConfig<object, object, object>> }\n | undefined;\n if (mod && mod.registry) {\n for (const [tag, newConfig] of mod.registry.entries()) {\n registry.set(tag, newConfig);\n // Update all instances to use new config (browser only)\n if (typeof document !== 'undefined' && document.querySelectorAll) {\n try {\n document.querySelectorAll(tag).forEach((el) => {\n const customEl = el as CustomElement;\n if (typeof customEl._cfg !== 'undefined') {\n customEl._cfg = newConfig;\n }\n // HMR: Preserve existing state by keeping the context object intact.\n // Instead of re-executing the component function (which would create new refs),\n // we just update the config and re-render with the existing context.\n // This ensures refs and other reactive state are preserved across HMR updates.\n if (typeof customEl._render === 'function') {\n customEl._render(newConfig);\n }\n });\n } catch (error) {\n devWarn('HMR update failed:', error);\n }\n }\n }\n }\n });\n }\n}\n","/**\n * Namespace-aware attribute helpers.\n * Provides small, fast utilities to set/remove attributes using the\n * appropriate namespace when an attribute uses a known prefix (e.g. xlink:href).\n */\n\nconst ATTR_NAMESPACE_MAP: Record<string, string> = {\n xlink: 'http://www.w3.org/1999/xlink',\n xml: 'http://www.w3.org/XML/1998/namespace',\n};\n\n/**\n * Set attribute using namespace when the key contains a known prefix.\n */\nexport function setAttributeSmart(\n el: Element,\n key: string,\n value: string,\n): void {\n try {\n if (!key || !key.includes(':')) {\n el.setAttribute(key, value);\n return;\n }\n const idx = key.indexOf(':');\n const prefix = key.substring(0, idx);\n const local = key.substring(idx + 1);\n const ns = ATTR_NAMESPACE_MAP[prefix];\n if (ns) el.setAttributeNS(ns, local, value);\n else el.setAttribute(key, value);\n } catch {\n try {\n // Fallback to un-namespaced setAttribute on error\n el.setAttribute(key, value);\n } catch {\n /* swallow */\n }\n }\n}\n\n/**\n * Remove attribute using namespace when the key contains a known prefix.\n */\nexport function removeAttributeSmart(el: Element, key: string): void {\n try {\n if (!key || !key.includes(':')) {\n el.removeAttribute(key);\n return;\n }\n const idx = key.indexOf(':');\n const prefix = key.substring(0, idx);\n const local = key.substring(idx + 1);\n const ns = ATTR_NAMESPACE_MAP[prefix];\n if (ns) el.removeAttributeNS(ns, local);\n else el.removeAttribute(key);\n } catch {\n try {\n el.removeAttribute(key);\n } catch {\n /* swallow */\n }\n }\n}\n\nexport const __TEST_ONLY_ATTR_NS_MAP = ATTR_NAMESPACE_MAP;\n\n// Common element namespace URIs and a small tag->namespace map used by\n// both the client renderer and the SSR serializer. Exporting these from\n// this module keeps namespace knowledge centralized and prevents\n// accidental duplication between runtime and SSR code.\nexport const SVG_NS = 'http://www.w3.org/2000/svg';\nexport const MATHML_NS = 'http://www.w3.org/1998/Math/MathML';\n\nexport const TAG_NAMESPACE_MAP: Record<string, string> = {\n svg: SVG_NS,\n math: MATHML_NS,\n};\n"],"mappings":";;AAkBA,IAAa,oBAAW,IAAI,KAGzB,EAIG,IAAiB,OAAO,IAAI,eAAe;AAQjD,SAAgB,IAAmC;AAOjD,KAAI,EAJF,OAAO,SAAW,OAClB,OAAO,WAAa,OACpB,OAAO,YAAc,KAGrB,KAAI;EACF,IAAM,IAAI;AACV,MAAI,CAAC,EAAE,IAAiB;GAEtB,IAAM,IAAU,OAAO,YAAY;AAIjC,GAHF,EAAE,KAAkB,IAAI,IAAI,CAAC,GAAG,EAAS,SAAS,CAAC,CAAC,EAGlD,EAAE,GACF,YAAY;;UAET,GAAO;AAEd,IAAQ,yCAAyC,EAAM;;;;;AChD7D,IAAM,IAA6C;CACjD,OAAO;CACP,KAAK;CACN;AAKD,SAAgB,EACd,GACA,GACA,GACM;AACN,KAAI;AACF,MAAI,CAAC,KAAO,CAAC,EAAI,SAAS,IAAI,EAAE;AAC9B,KAAG,aAAa,GAAK,EAAM;AAC3B;;EAEF,IAAM,IAAM,EAAI,QAAQ,IAAI,EACtB,IAAS,EAAI,UAAU,GAAG,EAAI,EAC9B,IAAQ,EAAI,UAAU,IAAM,EAAE,EAC9B,IAAK,EAAmB;AAC9B,EAAI,IAAI,EAAG,eAAe,GAAI,GAAO,EAAM,GACtC,EAAG,aAAa,GAAK,EAAM;SAC1B;AACN,MAAI;AAEF,KAAG,aAAa,GAAK,EAAM;UACrB;;;AASZ,SAAgB,EAAqB,GAAa,GAAmB;AACnE,KAAI;AACF,MAAI,CAAC,KAAO,CAAC,EAAI,SAAS,IAAI,EAAE;AAC9B,KAAG,gBAAgB,EAAI;AACvB;;EAEF,IAAM,IAAM,EAAI,QAAQ,IAAI,EACtB,IAAS,EAAI,UAAU,GAAG,EAAI,EAC9B,IAAQ,EAAI,UAAU,IAAM,EAAE,EAC9B,IAAK,EAAmB;AAC9B,EAAI,IAAI,EAAG,kBAAkB,GAAI,EAAM,GAClC,EAAG,gBAAgB,EAAI;SACtB;AACN,MAAI;AACF,KAAG,gBAAgB,EAAI;UACjB;;;AAYZ,IAAa,IAAS,8BAGT,IAA4C;CACvD,KAAK;CACL,MAJuB;CAKxB"}
@@ -0,0 +1,2 @@
1
+ const e=require(`./logger-Dkht1dCX.cjs`);var t=new Map,n=Symbol.for(`cer.registry`);function r(){if(!(typeof window>`u`&&typeof document>`u`&&typeof navigator>`u`))try{let e=globalThis;if(!e[n]){let r=crypto.randomUUID();e[n]=new Map([...t.entries()]),e[n].__realmId=r}}catch(t){e.r(`Could not initialize global registry:`,t)}}var i={xlink:`http://www.w3.org/1999/xlink`,xml:`http://www.w3.org/XML/1998/namespace`};function a(e,t,n){try{if(!t||!t.includes(`:`)){e.setAttribute(t,n);return}let r=t.indexOf(`:`),a=t.substring(0,r),o=t.substring(r+1),s=i[a];s?e.setAttributeNS(s,o,n):e.setAttribute(t,n)}catch{try{e.setAttribute(t,n)}catch{}}}function o(e,t){try{if(!t||!t.includes(`:`)){e.removeAttribute(t);return}let n=t.indexOf(`:`),r=t.substring(0,n),a=t.substring(n+1),o=i[r];o?e.removeAttributeNS(o,a):e.removeAttribute(t)}catch{try{e.removeAttribute(t)}catch{}}}var s=`http://www.w3.org/2000/svg`,c={svg:s,math:`http://www.w3.org/1998/Math/MathML`};Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return r}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return t}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return s}});
2
+ //# sourceMappingURL=namespace-helpers-yYIb7INq.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"namespace-helpers-Bf7rm9JV.cjs","names":[],"sources":["../src/lib/runtime/component/registry.ts","../src/lib/runtime/namespace-helpers.ts"],"sourcesContent":["import type { ComponentConfig } from '../types';\nimport { devWarn } from '../logger';\n\n// Interface for custom element with framework-specific properties\ninterface CustomElement extends HTMLElement {\n _cfg?: ComponentConfig<object, object, object>;\n _render?: (config: ComponentConfig<object, object, object>) => void;\n onLoadingStateChange?: (loading: boolean) => void;\n onErrorStateChange?: (error: Error | null) => void;\n}\n\n/**\n * @internal\n * Runtime registry of component configs.\n * NOTE: This is an internal implementation detail. Do not import from the\n * published package in consumer code — it is intended for runtime/HMR and\n * internal tests only. Consumers should use the public `component` API.\n */\nexport const registry = new Map<\n string,\n ComponentConfig<object, object, object>\n>();\n\n// Expose the registry for browser/HMR use without overwriting existing globals\n// (avoid cross-request mutation in SSR and preserve HMR behavior).\nconst GLOBAL_REG_KEY = Symbol.for('cer.registry');\n\n/**\n * Lazily initialize the global registry slot with SSR safety.\n * This avoids performing a write to globalThis at module-import time\n * (which is a side-effect that prevents bundlers from tree-shaking).\n * Enhanced with SSR detection and multi-tenant safety.\n */\nexport function initGlobalRegistryIfNeeded(): void {\n // Enhanced SSR detection\n const isSSR =\n typeof window === 'undefined' &&\n typeof document === 'undefined' &&\n typeof navigator === 'undefined';\n\n if (!isSSR) {\n try {\n const g = globalThis as Record<string | symbol, unknown>;\n if (!g[GLOBAL_REG_KEY]) {\n // Use a unique registry per realm to avoid cross-contamination\n const realmId = crypto.randomUUID();\n g[GLOBAL_REG_KEY] = new Map([...registry.entries()]);\n // Store realm identifier for debugging\n (\n g[GLOBAL_REG_KEY] as Record<string, unknown> & { __realmId?: string }\n ).__realmId = realmId;\n }\n } catch (error) {\n // Gracefully handle cases where globalThis access is restricted\n devWarn('Could not initialize global registry:', error);\n }\n }\n}\n\n// --- Hot Module Replacement (HMR) ---\n{\n type HMRImportMeta = {\n hot?: { accept: (fn: (newModule?: unknown) => void) => void };\n };\n const hmrHot = (import.meta as HMRImportMeta).hot;\n if (hmrHot) {\n hmrHot.accept((newModule: unknown) => {\n // Update registry with new configs from the hot module (SSR-safe)\n const mod = newModule as\n | { registry?: Map<string, ComponentConfig<object, object, object>> }\n | undefined;\n if (mod && mod.registry) {\n for (const [tag, newConfig] of mod.registry.entries()) {\n registry.set(tag, newConfig);\n // Update all instances to use new config (browser only)\n if (typeof document !== 'undefined' && document.querySelectorAll) {\n try {\n document.querySelectorAll(tag).forEach((el) => {\n const customEl = el as CustomElement;\n if (typeof customEl._cfg !== 'undefined') {\n customEl._cfg = newConfig;\n }\n // HMR: Preserve existing state by keeping the context object intact.\n // Instead of re-executing the component function (which would create new refs),\n // we just update the config and re-render with the existing context.\n // This ensures refs and other reactive state are preserved across HMR updates.\n if (typeof customEl._render === 'function') {\n customEl._render(newConfig);\n }\n });\n } catch (error) {\n devWarn('HMR update failed:', error);\n }\n }\n }\n }\n });\n }\n}\n","/**\n * Namespace-aware attribute helpers.\n * Provides small, fast utilities to set/remove attributes using the\n * appropriate namespace when an attribute uses a known prefix (e.g. xlink:href).\n */\n\nconst ATTR_NAMESPACE_MAP: Record<string, string> = {\n xlink: 'http://www.w3.org/1999/xlink',\n xml: 'http://www.w3.org/XML/1998/namespace',\n};\n\n/**\n * Set attribute using namespace when the key contains a known prefix.\n */\nexport function setAttributeSmart(\n el: Element,\n key: string,\n value: string,\n): void {\n try {\n if (!key || !key.includes(':')) {\n el.setAttribute(key, value);\n return;\n }\n const idx = key.indexOf(':');\n const prefix = key.substring(0, idx);\n const local = key.substring(idx + 1);\n const ns = ATTR_NAMESPACE_MAP[prefix];\n if (ns) el.setAttributeNS(ns, local, value);\n else el.setAttribute(key, value);\n } catch {\n try {\n // Fallback to un-namespaced setAttribute on error\n el.setAttribute(key, value);\n } catch {\n /* swallow */\n }\n }\n}\n\n/**\n * Remove attribute using namespace when the key contains a known prefix.\n */\nexport function removeAttributeSmart(el: Element, key: string): void {\n try {\n if (!key || !key.includes(':')) {\n el.removeAttribute(key);\n return;\n }\n const idx = key.indexOf(':');\n const prefix = key.substring(0, idx);\n const local = key.substring(idx + 1);\n const ns = ATTR_NAMESPACE_MAP[prefix];\n if (ns) el.removeAttributeNS(ns, local);\n else el.removeAttribute(key);\n } catch {\n try {\n el.removeAttribute(key);\n } catch {\n /* swallow */\n }\n }\n}\n\nexport const __TEST_ONLY_ATTR_NS_MAP = ATTR_NAMESPACE_MAP;\n\n// Common element namespace URIs and a small tag->namespace map used by\n// both the client renderer and the SSR serializer. Exporting these from\n// this module keeps namespace knowledge centralized and prevents\n// accidental duplication between runtime and SSR code.\nexport const SVG_NS = 'http://www.w3.org/2000/svg';\nexport const MATHML_NS = 'http://www.w3.org/1998/Math/MathML';\n\nexport const TAG_NAMESPACE_MAP: Record<string, string> = {\n svg: SVG_NS,\n math: MATHML_NS,\n};\n"],"mappings":"yCAkBA,IAAa,EAAW,IAAI,IAOtB,EAAiB,OAAO,IAAI,cAAA,EAQlC,SAAgB,GAAmC,CAOjD,GAAI,EAJF,OAAO,OAAW,KAClB,OAAO,SAAa,KACpB,OAAO,UAAc,KAGrB,GAAI,CACF,MAAM,EAAI,WACV,GAAI,CAAC,EAAE,CAAA,EAAiB,CAEtB,MAAM,EAAU,OAAO,WAAA,EACvB,EAAE,CAAA,EAAkB,IAAI,IAAI,CAAC,GAAG,EAAS,QAAA,CAAS,CAAC,EAGjD,EAAE,CAAA,EACF,UAAY,SAET,EAAO,CAEd,EAAA,QAAQ,wCAAyC,CAAA,GChDvD,IAAM,EAA6C,CACjD,MAAO,+BACP,IAAK,wCAMP,SAAgB,EACd,EACA,EACA,EACM,CACN,GAAI,CACF,GAAI,CAAC,GAAO,CAAC,EAAI,SAAS,GAAA,EAAM,CAC9B,EAAG,aAAa,EAAK,CAAA,EACrB,OAEF,MAAM,EAAM,EAAI,QAAQ,GAAA,EAClB,EAAS,EAAI,UAAU,EAAG,CAAA,EAC1B,EAAQ,EAAI,UAAU,EAAM,CAAA,EAC5B,EAAK,EAAmB,CAAA,EAC1B,EAAI,EAAG,eAAe,EAAI,EAAO,CAAA,EAChC,EAAG,aAAa,EAAK,CAAA,OACpB,CACN,GAAI,CAEF,EAAG,aAAa,EAAK,CAAA,OACf,CAAA,GASZ,SAAgB,EAAqB,EAAa,EAAmB,CACnE,GAAI,CACF,GAAI,CAAC,GAAO,CAAC,EAAI,SAAS,GAAA,EAAM,CAC9B,EAAG,gBAAgB,CAAA,EACnB,OAEF,MAAM,EAAM,EAAI,QAAQ,GAAA,EAClB,EAAS,EAAI,UAAU,EAAG,CAAA,EAC1B,EAAQ,EAAI,UAAU,EAAM,CAAA,EAC5B,EAAK,EAAmB,CAAA,EAC1B,EAAI,EAAG,kBAAkB,EAAI,CAAA,EAC5B,EAAG,gBAAgB,CAAA,OAClB,CACN,GAAI,CACF,EAAG,gBAAgB,CAAA,OACb,CAAA,GAYZ,IAAa,EAAS,6BACT,EAAY,qCAEZ,EAA4C,CACvD,IAAK,EACL,KAAM"}
1
+ {"version":3,"file":"namespace-helpers-yYIb7INq.cjs","names":[],"sources":["../src/lib/runtime/component/registry.ts","../src/lib/runtime/namespace-helpers.ts"],"sourcesContent":["import type { ComponentConfig } from '../types';\nimport { devWarn } from '../logger';\n\n// Interface for custom element with framework-specific properties\ninterface CustomElement extends HTMLElement {\n _cfg?: ComponentConfig<object, object, object>;\n _render?: (config: ComponentConfig<object, object, object>) => void;\n onLoadingStateChange?: (loading: boolean) => void;\n onErrorStateChange?: (error: Error | null) => void;\n}\n\n/**\n * @internal\n * Runtime registry of component configs.\n * NOTE: This is an internal implementation detail. Do not import from the\n * published package in consumer code — it is intended for runtime/HMR and\n * internal tests only. Consumers should use the public `component` API.\n */\nexport const registry = new Map<\n string,\n ComponentConfig<object, object, object>\n>();\n\n// Expose the registry for browser/HMR use without overwriting existing globals\n// (avoid cross-request mutation in SSR and preserve HMR behavior).\nconst GLOBAL_REG_KEY = Symbol.for('cer.registry');\n\n/**\n * Lazily initialize the global registry slot with SSR safety.\n * This avoids performing a write to globalThis at module-import time\n * (which is a side-effect that prevents bundlers from tree-shaking).\n * Enhanced with SSR detection and multi-tenant safety.\n */\nexport function initGlobalRegistryIfNeeded(): void {\n // Enhanced SSR detection\n const isSSR =\n typeof window === 'undefined' &&\n typeof document === 'undefined' &&\n typeof navigator === 'undefined';\n\n if (!isSSR) {\n try {\n const g = globalThis as Record<string | symbol, unknown>;\n if (!g[GLOBAL_REG_KEY]) {\n // Use a unique registry per realm to avoid cross-contamination\n const realmId = crypto.randomUUID();\n g[GLOBAL_REG_KEY] = new Map([...registry.entries()]);\n // Store realm identifier for debugging\n (\n g[GLOBAL_REG_KEY] as Record<string, unknown> & { __realmId?: string }\n ).__realmId = realmId;\n }\n } catch (error) {\n // Gracefully handle cases where globalThis access is restricted\n devWarn('Could not initialize global registry:', error);\n }\n }\n}\n\n// --- Hot Module Replacement (HMR) ---\n{\n type HMRImportMeta = {\n hot?: { accept: (fn: (newModule?: unknown) => void) => void };\n };\n const hmrHot = (import.meta as HMRImportMeta).hot;\n if (hmrHot) {\n hmrHot.accept((newModule: unknown) => {\n // Update registry with new configs from the hot module (SSR-safe)\n const mod = newModule as\n | { registry?: Map<string, ComponentConfig<object, object, object>> }\n | undefined;\n if (mod && mod.registry) {\n for (const [tag, newConfig] of mod.registry.entries()) {\n registry.set(tag, newConfig);\n // Update all instances to use new config (browser only)\n if (typeof document !== 'undefined' && document.querySelectorAll) {\n try {\n document.querySelectorAll(tag).forEach((el) => {\n const customEl = el as CustomElement;\n if (typeof customEl._cfg !== 'undefined') {\n customEl._cfg = newConfig;\n }\n // HMR: Preserve existing state by keeping the context object intact.\n // Instead of re-executing the component function (which would create new refs),\n // we just update the config and re-render with the existing context.\n // This ensures refs and other reactive state are preserved across HMR updates.\n if (typeof customEl._render === 'function') {\n customEl._render(newConfig);\n }\n });\n } catch (error) {\n devWarn('HMR update failed:', error);\n }\n }\n }\n }\n });\n }\n}\n","/**\n * Namespace-aware attribute helpers.\n * Provides small, fast utilities to set/remove attributes using the\n * appropriate namespace when an attribute uses a known prefix (e.g. xlink:href).\n */\n\nconst ATTR_NAMESPACE_MAP: Record<string, string> = {\n xlink: 'http://www.w3.org/1999/xlink',\n xml: 'http://www.w3.org/XML/1998/namespace',\n};\n\n/**\n * Set attribute using namespace when the key contains a known prefix.\n */\nexport function setAttributeSmart(\n el: Element,\n key: string,\n value: string,\n): void {\n try {\n if (!key || !key.includes(':')) {\n el.setAttribute(key, value);\n return;\n }\n const idx = key.indexOf(':');\n const prefix = key.substring(0, idx);\n const local = key.substring(idx + 1);\n const ns = ATTR_NAMESPACE_MAP[prefix];\n if (ns) el.setAttributeNS(ns, local, value);\n else el.setAttribute(key, value);\n } catch {\n try {\n // Fallback to un-namespaced setAttribute on error\n el.setAttribute(key, value);\n } catch {\n /* swallow */\n }\n }\n}\n\n/**\n * Remove attribute using namespace when the key contains a known prefix.\n */\nexport function removeAttributeSmart(el: Element, key: string): void {\n try {\n if (!key || !key.includes(':')) {\n el.removeAttribute(key);\n return;\n }\n const idx = key.indexOf(':');\n const prefix = key.substring(0, idx);\n const local = key.substring(idx + 1);\n const ns = ATTR_NAMESPACE_MAP[prefix];\n if (ns) el.removeAttributeNS(ns, local);\n else el.removeAttribute(key);\n } catch {\n try {\n el.removeAttribute(key);\n } catch {\n /* swallow */\n }\n }\n}\n\nexport const __TEST_ONLY_ATTR_NS_MAP = ATTR_NAMESPACE_MAP;\n\n// Common element namespace URIs and a small tag->namespace map used by\n// both the client renderer and the SSR serializer. Exporting these from\n// this module keeps namespace knowledge centralized and prevents\n// accidental duplication between runtime and SSR code.\nexport const SVG_NS = 'http://www.w3.org/2000/svg';\nexport const MATHML_NS = 'http://www.w3.org/1998/Math/MathML';\n\nexport const TAG_NAMESPACE_MAP: Record<string, string> = {\n svg: SVG_NS,\n math: MATHML_NS,\n};\n"],"mappings":"yCAkBA,IAAa,EAAW,IAAI,IAOtB,EAAiB,OAAO,IAAI,eAAe,CAQjD,SAAgB,GAAmC,CAOjD,GAAI,EAJF,OAAO,OAAW,KAClB,OAAO,SAAa,KACpB,OAAO,UAAc,KAGrB,GAAI,CACF,IAAM,EAAI,WACV,GAAI,CAAC,EAAE,GAAiB,CAEtB,IAAM,EAAU,OAAO,YAAY,CACnC,EAAE,GAAkB,IAAI,IAAI,CAAC,GAAG,EAAS,SAAS,CAAC,CAAC,CAGlD,EAAE,GACF,UAAY,SAET,EAAO,CAEd,EAAA,EAAQ,wCAAyC,EAAM,EChD7D,IAAM,EAA6C,CACjD,MAAO,+BACP,IAAK,uCACN,CAKD,SAAgB,EACd,EACA,EACA,EACM,CACN,GAAI,CACF,GAAI,CAAC,GAAO,CAAC,EAAI,SAAS,IAAI,CAAE,CAC9B,EAAG,aAAa,EAAK,EAAM,CAC3B,OAEF,IAAM,EAAM,EAAI,QAAQ,IAAI,CACtB,EAAS,EAAI,UAAU,EAAG,EAAI,CAC9B,EAAQ,EAAI,UAAU,EAAM,EAAE,CAC9B,EAAK,EAAmB,GAC1B,EAAI,EAAG,eAAe,EAAI,EAAO,EAAM,CACtC,EAAG,aAAa,EAAK,EAAM,MAC1B,CACN,GAAI,CAEF,EAAG,aAAa,EAAK,EAAM,MACrB,IASZ,SAAgB,EAAqB,EAAa,EAAmB,CACnE,GAAI,CACF,GAAI,CAAC,GAAO,CAAC,EAAI,SAAS,IAAI,CAAE,CAC9B,EAAG,gBAAgB,EAAI,CACvB,OAEF,IAAM,EAAM,EAAI,QAAQ,IAAI,CACtB,EAAS,EAAI,UAAU,EAAG,EAAI,CAC9B,EAAQ,EAAI,UAAU,EAAM,EAAE,CAC9B,EAAK,EAAmB,GAC1B,EAAI,EAAG,kBAAkB,EAAI,EAAM,CAClC,EAAG,gBAAgB,EAAI,MACtB,CACN,GAAI,CACF,EAAG,gBAAgB,EAAI,MACjB,IAYZ,IAAa,EAAS,6BAGT,EAA4C,CACvD,IAAK,EACL,KAJuB,qCAKxB"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Resolves a component() tag argument to the actual registered tag name.
3
+ * Single source of truth used by both factory.ts (runtime) and
4
+ * vite-plugin.ts (build time) so the two can never drift apart.
5
+ *
6
+ * Rules:
7
+ * camelCase → kebab-case (myButton → my-button)
8
+ * no hyphen → cer- prefix (app → cer-app)
9
+ * has hyphen → unchanged (ks-badge → ks-badge)
10
+ */
11
+ export declare function resolveTagName(name: string): string;