@jasonshimmy/custom-elements-runtime 2.5.1 → 2.5.2

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 (36) hide show
  1. package/dist/custom-elements-runtime.cjs.js +1 -18
  2. package/dist/custom-elements-runtime.cjs.js.map +1 -1
  3. package/dist/custom-elements-runtime.es.js +150 -3644
  4. package/dist/custom-elements-runtime.es.js.map +1 -1
  5. package/dist/custom-elements-runtime.router.cjs.js +19 -19
  6. package/dist/custom-elements-runtime.router.cjs.js.map +1 -1
  7. package/dist/custom-elements-runtime.router.es.js +762 -454
  8. package/dist/custom-elements-runtime.router.es.js.map +1 -1
  9. package/dist/custom-elements-runtime.ssr.cjs.js +1 -1
  10. package/dist/custom-elements-runtime.ssr.es.js +1 -1
  11. package/dist/custom-elements-runtime.transitions.cjs.js +1 -1
  12. package/dist/custom-elements-runtime.transitions.es.js +1 -1
  13. package/dist/index.d.ts +2 -0
  14. package/dist/namespace-helpers-BCVTzhAO.cjs +5 -0
  15. package/dist/namespace-helpers-BCVTzhAO.cjs.map +1 -0
  16. package/dist/namespace-helpers-CF28TyaG.js +786 -0
  17. package/dist/namespace-helpers-CF28TyaG.js.map +1 -0
  18. package/dist/router.d.ts +82 -21
  19. package/dist/runtime/monitoring/health-monitor.d.ts +99 -0
  20. package/dist/runtime/render.d.ts +1 -1
  21. package/dist/runtime/scheduler.d.ts +46 -0
  22. package/dist/template-compiler-CXHEnaBh.cjs +17 -0
  23. package/dist/template-compiler-CXHEnaBh.cjs.map +1 -0
  24. package/dist/template-compiler-DD_VZrte.js +3729 -0
  25. package/dist/template-compiler-DD_VZrte.js.map +1 -0
  26. package/dist/{transitions-CZ21fzhh.js → transitions-Bx0Nc9zR.js} +256 -255
  27. package/dist/transitions-Bx0Nc9zR.js.map +1 -0
  28. package/dist/{transitions-RXe2brRm.cjs → transitions-DfcqL-X4.cjs} +4 -4
  29. package/dist/transitions-DfcqL-X4.cjs.map +1 -0
  30. package/package.json +9 -8
  31. package/dist/namespace-helpers-BsKQl3aH.cjs +0 -5
  32. package/dist/namespace-helpers-BsKQl3aH.cjs.map +0 -1
  33. package/dist/namespace-helpers-Dw1mgQab.js +0 -692
  34. package/dist/namespace-helpers-Dw1mgQab.js.map +0 -1
  35. package/dist/transitions-CZ21fzhh.js.map +0 -1
  36. package/dist/transitions-RXe2brRm.cjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"namespace-helpers-CF28TyaG.js","sources":["../src/lib/runtime/scheduler.ts","../src/lib/runtime/reactive-proxy-cache.ts","../src/lib/runtime/reactive.ts","../src/lib/runtime/helpers.ts","../src/lib/runtime/namespace-helpers.ts"],"sourcesContent":["/**\n * Update Scheduler for batching DOM updates\n * Prevents excessive re-renders and improves performance\n */\nimport { devWarn, devError } from './logger';\n\n/**\n * Environment detection utilities\n */\ninterface TestEnvironment {\n isTest: boolean;\n isVitest: boolean;\n isCypress: boolean;\n}\n\n/**\n * Detect test environment with improved reliability\n */\nfunction detectTestEnvironment(): TestEnvironment {\n // Check Node.js environment first\n const nodeEnv = (() => {\n try {\n const process = (\n globalThis as { process?: { env?: { NODE_ENV?: string } } }\n ).process;\n return process?.env?.NODE_ENV;\n } catch {\n return undefined;\n }\n })();\n\n // Check browser test environments\n const browserTestEnv = (() => {\n try {\n if (typeof window === 'undefined')\n return { vitest: false, cypress: false };\n\n const win = window as { __vitest__?: unknown; Cypress?: unknown };\n return {\n vitest: Boolean(win.__vitest__),\n cypress: Boolean(win.Cypress),\n };\n } catch {\n return { vitest: false, cypress: false };\n }\n })();\n\n const isTest =\n nodeEnv === 'test' || browserTestEnv.vitest || browserTestEnv.cypress;\n\n return {\n isTest,\n isVitest: browserTestEnv.vitest,\n isCypress: browserTestEnv.cypress,\n };\n}\n\nclass UpdateScheduler {\n private pendingUpdates = new Map<string | (() => void), () => void>();\n private isFlushScheduled = false;\n private isFlushing = false;\n private readonly testEnv: TestEnvironment;\n private lastCleanup = 0;\n private readonly CLEANUP_INTERVAL = 5 * 60 * 1000; // 5 minutes\n private readonly MAX_PENDING_SIZE = 10000; // Prevent memory bloat\n\n constructor() {\n // Cache environment detection result to avoid repeated checks\n this.testEnv = detectTestEnvironment();\n this.schedulePeriodicCleanup();\n }\n\n /**\n * Schedule an update to be executed in the next microtask\n * Uses component identity to deduplicate multiple render requests for the same component\n */\n schedule(update: () => void, componentId?: string): void {\n // IMPORTANT: Never use update.toString() as it breaks with minification!\n // Use the componentId if provided, otherwise use the function reference directly as the key\n // since Map supports using function references as keys (identity-based comparison)\n const key = componentId || update;\n\n // Prevent memory bloat by limiting pending updates\n if (this.pendingUpdates.size >= this.MAX_PENDING_SIZE) {\n this.performEmergencyCleanup();\n }\n\n this.pendingUpdates.set(key, update);\n\n if (!this.isFlushScheduled) {\n this.scheduleFlush();\n }\n }\n\n /**\n * Schedule the flush operation based on environment\n */\n private scheduleFlush(): void {\n this.isFlushScheduled = true;\n\n if (this.testEnv.isTest && !this.isFlushing) {\n // Safe to flush synchronously in test environment to avoid timing issues\n this.flush();\n } else {\n // Batch via microtask in production or when already flushing\n queueMicrotask(() => this.flush());\n }\n }\n\n /**\n * Execute all pending updates\n */\n private flush(): void {\n // Prevent reentrant flushes\n if (this.isFlushing) {\n return;\n }\n\n this.isFlushing = true;\n\n // Capture current updates and reset state\n const updates = this.pendingUpdates;\n this.pendingUpdates = new Map();\n this.isFlushScheduled = false;\n\n try {\n // Execute all updates in batch\n for (const update of updates.values()) {\n try {\n update();\n } catch (error) {\n // Continue with other updates even if one fails\n devError('Error in batched update:', error);\n }\n }\n } finally {\n this.isFlushing = false;\n }\n }\n\n /**\n * Force flush any pending DOM updates immediately. This is useful in\n * test environments or callers that require synchronous guarantees after\n * state changes. Prefer relying on the scheduler's automatic flush when\n * possible; use this only when a caller needs to synchronously observe\n * rendered DOM changes.\n */\n flushImmediately(): void {\n if (this.pendingUpdates.size === 0) {\n return;\n }\n\n // Clear any scheduled flush since we're doing it now\n this.isFlushScheduled = false;\n this.flush();\n }\n\n /**\n * Get the number of pending updates\n */\n get pendingCount(): number {\n return this.pendingUpdates.size;\n }\n\n /**\n * Check if there are pending updates\n */\n get hasPendingUpdates(): boolean {\n return this.pendingUpdates.size > 0;\n }\n\n /**\n * Check if currently flushing updates\n */\n get isFlushingUpdates(): boolean {\n return this.isFlushing;\n }\n\n /**\n * Schedule periodic cleanup to prevent memory leaks\n */\n private schedulePeriodicCleanup(): void {\n if (this.testEnv.isTest) return; // Skip in tests\n\n const cleanup = () => {\n this.performPeriodicCleanup();\n if (!this.testEnv.isTest) {\n setTimeout(cleanup, this.CLEANUP_INTERVAL);\n }\n };\n\n setTimeout(cleanup, this.CLEANUP_INTERVAL);\n }\n\n /**\n * Perform periodic cleanup of stale entries\n */\n private performPeriodicCleanup(): void {\n const now = Date.now();\n if (now - this.lastCleanup < this.CLEANUP_INTERVAL) return;\n\n // In normal operation, pending updates should be processed quickly\n // If we have many pending updates for a long time, something might be wrong\n if (this.pendingUpdates.size > 100) {\n devWarn(\n `Scheduler has ${this.pendingUpdates.size} pending updates. Consider investigating.`,\n );\n }\n\n this.lastCleanup = now;\n }\n\n /**\n * Emergency cleanup when pending updates exceed safe limits\n */\n private performEmergencyCleanup(): void {\n devWarn(\n 'Scheduler emergency cleanup: too many pending updates, clearing oldest entries',\n );\n\n // Clear half of the pending updates (oldest first by insertion order)\n const entries = Array.from(this.pendingUpdates.entries());\n const toRemove = Math.floor(entries.length / 2);\n\n for (let i = 0; i < toRemove; i++) {\n this.pendingUpdates.delete(entries[i][0]);\n }\n }\n}\n\n// Global scheduler instance\nexport const updateScheduler = new UpdateScheduler();\n\n/**\n * Schedule a DOM update to be batched with optional component identity\n */\nexport function scheduleDOMUpdate(\n update: () => void,\n componentId?: string,\n): void {\n updateScheduler.schedule(update, componentId);\n}\n\n/**\n * Force flush any pending DOM updates immediately. This is useful in\n * test environments or callers that require synchronous guarantees after\n * state changes. Prefer relying on the scheduler's automatic flush when\n * possible; use this only when a caller needs to synchronously observe\n * rendered DOM changes.\n */\nexport function flushDOMUpdates(): void {\n updateScheduler.flushImmediately();\n}\n","/**\n * Reactive proxy cache to optimize proxy creation and reuse\n * Uses WeakMap for automatic garbage collection when objects are no longer referenced\n */\n\n/**\n * Cache for reactive proxies to avoid creating multiple proxies for the same object\n */\n// legacy symbol marker removed — use WeakSet and non-enumerable flag instead\n// Track actual proxy instances with a WeakSet for robust detection\nconst proxiedObjects = new WeakSet<object>();\n// No legacy flag: rely solely on WeakSet and WeakMap for proxy detection\n\nclass ReactiveProxyCache {\n private static cache = new WeakMap<object, object>();\n private static arrayHandlerCache = new WeakMap<\n object,\n ProxyHandler<object>\n >();\n private static objectHandlerCache = new WeakMap<\n object,\n ProxyHandler<object>\n >();\n\n /**\n * Get or create a reactive proxy for an object\n */\n static getOrCreateProxy<T extends object>(\n obj: T,\n reactiveState: {\n triggerUpdate: () => void;\n makeReactiveValue: (value: unknown) => unknown;\n },\n isArray: boolean = false,\n ): T {\n // Check if we already have a cached proxy\n const cached = this.cache.get(obj);\n if (cached) {\n return cached as T;\n }\n\n // Create appropriate handler\n const handler = isArray\n ? this.getOrCreateArrayHandler(reactiveState)\n : this.getOrCreateObjectHandler(reactiveState);\n\n // Create proxy\n const proxy = new Proxy(obj, handler);\n\n // Mark and track the proxy instance (do this via the optimizer helper)\n try {\n ProxyOptimizer.markAsProxy(proxy as Record<string | symbol, unknown>);\n } catch {\n void 0;\n }\n\n // Cache the proxy by the original target object\n this.cache.set(obj, proxy);\n\n return proxy as T;\n }\n\n /**\n * Get or create a cached array handler\n */\n private static getOrCreateArrayHandler(reactiveState: {\n triggerUpdate: () => void;\n makeReactiveValue: (value: unknown) => unknown;\n }): ProxyHandler<object> {\n // Create a unique handler for this reactive state\n if (!this.arrayHandlerCache.has(reactiveState)) {\n const handler: ProxyHandler<unknown[]> = {\n get: (target, prop, receiver) => {\n const value = Reflect.get(target, prop, receiver);\n\n // Intercept array mutating methods\n if (typeof value === 'function' && typeof prop === 'string') {\n const mutatingMethods = [\n 'push',\n 'pop',\n 'shift',\n 'unshift',\n 'splice',\n 'sort',\n 'reverse',\n 'fill',\n 'copyWithin',\n ];\n if (mutatingMethods.includes(prop)) {\n return function (...args: unknown[]) {\n const result = value.apply(target, args);\n // Trigger update after mutation\n reactiveState.triggerUpdate();\n return result;\n };\n }\n }\n\n return value;\n },\n set: (target, prop, value) => {\n (target as unknown as Record<string | symbol, unknown>)[prop] =\n reactiveState.makeReactiveValue(value);\n reactiveState.triggerUpdate();\n return true;\n },\n deleteProperty: (target, prop) => {\n delete (target as unknown as Record<string | symbol, unknown>)[prop];\n reactiveState.triggerUpdate();\n return true;\n },\n };\n\n this.arrayHandlerCache.set(reactiveState, handler);\n }\n\n return this.arrayHandlerCache.get(reactiveState)!;\n }\n\n /**\n * Get or create a cached object handler\n */\n private static getOrCreateObjectHandler(reactiveState: {\n triggerUpdate: () => void;\n makeReactiveValue: (value: unknown) => unknown;\n }): ProxyHandler<object> {\n // Create a unique handler for this reactive state\n if (!this.objectHandlerCache.has(reactiveState)) {\n const handler: ProxyHandler<Record<string | symbol, unknown>> = {\n get: (target, prop, receiver) => {\n return Reflect.get(target, prop, receiver);\n },\n set: (target, prop, value) => {\n (target as Record<string | symbol, unknown>)[prop] =\n reactiveState.makeReactiveValue(value);\n reactiveState.triggerUpdate();\n return true;\n },\n deleteProperty: (target, prop) => {\n delete (target as Record<string | symbol, unknown>)[prop];\n reactiveState.triggerUpdate();\n return true;\n },\n };\n\n this.objectHandlerCache.set(reactiveState, handler);\n }\n\n return this.objectHandlerCache.get(reactiveState)!;\n }\n\n /**\n * Check if an object already has a cached proxy\n */\n static hasProxy(obj: object): boolean {\n return this.cache.has(obj);\n }\n\n /**\n * Clear all cached proxies (useful for testing)\n */\n static clear(): void {\n this.cache = new WeakMap();\n this.arrayHandlerCache = new WeakMap();\n this.objectHandlerCache = new WeakMap();\n }\n\n /**\n * Get cache statistics (for debugging)\n * Note: WeakMap doesn't provide size, so this is limited\n */\n static getStats(): { hasCachedProxies: boolean } {\n // WeakMap doesn't expose size, but we can check if we have any handlers cached\n return {\n hasCachedProxies: this.cache instanceof WeakMap,\n };\n }\n}\n\n/**\n * Optimized proxy creation utilities\n */\nclass ProxyOptimizer {\n // Cache a stable reactiveContext object keyed by onUpdate -> makeReactive\n // This allows handler caches in ReactiveProxyCache to reuse handlers\n // for identical reactive contexts instead of creating a new context object\n // on each createReactiveProxy call.\n private static contextCache = new WeakMap<\n (...args: unknown[]) => unknown,\n WeakMap<\n (...args: unknown[]) => unknown,\n {\n triggerUpdate: () => void;\n makeReactiveValue: (value: unknown) => unknown;\n }\n >\n >();\n /**\n * Create an optimized reactive proxy with minimal overhead\n */\n static createReactiveProxy<T extends object>(\n obj: T,\n onUpdate: () => void,\n makeReactive: (value: unknown) => unknown,\n ): T {\n // If the argument is already a proxy instance, return it directly.\n try {\n if (proxiedObjects.has(obj)) return obj;\n } catch {\n // ignore\n }\n\n const isArray = Array.isArray(obj);\n\n // Reuse a stable reactiveContext object per (onUpdate, makeReactive) pair.\n let inner = this.contextCache.get(onUpdate);\n if (!inner) {\n inner = new WeakMap();\n this.contextCache.set(onUpdate, inner);\n }\n let reactiveContext = inner.get(makeReactive);\n if (!reactiveContext) {\n reactiveContext = {\n triggerUpdate: onUpdate,\n makeReactiveValue: makeReactive,\n };\n inner.set(makeReactive, reactiveContext);\n }\n\n // Delegate to the cache which will return an existing proxy for the target\n // or create one if it doesn't exist yet.\n return ReactiveProxyCache.getOrCreateProxy(obj, reactiveContext, isArray);\n }\n\n /**\n * Mark an object as a proxy (for optimization)\n */\n static markAsProxy(obj: object): void {\n if (!obj) return;\n\n // Prefer adding the actual proxy instance to the WeakSet which does not trigger proxy traps\n try {\n proxiedObjects.add(obj);\n } catch {\n // ignore\n }\n }\n}\n\nexport { ReactiveProxyCache, ProxyOptimizer };\n","import { scheduleDOMUpdate } from './scheduler';\nimport { ProxyOptimizer } from './reactive-proxy-cache';\nimport { devWarn } from './logger';\n\n/**\n * Global reactive system for tracking dependencies and triggering updates\n */\nclass ReactiveSystem {\n // Use a stack to support nested callers (component render -> watcher)\n // so that watchers can temporarily become the \"current component\" while\n // establishing dependencies without clobbering the outer component id.\n private currentComponentStack: string[] = [];\n // Consolidated component data: stores dependencies, render function, state index, and last warning time\n private componentData = new Map<\n string,\n {\n dependencies: Set<ReactiveState<unknown>>;\n renderFn: () => void;\n stateIndex: number;\n lastWarnTime: number;\n // watchers registered by the component during render\n watchers: Map<string, string>;\n }\n >();\n // Flat storage: compound key `${componentId}:${stateIndex}` -> ReactiveState\n private stateStorage = new Map<string, ReactiveState<unknown>>();\n private trackingDisabled = false;\n\n /**\n * Set the current component being rendered for dependency tracking\n */\n setCurrentComponent(componentId: string, renderFn: () => void): void {\n // Push onto the stack so nested calls can restore previous component\n this.currentComponentStack.push(componentId);\n // (no-op) push logged in debug builds\n if (!this.componentData.has(componentId)) {\n this.componentData.set(componentId, {\n dependencies: new Set(),\n renderFn,\n stateIndex: 0,\n lastWarnTime: 0,\n watchers: new Map(),\n });\n } else {\n const data = this.componentData.get(componentId)!;\n // Clean up watchers from previous renders so they don't accumulate\n if (data.watchers && data.watchers.size) {\n for (const wid of data.watchers.values()) {\n try {\n this.cleanup(wid);\n } catch {\n // swallow\n }\n }\n data.watchers.clear();\n }\n data.renderFn = renderFn;\n data.stateIndex = 0; // Reset state index for this render\n }\n }\n\n /**\n * Clear the current component after rendering\n */\n clearCurrentComponent(): void {\n // Pop the current component off the stack and restore the previous one\n this.currentComponentStack.pop();\n }\n\n /**\n * Get the current component id (top of stack) or null\n */\n getCurrentComponentId(): string | null {\n return this.currentComponentStack.length\n ? this.currentComponentStack[this.currentComponentStack.length - 1]\n : null;\n }\n\n /**\n * Register a watcher id under a component so it can be cleaned up on re-render\n */\n registerWatcher(componentId: string, watcherId: string): void {\n const data = this.componentData.get(componentId);\n if (!data) return;\n data.watchers.set(watcherId, watcherId);\n }\n\n /**\n * Temporarily disable dependency tracking\n */\n disableTracking(): void {\n this.trackingDisabled = true;\n }\n\n /**\n * Re-enable dependency tracking\n */\n enableTracking(): void {\n this.trackingDisabled = false;\n }\n\n /**\n * Check if a component is currently rendering\n */\n isRenderingComponent(): boolean {\n return this.currentComponentStack.length > 0;\n }\n\n /**\n * Return whether we should emit a render-time warning for the current component.\n * This throttles warnings to avoid spamming the console for legitimate rapid updates.\n */\n shouldEmitRenderWarning(): boolean {\n const current = this.currentComponentStack.length\n ? this.currentComponentStack[this.currentComponentStack.length - 1]\n : null;\n if (!current) return true;\n const data = this.componentData.get(current);\n if (!data) return true;\n\n const now = Date.now();\n const THROTTLE_MS = 1000; // 1 second per component\n if (now - data.lastWarnTime < THROTTLE_MS) return false;\n\n data.lastWarnTime = now;\n return true;\n }\n\n /**\n * Execute a function with tracking disabled\n */\n withoutTracking<T>(fn: () => T): T {\n const wasDisabled = this.trackingDisabled;\n this.trackingDisabled = true;\n try {\n return fn();\n } finally {\n this.trackingDisabled = wasDisabled;\n }\n }\n\n /**\n * Get or create a state instance for the current component\n */\n getOrCreateState<T>(initialValue: T): ReactiveState<T> {\n const current = this.currentComponentStack.length\n ? this.currentComponentStack[this.currentComponentStack.length - 1]\n : null;\n if (!current) {\n return new ReactiveState(initialValue);\n }\n\n const data = this.componentData.get(current);\n if (!data) {\n return new ReactiveState(initialValue);\n }\n const stateKey = `${current}:${data.stateIndex++}`;\n let state = this.stateStorage.get(stateKey) as ReactiveState<T> | undefined;\n\n if (!state) {\n state = new ReactiveState(initialValue);\n this.stateStorage.set(stateKey, state);\n }\n\n return state;\n }\n\n /**\n * Track a dependency for the current component\n */\n trackDependency(state: ReactiveState<unknown>): void {\n if (this.trackingDisabled) return;\n const current = this.currentComponentStack.length\n ? this.currentComponentStack[this.currentComponentStack.length - 1]\n : null;\n if (!current) return;\n\n const data = this.componentData.get(current);\n if (data) {\n data.dependencies.add(state);\n state.addDependent(current);\n // dependency tracked\n }\n }\n\n /**\n * Trigger updates for all components that depend on a state\n */\n triggerUpdate(state: ReactiveState<unknown>): void {\n const deps = state.getDependents();\n // trigger update for dependents\n for (const componentId of deps) {\n const data = this.componentData.get(componentId);\n if (data) {\n scheduleDOMUpdate(data.renderFn, componentId);\n }\n }\n }\n\n /**\n * Clean up component dependencies when component is destroyed\n */\n cleanup(componentId: string): void {\n const data = this.componentData.get(componentId);\n if (data) {\n for (const state of data.dependencies) {\n state.removeDependent(componentId);\n }\n this.componentData.delete(componentId);\n }\n // Remove any flat-stored state keys for this component\n const prefix = componentId + ':';\n for (const key of this.stateStorage.keys()) {\n if (key.startsWith(prefix)) {\n this.stateStorage.delete(key);\n }\n }\n }\n}\n\nconst reactiveSystem = new ReactiveSystem();\n\n// Export for internal use\nexport { reactiveSystem };\n\n/**\n * Internal reactive state class\n */\nexport class ReactiveState<T> {\n private _value: T;\n private dependents = new Set<string>();\n\n constructor(initialValue: T) {\n this._value = this.makeReactive(initialValue);\n // Mark instances with a stable cross-bundle symbol so other modules\n // can reliably detect ReactiveState objects even when classes are\n // renamed/minified or when multiple copies of the package exist.\n try {\n // Use a global symbol key to make it resilient across realms/bundles\n const key = Symbol.for('@cer/ReactiveState');\n Object.defineProperty(this, key, {\n value: true,\n enumerable: false,\n configurable: false,\n });\n } catch {\n // ignore if Symbol.for or defineProperty fails in exotic runtimes\n }\n }\n\n get value(): T {\n // Track this state as a dependency when accessed during render\n reactiveSystem.trackDependency(this);\n return this._value;\n }\n\n set value(newValue: T) {\n // Check for state modifications during render (potential infinite loop)\n if (reactiveSystem.isRenderingComponent()) {\n if (reactiveSystem.shouldEmitRenderWarning()) {\n devWarn(\n '🚨 State modification detected during render! This can cause infinite loops.\\n' +\n ' • Move state updates to event handlers\\n' +\n ' • Use useEffect/watch for side effects\\n' +\n \" • Ensure computed properties don't modify state\",\n );\n }\n }\n\n this._value = this.makeReactive(newValue);\n // Trigger updates for all dependent components\n reactiveSystem.triggerUpdate(this);\n }\n\n addDependent(componentId: string): void {\n this.dependents.add(componentId);\n }\n\n removeDependent(componentId: string): void {\n this.dependents.delete(componentId);\n }\n\n getDependents(): Set<string> {\n return this.dependents;\n }\n\n private makeReactive<U>(obj: U): U {\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n // Skip reactivity for DOM nodes - they should not be made reactive\n if (\n (obj as unknown) instanceof Node ||\n (obj as unknown) instanceof Element ||\n (obj as unknown) instanceof HTMLElement\n ) {\n return obj;\n }\n\n // Use optimized proxy creation\n return ProxyOptimizer.createReactiveProxy(\n obj as unknown as object,\n () => reactiveSystem.triggerUpdate(this),\n (value: unknown) => this.makeReactive(value),\n ) as U;\n }\n}\n\n/**\n * Create reactive state that automatically triggers component re-renders\n * when accessed during render and modified afterwards.\n * Defaults to null if no initial value is provided (Vue-style ref).\n *\n * @example\n * ```ts\n * const counter = ref(0);\n * const user = ref({ name: 'John', age: 30 });\n * const emptyRef = ref(); // defaults to null\n *\n * // Usage in component\n * counter.value++; // triggers re-render\n * user.value.name = 'Jane'; // triggers re-render\n * console.log(emptyRef.value); // null\n * ```\n */\nexport function ref(): ReactiveState<null>;\nexport function ref<T>(initialValue: T): ReactiveState<T>;\nexport function ref<T>(initialValue?: T): ReactiveState<T | null> {\n // Ensure the created state has the union type T | null and explicitly\n // tell getOrCreateState the correct generic to avoid conditional-type recursion.\n return reactiveSystem.getOrCreateState<T | null>(\n (initialValue === undefined ? null : (initialValue as T)) as T | null,\n );\n}\n\n/**\n * Type guard to detect ReactiveState instances in a robust way that works\n * across bundlers, minifiers, and multiple package copies.\n */\nexport function isReactiveState(v: unknown): v is ReactiveState<unknown> {\n if (!v || typeof v !== 'object') return false;\n try {\n const key = Symbol.for('@cer/ReactiveState');\n // Safely check for the presence of the symbol-keyed property without indexing with a unique symbol\n return Object.prototype.hasOwnProperty.call(v, key);\n } catch {\n return false;\n }\n}\n\n/**\n * Create computed state that derives from other reactive state\n *\n * @example\n * ```ts\n * const firstName = ref('John');\n * const lastName = ref('Doe');\n * const fullName = computed(() => `${firstName.value} ${lastName.value}`);\n * ```\n */\nexport function computed<T>(fn: () => T): { readonly value: T } {\n const computedState = new ReactiveState(fn());\n\n // We need to track dependencies when the computed function runs\n // For now, we'll re-evaluate on every access (can be optimized later)\n return {\n get value(): T {\n reactiveSystem.trackDependency(computedState as ReactiveState<unknown>);\n return fn();\n },\n };\n}\n\n/**\n * Create a watcher that runs when dependencies change\n *\n * @example\n * ```ts\n * const count = ref(0);\n * watch(() => count.value, (newVal, oldVal) => {\n * console.log(`Count changed from ${oldVal} to ${newVal}`);\n * });\n * ```\n */\nexport function watch<T>(\n source: ReactiveState<T>,\n callback: (newValue: T, oldValue?: T) => void,\n options?: { immediate?: boolean },\n): () => void;\nexport function watch<T>(\n source: () => T,\n callback: (newValue: T, oldValue?: T) => void,\n options?: { immediate?: boolean },\n): () => void;\nexport function watch<T>(\n source: ReactiveState<T> | (() => T),\n callback: (newValue: T, oldValue?: T) => void,\n options?: { immediate?: boolean },\n): () => void {\n // Note: we must establish reactive dependencies first (a tracked\n // call) and only then capture the initial `oldValue`. Capturing\n // `oldValue` before registering as a dependent means the first\n // tracked value may differ and lead to missed or spurious callbacks.\n let oldValue: T;\n // Normalize source: accept either a ReactiveState or a getter function\n const getter: () => T = ((): (() => T) => {\n // runtime check for ReactiveState instances\n if (isReactiveState(source)) {\n // cast to ReactiveState<T> and return getter\n return () => (source as ReactiveState<T>).value;\n }\n return source as () => T;\n })();\n\n // Create a dummy component to track dependencies\n const watcherId = `watch-${Math.random().toString(36).substr(2, 9)}`;\n\n // If called during a component render, register this watcher under that\n // component so watchers created in render are cleaned up on re-render.\n try {\n const parentComp = reactiveSystem.getCurrentComponentId();\n if (parentComp) {\n reactiveSystem.registerWatcher(parentComp, watcherId);\n }\n } catch {\n /* ignore */\n }\n\n const updateWatcher = () => {\n reactiveSystem.setCurrentComponent(watcherId, updateWatcher);\n const newValue = getter();\n reactiveSystem.clearCurrentComponent();\n\n if (newValue !== oldValue) {\n callback(newValue, oldValue);\n oldValue = newValue;\n }\n };\n\n // Initial run to establish dependencies\n reactiveSystem.setCurrentComponent(watcherId, updateWatcher);\n // Capture the tracked initial value as the baseline\n oldValue = getter();\n reactiveSystem.clearCurrentComponent();\n\n // If immediate is requested, invoke the callback once with the\n // current value as `newValue` and `undefined` as the previous value\n // to match Vue's common semantics.\n if (options && options.immediate) {\n callback(oldValue, undefined);\n }\n\n // Return cleanup function\n return () => {\n reactiveSystem.cleanup(watcherId);\n };\n}\n","/**\n * Safe execution helper - silently ignores errors\n */\nexport const safe = (fn: () => void): void => {\n try {\n fn();\n } catch {\n void 0;\n }\n};\n\nimport { isReactiveState } from './reactive';\nimport { devWarn } from './logger';\n\n// Caches for string transformations to improve performance\nconst KEBAB_CASE_CACHE = new Map<string, string>();\nconst CAMEL_CASE_CACHE = new Map<string, string>();\nconst HTML_ESCAPE_CACHE = new Map<string, string>();\n\n// Cache size limits to prevent memory bloat\nconst MAX_CACHE_SIZE = 500;\n\n// Module-level state for entity map and loader. Using module-level vars avoids\n// reliance on attaching properties to functions which can be brittle when\n// minifiers are configured to mangle properties.\nlet _namedEntityMap: Record<string, string> | undefined;\n// eslint-disable-next-line prefer-const\nlet _namedEntityMapLoader: (() => Promise<Record<string, string>>) | undefined;\nlet _usedEntityFallback = false;\nlet _warnedEntityFallback = false;\n// Module-level decode element used in browser environments to avoid attaching\n// an element to the function object (function properties can be mangled by\n// aggressive minifiers). Keep a function-attached reference only for backward\n// compatibility but prefer `_decodeEl` at runtime.\nlet _decodeEl: HTMLDivElement | undefined;\n// NOTE (internal): The runtime prefers module-level state for the entity map\n// and decode element to ensure minifier-safe behavior in production builds.\n// We intentionally retain assignments to function-attached properties in a\n// few places solely for backward compatibility with older tests and code\n// paths. New code should rely on `registerEntityMap`, `loadEntityMap`, and\n// the exported `decodeEntities` function rather than inspecting internal\n// function properties.\n// Use globalThis to avoid TypeScript requiring Node typings for `process`.\nconst _isNode = !!(globalThis as { process?: { versions?: { node?: string } } })\n .process?.versions?.node;\n\n/**\n * Convert camelCase to kebab-case with caching\n */\nexport function toKebab(str: string): string {\n if (KEBAB_CASE_CACHE.has(str)) {\n return KEBAB_CASE_CACHE.get(str)!;\n }\n\n const result = str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();\n\n // Prevent memory bloat with size limit\n if (KEBAB_CASE_CACHE.size < MAX_CACHE_SIZE) {\n KEBAB_CASE_CACHE.set(str, result);\n }\n\n return result;\n}\n\n/**\n * Convert kebab-case to camelCase with caching\n */\nexport function toCamel(str: string): string {\n if (CAMEL_CASE_CACHE.has(str)) {\n return CAMEL_CASE_CACHE.get(str)!;\n }\n\n const result = str.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());\n\n if (CAMEL_CASE_CACHE.size < MAX_CACHE_SIZE) {\n CAMEL_CASE_CACHE.set(str, result);\n }\n\n return result;\n}\n\n/**\n * Clear string transformation caches (useful for testing)\n */\nexport function clearStringCaches(): void {\n KEBAB_CASE_CACHE.clear();\n CAMEL_CASE_CACHE.clear();\n HTML_ESCAPE_CACHE.clear();\n}\n\n/**\n * Get cache statistics for debugging\n */\nexport function getStringCacheStats(): {\n kebabCacheSize: number;\n camelCacheSize: number;\n htmlEscapeCacheSize: number;\n} {\n return {\n kebabCacheSize: KEBAB_CASE_CACHE.size,\n camelCacheSize: CAMEL_CASE_CACHE.size,\n htmlEscapeCacheSize: HTML_ESCAPE_CACHE.size,\n };\n}\n\nexport function escapeHTML(\n str: string | number | boolean,\n): string | number | boolean {\n if (typeof str === 'string') {\n // Check cache first for frequently escaped strings\n if (HTML_ESCAPE_CACHE.has(str)) {\n return HTML_ESCAPE_CACHE.get(str)!;\n }\n\n const result = str.replace(\n /[&<>\"']/g,\n (c) =>\n ({\n '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&quot;',\n \"'\": '&#39;',\n })[c]!,\n );\n\n // Only cache strings that contain entities to escape\n if (result !== str && HTML_ESCAPE_CACHE.size < MAX_CACHE_SIZE) {\n HTML_ESCAPE_CACHE.set(str, result);\n }\n\n return result;\n }\n return str;\n}\n\n/**\n * Decode HTML entities (named and numeric) into their character equivalents.\n * - In browser: uses a DOM-based technique to decode entities while preserving\n * existing raw tags.\n * - In non-DOM (SSR) environments: handles numeric references and a conservative\n * named-entity map for common entities.\n *\n * @param str - string containing HTML entities\n * @returns decoded string\n */\nexport function decodeEntities(str: string): string {\n if (!str) return '';\n const s = String(str);\n\n // Browser environment: use a DOM element to decode the full set of named entities.\n if (\n typeof document !== 'undefined' &&\n typeof document.createElement === 'function'\n ) {\n const SENTINEL_L = '\\uF000';\n const SENTINEL_G = '\\uF001';\n // Protect existing literal tags so they won't be parsed as HTML by innerHTML\n const protectedStr = s.replace(/</g, SENTINEL_L).replace(/>/g, SENTINEL_G);\n\n // Prefer module-level el to avoid relying on function-attached properties\n // which can be renamed/mangled by some minifiers. Keep function-attached\n // `_el` for backward compatibility but do not depend on it.\n const el = _decodeEl || (_decodeEl = document.createElement('div'));\n try {\n (decodeEntities as { _el?: HTMLElement })._el = el;\n } catch {\n void 0;\n }\n\n el.innerHTML = protectedStr;\n const decoded = el.textContent || '';\n return decoded\n .replace(new RegExp(SENTINEL_L, 'g'), '<')\n .replace(new RegExp(SENTINEL_G, 'g'), '>');\n }\n\n // SSR / non-DOM fallback: handle numeric refs and named entities via an external JSON map.\n // Keep a tiny inline map for the most common entities so decodeEntities remains sync.\n const tinyMap: Record<string, string> = {\n lt: '<',\n gt: '>',\n amp: '&',\n quot: '\"',\n apos: \"'\",\n nbsp: '\\u00A0',\n };\n\n // Prefer module-level registered map first (minifier-safe). Keep function\n // attached map as a fallback for backward compatibility only.\n const registered =\n _namedEntityMap ??\n (decodeEntities as { _namedMap?: Record<string, string> })._namedMap;\n\n // Select map: module-level registered > function-attached registered > sync require (Node-only) > tinyMap.\n let namedMap: Record<string, string> | undefined = registered;\n\n if (!namedMap && _isNode) {\n // Try to synchronously require the JSON in Node-like environments without importing `require`.\n try {\n // Use globalThis to avoid referencing `require` directly (prevents TS needing node types)\n const maybeRequire = (globalThis as { require?: (id: string) => unknown })\n .require;\n if (typeof maybeRequire === 'function') {\n // Try several common require paths (installed package, dist layout, src layout)\n const candidates = [\n '@jasonshimmy/custom-elements-runtime/entities.json', // installed package export\n '../../entities.json', // dist/runtime -> ../../entities.json\n '../../../entities.json', // src/lib/runtime -> ../../../entities.json\n '../entities.json',\n './entities.json',\n ];\n for (const p of candidates) {\n try {\n const m = maybeRequire(p);\n // Ensure the required value is an object before assigning and cast it to the expected type\n if (m && typeof m === 'object') {\n namedMap = m as Record<string, string>;\n break;\n }\n } catch {\n void 0;\n }\n }\n }\n } catch {\n void 0;\n }\n }\n\n // If we still don't have a map, fall back to tinyMap and trigger background loader if present.\n if (!namedMap) {\n namedMap = tinyMap;\n // Keep both module and function-level flags in sync for backward compatibility.\n // Mark fallback usage primarily on module-level flags (minifier-safe).\n _usedEntityFallback = true;\n try {\n (decodeEntities as { _usedFallback?: boolean })._usedFallback = true;\n } catch {\n void 0;\n }\n const loader =\n (\n decodeEntities as {\n _namedMapLoader?: () => Promise<Record<string, string>>;\n }\n )._namedMapLoader ?? _namedEntityMapLoader;\n if (loader) {\n // Load asynchronously; when ready, cache it for future sync calls and sync to function props.\n loader()\n .then((m: Record<string, string>) => {\n _namedEntityMap = m;\n try {\n (\n decodeEntities as { _namedMap?: Record<string, string> }\n )._namedMap = m;\n } catch {\n void 0;\n }\n })\n .catch(() => {});\n }\n }\n\n // Emit a one-time dev warning if we used the tiny fallback.\n // Prefer module-level flags first, then function-attached fallbacks for\n // backward compatibility. This avoids depending on function property names\n // which some minifiers may mangle.\n if (\n (_usedEntityFallback ||\n (decodeEntities as { _usedFallback?: boolean })._usedFallback) &&\n !(\n _warnedEntityFallback ||\n (decodeEntities as { _warnedFallback?: boolean })._warnedFallback\n )\n ) {\n _warnedEntityFallback = true;\n try {\n (decodeEntities as { _warnedFallback?: boolean })._warnedFallback = true;\n } catch {\n void 0;\n }\n try {\n devWarn(\n 'decodeEntities: using small SSR fallback entity map. Register the full entities.json via registerEntityMap(entities) on the server to enable full HTML5 named-entity decoding.',\n );\n } catch {\n void 0;\n }\n }\n\n // Replace entities: numeric (hex/dec) or named.\n return s.replace(/&(#x?[0-9a-fA-F]+|[a-zA-Z]+);/g, (_, entity) => {\n if (entity.charCodeAt(0) === 35) {\n // '#'\n const isHex = (entity.charAt(1) || '').toLowerCase() === 'x';\n const num = isHex\n ? parseInt(entity.slice(2), 16)\n : parseInt(entity.slice(1), 10);\n return Number.isNaN(num) ? `&${entity};` : String.fromCodePoint(num);\n }\n const mapped =\n (namedMap as Record<string, string>)[entity] ??\n (registered && registered[entity]);\n return mapped !== undefined ? mapped : `&${entity};`;\n });\n}\n\n/**\n * Dynamically load the full named-entity map (used in SSR). Exported for testing and\n * to allow bundlers to exclude the JSON from client bundles when dynamic import\n * is used behind a DOM check.\n */\nexport async function loadEntityMap(): Promise<Record<string, string>> {\n // Prefer dynamic import so bundlers can code-split or ignore this file for browser bundles.\n // Try the published package export first; in installed packages this is usually the most\n // reliable path. Make the specifier a runtime string to discourage bundlers from inlining.\n const pkgExport = [\n '@jasonshimmy',\n 'custom-elements-runtime',\n 'entities.json',\n ].join('/');\n try {\n // @vite-ignore: dynamic import specifier constructed at runtime\n const mPkg = await import(/* @vite-ignore */ pkgExport as string);\n return (mPkg && (mPkg.default || mPkg)) as Record<string, string>;\n } catch {\n // Next try relative local JSON (useful during development or mono-repo installs)\n try {\n // Try several reasonable local import paths (development vs built layouts)\n const localCandidates = [\n pkgExport, // try package export via dynamic import too (best for installed packages)\n './entities.json',\n '../../entities.json',\n '../../../entities.json',\n ];\n for (const p of localCandidates) {\n try {\n // @vite-ignore: intentionally dynamic path candidates for dev/local resolution\n const mLocal = await import(/* @vite-ignore */ p as string);\n if (mLocal)\n return (mLocal && (mLocal.default || mLocal)) as Record<\n string,\n string\n >;\n } catch {\n void 0;\n }\n }\n // If none of the dynamic imports succeeded, fall back to the small map.\n return {\n lt: '<',\n gt: '>',\n amp: '&',\n quot: '\"',\n apos: \"'\",\n nbsp: '\\u00A0',\n };\n } catch {\n // Final small fallback\n return {\n lt: '<',\n gt: '>',\n amp: '&',\n quot: '\"',\n apos: \"'\",\n nbsp: '\\u00A0',\n };\n }\n }\n}\n\n// Attach loader to module state and (for backward compatibility) to the function\n// as well. Using module-level state avoids property-mangling risks in minified\n// builds; attaching to the function keeps tests that reference the property\n// working until they can be updated.\n_namedEntityMapLoader = loadEntityMap;\n(\n decodeEntities as typeof decodeEntities & {\n _namedMapLoader?: typeof loadEntityMap;\n }\n)._namedMapLoader = loadEntityMap;\n\n/**\n * Register a full named-entity map for SSR. Intended for server startup code to\n * provide the authoritative HTML5 entity mapping. This keeps the client bundle\n * small because the map is only injected on the server side.\n *\n * registerEntityMap should be called once at server startup prior to rendering.\n */\nexport function registerEntityMap(\n map: Record<string, string>,\n options?: { overwrite?: boolean },\n): void {\n if (!map || typeof map !== 'object') return;\n const existing = _namedEntityMap;\n if (existing && !options?.overwrite) return; // first registration wins by default\n _namedEntityMap = map;\n}\n\n/**\n * Clear any registered entity map. Useful for tests or restarting state.\n */\nexport function clearRegisteredEntityMap(): void {\n _namedEntityMap = undefined;\n}\n\n/**\n * Wrap a string as raw HTML. This is intentionally unsafe — callers must\n * sanitize untrusted input before using this. The returned object provides\n * two property names to be compatible with different parts of the runtime.\n */\nexport function unsafeHTML(html: string): {\n __unsafeHTML: string;\n __rawHTML: string;\n} {\n const s = String(html);\n // Provide both property names to be compatible with compiler/renderer expectations\n return { __unsafeHTML: s, __rawHTML: s };\n}\n\n/** Type-guard for unsafeHTML wrapper */\nexport function isUnsafeHTML(\n value: unknown,\n): value is { __unsafeHTML?: string; __rawHTML?: string } {\n return (\n !!value &&\n (typeof (value as { __unsafeHTML?: unknown }).__unsafeHTML === 'string' ||\n typeof (value as { __rawHTML?: unknown }).__rawHTML === 'string')\n );\n}\n\n/**\n * Get nested property value from object using dot notation\n */\nexport function getNestedValue(\n obj: Record<string, unknown>,\n path: string,\n): unknown {\n if (typeof path === 'string') {\n // Handle empty path explicitly: return undefined to indicate no lookup\n if (path === '') return undefined;\n const keys = path.split('.');\n let current: unknown = obj;\n\n for (const key of keys) {\n if (current == null || typeof current !== 'object') {\n current = undefined;\n break;\n }\n current = (current as Record<string, unknown>)[key];\n }\n\n // If the result is a ReactiveState object, return its value\n if (isReactiveState(current)) {\n return (current as { value: unknown }).value;\n }\n return current;\n }\n return path;\n}\n\n/**\n * Set nested property value in object using dot notation\n */\nexport function setNestedValue(\n obj: Record<string, unknown>,\n path: string,\n value: unknown,\n): void {\n const keys = String(path).split('.');\n const lastKey = keys.pop();\n if (!lastKey) return;\n const target = keys.reduce(\n (current: Record<string, unknown>, key: string) => {\n if (current[key] == null) current[key] = {};\n return current[key] as Record<string, unknown>;\n },\n obj,\n ) as Record<string, unknown>;\n\n // If target[lastKey] is a ReactiveState object, set its value property\n if (isReactiveState(target[lastKey])) {\n target[lastKey].value = value;\n } else {\n target[lastKey] = value;\n }\n}\n\n/**\n * Safely unwrap reactive-like wrappers to their inner primitive when safe.\n * Returns the original value when it's not safe to coerce to a primitive.\n */\nexport function unwrapIfPrimitive(val: unknown): unknown {\n try {\n if (val && typeof val === 'object') {\n if (isReactiveState(val)) return (val as { value: unknown }).value;\n if ('value' in val) {\n const maybe = (val as { value: unknown }).value;\n // Only return primitive inner values; otherwise return original\n if (\n maybe === null ||\n maybe === undefined ||\n typeof maybe === 'string' ||\n typeof maybe === 'number' ||\n typeof maybe === 'boolean'\n ) {\n return maybe;\n }\n return val;\n }\n }\n } catch {\n // ignore\n }\n return val;\n}\n\n/**\n * Return a serialized string for an attribute value when safe to write to DOM.\n * Returns `null` when the value should not be written as an attribute.\n */\nexport function safeSerializeAttr(val: unknown): string | null {\n const v = unwrapIfPrimitive(val);\n if (v === null || v === undefined) return null;\n const t = typeof v;\n if (t === 'string' || t === 'number' || t === 'boolean') return String(v);\n return null; // complex objects, nodes, functions -> do not serialize\n}\n\n/**\n * Determine if an attribute name is class-like and should be preserved on hosts.\n * Class-like: exactly 'class', camelCase ending with 'Class', or kebab-case ending with '-class'.\n */\nexport function isClassLikeAttr(name: string): boolean {\n if (!name || typeof name !== 'string') return false;\n if (name === 'class') return true;\n if (name.endsWith('Class')) return true;\n // Kebab-case: consider attributes where one of the hyphen-separated tokens is 'class'\n if (name.includes('-')) {\n try {\n const parts = name.split('-');\n if (parts.some((p) => p === 'class')) return true;\n } catch {\n // fallthrough\n }\n }\n return false;\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"],"names":["detectTestEnvironment","nodeEnv","browserTestEnv","win","UpdateScheduler","update","componentId","key","updates","error","devError","cleanup","now","devWarn","entries","toRemove","i","updateScheduler","scheduleDOMUpdate","flushDOMUpdates","proxiedObjects","ReactiveProxyCache","obj","reactiveState","isArray","cached","handler","proxy","ProxyOptimizer","target","prop","receiver","value","args","result","onUpdate","makeReactive","inner","reactiveContext","ReactiveSystem","renderFn","data","wid","watcherId","current","fn","wasDisabled","initialValue","ReactiveState","stateKey","state","deps","prefix","reactiveSystem","newValue","ref","isReactiveState","v","computed","computedState","watch","source","callback","options","oldValue","getter","parentComp","updateWatcher","safe","KEBAB_CASE_CACHE","CAMEL_CASE_CACHE","HTML_ESCAPE_CACHE","MAX_CACHE_SIZE","_namedEntityMap","_namedEntityMapLoader","_usedEntityFallback","_warnedEntityFallback","_decodeEl","_isNode","toKebab","str","toCamel","_","letter","escapeHTML","c","decodeEntities","s","protectedStr","el","tinyMap","registered","namedMap","maybeRequire","candidates","p","m","loader","entity","num","mapped","loadEntityMap","pkgExport","mPkg","localCandidates","mLocal","unsafeHTML","html","isUnsafeHTML","getNestedValue","path","keys","setNestedValue","lastKey","unwrapIfPrimitive","val","maybe","safeSerializeAttr","t","isClassLikeAttr","name","ATTR_NAMESPACE_MAP","setAttributeSmart","idx","local","ns","removeAttributeSmart","SVG_NS","MATHML_NS","TAG_NAMESPACE_MAP"],"mappings":"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"}
package/dist/router.d.ts CHANGED
@@ -1,51 +1,75 @@
1
1
  import { type Store } from './store';
2
+ /**
3
+ * Represents a component that can be rendered by the router.
4
+ * Can be either a class constructor or a function component.
5
+ */
2
6
  export type RouteComponent = {
3
7
  new (...args: unknown[]): unknown;
4
8
  } | ((...args: unknown[]) => unknown);
9
+ /**
10
+ * Represents the current state of the router.
11
+ */
5
12
  export interface RouteState {
13
+ /** The current path without base, query, or fragment */
6
14
  path: string;
15
+ /** Route parameters extracted from dynamic path segments */
7
16
  params: Record<string, string>;
17
+ /** Query parameters from the URL search string */
8
18
  query: Record<string, string>;
19
+ /** Optional fragment (hash) portion of the URL, without the leading '#' */
9
20
  fragment?: string;
10
21
  }
22
+ /**
23
+ * Result type for route guards.
24
+ * - `true`: Allow navigation
25
+ * - `false`: Block navigation
26
+ * - `string`: Redirect to the specified path
27
+ */
11
28
  export type GuardResult = boolean | string | Promise<boolean | string>;
29
+ /**
30
+ * Defines a route in the router configuration.
31
+ */
12
32
  export interface Route {
33
+ /** The path pattern for this route (e.g., '/users/:id') */
13
34
  path: string;
14
- /**
15
- * Statically available component (already imported)
16
- */
35
+ /** Statically available component (already imported) */
17
36
  component?: string | (() => unknown);
18
- /**
19
- * Lazy loader that resolves to something renderable
20
- */
37
+ /** Lazy loader that resolves to something renderable */
21
38
  load?: () => Promise<{
22
39
  default: string | HTMLElement | ((...args: unknown[]) => unknown);
23
40
  }>;
24
- /**
25
- * Runs before matching — return false to cancel,
26
- * or a string to redirect
27
- */
41
+ /** Guard that runs before matching — return false to cancel, or a string to redirect */
28
42
  beforeEnter?: (to: RouteState, from: RouteState) => GuardResult;
29
- /**
30
- * Runs right before navigation commits — can cancel or redirect
31
- */
43
+ /** Guard that runs right before navigation commits — can cancel or redirect */
32
44
  onEnter?: (to: RouteState, from: RouteState) => GuardResult;
33
- /**
34
- * Runs after navigation completes — cannot cancel
35
- */
45
+ /** Hook that runs after navigation completes — cannot cancel */
36
46
  afterEnter?: (to: RouteState, from: RouteState) => void;
37
47
  }
48
+ /**
49
+ * Props interface for the router-link component.
50
+ */
38
51
  export interface RouterLinkProps {
52
+ /** Target path or URL to navigate to */
39
53
  to: string;
54
+ /** HTML tag to render ('a' or 'button') */
40
55
  tag: string;
56
+ /** Whether to use replace instead of push navigation */
41
57
  replace: boolean;
58
+ /** Whether to use exact matching for active state */
42
59
  exact: boolean;
60
+ /** CSS class applied when link is active */
43
61
  activeClass: string;
62
+ /** CSS class applied when link is exactly active */
44
63
  exactActiveClass: string;
64
+ /** Value for aria-current attribute when exactly active */
45
65
  ariaCurrentValue: string;
66
+ /** Whether the link is disabled */
46
67
  disabled: boolean;
68
+ /** Whether this is an external link */
47
69
  external: boolean;
70
+ /** Additional CSS classes */
48
71
  class?: string;
72
+ /** Additional inline styles */
49
73
  style?: string;
50
74
  }
51
75
  export interface RouterLinkComputed {
@@ -58,23 +82,44 @@ export interface RouterLinkComputed {
58
82
  disabledAttr: string;
59
83
  externalAttr: string;
60
84
  }
85
+ /**
86
+ * Configuration object for initializing the router.
87
+ */
61
88
  export interface RouterConfig {
89
+ /** Array of route definitions */
62
90
  routes: Route[];
91
+ /** Base path for all routes */
63
92
  base?: string;
93
+ /** Initial URL for SSR mode */
64
94
  initialUrl?: string;
65
- /**
66
- * Configure fragment (hash) scrolling behavior. Either a boolean to enable/disable
67
- * or an object to enable and provide an offset in pixels to account for fixed
68
- * headers.
69
- */
95
+ /** Configure fragment (hash) scrolling behavior */
70
96
  scrollToFragment?: boolean | {
97
+ /** Whether fragment scrolling is enabled */
71
98
  enabled?: boolean;
99
+ /** Offset in pixels to account for fixed headers */
72
100
  offset?: number;
101
+ /** Timeout in ms to wait for element to appear */
73
102
  timeoutMs?: number;
74
103
  };
75
104
  }
105
+ /**
106
+ * Parse URL search string into query parameters object.
107
+ * @param search - The search string (with or without leading '?')
108
+ * @returns Object with query parameter key-value pairs
109
+ */
76
110
  export declare const parseQuery: (search: string) => Record<string, string>;
111
+ /**
112
+ * Serialize query parameters object into URL search string.
113
+ * @param q - Query parameters object
114
+ * @returns Search string with leading '?' or empty string
115
+ */
77
116
  export declare const serializeQuery: (q: Record<string, string> | undefined) => string;
117
+ /**
118
+ * Normalize a path for consistent route matching.
119
+ * Ensures leading slash, removes trailing slash, and collapses duplicate slashes.
120
+ * @param p - Path string to normalize
121
+ * @returns Normalized path string
122
+ */
78
123
  export declare function normalizePathForRoute(p: string): string;
79
124
  export declare const matchRoute: (routes: Route[], path: string) => {
80
125
  route: Route | null;
@@ -87,6 +132,7 @@ export declare const matchRoute: (routes: Route[], path: string) => {
87
132
  */
88
133
  export declare function resolveRouteComponent(route: Route): Promise<string | HTMLElement | ((...args: unknown[]) => unknown)>;
89
134
  export declare function useRouter(config: RouterConfig): {
135
+ _cleanupScrollState: () => void;
90
136
  store: Store<RouteState>;
91
137
  push: (path: string) => Promise<void>;
92
138
  replace: (path: string) => Promise<void>;
@@ -105,25 +151,39 @@ export declare function useRouter(config: RouterConfig): {
105
151
  * Explicit Router instance type exported for clearer typing across the
106
152
  * codebase and tests.
107
153
  */
154
+ /**
155
+ * Router instance interface providing navigation and state management.
156
+ */
108
157
  export interface Router {
158
+ /** Reactive store containing current route state */
109
159
  store: Store<RouteState>;
160
+ /** Navigate to a path (adds to history) */
110
161
  push: (path: string) => Promise<void>;
162
+ /** Navigate to a path (replaces current history entry) */
111
163
  replace: (path: string) => Promise<void>;
164
+ /** Go back in browser history */
112
165
  back: () => void;
166
+ /** Subscribe to route state changes */
113
167
  subscribe: Store<RouteState>['subscribe'];
168
+ /** Match a path against configured routes */
114
169
  matchRoute: (path: string) => {
115
170
  route: Route | null;
116
171
  params: Record<string, string>;
117
172
  };
173
+ /** Get current route state */
118
174
  getCurrent: () => RouteState;
175
+ /** Resolve a route's component */
119
176
  resolveRouteComponent: typeof resolveRouteComponent;
177
+ /** Base path for the router */
120
178
  base: string;
179
+ /** Scroll to a fragment/hash element */
121
180
  scrollToFragment: (frag?: string) => Promise<boolean>;
122
181
  }
123
182
  export declare function matchRouteSSR(routes: Route[], path: string): {
124
183
  route: Route | null;
125
184
  params: Record<string, string>;
126
185
  };
186
+ export declare const activeRouterProxy: Router;
127
187
  /**
128
188
  * Singleton router instance for global access.
129
189
  *
@@ -131,6 +191,7 @@ export declare function matchRouteSSR(routes: Route[], path: string): {
131
191
  * issue with component.
132
192
  */
133
193
  export declare function initRouter(config: RouterConfig): {
194
+ _cleanupScrollState: () => void;
134
195
  store: Store<RouteState>;
135
196
  push: (path: string) => Promise<void>;
136
197
  replace: (path: string) => Promise<void>;
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Runtime Health Monitoring System
3
+ * Tracks framework health metrics and provides early warning for potential issues
4
+ */
5
+ interface HealthMetric {
6
+ name: string;
7
+ value: number;
8
+ threshold: number;
9
+ status: 'healthy' | 'warning' | 'critical';
10
+ lastUpdated: number;
11
+ history: number[];
12
+ }
13
+ interface HealthReport {
14
+ overall: 'healthy' | 'warning' | 'critical';
15
+ metrics: Record<string, HealthMetric>;
16
+ timestamp: number;
17
+ recommendations: string[];
18
+ }
19
+ export declare class HealthMonitor {
20
+ private metrics;
21
+ private readonly maxHistorySize;
22
+ private readonly checkInterval;
23
+ private intervalId;
24
+ private listeners;
25
+ constructor();
26
+ /**
27
+ * Initialize default health metrics
28
+ */
29
+ private initializeMetrics;
30
+ /**
31
+ * Add a new health metric
32
+ */
33
+ private addMetric;
34
+ /**
35
+ * Update a specific health metric
36
+ */
37
+ updateMetric(name: string, value: number): void;
38
+ /**
39
+ * Calculate health status based on value and threshold
40
+ */
41
+ private calculateStatus;
42
+ /**
43
+ * Get current health report
44
+ */
45
+ getHealthReport(): HealthReport;
46
+ /**
47
+ * Generate actionable recommendations based on metrics
48
+ */
49
+ private generateRecommendations;
50
+ /**
51
+ * Start periodic health monitoring
52
+ */
53
+ private startMonitoring;
54
+ /**
55
+ * Perform comprehensive health check
56
+ */
57
+ private performHealthCheck;
58
+ /**
59
+ * Update memory-related metrics
60
+ */
61
+ private updateMemoryMetrics;
62
+ /**
63
+ * Add health report listener
64
+ */
65
+ addListener(listener: (report: HealthReport) => void): void;
66
+ /**
67
+ * Remove health report listener
68
+ */
69
+ removeListener(listener: (report: HealthReport) => void): void;
70
+ /**
71
+ * Notify all listeners of health report
72
+ */
73
+ private notifyListeners;
74
+ /**
75
+ * Stop health monitoring
76
+ */
77
+ stop(): void;
78
+ /**
79
+ * Get specific metric history for analysis
80
+ */
81
+ getMetricHistory(name: string): number[];
82
+ /**
83
+ * Clear all metrics history
84
+ */
85
+ clearHistory(): void;
86
+ }
87
+ /**
88
+ * Get the global health monitor instance
89
+ */
90
+ export declare function getHealthMonitor(): HealthMonitor;
91
+ /**
92
+ * Update a health metric from anywhere in the framework
93
+ */
94
+ export declare function updateHealthMetric(name: string, value: number): void;
95
+ /**
96
+ * Get current health status
97
+ */
98
+ export declare function getHealthStatus(): HealthReport;
99
+ export {};
@@ -23,6 +23,6 @@ export declare function renderOutput<S extends object, C extends object, P exten
23
23
  */
24
24
  export declare function requestRender(renderFn: () => void, lastRenderTime: number, renderCount: number, setLastRenderTime: (t: number) => void, setRenderCount: (c: number) => void, renderTimeoutId: ReturnType<typeof setTimeout> | null, setRenderTimeoutId: (id: ReturnType<typeof setTimeout> | null) => void): void;
25
25
  /**
26
- * Applies styles to the shadowRoot.
26
+ * Applies styles to the shadowRoot with improved structure and maintainability.
27
27
  */
28
28
  export declare function applyStyle<S extends object, C extends object, P extends object, T extends object>(shadowRoot: ShadowRoot | null, context: ComponentContext<S, C, P, T>, htmlString: string, styleSheet: CSSStyleSheet | null, setStyleSheet: (sheet: CSSStyleSheet | null) => void): void;
@@ -1,23 +1,69 @@
1
1
  declare class UpdateScheduler {
2
2
  private pendingUpdates;
3
3
  private isFlushScheduled;
4
+ private isFlushing;
5
+ private readonly testEnv;
6
+ private lastCleanup;
7
+ private readonly CLEANUP_INTERVAL;
8
+ private readonly MAX_PENDING_SIZE;
9
+ constructor();
4
10
  /**
5
11
  * Schedule an update to be executed in the next microtask
6
12
  * Uses component identity to deduplicate multiple render requests for the same component
7
13
  */
8
14
  schedule(update: () => void, componentId?: string): void;
15
+ /**
16
+ * Schedule the flush operation based on environment
17
+ */
18
+ private scheduleFlush;
9
19
  /**
10
20
  * Execute all pending updates
11
21
  */
12
22
  private flush;
23
+ /**
24
+ * Force flush any pending DOM updates immediately. This is useful in
25
+ * test environments or callers that require synchronous guarantees after
26
+ * state changes. Prefer relying on the scheduler's automatic flush when
27
+ * possible; use this only when a caller needs to synchronously observe
28
+ * rendered DOM changes.
29
+ */
30
+ flushImmediately(): void;
13
31
  /**
14
32
  * Get the number of pending updates
15
33
  */
16
34
  get pendingCount(): number;
35
+ /**
36
+ * Check if there are pending updates
37
+ */
38
+ get hasPendingUpdates(): boolean;
39
+ /**
40
+ * Check if currently flushing updates
41
+ */
42
+ get isFlushingUpdates(): boolean;
43
+ /**
44
+ * Schedule periodic cleanup to prevent memory leaks
45
+ */
46
+ private schedulePeriodicCleanup;
47
+ /**
48
+ * Perform periodic cleanup of stale entries
49
+ */
50
+ private performPeriodicCleanup;
51
+ /**
52
+ * Emergency cleanup when pending updates exceed safe limits
53
+ */
54
+ private performEmergencyCleanup;
17
55
  }
18
56
  export declare const updateScheduler: UpdateScheduler;
19
57
  /**
20
58
  * Schedule a DOM update to be batched with optional component identity
21
59
  */
22
60
  export declare function scheduleDOMUpdate(update: () => void, componentId?: string): void;
61
+ /**
62
+ * Force flush any pending DOM updates immediately. This is useful in
63
+ * test environments or callers that require synchronous guarantees after
64
+ * state changes. Prefer relying on the scheduler's automatic flush when
65
+ * possible; use this only when a caller needs to synchronously observe
66
+ * rendered DOM changes.
67
+ */
68
+ export declare function flushDOMUpdates(): void;
23
69
  export {};