@koppajs/koppajs-core 3.0.7 → 3.0.9

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../src/utils/logger.ts","../src/types.ts","../src/utils/helper.ts","../src/utils/dom.ts","../src/utils/object.ts","../src/utils/string.ts","../src/utils/script.ts","../src/utils/hook-registry.ts","../src/utils/extension-registry.ts","../src/utils/type-guards.ts","../src/utils/extend.ts","../src/utils/reconcile.ts","../src/utils/identity.ts","../src/event-handler.ts","../src/global-event-cleaner.ts","../src/model.ts","../src/template-processor.ts","../src/compose.ts","../src/component.ts","../src/index.ts"],"sourcesContent":["/**\n * Logging system with configurable log levels and emoji indicators.\n * Supports different configurations for development and production.\n */\n\n/**\n * Log levels in order of severity.\n */\nexport enum LogLevel {\n DEBUG = 0,\n INFO = 1,\n WARN = 2,\n ERROR = 3,\n NONE = 4,\n}\n\nconst EMOJIS = {\n ERROR: '❌',\n WARN: '⚠️',\n INFO: 'ℹ️',\n DEBUG: '🔍',\n} as const\n\ntype LogContext = {\n component?: string\n method?: string\n [key: string]: unknown\n}\n\n/**\n * Logger class for consistent logging across the framework.\n */\nclass Logger {\n private level: LogLevel = LogLevel.ERROR\n private isDevelopment: boolean = false\n\n /**\n * Initialize logger with environment detection.\n * @param options - Logger configuration options\n * @param options.level - Minimum log level (defaults based on environment)\n * @param options.isDevelopment - Whether in development mode\n */\n init(options?: { level?: LogLevel; isDevelopment?: boolean }): void {\n this.isDevelopment =\n options?.isDevelopment ??\n (typeof process !== 'undefined' && process.env?.NODE_ENV === 'development') ??\n false\n\n // Default: ERROR in production, DEBUG in development\n this.level = options?.level ?? (this.isDevelopment ? LogLevel.DEBUG : LogLevel.ERROR)\n }\n\n /**\n * Set the minimum log level.\n * @param level - Minimum log level to display\n */\n setLevel(level: LogLevel): void {\n this.level = level\n }\n\n /**\n * Get current log level.\n * @returns Current minimum log level\n */\n getLevel(): LogLevel {\n return this.level\n }\n\n private shouldLog(level: LogLevel): boolean {\n return level >= this.level\n }\n\n private formatMessage(emoji: string, message: string, context?: LogContext): string {\n const parts = [emoji, message]\n\n if (context) {\n const contextStr = Object.entries(context)\n .map(([key, value]) => `${key}: ${value}`)\n .join(', ')\n if (contextStr) {\n parts.push(`[${contextStr}]`)\n }\n }\n\n return parts.join(' ')\n }\n\n /**\n * Log an error message.\n * @param message - Error message\n * @param args - Additional arguments to log\n */\n error(message: string, ...args: any[]): void {\n if (!this.shouldLog(LogLevel.ERROR)) return\n console.error(this.formatMessage(EMOJIS.ERROR, message), ...args)\n }\n\n /**\n * Log a warning message.\n * @param message - Warning message\n * @param args - Additional arguments to log\n */\n warn(message: string, ...args: any[]): void {\n if (!this.shouldLog(LogLevel.WARN)) return\n console.warn(this.formatMessage(EMOJIS.WARN, message), ...args)\n }\n\n /**\n * Log an info message.\n * @param message - Info message\n * @param args - Additional arguments to log\n */\n info(message: string, ...args: any[]): void {\n if (!this.shouldLog(LogLevel.INFO)) return\n console.info(this.formatMessage(EMOJIS.INFO, message), ...args)\n }\n\n /**\n * Log a debug message.\n * @param message - Debug message\n * @param args - Additional arguments to log\n */\n debug(message: string, ...args: any[]): void {\n if (!this.shouldLog(LogLevel.DEBUG)) return\n console.debug(this.formatMessage(EMOJIS.DEBUG, message), ...args)\n }\n\n /**\n * Log an error with context information.\n * @param message - Error message\n * @param context - Context object with additional information\n * @param error - Optional error object\n */\n errorWithContext(message: string, context: LogContext, error?: Error | unknown): void {\n if (!this.shouldLog(LogLevel.ERROR)) return\n const formatted = this.formatMessage(EMOJIS.ERROR, message, context)\n if (error) {\n console.error(formatted, error)\n } else {\n console.error(formatted)\n }\n }\n\n /**\n * Log a warning with context information.\n * @param message - Warning message\n * @param context - Context object with additional information\n */\n warnWithContext(message: string, context: LogContext): void {\n if (!this.shouldLog(LogLevel.WARN)) return\n console.warn(this.formatMessage(EMOJIS.WARN, message, context))\n }\n}\n\n// Singleton instance\nexport const logger = new Logger()\n\n// Auto-initialize on import\nlogger.init()\n","// Public type anchor for the entire KoppaJS ecosystem.\n//\n// This file intentionally contains:\n// - The public runtime types (ComponentSource, CoreCallable, etc.)\n// - Ambient declarations that must be visible to consumers (e.g. *.kpa modules)\n// - Global augmentations (HTMLElement helpers)\n//\n// Rationale:\n// TypeScript only loads what is reachable from the package's \"types\" entry\n// (dist/index.d.ts). By placing ambient declarations here, they are guaranteed\n// to be included for all consumers without requiring local project d.ts files.\n\nexport {}\n\n/* -------------------------------------------------------------------------- */\n/* Ambient Module Declarations */\n/* -------------------------------------------------------------------------- */\n\nimport './kpa.d.ts'\n\n/* -------------------------------------------------------------------------- */\n/* Global Augmentations */\n/* -------------------------------------------------------------------------- */\n\nimport './globals.d.ts'\n\n/* -------------------------------------------------------------------------- */\n/* Public Core Types */\n/* -------------------------------------------------------------------------- */\n\n// export const EVENT_STORE: unique symbol = Symbol(\"eventStore\");\n\n/**\n * Symbol to identify whether a function is bound to this.\n */\nexport const BOUND: unique symbol = Symbol('isBounded')\n\n/**\n * Symbol to identify whether an object is a Proxy.\n */\nexport const IS_PROXY: unique symbol = Symbol('isProxy')\n\n/**\n * Arguments for the Core.take() method.\n * Either a ComponentSource with a name, or a Plugin/Module.\n */\nexport type TakeArgs = [ComponentSource, string] | [IPlugin | IModule]\n\n/**\n * Generic function type.\n */\nexport type AnyFn = (...args: any[]) => unknown\n\n/**\n * Function that has been bound to a context.\n */\nexport type BoundFn = AnyFn & { [BOUND]?: true }\n\n/**\n * Main Core API interface.\n */\nexport interface CoreCallable {\n (): void\n take: {\n (component: ComponentSource, name: string): void\n (pluginOrModule: IPlugin | IModule): void\n }\n}\n\n/**\n * Registry for lifecycle hooks.\n */\nexport type LifecycleRegistry = Map<LifecycleHook, Set<HookCallback>>\n\n/**\n * Callback function for lifecycle hooks.\n * @param context - Optional state context passed to the hook\n */\nexport type HookCallback = (context?: State | undefined) => Promise<void>\n\n/**\n * Context provided to plugins and modules during installation.\n */\nexport interface CoreCtx {\n registerHook: (hookName: LifecycleHook, callback: HookCallback) => void\n take: CoreCallable['take']\n}\n\n/* -------------------------------------------------------------------------- */\n/* Extensions */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Shared base extension interface.\n */\nexport interface IBaseExtension {\n /** Unique name of the extension */\n name: string\n /**\n * Installation method called when extension is registered.\n * @param context - Core context with registration utilities\n * @returns Optional cleanup function\n */\n install(context: CoreCtx): (() => void) | void\n}\n\n/**\n * Plugin extension interface.\n * Plugins provide setup methods that run in component context.\n */\nexport interface IPlugin extends IBaseExtension {\n /**\n * Setup method called for each component instance.\n * @this {State} - Component state as this context\n * @returns Plugin data or cleanup function\n */\n setup(this: State): Record<string, unknown> | (() => void)\n attach: never\n}\n\n/**\n * Internal helper type (no global augmentation of HTMLElement required).\n */\nexport type HTMLElementWithInstance = HTMLElement & {\n instance?: ComponentInstance\n}\n\n/**\n * Context provided to modules during attachment.\n */\nexport interface ModuleContext {\n element: HTMLElementWithInstance\n parent?: ComponentInstance\n core: {\n take: CoreCallable['take']\n }\n}\n\n/**\n * Module extension interface.\n * Modules attach to component elements and provide element-level functionality.\n */\nexport interface IModule extends IBaseExtension {\n /**\n * Attach method called when component is created.\n * @this {ModuleContext} - Module context with element and parent\n * @returns Optional module data to attach to component\n */\n attach(this: ModuleContext): Record<string, unknown> | void\n setup?: never\n}\n\n/* -------------------------------------------------------------------------- */\n/* ComponentSource Contract */\n/* -------------------------------------------------------------------------- */\n\n/**\n * # ComponentSource Contract\n *\n * This interface defines the contract between the KoppaJS Vite Plugin and\n * the Core runtime. The plugin produces ComponentSource objects when\n * transforming `.kpa` files, and the core consumes them at runtime.\n *\n * ## Field Categories\n *\n * ### REQUIRED Fields (must exist, core will fail without them)\n * - `template` - HTML template string\n * - `script` - JavaScript controller code string\n * - `style` - CSS style string (can be empty string)\n *\n * ### OPTIONAL Fields (may exist, core handles absence gracefully)\n * - `scriptMap` - Sourcemap for debugging (null or object)\n * - `type` - Component composition mode (\"options\" | \"composite\")\n * - `deps` - Async import map for [ts] block dependencies\n * - `structAttr`- Custom attribute name for structural identity\n *\n * ### IGNORED Fields (allowed but unused by core runtime)\n * - Any additional fields not listed above are permitted and will be\n * ignored by the core runtime. This allows forward compatibility\n * with plugin extensions without breaking existing core versions.\n *\n * ## Version Compatibility\n *\n * The plugin is expected to emit exactly these fields. Extra fields\n * (e.g., debug metadata) may be added by the plugin but will not be\n * processed by the core.\n *\n * @see https://github.com/koppajs/koppajs-core for full documentation\n */\n\n/**\n * Async import function for a single dependency.\n * Returns a promise that resolves to the imported module or value.\n */\nexport interface DepInfo {\n (): Promise<unknown>\n}\n\n/**\n * Map of dependency identifiers to async import functions.\n * Each key is the local identifier used in the component script,\n * and the value is an async function that resolves the import.\n */\nexport type Deps = Record<string, DepInfo> | null\n\n/**\n * Component source payload produced by the Vite plugin for `.kpa` files.\n *\n * This is the primary interface for the Core ↔ Plugin contract.\n * See the ComponentSource Contract documentation above for field categories.\n */\nexport interface ComponentSource {\n /* ------------------------------------------------------------------------ */\n /* REQUIRED Fields - Core will fail without these */\n /* ------------------------------------------------------------------------ */\n\n /**\n * HTML template string for the component.\n * Contains the component's DOM structure with KoppaJS directives.\n * @required\n */\n template: string\n\n /**\n * JavaScript controller code string.\n * Executed at runtime to produce the component controller.\n * @required\n */\n script: string\n\n /**\n * CSS style string for the component.\n * Injected into document head with component-scoped ID.\n * Can be empty string if component has no styles.\n * @required\n */\n style: string\n\n /* ------------------------------------------------------------------------ */\n /* OPTIONAL Fields - Core handles absence gracefully */\n /* ------------------------------------------------------------------------ */\n\n /**\n * Optional sourcemap payload for dynamic script execution.\n * The vite-plugin emits this as a parsed sourcemap object (or null).\n * The core runtime may re-attach this map for DevTools when evaluating scripts.\n * @optional\n */\n scriptMap?: unknown | null\n\n /**\n * Component composition type.\n *\n * - \"options\" (default): Creates a userContext that combines methods and state,\n * and binds it to `this` in lifecycle hooks and methods.\n * - \"composite\": No userContext is created, no `this` binding occurs.\n * Used for components that compose behavior from multiple sources.\n *\n * If not specified, defaults to \"options\".\n * @optional\n */\n type?: 'options' | 'composite'\n\n /**\n * Imported dependencies from [ts] block.\n * Each key is the local identifier, value is an async function that resolves the import.\n * The core runtime resolves these before evaluating the controller script.\n * @optional\n */\n deps?: Deps\n\n /**\n * Optional HTML attribute name to use for structural identity fallback.\n * If specified and no structId is set via runtime helper, the reconciliation\n * will attempt to read structId from this attribute.\n * Default: 'data-k-struct'\n * @optional\n */\n structAttr?: string\n\n /* ------------------------------------------------------------------------ */\n /* IGNORED Fields - Extra fields allowed for forward compatibility */\n /* ------------------------------------------------------------------------ */\n\n /**\n * Index signature to allow extra fields from the plugin.\n * These fields are ignored by the core runtime but permitted\n * for forward compatibility with plugin extensions.\n *\n * Common ignored fields might include:\n * - Debug metadata\n * - Plugin-specific configuration\n * - Future extension points\n */\n [key: string]: unknown\n}\n\n/**\n * Public extension union.\n */\nexport type IExtension = ComponentSource | IPlugin | IModule\n\n/* -------------------------------------------------------------------------- */\n/* Component Types */\n/* -------------------------------------------------------------------------- */\n\ninterface PropsDefinition {\n type?: string\n required?: boolean\n default?: any\n regex?: string\n}\n\n/**\n * Event definition tuple: [eventType, target, handler]\n * - eventType: DOM event name (e.g., \"click\", \"input\")\n * - target: Selector string, Element, Window, or ref object\n * - handler: Event handler function\n */\nexport type EventDefinition = [\n string,\n string | Element | Window | { ref: string; selector?: string },\n AnyFn,\n]\n\n/**\n * Component reactive state object.\n */\nexport type State = Record<string, any>\n\n/**\n * Component methods object.\n */\nexport type Methods = Record<string, AnyFn>\n\n/**\n * Component props definition.\n */\nexport type Props = Record<string, PropsDefinition>\n\n/**\n * Component events array.\n */\nexport type Events = Array<EventDefinition>\n\n/**\n * List of property paths to watch for changes.\n */\nexport type WatchList = string[]\n\n/**\n * Snapshot of watched properties.\n */\nexport type WatchListSnapshot = { parent: object; properties: string[] }\n\n/**\n * Component element references.\n */\nexport type Refs = Record<string, HTMLElement>\n\n/**\n * Options for composeBySource function.\n */\nexport type ComposeOptions = {\n /** Index of layer to write to when property doesn't exist in any layer */\n defaultWriteIndex?: number\n /** Whether to include prototype properties in layer search */\n includePrototype?: boolean\n}\n\nexport const lifecycleHooks = [\n 'created',\n 'beforeMount',\n 'mounted',\n 'beforeUpdate',\n 'updated',\n 'beforeDestroy',\n 'destroyed',\n 'processed',\n] as const\n\n/**\n * Available lifecycle hook names.\n */\nexport type LifecycleHook = (typeof lifecycleHooks)[number]\n\n/**\n * Lifecycle hook handler function.\n * @this {State} - Component state as this context\n */\nexport type LifecycleHandler = (this: State) => void | Promise<void>\n\ninterface LifecycleHooks {\n created?: LifecycleHandler\n beforeMount?: LifecycleHandler\n mounted?: LifecycleHandler\n beforeUpdate?: LifecycleHandler\n updated?: LifecycleHandler\n beforeDestroy?: LifecycleHandler\n destroyed?: LifecycleHandler\n processed?: LifecycleHandler\n}\n\nexport interface Lifecycle {\n on: (name: LifecycleHook, fn: (this: State) => void | Promise<void>) => void\n off: (name: LifecycleHook, fn: (this: State) => void | Promise<void>) => void\n clear: () => void\n emit(hook: LifecycleHook): Promise<void>\n}\n\n/**\n * Context provided to component script during compilation.\n */\nexport interface ComponentContext {\n /** Element references */\n $refs: Refs\n /** Parent component instance */\n $parent?: ComponentInstance\n /** Emit event to parent components */\n $emit: (eventName: string, ...args: unknown[]) => void\n /** Get plugin data */\n $take: (pluginName: string) => Record<string, unknown> | AnyFn | void | undefined\n\n /** Dynamic module properties ($router, $store, ...) */\n [key: `$${string}`]: unknown\n}\n\n/**\n * Compiled component script function.\n * @param context - Component context with $refs, $parent, etc.\n * @returns Component controller with state, methods, etc.\n */\nexport type CompiledScript = (context: ComponentContext) => ComponentController\n\n/**\n * Component controller returned from compiled script.\n * Contains component definition: state, methods, props, events, etc.\n */\nexport interface ComponentController extends LifecycleHooks {\n /** Component reactive state */\n state?: State\n /** User context (composed from methods + state for \"options\" type) */\n userContext?: State\n /** Component methods */\n methods?: Methods\n /** Component props definition */\n props?: Props\n /** Component events */\n events?: Events\n /** Properties to watch for changes */\n watchList?: WatchList\n}\n\n/**\n * Runtime component instance.\n * Extends ComponentController with runtime properties like element, template, etc.\n */\nexport interface ComponentInstance\n extends ComponentContext, Omit<ComponentController, keyof LifecycleHooks> {\n element: HTMLElementWithInstance\n template: HTMLTemplateElement\n readyPromise: Promise<void>\n lifecycleRegistry: LifecycleRegistry\n}\n","import { BOUND, type AnyFn, type BoundFn, type State, type Methods } from '../types'\nimport { logger } from './logger'\n\n/**\n * Binds a function to a context once, preventing multiple bindings.\n * Uses a symbol to mark bound functions.\n * @param fn - Function to bind\n * @param userContext - Context to bind function to\n * @returns Bound function (or original if already bound or not a function)\n */\nexport function bindOnce(fn: AnyFn, userContext: State): AnyFn {\n if (typeof fn !== 'function') return fn\n\n const maybe = fn as BoundFn\n if (maybe[BOUND]) return fn\n\n const bound = fn.bind(userContext) as BoundFn\n bound[BOUND] = true\n return bound\n}\n\n/**\n * Binds all methods from the `methods` object to the provided `userContext`.\n * @param methods - A map of method names and functions\n * @param userContext - The user context object (this context for user functions)\n */\nexport function bindMethods(methods: Methods, userContext: State): void {\n for (const name in methods) {\n const fn = methods[name]\n if (Object.prototype.hasOwnProperty.call(methods, name) && typeof fn === 'function') {\n try {\n methods[name] = bindOnce(fn, userContext)\n } catch (error) {\n logger.errorWithContext(\n `Failed to bind method \"${name}\"`,\n { methodName: name },\n error,\n )\n }\n }\n }\n}\n\n/**\n * Checks if a string contains basic HTML tags.\n * @param input - The input string to check\n * @returns True if the string contains HTML-like syntax, otherwise false\n */\nexport function containsHTML(input: string): boolean {\n return /<\\/?[a-z][^>]*>/i.test(input)\n}\n\n/**\n * Safely retrieves a value from a nested object using a string path.\n * Supports dot/bracket notation: \"foo.bar[0].baz\"\n * Does NOT throw (returns undefined on invalid access).\n * @param obj - Object to read from\n * @param path - Property path (dot/bracket notation)\n * @returns Value at path or undefined if not found\n */\nexport function getValueByPath(obj: unknown, path: string): unknown {\n if (obj == null || typeof path !== 'string') return undefined\n\n const tokens = path\n .trim()\n .replace(/\\[(\\w+)\\]/g, '.$1')\n .split('.')\n .filter(Boolean)\n\n try {\n return tokens.reduce((acc: unknown, key) => {\n if (acc == null) return undefined\n return (acc as Record<string, unknown>)[key]\n }, obj)\n } catch {\n return undefined\n }\n}\n\n/**\n * Resolves a type constructor or string into a normalized lowercase type name.\n * Used for comparing prop types during runtime validation.\n * @param input - A string type name or a constructor function\n * @returns A lowercase string type (e.g. \"string\", \"array\") or \"unknown\"\n */\nexport function getExpectedPropTypeName(input: unknown): string {\n if (typeof input === 'string') return input.toLowerCase()\n if (typeof input === 'function' && typeof input.name === 'string') {\n return input.name.toLowerCase()\n }\n return 'unknown'\n}\n\n/**\n * Checks whether a string is a simple property path expression.\n * Supports: foo.bar.baz, foo[0].bar, foo.bar[0].baz\n * @param expression - Expression string to check\n * @returns True if expression is a simple path\n */\nexport function isSimplePathExpression(expression: string): boolean {\n const exp = expression.trim()\n\n // allow dot + bracket numeric/index or identifier in brackets\n // examples: a.b, a[0], a['x'] is NOT supported here (intentionally)\n return /^[a-zA-Z_$][0-9a-zA-Z_$]*(?:\\[(?:\\d+|\\w+)\\]|\\.[a-zA-Z_$][0-9a-zA-Z_$]*)*$/.test(\n exp,\n )\n}\n\n/**\n * Sets a value on a nested object using a dot/bracket-notated path.\n * Does NOT create missing objects/arrays. Children may not \"invent\" structure in parent.\n * Throws descriptive errors when the path is invalid or non-writable.\n * Supports bracket tokens like [0] or [key] (key treated as string unless numeric).\n * @param obj - Object to write to\n * @param path - Property path (dot/bracket notation)\n * @param value - Value to set\n * @throws Error if path is invalid or property is read-only\n */\nexport function setValueByPath(obj: unknown, path: string, value: unknown): void {\n if (obj == null || (typeof obj !== 'object' && typeof obj !== 'function')) {\n throw new Error('❌ setValueByPath: target must be an object.')\n }\n if (typeof path !== 'string' || !path.trim()) {\n throw new Error('❌ setValueByPath: path must be a non-empty string.')\n }\n\n const tokens = path\n .trim()\n .replace(/\\[(\\w+)\\]/g, '.$1')\n .split('.')\n .filter(Boolean)\n\n if (tokens.length === 0) {\n throw new Error(`❌ setValueByPath: invalid path \"${path}\".`)\n }\n\n const hasOwn = (o: object, k: string) => Object.prototype.hasOwnProperty.call(o, k)\n\n const last = tokens.pop()!\n let target = obj as Record<string, unknown>\n\n for (const key of tokens) {\n if (target == null || (typeof target !== 'object' && typeof target !== 'function')) {\n throw new Error(\n `❌ setValueByPath: invalid path \"${path}\". Segment \"${key}\" is not an object.`,\n )\n }\n\n // IMPORTANT: no prototype traversal, no implicit creation\n if (!hasOwn(target, key)) {\n throw new Error(\n `❌ setValueByPath: invalid path \"${path}\". Missing segment \"${key}\".`,\n )\n }\n\n const next = target[key]\n\n if (next == null || (typeof next !== 'object' && typeof next !== 'function')) {\n throw new Error(\n `❌ setValueByPath: invalid path \"${path}\". Segment \"${key}\" is not an object.`,\n )\n }\n\n target = next as Record<string, unknown>\n }\n\n if (target == null || (typeof target !== 'object' && typeof target !== 'function')) {\n throw new Error(\n `❌ setValueByPath: invalid path \"${path}\". Final target is not an object.`,\n )\n }\n\n // IMPORTANT: final key must be an OWN property, otherwise assignment would create it\n if (!hasOwn(target, last)) {\n throw new Error(\n `❌ setValueByPath: invalid path \"${path}\". Final key \"${last}\" does not exist.`,\n )\n }\n\n const desc = Object.getOwnPropertyDescriptor(target, last)\n\n // If descriptor exists and is not writable and has no setter -> reject\n if (desc && desc.writable === false && !desc.set) {\n throw new Error(\n `❌ setValueByPath: cannot write \"${path}\". Property \"${last}\" is read-only.`,\n )\n }\n\n target[last] = value\n}\n","export const domExtensions: { [key: string]: PropertyDescriptor } = {\n select: {\n get(this: HTMLElement): (s: string) => HTMLElement | null {\n return (s: string) =>\n this instanceof HTMLInputElement || this instanceof HTMLTextAreaElement\n ? (this.select(), null)\n : this.querySelector(s)\n },\n },\n\n selectAll: {\n get(this: HTMLElement): (s: string) => NodeList {\n return (s: string) => this.querySelectorAll(s)\n },\n },\n\n addClass: {\n get(this: HTMLElement): (classes: string) => HTMLElement {\n return (classes: string) => {\n classes\n .split(/\\s+/)\n .map((c) => c.trim())\n .filter((c) => c.length > 0)\n .forEach((c) => this.classList.add(c))\n return this\n }\n },\n },\n\n removeClass: {\n get(this: HTMLElement): (classes: string) => HTMLElement {\n return (classes: string) => {\n classes\n .split(/\\s+/)\n .map((c) => c.trim())\n .filter((c) => c.length > 0)\n .forEach((c) => this.classList.remove(c))\n return this\n }\n },\n },\n\n toggleClass: {\n get(this: HTMLElement): (classes: string) => HTMLElement {\n return (classes: string) => {\n classes\n .split(/\\s+/)\n .map((c) => c.trim())\n .filter((c) => c.length > 0)\n .forEach((c) => this.classList.toggle(c))\n return this\n }\n },\n },\n\n hasClass: {\n get(this: HTMLElement): (c: string) => boolean {\n return (c: string) => this.classList.contains(c.trim())\n },\n },\n\n replaceWith: {\n get(this: HTMLElement): (newNode: HTMLElement | string) => void {\n return (newNode: HTMLElement | string) => {\n if (!this.parentNode) return\n if (newNode instanceof HTMLElement) {\n this.parentNode.replaceChild(newNode, this)\n } else if (typeof newNode === 'string') {\n this.insertAdjacentText('beforebegin', newNode)\n this.remove()\n }\n }\n },\n },\n\n siblings: {\n get(this: HTMLElement): (callback?: (sibling: HTMLElement) => void) => HTMLElement[] {\n return (callback) => {\n if (!this.parentNode) return []\n\n const siblings: HTMLElement[] = []\n let sibling: ChildNode | null = this.parentNode.firstChild\n\n while (sibling) {\n if (\n sibling.nodeType === Node.ELEMENT_NODE &&\n sibling !== this &&\n sibling instanceof HTMLElement\n ) {\n callback?.(sibling)\n siblings.push(sibling)\n }\n sibling = sibling.nextSibling\n }\n\n return siblings\n }\n },\n },\n\n before: {\n get(this: HTMLElement): (newNode: HTMLElement | string) => void {\n return (newNode: HTMLElement | string) => {\n if (!this.parentNode) return\n if (newNode instanceof HTMLElement) this.parentNode.insertBefore(newNode, this)\n else this.insertAdjacentHTML('beforebegin', newNode.toString())\n }\n },\n },\n\n after: {\n get(this: HTMLElement): (newNode: HTMLElement | string) => void {\n return (newNode: HTMLElement | string) => {\n if (!this.parentNode) return\n if (newNode instanceof HTMLElement)\n this.parentNode.insertBefore(newNode, this.nextSibling)\n else this.insertAdjacentHTML('afterend', newNode.toString())\n }\n },\n },\n\n attr: {\n get(this: HTMLElement): (attrName: string, attrValue?: string) => string | null {\n return (attrName: string, attrValue?: string) => {\n if (attrValue !== undefined) this.setAttribute(attrName, attrValue || 'true')\n return this.getAttribute(attrName)\n }\n },\n },\n}\n","export const objectExtensions: { [key: string]: PropertyDescriptor } = {}\n","import { getValueByPath, isSimplePathExpression } from './helper'\nimport { logger } from './logger'\n\n/**\n * Converts a kebab-case string to camelCase.\n * @param s - The kebab-case string to convert\n * @returns The converted camelCase string\n */\nexport function kebabToCamel(s: string): string {\n return s.replace(/-./g, (x) => x[1]!.toUpperCase())\n}\n\n// Hard block: forbid common dangerous identifiers / capabilities.\n// (This is a heuristic, not a formal proof.)\nconst FORBIDDEN_KEYWORDS_REGEX =\n /(?:\\bwindow\\b|\\bdocument\\b|\\bglobalThis\\b|\\bFunction\\b|\\beval\\b|\\bsetTimeout\\b|\\bsetInterval\\b|\\bfetch\\b|\\bXMLHttpRequest\\b|\\bimport\\b|\\brequire\\b|\\bthis\\b)/\n\n/**\n * Cache for compiled expression functions.\n * Key format: \"expression|var1,var2,var3\" (expression + sorted allowed vars)\n * This avoids recreating Functions on every render.\n */\nconst expressionCache = new Map<string, (...args: unknown[]) => unknown>()\n\n/**\n * Maximum cache size to prevent memory leaks in long-running apps.\n */\nconst MAX_CACHE_SIZE = 1000\n\n/**\n * Cache for sorted state keys per state object.\n * Avoids recomputing Object.keys(state).sort() for every complex expression.\n * Uses WeakMap so entries are GC'd when state objects are collected.\n * Invalidation uses a fingerprint of the actual key names (not just count),\n * so key swaps (delete + add with same count) are detected correctly.\n */\nconst sortedKeysCache = new WeakMap<\n Record<string, unknown>,\n { keys: string[]; fingerprint: string }\n>()\n\n/**\n * Gets sorted keys for a state object, using cache when possible.\n * Invalidates cache when the actual set of key names changes.\n */\nfunction getCachedSortedKeys(state: Record<string, unknown>): string[] {\n const currentKeys = Object.keys(state)\n const fingerprint = currentKeys.join('\\0')\n const cached = sortedKeysCache.get(state)\n if (cached && cached.fingerprint === fingerprint) {\n return cached.keys\n }\n const sorted = currentKeys.sort()\n sortedKeysCache.set(state, { keys: sorted, fingerprint })\n return sorted\n}\n\n/**\n * Evaluates a JavaScript expression in a controlled, restricted scope.\n * Blocks access to dangerous globals (window, document, eval, etc.).\n * Treats simple property paths as \"safe\" and resolves them via getValueByPath.\n * Evaluates complex expressions using Function, but only with variables from state.\n * Functions are called with state as this context.\n * Note: This is not a full sandbox. It's \"restricted and pragmatic\".\n * @param expression - Expression string to evaluate\n * @param state - State object to use as context\n * @returns Evaluated result or undefined on error/forbidden keywords\n */\nexport function evaluateExpression(\n expression: string,\n state: Record<string, unknown> = {},\n): unknown {\n const exp = (expression ?? '').trim()\n if (!exp) return undefined\n\n try {\n if (FORBIDDEN_KEYWORDS_REGEX.test(exp)) {\n return undefined\n }\n\n // Simple paths: resolve safely (supports brackets via isSimplePathExpression)\n if (isSimplePathExpression(exp)) {\n const value = getValueByPath(state, exp)\n if (typeof value === 'function') return value.call(state)\n return value\n }\n\n // Complex expression:\n // Only expose top-level keys from state as function parameters.\n // Everything else is not directly reachable unless referenced through those vars.\n const allowedVars = getCachedSortedKeys(state)\n\n // Build cache key from expression and variable names\n const cacheKey = `${exp}|${allowedVars.join(',')}`\n\n // Check cache for compiled function\n let evalFunction = expressionCache.get(cacheKey)\n\n if (!evalFunction) {\n // Use strict mode; expression is evaluated as a return value.\n const functionBody = `\"use strict\"; return (${exp});`\n evalFunction = new Function(...allowedVars, functionBody) as (\n ...args: unknown[]\n ) => unknown\n\n // Prevent unbounded cache growth\n if (expressionCache.size >= MAX_CACHE_SIZE) {\n // Remove oldest entry (first inserted)\n const firstKey = expressionCache.keys().next().value\n if (firstKey) expressionCache.delete(firstKey)\n }\n\n expressionCache.set(cacheKey, evalFunction)\n }\n\n return evalFunction(...allowedVars.map((key) => state[key]))\n } catch (error) {\n logger.debug(`Expression evaluation failed: ${exp}`, error)\n return undefined\n }\n}\n","import type { CompiledScript, ComponentContext, ComponentController } from '../types'\nimport { logger } from './logger'\n\n/**\n * Resolved dependencies object passed to the compiled script.\n * Keys are the local identifiers, values are the resolved import values.\n */\nexport type ResolvedDeps = Record<string, unknown>\n\n/**\n * Generates var declarations for injected dependencies.\n * Creates `var <IDENT> = __deps.<IDENT>;` for each dependency.\n *\n * @param depKeys - Array of dependency identifier names\n * @returns Injection header string to prepend to function body\n */\nfunction generateDepsInjectionHeader(depKeys: string[]): string {\n if (depKeys.length === 0) return ''\n\n // Generate var declarations for each dependency\n // No collision handling - redeclarations will throw SyntaxError naturally\n return depKeys.map((key) => `var ${key} = __deps.${key};`).join('\\n') + '\\n'\n}\n\n/**\n * Compiles component script string into an executable function.\n * Exposes context variables ($refs, $parent, etc.) and dynamic module properties.\n * Optionally injects resolved dependencies as local variables.\n *\n * @param strg - Component script string\n * @param resolvedDeps - Optional resolved dependencies to inject as local variables\n * @returns Compiled script function\n * @throws Error if compilation fails\n * @throws SyntaxError if user script redeclares an injected dependency name\n */\nexport function compileCode(strg: string, resolvedDeps?: ResolvedDeps): CompiledScript {\n const sanitizedCode = strg.replace(/\\$-\\{/g, '${')\n\n // Generate injection header for dependencies\n const depKeys = resolvedDeps ? Object.keys(resolvedDeps) : []\n const depsInjection = generateDepsInjectionHeader(depKeys)\n\n const functionBody = `\n const { $refs, $parent, $emit, $take, $handleEventFromChild, ...rest } = context;\n\n // Expose all $*-prefixed context entries (e.g. $router, $store) as local variables\n for (const [key, value] of Object.entries(rest)) {\n if (key.startsWith('$')) {\n // NOTE: this runs inside a dynamically generated function anyway\n // so using eval here does not make the environment less safe than it already is.\n eval('var ' + key + ' = value');\n }\n }\n\n // Inject resolved dependencies as local variables\n ${depsInjection}\n\n return (${sanitizedCode});\n `\n\n try {\n // Include __deps parameter if we have dependencies\n const rawFn = resolvedDeps\n ? new Function('context', '__deps', functionBody)\n : new Function('context', functionBody)\n\n const compiled = ((context: ComponentContext) =>\n resolvedDeps ? rawFn(context, resolvedDeps) : rawFn(context)) satisfies (\n context: ComponentContext,\n ) => ComponentController\n\n return compiled\n } catch (error) {\n logger.errorWithContext('Failed to compile dynamic code', { functionBody }, error)\n throw error\n }\n}\n","import type { State, HookCallback, LifecycleHook, LifecycleRegistry } from '../types'\nimport { logger } from './logger'\n\n/**\n * Creates a new lifecycle hook registry.\n * @returns New empty lifecycle registry\n */\nexport function createHookRegistry(): LifecycleRegistry {\n return new Map()\n}\n\nconst globalHookRegistry = createHookRegistry()\n\n/**\n * Registers a hook callback for the given event name.\n * Creates the internal Set if it doesn't exist yet.\n * @param registry - Registry to register in, or \"global\" for global registry\n * @param name - Lifecycle hook name\n * @param cb - Callback function to register\n */\nexport function hookOn(\n registry: LifecycleRegistry | 'global',\n name: LifecycleHook,\n cb: HookCallback,\n): void {\n if (registry === 'global') registry = globalHookRegistry\n if (!registry.has(name)) registry.set(name, new Set())\n registry.get(name)!.add(cb)\n}\n\n/**\n * Unregisters a specific hook callback for the given event name.\n * @param registry - Registry to unregister from, or \"global\" for global registry\n * @param name - Lifecycle hook name\n * @param cb - Callback function to unregister\n */\nexport function hookOff(\n registry: LifecycleRegistry | 'global',\n name: LifecycleHook,\n cb: HookCallback,\n): void {\n if (registry === 'global') registry = globalHookRegistry\n registry.get(name)?.delete(cb)\n}\n\n/**\n * Emits an event to all registered callbacks for the given name.\n * Each callback is wrapped in try-catch to prevent one failure from stopping others.\n * @param registry - Registry to emit from, or \"global\" for global registry\n * @param name - Lifecycle hook name\n * @param context - Optional state context to pass to callbacks\n */\nexport async function hookEmit(\n registry: LifecycleRegistry | 'global',\n name: LifecycleHook,\n context?: State,\n): Promise<void> {\n if (registry === 'global') registry = globalHookRegistry\n const listeners = Array.from(registry.get(name) ?? [])\n for (const fn of listeners) {\n try {\n await fn(context)\n } catch (error) {\n logger.errorWithContext(`Hook \"${name}\" callback failed`, { hook: name }, error)\n }\n }\n}\n\n/**\n * Clears all registered hooks in the registry.\n * @param registry - Registry to clear, or \"global\" for global registry\n */\nexport function hookClear(registry: LifecycleRegistry | 'global'): void {\n if (registry === 'global') registry = globalHookRegistry\n registry.clear()\n}\n","import type { IModule, IPlugin } from '../types'\n\n/**\n * Global registry for extensions (plugins and modules).\n * Plugins provide setup methods for components.\n * Modules provide attach methods for component elements.\n */\nexport const ExtensionRegistry: {\n modules: Record<string, IModule>\n plugins: Record<string, IPlugin>\n} = {\n modules: {},\n plugins: {},\n}\n","import type {\n ComponentInstance,\n ComponentSource,\n HTMLElementWithInstance,\n IModule,\n IPlugin,\n} from '../types'\n\n/* -------------------------------------------------------------------------- */\n/* ComponentSource Contract Guard */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Runtime type guard for the ComponentSource contract.\n *\n * Validates that an object conforms to the ComponentSource interface by\n * checking for REQUIRED fields only. Optional fields are not validated\n * (absence is acceptable), and unknown extra fields are ignored.\n *\n * ## Contract Validation Rules:\n *\n * **REQUIRED** (must be present and be strings):\n * - `template` - HTML template string\n * - `script` - JavaScript controller code string\n * - `style` - CSS style string\n *\n * **OPTIONAL** (not validated, absence is acceptable):\n * - `scriptMap`, `type`, `deps`, `structAttr`\n *\n * **IGNORED** (extra fields are allowed and not validated):\n * - Any additional properties are permitted for forward compatibility\n *\n * @param ext - The object to test\n * @returns True if the object satisfies the ComponentSource contract\n *\n * @example\n * ```ts\n * // Valid minimal ComponentSource\n * isComponentSource({ template: '', script: '', style: '' }) // true\n *\n * // Valid with optional fields\n * isComponentSource({ template: '', script: '', style: '', deps: null }) // true\n *\n * // Valid with extra fields (ignored)\n * isComponentSource({ template: '', script: '', style: '', debug: true }) // true\n *\n * // Invalid - missing required field\n * isComponentSource({ template: '', script: '' }) // false\n *\n * // Invalid - wrong type\n * isComponentSource({ template: 123, script: '', style: '' }) // false\n * ```\n */\nexport function isComponentSource(ext: unknown): ext is ComponentSource {\n if (ext == null || typeof ext !== 'object') return false\n const obj = ext as Record<string, unknown>\n\n // Validate REQUIRED fields only (must be strings)\n // Optional fields are not validated - absence is acceptable\n // Extra fields are ignored - forward compatibility\n return (\n typeof obj.template === 'string' &&\n typeof obj.script === 'string' &&\n typeof obj.style === 'string'\n )\n}\n\n/**\n * Determines whether the given object is a valid Plugin.\n *\n * @param ext - The object to test\n * @returns True if the object has a `setup` function and no `attach` method\n */\nexport function isPlugin(ext: unknown): ext is IPlugin {\n if (ext == null || typeof ext !== 'object') return false\n const obj = ext as Record<string, unknown>\n return typeof obj.setup === 'function' && obj.attach === undefined\n}\n\n/**\n * Determines whether the given object is a valid Module.\n *\n * @param ext - The object to test\n * @returns True if the object has an `attach` function and no `setup` method\n */\nexport function isModule(ext: unknown): ext is IModule {\n if (ext == null || typeof ext !== 'object') return false\n const obj = ext as Record<string, unknown>\n return typeof obj.attach === 'function' && obj.setup === undefined\n}\n\n/**\n * Checks whether a DOM element has the `instance` slot (may be undefined).\n *\n * @param el - The value to check\n * @returns True if el is an HTMLElement and carries an `instance` property\n */\nexport function isHTMLElementWithInstance(el: unknown): el is HTMLElementWithInstance {\n return el instanceof HTMLElement && 'instance' in el\n}\n\n/**\n * Checks whether a DOM element has a *set* component instance.\n *\n * @param el - The value to check\n * @returns True if el is HTMLElementWithInstance and instance is defined\n */\nexport function hasComponentInstance(\n el: unknown,\n): el is HTMLElementWithInstance & { instance: ComponentInstance } {\n return (\n el instanceof HTMLElement &&\n 'instance' in el &&\n (el as HTMLElementWithInstance).instance !== undefined\n )\n}\n\n/**\n * Validates that a RegExp match array represents a valid loop definition.\n *\n * Used for syntax like `item in collection`.\n *\n * @param match - The result of RegExp.match()\n * @returns True if the match has exactly three elements and valid capture groups\n */\nexport function isValidLoopMatch(\n match: RegExpMatchArray | null,\n): match is [string, string, string] {\n return !!match && match.length === 3 && Boolean(match[1]) && Boolean(match[2])\n}\n","import { objectExtensions } from './object'\nimport { domExtensions } from './dom'\n\n/**\n * Extends global prototypes with KoppaJS helper utilities.\n *\n * - Object.prototype is always extended (always available in JS)\n * - HTMLElement.prototype is only extended when DOM APIs exist\n *\n * In Node/SSR environments DOM-specific extensions are skipped automatically.\n */\nexport const extend = () => {\n Object.defineProperties(Object.prototype, objectExtensions)\n\n if (typeof HTMLElement !== 'undefined') {\n Object.defineProperties(HTMLElement.prototype, domExtensions)\n }\n}\n","/**\n * DOM Reconciliation Utility\n *\n * Provides efficient DOM diffing to update the DOM without destroying\n * and recreating custom element instances. This prevents infinite mount\n * loops when parent components re-render.\n */\n\nimport { getStructId, getSlotId, setStructId } from './index'\n\n/**\n * Checks if an element is a custom element (has a hyphen in the tag name).\n * @param node - The node to check\n * @returns True if the node is a custom element\n */\nfunction isCustomElement(node: Node): node is HTMLElement {\n return (\n node.nodeType === Node.ELEMENT_NODE && (node as HTMLElement).tagName.includes('-')\n )\n}\n\n/** * Removes all structAttr attributes from custom elements in the container.\n * Also reads the attribute value and stores it as a symbol before removal.\n * This ensures the attribute is never visible in the final DOM.\n * @param container - The container to process\n * @param structAttr - The attribute name to remove\n */\nfunction cleanupStructAttributes(container: Node, structAttr: string): void {\n const walker = document.createTreeWalker(container, NodeFilter.SHOW_ELEMENT, {\n acceptNode: (node) =>\n isCustomElement(node) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP,\n })\n\n let node = walker.nextNode() as HTMLElement | null\n while (node) {\n const attrValue = node.getAttribute(structAttr)\n if (attrValue !== null) {\n // Store as symbol if not already set\n if (getStructId(node) === undefined) {\n setStructId(node, attrValue)\n }\n // Remove the attribute from DOM\n node.removeAttribute(structAttr)\n }\n node = walker.nextNode() as HTMLElement | null\n }\n}\n\n/** * Generates an identity key for a node based on its structural and slot identifiers.\n * For custom elements:\n * - non-loop: (tagName, structId)\n * - loop: (tagName, structId, slotId)\n * @param node - The node to generate an identity key for\n * @param structAttr - Optional attribute name to fallback to if structId is not set\n * @returns The identity key string, or null if the node doesn't have identity\n */\nfunction getNodeIdentity(node: Node, structAttr?: string): string | null {\n if (!isCustomElement(node)) return null\n\n const tagName = (node as HTMLElement).tagName\n let structId = getStructId(node)\n const slotId = getSlotId(node)\n\n // Fallback: if no structId is set via runtime helper, read from attribute\n if (structId === undefined && structAttr) {\n const attrValue = (node as HTMLElement).getAttribute(structAttr)\n if (attrValue !== null) {\n setStructId(node, attrValue)\n structId = attrValue\n // Remove the attribute from DOM - the symbol is now the source of truth\n ;(node as HTMLElement).removeAttribute(structAttr)\n }\n }\n\n // Node must have at least structId to have identity\n if (structId === undefined) return null\n\n // Loop context: include slotId if present\n if (slotId !== undefined) {\n return `${tagName}:${String(structId)}:${String(slotId)}`\n }\n\n // Non-loop context: just tagName and structId\n return `${tagName}:${String(structId)}`\n}\n\n/**\n * Checks if two nodes are structurally equivalent for reconciliation purposes.\n * Custom elements match if they have the same tag name.\n * Regular elements match if they have the same tag name.\n * Text nodes match if they are both text nodes (content can differ).\n * @param nodeA - First node\n * @param nodeB - Second node\n * @returns True if the nodes are considered equivalent\n */\nfunction isSameNodeType(nodeA: Node, nodeB: Node): boolean {\n // Different node types\n if (nodeA.nodeType !== nodeB.nodeType) return false\n\n // Text nodes\n if (nodeA.nodeType === Node.TEXT_NODE) return true\n\n // Comment nodes\n if (nodeA.nodeType === Node.COMMENT_NODE) return true\n\n // Element nodes - compare tag names\n if (nodeA.nodeType === Node.ELEMENT_NODE) {\n return (nodeA as HTMLElement).tagName === (nodeB as HTMLElement).tagName\n }\n\n return false\n}\n\n/**\n * Updates attributes on an existing element to match the new element.\n * Preserves event handlers and only updates changed attributes.\n * @param existing - The existing element to update\n * @param updated - The new element with desired attributes\n */\nfunction reconcileAttributes(existing: HTMLElement, updated: HTMLElement): void {\n // Get all attribute names from both elements\n const existingAttrs = new Set(existing.getAttributeNames())\n const updatedAttrs = new Set(updated.getAttributeNames())\n\n // Remove attributes that no longer exist (except event handlers which start with @)\n for (const attr of existingAttrs) {\n if (!updatedAttrs.has(attr) && !attr.startsWith('@')) {\n existing.removeAttribute(attr)\n }\n }\n\n // Add or update attributes from the new element\n for (const attr of updatedAttrs) {\n const newValue = updated.getAttribute(attr)\n const existingValue = existing.getAttribute(attr)\n\n if (newValue !== existingValue) {\n if (newValue === null) {\n existing.removeAttribute(attr)\n } else {\n existing.setAttribute(attr, newValue)\n }\n }\n }\n}\n\n/**\n * Recursively reconciles the children of a container element.\n * This is the core diffing algorithm that preserves custom element instances.\n * Uses identity-based matching for custom elements to enable reordering without replacement.\n * @param existing - The existing container element\n * @param updated - The new container element (from template processing)\n * @param structAttr - Optional attribute name for structural identity fallback\n */\nfunction reconcileChildren(\n existing: HTMLElement,\n updated: HTMLElement,\n structAttr?: string,\n): void {\n const existingChildren = Array.from(existing.childNodes)\n const updatedChildren = Array.from(updated.childNodes)\n\n // Build identity map for existing custom elements\n const existingByIdentity = new Map<string, Node>()\n const existingUsed = new Set<Node>()\n\n for (const child of existingChildren) {\n const identity = getNodeIdentity(child, structAttr)\n if (identity !== null && !existingByIdentity.has(identity)) {\n existingByIdentity.set(identity, child)\n }\n }\n\n // Process each position in the updated children\n for (let i = 0; i < updatedChildren.length; i++) {\n const updatedChild = updatedChildren[i]\n const existingChild = existingChildren[i]\n const updatedIdentity = getNodeIdentity(updatedChild, structAttr)\n\n // Try to find a matching existing node by identity (for custom elements)\n let matchedNode: Node | null = null\n\n if (updatedIdentity !== null && existingByIdentity.has(updatedIdentity)) {\n matchedNode = existingByIdentity.get(updatedIdentity)!\n existingUsed.add(matchedNode)\n }\n\n // If we found a matching custom element by identity\n if (matchedNode && isCustomElement(matchedNode)) {\n // Move or keep the matched element at the correct position\n if (existingChild !== matchedNode) {\n // Need to move the element to the correct position\n if (i < existing.childNodes.length) {\n existing.insertBefore(matchedNode, existing.childNodes[i])\n } else {\n existing.appendChild(matchedNode)\n }\n }\n\n // Update attributes on the preserved custom element\n reconcileAttributes(matchedNode as HTMLElement, updatedChild as HTMLElement)\n // Do NOT update children or textContent - custom elements manage their own content\n continue\n }\n\n // No identity match found\n // For custom elements with identity, check if we should use positional or replace\n if (isCustomElement(updatedChild) && updatedIdentity !== null) {\n // This is a custom element with identity but no match found\n // We need to replace whatever is at this position\n // Use the actual node (not a clone) to preserve attached event listeners\n if (existingChild) {\n existing.replaceChild(updatedChild, existingChild)\n } else {\n existing.appendChild(updatedChild)\n }\n continue\n }\n\n // Non-identity nodes - fall back to positional matching\n // New node to add - use actual node to preserve attached event listeners\n if (!existingChild) {\n existing.appendChild(updatedChild)\n continue\n }\n\n // Check if they're the same type (positional match)\n if (!isSameNodeType(existingChild, updatedChild)) {\n // Different types - replace entirely, use actual node to preserve event listeners\n existing.replaceChild(updatedChild, existingChild)\n continue\n }\n\n // Same type - reconcile based on node type\n if (existingChild.nodeType === Node.TEXT_NODE) {\n // Text node - just update content if different\n if (existingChild.textContent !== updatedChild.textContent) {\n existingChild.textContent = updatedChild.textContent\n }\n continue\n }\n\n if (existingChild.nodeType === Node.COMMENT_NODE) {\n // Comment node - update if different\n if (existingChild.textContent !== updatedChild.textContent) {\n existingChild.textContent = updatedChild.textContent\n }\n continue\n }\n\n if (existingChild.nodeType === Node.ELEMENT_NODE) {\n const existingEl = existingChild as HTMLElement\n const updatedEl = updatedChild as HTMLElement\n\n // Custom elements need special handling\n if (isCustomElement(existingEl)) {\n // For custom elements without identity (positional match), only update attributes\n // Do NOT update children or textContent - custom elements manage their own content\n reconcileAttributes(existingEl, updatedEl)\n continue\n }\n\n // Regular HTML elements - update attributes and recurse into children\n reconcileAttributes(existingEl, updatedEl)\n reconcileChildren(existingEl, updatedEl, structAttr)\n }\n }\n\n // Remove any extra children that weren't matched or needed\n while (existing.childNodes.length > updatedChildren.length) {\n const lastChild = existing.lastChild\n if (lastChild) {\n existing.removeChild(lastChild)\n }\n }\n}\n\n/**\n * Reconciles the DOM content of a host element with new content.\n * This is the main entry point for DOM reconciliation.\n *\n * The algorithm:\n * 1. For the first render (host has no children), simply append the new content\n * 2. For subsequent renders, diff the existing children against new content\n * 3. Preserve custom element instances where possible\n * 4. Only update what has changed\n *\n * @param host - The host element to update\n * @param newContent - The new DocumentFragment with desired content\n * @param isFirstRender - Whether this is the initial render\n * @param structAttr - Optional attribute name for structural identity fallback\n */\nexport function reconcileDOM(\n host: HTMLElement,\n newContent: DocumentFragment,\n isFirstRender: boolean,\n structAttr?: string,\n): void {\n // First render - just append everything (no existing content to preserve)\n if (isFirstRender || host.childNodes.length === 0) {\n // Clean up structAttr attributes before inserting into DOM\n // This ensures the attribute is never visible to the user\n if (structAttr) {\n cleanupStructAttributes(newContent, structAttr)\n }\n host.replaceChildren(newContent)\n return\n }\n\n // Create a temporary container to work with the new content\n const tempContainer = document.createElement('div')\n tempContainer.appendChild(newContent)\n\n // Reconcile the children\n reconcileChildren(host as HTMLElement, tempContainer, structAttr)\n}\n","// Canonical identity layer for DOM nodes\nexport const STRUCT_ID = Symbol('STRUCT_ID')\nexport const SLOT_ID = Symbol('SLOT_ID')\n\n/** Internal type for objects with symbol-based identity markers */\ntype IdentifiableNode = {\n [STRUCT_ID]?: unknown\n [SLOT_ID]?: unknown\n}\n\nfunction setNonEnumerableProp(node: object, key: symbol, value: unknown) {\n Object.defineProperty(node, key, {\n value,\n writable: true,\n configurable: true,\n enumerable: false,\n })\n}\n\nexport function setStructId(node: object, id: unknown) {\n setNonEnumerableProp(node, STRUCT_ID, id)\n}\n\nexport function getStructId(node: object): unknown {\n return Object.prototype.hasOwnProperty.call(node, STRUCT_ID)\n ? (node as IdentifiableNode)[STRUCT_ID]\n : undefined\n}\n\nexport function setSlotId(node: object, id: unknown) {\n setNonEnumerableProp(node, SLOT_ID, id)\n}\n\nexport function getSlotId(node: object): unknown {\n return Object.prototype.hasOwnProperty.call(node, SLOT_ID)\n ? (node as IdentifiableNode)[SLOT_ID]\n : undefined\n}\n","import { bindOnce, logger } from './utils'\nimport type { AnyFn, State, Events, Refs, Methods } from './types'\n\n/**\n * Cleanup entry for a registered event listener.\n */\ntype EventCleanupEntry = {\n target: EventTarget\n type: string\n handler: EventListenerOrEventListenerObject\n}\n\n/**\n * Sets up custom event listeners for component events.\n * Handles window events, selector-based events, and ref-based events.\n * Returns a cleanup function that removes all listeners added by this call.\n * @param userContext - User context to bind handlers to\n * @param events - Array of event definitions\n * @param container - Document fragment to query selectors from\n * @param refs - Component element references\n * @returns Cleanup function that removes all listeners added by this call\n */\nexport function setupEvents(\n userContext: State,\n events: Events,\n container: DocumentFragment,\n refs: Refs,\n): () => void {\n if (!Array.isArray(events)) return () => {}\n\n const cleanupEntries: EventCleanupEntry[] = []\n\n events.forEach(([type, target, handler]) => {\n if (typeof type !== 'string' || typeof handler !== 'function') {\n logger.error('Provided handler is not a function', handler)\n return\n }\n\n let elements: (Element | Window)[] = []\n\n if (target === 'window') {\n elements = [window]\n } else if (typeof target === 'string') {\n if (target.startsWith('$refs.')) {\n const [refName, ...rest] = target.slice(6).split(' ')\n const ref = refs[refName]\n if (ref) {\n elements = rest.length\n ? Array.from(ref.querySelectorAll(rest.join(' ')))\n : [ref]\n }\n } else {\n elements = Array.from(container.querySelectorAll(target))\n }\n } else if (target instanceof Element || target instanceof Window) {\n elements = [target]\n } else if (typeof target === 'object' && target && 'ref' in target) {\n const { ref: refName, selector } = target\n const ref = refs[refName]\n if (ref) {\n elements = selector ? Array.from(ref.querySelectorAll(selector)) : [ref]\n }\n }\n\n for (const el of elements) {\n // Handler is already bound if userContext is a compose object (options type)\n // For composite type, userContext === state and handler should be bound to state\n const boundHandler = bindOnce(handler, userContext)\n el.addEventListener(type, boundHandler)\n cleanupEntries.push({ target: el, type, handler: boundHandler })\n }\n })\n\n return () => {\n for (const { target, type, handler } of cleanupEntries) {\n target.removeEventListener(type, handler)\n }\n cleanupEntries.length = 0\n }\n}\n\n/**\n * Regex to match event handler attributes: onClick, onclick, onMouseDown, onmousedown, etc.\n */\nconst EVENT_ATTR_REGEX = /^on([a-z]+)$/i\n\n/**\n * Binds native DOM event handlers from element attributes (e.g., onclick, oninput).\n * Walks all elements once instead of querying per event type for better performance.\n * Handlers are retrieved from userContext and assumed to be already bound (for options type).\n * @param userContext - User context containing event handlers\n * @param fragment - Document fragment to process\n */\nexport function bindNativeEvents(userContext: State, fragment: DocumentFragment): void {\n const walker = document.createTreeWalker(fragment, NodeFilter.SHOW_ELEMENT)\n let node = walker.nextNode() as HTMLElement | null\n\n while (node) {\n for (const attr of Array.from(node.attributes)) {\n const match = attr.name.match(EVENT_ATTR_REGEX)\n if (match) {\n const type = match[1]!.toLowerCase()\n const handlerName = attr.value\n if (handlerName) {\n const handler = userContext[handlerName]\n if (typeof handler === 'function') {\n // Handler is already bound via bindMethods, use directly\n node.removeAttribute(attr.name)\n node.addEventListener(type, handler as AnyFn)\n }\n }\n }\n }\n node = walker.nextNode() as HTMLElement | null\n }\n}\n\n/**\n * Binds native DOM event handlers for composite component type.\n * Walks all elements once instead of querying per event type for better performance.\n * Handlers are retrieved directly from methods object without binding.\n * @param methods - Methods object containing event handlers\n * @param fragment - Document fragment to process\n */\nexport function bindNativeEventsForComposite(\n methods: Methods,\n fragment: DocumentFragment,\n): void {\n const walker = document.createTreeWalker(fragment, NodeFilter.SHOW_ELEMENT)\n let node = walker.nextNode() as HTMLElement | null\n\n while (node) {\n for (const attr of Array.from(node.attributes)) {\n const match = attr.name.match(EVENT_ATTR_REGEX)\n if (match) {\n const type = match[1]!.toLowerCase()\n const handlerName = attr.value\n if (handlerName) {\n const handler = methods[handlerName]\n if (typeof handler === 'function') {\n // For composite type, use handler directly without binding\n node.removeAttribute(attr.name)\n node.addEventListener(type, handler)\n }\n }\n }\n }\n node = walker.nextNode() as HTMLElement | null\n }\n}\n\n/**\n * Sets up custom event listeners for composite component type.\n * Handlers are bound to state using bindOnce.\n * Returns a cleanup function that removes all listeners added by this call.\n * @param methods - Methods object (unused, kept for signature consistency)\n * @param state - Component state to bind handlers to\n * @param events - Array of event definitions\n * @param container - Document fragment to query selectors from\n * @param refs - Component element references\n * @returns Cleanup function that removes all listeners added by this call\n */\nexport function setupEventsForComposite(\n methods: Methods,\n state: State,\n events: Events,\n container: DocumentFragment,\n refs: Refs,\n): () => void {\n if (!Array.isArray(events)) return () => {}\n\n const cleanupEntries: EventCleanupEntry[] = []\n\n events.forEach(([type, target, handler]) => {\n if (typeof type !== 'string' || typeof handler !== 'function') {\n logger.error('Provided handler is not a function', handler)\n return\n }\n\n let elements: (Element | Window)[] = []\n\n if (target === 'window') {\n elements = [window]\n } else if (typeof target === 'string') {\n if (target.startsWith('$refs.')) {\n const [refName, ...rest] = target.slice(6).split(' ')\n const ref = refs[refName]\n if (ref) {\n elements = rest.length\n ? Array.from(ref.querySelectorAll(rest.join(' ')))\n : [ref]\n }\n } else {\n elements = Array.from(container.querySelectorAll(target))\n }\n } else if (target instanceof Element || target instanceof Window) {\n elements = [target]\n } else if (typeof target === 'object' && target && 'ref' in target) {\n const { ref: refName, selector } = target\n const ref = refs[refName]\n if (ref) {\n elements = selector ? Array.from(ref.querySelectorAll(selector)) : [ref]\n }\n }\n\n for (const el of elements) {\n // For composite type, bind handler to state (not userContext)\n const boundHandler = bindOnce(handler, state)\n el.addEventListener(type, boundHandler)\n cleanupEntries.push({ target: el, type, handler: boundHandler })\n }\n })\n\n return () => {\n for (const { target, type, handler } of cleanupEntries) {\n target.removeEventListener(type, handler)\n }\n cleanupEntries.length = 0\n }\n}\n","const EVENT_REGISTRY = new WeakMap<EventTarget, Set<EventListenerEntry>>()\n\ntype EventListenerEntry = {\n type: string\n listener: EventListenerOrEventListenerObject\n options?: boolean | AddEventListenerOptions\n}\n\nlet observer: MutationObserver | undefined\n\n/** Internal type for tracking patching status on globalThis */\ninterface KoppajsGlobalThis {\n __koppajsEventTrackingPatched?: boolean\n}\n\n/**\n * Patches EventTarget.prototype.addEventListener/removeEventListener\n * to globally track registered listeners.\n *\n * This only runs when EventTarget exists (browser/JSDOM).\n * In Node/SSR it is a safe no-op.\n */\nexport function patchGlobalEventTracking(): void {\n if (typeof EventTarget === 'undefined') return\n\n const g = globalThis as KoppajsGlobalThis\n\n if (g.__koppajsEventTrackingPatched) return\n g.__koppajsEventTrackingPatched = true\n\n const nativeAdd = EventTarget.prototype.addEventListener\n const nativeRemove = EventTarget.prototype.removeEventListener\n\n EventTarget.prototype.addEventListener = function (\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ) {\n if (!EVENT_REGISTRY.has(this)) {\n EVENT_REGISTRY.set(this, new Set())\n }\n\n EVENT_REGISTRY.get(this)!.add({ type, listener, options })\n return nativeAdd.call(this, type, listener, options)\n }\n\n EventTarget.prototype.removeEventListener = function (\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | EventListenerOptions,\n ) {\n const entries = EVENT_REGISTRY.get(this)\n if (entries) {\n for (const entry of entries) {\n if (entry.type === type && entry.listener === listener) {\n entries.delete(entry)\n break\n }\n }\n if (entries.size === 0) {\n EVENT_REGISTRY.delete(this)\n }\n }\n\n return nativeRemove.call(this, type, listener, options)\n }\n}\n\n/**\n * Removes all listeners registered on a specific EventTarget.\n */\nexport function cleanupAllEventListeners(target: EventTarget): void {\n const entries = EVENT_REGISTRY.get(target)\n if (!entries) return\n\n for (const { type, listener, options } of entries) {\n target.removeEventListener(type, listener, options)\n }\n\n EVENT_REGISTRY.delete(target)\n}\n\n/**\n * Recursively cleans up all event listeners in a DOM subtree.\n * This is only active in environments where DOM APIs exist.\n */\nexport function cleanupSubtree(root: Node): void {\n if (\n typeof document === 'undefined' ||\n typeof NodeFilter === 'undefined' ||\n typeof Element === 'undefined'\n ) {\n return\n }\n\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT)\n let node: Element | null = root instanceof Element ? root : null\n\n while (node) {\n if (EVENT_REGISTRY.has(node)) {\n cleanupAllEventListeners(node)\n }\n node = walker.nextNode() as Element | null\n }\n}\n\n/**\n * Starts a global MutationObserver that automatically cleans up\n * event listeners from removed DOM elements.\n *\n * In SSR/Node environments this function is a safe no-op.\n */\nexport function startGlobalDisconnectionObserver(): void {\n if (observer) return\n if (typeof MutationObserver === 'undefined' || typeof document === 'undefined') return\n if (!document.body) return\n\n observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n mutation.removedNodes.forEach((removedNode) => {\n if (removedNode.nodeType !== Node.ELEMENT_NODE) return\n cleanupSubtree(removedNode)\n })\n }\n })\n\n observer.observe(document.body, { childList: true, subtree: true })\n}\n\n/**\n * Stops the global observer (useful in tests).\n */\nexport function stopGlobalDisconnectionObserver(): void {\n if (!observer) return\n observer.disconnect()\n observer = undefined\n}\n","import { IS_PROXY } from './types'\n\n/**\n * WeakMap for Proxy cache - global for all models.\n * Maps original object -> proxy\n */\nconst globalProxyCache = new WeakMap<object, object>()\n\n/**\n * WeakMap for reverse lookup - proxy -> original object.\n * This allows us to find the original object from a proxy.\n */\nconst globalProxyToOriginalCache = new WeakMap<object, object>()\n\n/**\n * WeakMap for slot sidecars - tracks slotIds for each reactive array.\n * Maps array -> string[] where each string is a unique slotId for that array position.\n *\n * SLOT SIDECAR SYSTEM:\n * ====================\n * Reactive arrays maintain a parallel \"sidecar\" array of unique slot identifiers (slotIds).\n * Each element in a reactive array has a corresponding slotId that follows it through operations.\n *\n * Semantics:\n * - Structural operations (push/pop/shift/unshift/splice/reverse/sort) update slotIds identically\n * - Non-structural updates (arr[i] = x) preserve the slotId at index i\n * - Full array replacement (state.arr = newArr) creates a fresh sidecar with all new slotIds\n *\n * This enables frameworks to track element identity across array mutations for efficient\n * DOM reconciliation and state management.\n */\nconst globalSlotSidecars = new WeakMap<unknown[], string[]>()\n\n/**\n * Counter for generating unique slot IDs.\n */\nlet slotIdCounter = 0\n\n/**\n * Generates a new unique slot ID.\n */\nconst generateSlotId = (): string => {\n return `slot-${++slotIdCounter}`\n}\n\n/**\n * Type guard to check if value is an object.\n */\nconst isObject = (value: unknown): value is object =>\n typeof value === 'object' && value !== null\n\n/**\n * Converts a property key to a string.\n */\nconst toPropName = (property: PropertyKey): string =>\n typeof property === 'symbol' ? property.toString() : String(property)\n\n/**\n * Gets cached proxy for an object if it exists.\n */\nconst getCachedProxy = <O extends object>(obj: O): O | undefined => {\n const cached = globalProxyCache.get(obj)\n return cached && isObject(cached) ? (cached as O) : undefined\n}\n\n// Get the original object from a proxy (if it's a proxy) or return the object itself\nexport function getOriginalObject(obj: object): object {\n // Check if obj is a proxy by looking in the reverse cache\n const original = globalProxyToOriginalCache.get(obj)\n if (original) return original\n // If not found, obj is likely the original\n return obj\n}\n\n/**\n * Checks if an object is a reactive proxy.\n */\nexport const isProxy = (obj: unknown): boolean => {\n if (!isObject(obj)) return false\n return Reflect.get(obj, IS_PROXY) === true\n}\n\n/**\n * Gets the slotIds for a reactive array, if present.\n * Returns the sidecar array containing unique slot identifiers for each element,\n * or undefined if the array is not reactive or has no sidecar.\n * The returned array is readonly and should not be mutated directly.\n * @param arr - The array to retrieve slotIds for\n * @returns Readonly array of slotIds, or undefined if no sidecar exists\n */\nexport function getSlotIdsForArray(arr: unknown[]): readonly string[] | undefined {\n // Get the original array if arr is a proxy\n const originalArr = isProxy(arr) ? (getOriginalObject(arr) as unknown[]) : arr\n return globalSlotSidecars.get(originalArr)\n}\n\n/**\n * Checks if a value is a primitive type.\n */\nconst isPrimitive = (value: unknown): boolean =>\n value !== null &&\n (typeof value === 'string' ||\n typeof value === 'number' ||\n typeof value === 'boolean' ||\n typeof value === 'function' ||\n typeof value === 'undefined')\n\n/**\n * Gets or initializes the slotIds array for a reactive array.\n * If the array doesn't have a sidecar yet, creates one with fresh slotIds for each element.\n * @internal\n */\nconst getOrInitSlotIdsForArray = (arr: unknown[]): string[] => {\n let slotIds = globalSlotSidecars.get(arr)\n if (!slotIds) {\n slotIds = arr.map(() => generateSlotId())\n globalSlotSidecars.set(arr, slotIds)\n }\n return slotIds\n}\n\n/**\n * Ensures the slot sidecar invariant: slotIds array must have the same length as the data array.\n * This should be called after any structural mutation to validate consistency.\n * @internal\n */\nconst ensureSlotSidecarInvariant = (arr: unknown[]): void => {\n const slotIds = globalSlotSidecars.get(arr)\n if (slotIds && slotIds.length !== arr.length) {\n throw new Error(\n `Slot sidecar invariant violation: slotIds length (${slotIds.length}) does not match array length (${arr.length})`,\n )\n }\n}\n\n/**\n * Watcher callback info passed to watch callbacks.\n */\nexport interface WatcherInfo {\n changedPaths: Set<string>\n}\n\n/**\n * Watcher callback type.\n */\nexport type WatcherCallback = (info: WatcherInfo) => void\n\n/**\n * Creates a reactive model with proxy-based reactivity.\n * Tracks property changes and notifies observers when state changes.\n * Supports effect subscriptions via watch() with prefix-matching and batching.\n * @param initialData - Initial state object\n * @returns Reactive model with watch and observer methods\n */\nexport function createModel<T extends Record<string, unknown>>(\n initialData: T,\n): {\n state: T\n watch: (path: string, cb: WatcherCallback) => () => void\n addObserver: (observer: () => void) => void\n removeObserver: (observer: () => void) => void\n getStateVersion: () => number\n hasPendingChangesFor: (prefixes: string[]) => boolean\n flushChanges: () => Set<string>\n} {\n // Private state\n const observers = new Set<() => void>()\n const objectPaths = new WeakMap<object, string>() // Track each object's path in the state tree\n let stateVersion = 0 // Version counter for state changes\n let changedPaths = new Set<string>()\n\n // Watcher subscriptions: path prefix -> Set of callbacks\n const watchers = new Map<string, Set<WatcherCallback>>()\n\n /**\n * Checks if a changed path matches a watcher's path prefix.\n * A watcher for \"user\" matches \"user\" and anything starting with \"user.\".\n */\n const pathMatchesPrefix = (changedPath: string, watchPrefix: string): boolean => {\n if (changedPath === watchPrefix) return true\n if (changedPath.startsWith(watchPrefix + '.')) return true\n return false\n }\n\n /**\n * Builds the fully qualified path for a property on a target object.\n */\n const buildPath = (target: object, property: string): string => {\n const parentPath = objectPaths.get(target) ?? ''\n return parentPath ? `${parentPath}.${property}` : property\n }\n\n /**\n * Batched observer notification using microtask scheduling.\n * Multiple synchronous state mutations are coalesced into a single observer notification.\n */\n let notifyScheduled = false\n\n const notifyObservers = (path: string): void => {\n changedPaths.add(path)\n stateVersion++\n\n // Schedule a single batched notification via microtask\n if (!notifyScheduled) {\n notifyScheduled = true\n queueMicrotask(() => {\n notifyScheduled = false\n observers.forEach((observer) => {\n try {\n observer()\n } catch (e) {\n // Observers should handle their own errors\n console.error('Observer error:', e)\n }\n })\n })\n }\n }\n\n // Diff functions for arrays - now accept a path for notifying observers\n /**\n * Compares two arrays element-by-element by reference in O(n) time.\n * Determines if there are any differences and mutates oldArr to match newArr.\n */\n const diffArraysByReferenceNoDeepMerge = (\n oldArr: unknown[],\n newArr: unknown[],\n path: string,\n ): void => {\n if (oldArr === newArr) return\n\n let hasChanges = oldArr.length !== newArr.length\n if (!hasChanges) {\n for (let i = 0; i < oldArr.length; i++) {\n if (oldArr[i] !== newArr[i]) {\n hasChanges = true\n break\n }\n }\n }\n\n oldArr.splice(0, oldArr.length, ...newArr)\n\n if (hasChanges) {\n notifyObservers(path)\n }\n }\n\n const diffArraysSimple = (oldArr: unknown[], newArr: unknown[], path: string): void => {\n const oldSet = new Set(oldArr)\n const newSet = new Set(newArr)\n\n let hasChanges = false\n for (const item of oldSet) {\n if (!newSet.has(item)) {\n hasChanges = true\n break\n }\n }\n if (!hasChanges) {\n for (const item of newSet) {\n if (!oldSet.has(item)) {\n hasChanges = true\n break\n }\n }\n }\n\n if (hasChanges) {\n // Mutate oldArr to match newArr before notifying\n oldArr.splice(0, oldArr.length, ...newArr)\n notifyObservers(path)\n }\n }\n\n const diffArraysOptimized = (\n oldArr: unknown[],\n newArr: unknown[],\n path: string,\n ): void => {\n const oldSet = new Set(oldArr)\n const newSet = new Set(newArr)\n\n const onlyAddedOrRemoved =\n oldArr.length !== newArr.length ||\n [...oldSet].some((item) => !newSet.has(item)) ||\n [...newSet].some((item) => !oldSet.has(item))\n\n if (onlyAddedOrRemoved) diffArraysSimple(oldArr, newArr, path)\n else diffArraysByReferenceNoDeepMerge(oldArr, newArr, path)\n }\n\n const mergeInPlaceObject = (\n oldObj: Record<string, unknown>,\n newObj: Record<string, unknown>,\n basePath: string,\n ): boolean => {\n if (oldObj === newObj) return false\n\n let hasChanges = false\n\n // Remove properties not in new object\n for (const key of Object.keys(oldObj)) {\n if (!(key in newObj)) {\n hasChanges = true\n Reflect.deleteProperty(oldObj, key)\n }\n }\n\n // Add or update properties from new object\n for (const key of Object.keys(newObj)) {\n const oldVal = oldObj[key]\n const newVal = newObj[key]\n\n if (oldVal === newVal) continue\n\n const nestedPath = basePath ? `${basePath}.${key}` : key\n\n if (isObject(oldVal) && isProxy(oldVal) && isObject(newVal) && !isProxy(newVal)) {\n const nestedChanged = mergeInPlaceObject(\n oldVal as Record<string, unknown>,\n newVal as Record<string, unknown>,\n nestedPath,\n )\n if (nestedChanged) {\n hasChanges = true\n }\n if (oldVal !== newVal) {\n hasChanges = true\n Reflect.set(oldObj, key, newVal)\n }\n } else {\n hasChanges = true\n Reflect.set(oldObj, key, newVal)\n }\n }\n\n return hasChanges\n }\n\n /**\n * Updates the slot sidecar for an array after a structural mutation.\n * Handles push, pop, shift, unshift, splice, reverse, and sort operations.\n */\n const updateSlotSidecarForArrayMutation = (\n arr: unknown[],\n method: string,\n args: unknown[],\n ): void => {\n const slotIds = getOrInitSlotIdsForArray(arr)\n\n switch (method) {\n case 'push': {\n // Add new slotIds for each pushed element\n const newSlotIds = Array.from({ length: args.length }, () => generateSlotId())\n slotIds.push(...newSlotIds)\n break\n }\n case 'pop': {\n // Remove the last slotId\n slotIds.pop()\n break\n }\n case 'shift': {\n // Remove the first slotId\n slotIds.shift()\n break\n }\n case 'unshift': {\n // Add new slotIds at the beginning\n const newSlotIds = Array.from({ length: args.length }, () => generateSlotId())\n slotIds.unshift(...newSlotIds)\n break\n }\n case 'splice': {\n // Handle splice: remove elements and insert new ones\n const start = (args[0] as number) ?? 0\n const deleteCount =\n args[1] !== undefined ? (args[1] as number) : arr.length - start\n const itemsToInsert = args.slice(2)\n const newSlotIds = Array.from({ length: itemsToInsert.length }, () =>\n generateSlotId(),\n )\n slotIds.splice(start, deleteCount, ...newSlotIds)\n break\n }\n case 'reverse': {\n // Reverse the slotIds array to match the reversed data array\n slotIds.reverse()\n break\n }\n case 'sort': {\n // For sort, we need to reorder slotIds based on how the array was sorted\n // We'll store the original indices before sort and then reorder slotIds accordingly\n // This is handled by creating a copy of slotIds before sort and reordering after\n break\n }\n }\n\n ensureSlotSidecarInvariant(arr)\n }\n\n // Main reactive wrapper\n const makeReactive = <O extends object>(obj: O, parentPath = ''): O => {\n // Don't make DOM nodes, Window, or Document reactive - Proxies don't work with native DOM APIs\n if (obj instanceof Node || obj instanceof Window || obj instanceof Document) {\n return obj\n }\n\n const cached = getCachedProxy(obj)\n if (cached) return cached\n\n // Track this object's path in the state tree\n if (parentPath) {\n objectPaths.set(obj, parentPath)\n }\n\n // Initialize slot sidecar for arrays\n if (Array.isArray(obj)) {\n getOrInitSlotIdsForArray(obj)\n }\n\n const proxy = new Proxy(obj, {\n get: (target, property, receiver) => {\n if (property === IS_PROXY) return true\n // Handle toJSON for JSON.stringify - return the original object to avoid circular references\n if (property === 'toJSON') {\n return function () {\n // Return the original object (not the proxy) to avoid circular references\n return getOriginalObject(target)\n }\n }\n\n // Intercept array mutating methods to update slot sidecars\n if (Array.isArray(target) && typeof property === 'string') {\n const arrayMutatingMethods = [\n 'push',\n 'pop',\n 'shift',\n 'unshift',\n 'splice',\n 'reverse',\n 'sort',\n ]\n if (arrayMutatingMethods.includes(property)) {\n const originalMethod = (target as unknown[])[property as keyof unknown[]]\n if (typeof originalMethod === 'function') {\n return function (this: unknown[], ...args: unknown[]) {\n // For sort, we need to track the reordering by snapshotting before\n if (property === 'sort') {\n const slotIds = getOrInitSlotIdsForArray(target)\n // Create a snapshot of elements paired with their slotIds\n const snapshot = target.map((el, i) => ({\n el,\n slotId: slotIds[i] || generateSlotId(),\n }))\n\n // Execute the sort\n const result = originalMethod.apply(this, args as never)\n\n // Reorder slotIds to match the sorted array using Map for O(n) lookup\n const elementToIndices = new Map<unknown, number[]>()\n for (let i = 0; i < snapshot.length; i++) {\n const el = snapshot[i]!.el\n let indices = elementToIndices.get(el)\n if (!indices) {\n indices = []\n elementToIndices.set(el, indices)\n }\n indices.push(i)\n }\n\n for (let i = 0; i < target.length; i++) {\n const element = target[i]\n const indices = elementToIndices.get(element)\n if (indices && indices.length > 0) {\n const matchIdx = indices.shift()!\n slotIds[i] = snapshot[matchIdx]!.slotId\n } else {\n slotIds[i] = generateSlotId()\n }\n }\n\n ensureSlotSidecarInvariant(target)\n return result\n } else {\n // For other methods, call the method first then update sidecar\n const result = originalMethod.apply(this, args as never)\n updateSlotSidecarForArrayMutation(target, property, args)\n return result\n }\n }\n }\n }\n }\n\n const value = Reflect.get(target, property, receiver) as unknown\n // Automatically make nested objects/arrays reactive when accessed\n // Exception: don't make array elements reactive (when parent is array and property is numeric)\n const isArrayElement =\n Array.isArray(target) && typeof property === 'string' && /^\\d+$/.test(property)\n if (isObject(value) && !isProxy(value) && !isArrayElement) {\n // Make nested arrays reactive, but not other objects within arrays\n if (Array.isArray(value) || !Array.isArray(target)) {\n const propName = toPropName(property)\n const nestedPath = buildPath(target, propName)\n return makeReactive(value, nestedPath)\n }\n }\n return value\n },\n\n set: (target, property, value, receiver) => {\n const oldValue = Reflect.get(target, property, receiver) as unknown\n if (oldValue === value) return true\n\n const propName = toPropName(property)\n const path = buildPath(target, propName)\n\n // Handle direct array index assignment (non-structural update)\n // e.g., arr[2] = newValue - should keep the same slotId at index 2\n if (\n Array.isArray(target) &&\n typeof property === 'string' &&\n /^\\d+$/.test(property)\n ) {\n const index = parseInt(property, 10)\n if (index >= 0 && index < target.length) {\n // This is a non-structural update - just update the value, slotId stays the same\n const result = Reflect.set(target, property, value, receiver)\n notifyObservers(path)\n return result\n }\n }\n\n // Special array handling - full array replacement creates fresh sidecar\n if (Array.isArray(oldValue) && !isPrimitive(value) && Array.isArray(value)) {\n // Mutate oldValue in place to match the new array content\n diffArraysOptimized(oldValue, value, path)\n // Create a fresh slot sidecar for the mutated array (all new slotIds)\n // IMPORTANT: Derive slotIds from oldValue (the live array instance after mutation),\n // not from the transient 'value' reference that won't be stored\n const newSlotIds = oldValue.map(() => generateSlotId())\n globalSlotSidecars.set(oldValue, newSlotIds)\n return true\n }\n\n // Special object handling - merge in place and notify once\n if (\n isObject(oldValue) &&\n isProxy(oldValue) &&\n isObject(value) &&\n !isProxy(value)\n ) {\n const hasChanges = mergeInPlaceObject(\n oldValue as Record<string, unknown>,\n value as Record<string, unknown>,\n path,\n )\n if (hasChanges) {\n let finalVal: unknown = value\n if (isObject(finalVal) && !isProxy(finalVal)) {\n finalVal = makeReactive(finalVal, path)\n }\n Reflect.set(target, property, finalVal, receiver)\n notifyObservers(path)\n }\n return true\n }\n\n // Standard property assignment\n const result = Reflect.set(target, property, value, receiver)\n\n if (isObject(value) && !isProxy(value)) {\n const reactive = makeReactive(value, path)\n Reflect.set(target, property, reactive, receiver)\n // If the value is an array, initialize its slot sidecar\n if (Array.isArray(value)) {\n getOrInitSlotIdsForArray(value)\n }\n }\n\n // Single notification for this mutation\n notifyObservers(path)\n\n return result\n },\n\n deleteProperty: (target, property) => {\n // Skip internal/ephemeral properties to avoid triggering renders\n if (property === 'changedPaths') {\n return Reflect.deleteProperty(target, property)\n }\n\n const propName = toPropName(property)\n const path = buildPath(target, propName)\n const oldValue = Reflect.get(target, property) as unknown\n\n const isDeleted = Reflect.deleteProperty(target, property)\n\n if (isDeleted && oldValue !== undefined) {\n notifyObservers(path)\n }\n return isDeleted\n },\n })\n\n globalProxyCache.set(obj, proxy)\n globalProxyToOriginalCache.set(proxy, obj)\n return proxy\n }\n\n // Create reactive state\n const state = makeReactive(initialData)\n\n // Public API\n return {\n state,\n\n /**\n * Registers a watcher for a path prefix.\n * The callback is called at most once per flush cycle with the subset of\n * changed paths that match this watcher's prefix.\n *\n * Prefix-match rules:\n * - A watcher for \"user\" matches \"user\" and anything starting with \"user.\"\n *\n * @param path - The path prefix to watch\n * @param cb - Callback receiving { changedPaths: Set<string> } with matching paths\n * @returns A cleanup function stop() that unregisters this watcher (idempotent)\n */\n watch(path: string, cb: WatcherCallback): () => void {\n let callbacks = watchers.get(path)\n if (!callbacks) {\n callbacks = new Set()\n watchers.set(path, callbacks)\n }\n callbacks.add(cb)\n\n // Track if already stopped to make stop() idempotent\n let stopped = false\n\n // Return cleanup function\n return () => {\n if (stopped) return\n stopped = true\n\n const cbs = watchers.get(path)\n if (cbs) {\n cbs.delete(cb)\n if (cbs.size === 0) {\n watchers.delete(path)\n }\n }\n }\n },\n\n addObserver(observer: () => void): void {\n observers.add(observer)\n },\n\n removeObserver(observer: () => void): void {\n observers.delete(observer)\n },\n\n getStateVersion(): number {\n return stateVersion\n },\n\n /**\n * Checks if any pending changed path matches one of the given prefixes.\n * Useful for components with a watchList to skip irrelevant renders.\n * @param prefixes - Array of path prefixes to check against\n * @returns True if at least one pending change matches a prefix\n */\n hasPendingChangesFor(prefixes: string[]): boolean {\n for (const path of changedPaths) {\n for (const prefix of prefixes) {\n if (path === prefix || path.startsWith(prefix + '.')) return true\n }\n }\n return false\n },\n\n /**\n * Flushes changed paths and notifies watchers.\n * Each watcher callback is called at most once with the subset of changed paths\n * that match its prefix.\n *\n * @returns A copy of all changed paths since the last flush\n */\n flushChanges(): Set<string> {\n const result = new Set(changedPaths)\n\n // Notify watchers with their relevant subset of changed paths (batched)\n if (result.size > 0 && watchers.size > 0) {\n // Collect callbacks and their matching paths to avoid issues during iteration\n const callbacksToNotify = new Map<WatcherCallback, Set<string>>()\n\n for (const [prefix, callbacks] of watchers) {\n const matchingPaths = new Set<string>()\n for (const changedPath of result) {\n if (pathMatchesPrefix(changedPath, prefix)) {\n matchingPaths.add(changedPath)\n }\n }\n\n if (matchingPaths.size > 0) {\n for (const cb of callbacks) {\n // Merge paths if callback is registered under multiple prefixes\n const existingPaths = callbacksToNotify.get(cb)\n if (existingPaths) {\n for (const p of matchingPaths) {\n existingPaths.add(p)\n }\n } else {\n callbacksToNotify.set(cb, new Set(matchingPaths))\n }\n }\n }\n }\n\n // Call each callback exactly once with its merged matching paths\n for (const [cb, paths] of callbacksToNotify) {\n cb({ changedPaths: paths })\n }\n }\n\n changedPaths = new Set<string>()\n return result\n },\n }\n}\n","import { containsHTML, evaluateExpression, logger } from './utils'\nimport { setSlotId } from './utils'\nimport { getSlotIdsForArray } from './model'\nimport type { State, Refs } from './types'\n\ntype IfChainState = {\n hasHead: boolean\n resolved: boolean // true if chain already resolved by a kept if/else-if, so rest is removed\n}\n\n/**\n * Represents a parsed loop binding - either a single variable or a tuple [key, value].\n */\ntype LoopBinding =\n | { type: 'single'; itemVar: string }\n | { type: 'tuple'; keyVar: string; itemVar: string }\n\nconst IDENTIFIER_REGEX = /^[A-Za-z_$][A-Za-z0-9_$]*$/\n\n/**\n * Parses loop binding syntax: either \"item\" or \"[key, item]\".\n * @param bindingStr - The binding string to parse\n * @returns Parsed binding object\n * @throws Error if binding syntax is invalid\n */\nfunction parseLoopBinding(bindingStr: string): LoopBinding {\n const trimmed = bindingStr.trim()\n\n // Check for tuple binding: [key, item]\n if (trimmed.startsWith('[') && trimmed.endsWith(']')) {\n const inner = trimmed.slice(1, -1)\n const parts = inner.split(',').map((p) => p.trim())\n\n if (parts.length !== 2) {\n throw new Error('Invalid loop binding: expected <id> or [<id>, <id>]')\n }\n\n const [keyVar, itemVar] = parts\n\n if (!IDENTIFIER_REGEX.test(keyVar) || !IDENTIFIER_REGEX.test(itemVar)) {\n throw new Error('Invalid loop binding: expected <id> or [<id>, <id>]')\n }\n\n return { type: 'tuple', keyVar, itemVar }\n }\n\n // Single binding: item\n if (!IDENTIFIER_REGEX.test(trimmed)) {\n throw new Error('Invalid loop binding: expected <id> or [<id>, <id>]')\n }\n\n return { type: 'single', itemVar: trimmed }\n}\n\nfunction createFilteredTreeWalker(rootElement: Node): TreeWalker {\n const filter: NodeFilter = {\n acceptNode(node: Node): number {\n if (node.nodeType === Node.ELEMENT_NODE) return NodeFilter.FILTER_ACCEPT\n\n // Text nodes only if they contain {{ ... }}\n if (\n node.nodeType === Node.TEXT_NODE &&\n /\\{\\{(.+?)\\}\\}/g.test(node.nodeValue || '')\n ) {\n return NodeFilter.FILTER_ACCEPT\n }\n\n return NodeFilter.FILTER_SKIP\n },\n }\n\n return document.createTreeWalker(\n rootElement,\n NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT,\n filter,\n )\n}\n\n/**\n * Skips to the next node in the tree walker.\n * @param walker - TreeWalker instance\n * @returns Next node or null\n */\nfunction skipNode(walker: TreeWalker): Node | null {\n const current = walker.currentNode\n return current?.nextSibling\n ? (walker.currentNode = current.nextSibling)\n : walker.nextNode()\n}\n\n/**\n * Skips the entire subtree of the current node and moves to the next sibling or ancestor's sibling.\n * This is used to skip processing children of loop elements since they will be processed\n * recursively with the correct local state.\n * @param walker - TreeWalker instance\n * @param element - The element whose subtree should be skipped\n * @returns Next node outside the subtree or null\n */\nfunction skipSubtree(walker: TreeWalker, element: Node): Node | null {\n let next: Node | null = element.nextSibling\n\n // If no next sibling, walk up to find an ancestor with a next sibling\n if (!next) {\n let parent = element.parentNode\n while (parent && parent !== walker.root) {\n if (parent.nextSibling) {\n next = parent.nextSibling\n break\n }\n parent = parent.parentNode\n }\n }\n\n if (next) {\n walker.currentNode = next\n return next\n }\n\n return null\n}\n\n/**\n * Converts a template expression result to a string for rendering.\n * - null/undefined => \"\"\n * - true/false => \"\"\n * - otherwise => String(value) (e.g., 0 becomes \"0\")\n * @param value - The value to stringify\n * @returns String representation for template output\n */\nfunction stringifyTemplateValue(value: unknown): string {\n if (value == null) return ''\n if (value === true || value === false) return ''\n return String(value)\n}\n\n/**\n * Replaces {{ expression }} template strings with evaluated values.\n * @param template - Template string with {{ }} expressions\n * @param state - State object for evaluation\n * @returns String with expressions replaced\n */\nfunction replaceTemplateString(template: string, state: State): string {\n return template.replace(/\\{\\{(.+?)\\}\\}/g, (_, expression) => {\n const result = evaluateExpression(expression.trim(), state)\n return stringifyTemplateValue(result)\n })\n}\n\n/**\n * Applies loop directive to an element, creating multiple instances.\n * Supports both single binding (item in items) and tuple binding ([key, item] in items).\n * @param element - Element with loop attribute\n * @param state - Component state\n * @param refs - Component element references\n */\nexport async function applyLoop(\n element: HTMLElement,\n state: State,\n refs: Refs,\n): Promise<void> {\n const loopDefinition = element.getAttribute('loop')\n if (!loopDefinition) return\n\n element.removeAttribute('loop')\n\n // allow: <div loop=\"x in items\" if=\"...\"> ... </div>\n const toplevelIf = element.getAttribute('if')\n if (toplevelIf) element.removeAttribute('if')\n\n // Updated regex to capture the full binding part (single or tuple)\n const match = loopDefinition.match(/^(.+?)\\s+in\\s+(.+)$/)\n if (!match) {\n throw new Error('Invalid loop binding: expected <id> or [<id>, <id>]')\n }\n\n const [, bindingStr, collectionExp] = match\n const binding = parseLoopBinding(bindingStr)\n const raw = evaluateExpression(collectionExp.trim(), state)\n\n // Allow empty arrays/objects - they just render nothing\n if (raw === null || raw === undefined) {\n element.remove()\n return\n }\n\n if (typeof raw !== 'object') {\n logger.error('State source is not iterable', { collectionExp, raw })\n return\n }\n\n const isArray = Array.isArray(raw)\n const entries: [string, unknown][] = isArray\n ? (raw as unknown[]).map((value, idx) => [String(idx), value])\n : Object.entries(raw)\n const totalCount = entries.length\n const fragment = document.createDocumentFragment()\n\n // Pre-compute slotIds once before the loop (avoid repeated lookups)\n const slotIds = isArray ? getSlotIdsForArray(raw as unknown[]) : undefined\n\n // Create a single local state object and reuse it across iterations\n // (avoids N full state copies for large state or large loops)\n const localState: State = { ...state }\n\n let index = 0\n for (const [key, value] of entries) {\n // Overwrite loop-specific properties each iteration (cheap)\n localState.index = index\n localState.key = key\n localState.isFirst = index === 0\n localState.isLast = index === totalCount - 1\n localState.isEven = index % 2 === 0\n localState.isOdd = index % 2 !== 0\n\n // Apply binding\n if (binding.type === 'single') {\n localState[binding.itemVar] = value\n } else {\n // Tuple binding: first identifier gets key, second gets value\n localState[binding.keyVar] = key\n localState[binding.itemVar] = value\n }\n\n if (toplevelIf && !evaluateExpression(toplevelIf, localState)) {\n index++\n continue\n }\n\n const cloned = element.cloneNode(true)\n // Attach slotId from model sidecar for array iteration\n if (isArray && cloned instanceof HTMLElement) {\n if (slotIds && slotIds[index] !== undefined) {\n setSlotId(cloned, slotIds[index])\n }\n // If slotIds is missing or slotIds[index] is missing, gracefully skip (no slotId attached)\n }\n if (cloned instanceof HTMLElement) {\n // Safe to pass localState directly: await makes iterations sequential,\n // so localState values are stable for the entire processTemplate call.\n await processTemplate(cloned, localState, refs)\n fragment.appendChild(cloned)\n }\n\n index++\n }\n\n if (fragment.childNodes.length > 0 && element.parentNode) {\n element.parentNode.replaceChild(fragment, element)\n } else {\n // Empty collection - remove the template element\n element.remove()\n }\n}\n\n/**\n * Applies Vue-like if/else-if/else chain logic to an element.\n * Maintains chain state per parent element to handle nested conditionals.\n * - Elements between are neutral (do not break the chain).\n * - Chain is \"open\" after an `if` (even if it was removed).\n * - `else-if` and `else` bind to the last open chain in the same parent.\n * - Once an `else` is processed, the chain is consumed.\n * - A new `if` starts a new chain (overwrites any previous open chain).\n * @param element - Element with if/else-if/else attribute\n * @param state - Component state for condition evaluation\n * @param chainByParent - WeakMap storing chain state per parent node\n */\nfunction applyIfChainVueLoose(\n element: HTMLElement,\n state: State,\n chainByParent: WeakMap<Node, IfChainState>,\n): void {\n const parent = element.parentNode\n\n // Helper: get existing chain, or empty one\n const getChain = (): IfChainState | undefined => {\n if (!parent) return undefined\n return chainByParent.get(parent)\n }\n\n const setChain = (next: IfChainState) => {\n if (!parent) return\n chainByParent.set(parent, next)\n }\n\n const clearChain = () => {\n if (!parent) return\n chainByParent.delete(parent)\n }\n\n // IF\n const ifCond = element.getAttribute('if')\n if (ifCond !== null) {\n const ok = !!evaluateExpression(ifCond, state)\n\n // New IF starts a new chain for this parent (overwrite)\n setChain({ hasHead: true, resolved: ok })\n\n if (!ok) {\n element.remove()\n } else {\n element.removeAttribute('if')\n }\n return\n }\n\n // ELSE-IF\n const elseIfCond = element.getAttribute('else-if')\n if (elseIfCond !== null) {\n const chain = getChain()\n\n // No preceding chain\n if (!chain?.hasHead) {\n element.remove()\n return\n }\n\n // Chain already resolved by earlier if/else-if => remove\n if (chain.resolved) {\n element.remove()\n return\n }\n\n const ok = !!evaluateExpression(elseIfCond, state)\n\n // Update chain resolution\n setChain({ hasHead: true, resolved: ok })\n\n if (!ok) {\n element.remove()\n } else {\n element.removeAttribute('else-if')\n }\n return\n }\n\n // ELSE\n if (element.hasAttribute('else')) {\n const chain = getChain()\n\n // No preceding chain\n if (!chain?.hasHead) {\n element.remove()\n return\n }\n\n if (chain.resolved) {\n // Something earlier was kept => else removed\n element.remove()\n } else {\n // Nothing earlier kept => else kept\n element.removeAttribute('else')\n }\n\n // ELSE always consumes the chain\n clearChain()\n return\n }\n\n // Any other element: neutral (does NOT break chain)\n}\n\nasync function processNodeBatch(\n pendingNodes: { node: HTMLElement | Text; state: State }[],\n refs: Refs,\n batchSize = 50,\n): Promise<void> {\n // Persist across batches: chain must survive batch boundaries\n const chainByParent = new WeakMap<Node, IfChainState>()\n\n for (let i = 0; i < pendingNodes.length; i += batchSize) {\n const batch = pendingNodes.slice(i, i + batchSize)\n\n for (const { node, state } of batch) {\n if (node instanceof HTMLElement) {\n // LOOP handled separately\n if (node.hasAttribute('loop')) {\n await applyLoop(node, state, refs)\n continue\n }\n\n // IF / ELSE-IF / ELSE\n if (\n node.hasAttribute('if') ||\n node.hasAttribute('else') ||\n node.hasAttribute('else-if')\n ) {\n applyIfChainVueLoose(node, state, chainByParent)\n continue\n }\n\n // Any other element is neutral for the chain\n continue\n }\n\n // TEXT is neutral for the chain\n const newContent = replaceTemplateString(node.nodeValue!, state)\n if (containsHTML(newContent)) {\n const frag = document.createRange().createContextualFragment(newContent)\n node.replaceWith(frag)\n } else {\n node.nodeValue = newContent\n }\n }\n\n if (i + batchSize < pendingNodes.length) {\n await new Promise(requestAnimationFrame)\n }\n }\n}\n\n/**\n * Processes a template tree, evaluating expressions, loops, and conditionals.\n * Handles attribute interpolation, ref collection, and text node replacement.\n * @param root - Root node to process\n * @param state - Component state for expression evaluation\n * @param refs - Component element references (populated during processing)\n */\nexport async function processTemplate(\n root: Node,\n state: State,\n refs: Refs,\n): Promise<void> {\n try {\n const walker = createFilteredTreeWalker(root)\n const processed = new Set<Node>()\n const pending: { node: HTMLElement | Text; state: State }[] = []\n\n let current: Node | null = walker.currentNode\n\n while (current) {\n if (processed.has(current)) {\n current = walker.nextNode()\n continue\n }\n\n processed.add(current)\n\n if (current.nodeType === Node.ELEMENT_NODE && current instanceof HTMLElement) {\n const el = current\n\n // Queue loops (and skip their subtree completely)\n if (el.hasAttribute('loop')) {\n pending.push({ node: el, state })\n current = skipSubtree(walker, el)\n continue\n }\n\n // Queue if/else-if/else nodes for ordered evaluation\n if (\n el.hasAttribute('if') ||\n el.hasAttribute('else') ||\n el.hasAttribute('else-if')\n ) {\n pending.push({ node: el, state })\n }\n\n // refs + attribute interpolation + dynamic bindings\n for (const attr of Array.from(el.attributes)) {\n if (attr.name === 'ref') refs[attr.value] = el\n\n // Handle dynamic attribute bindings (:class, :href, :data-*, etc.)\n if (attr.name.startsWith(':')) {\n const realAttrName = attr.name.slice(1)\n const expr = attr.value.trim()\n\n try {\n const evaluated = evaluateExpression(expr, state)\n\n // Special handling for :class with object syntax\n if (\n realAttrName === 'class' &&\n typeof evaluated === 'object' &&\n evaluated !== null\n ) {\n const classesToAdd: string[] = []\n for (const [className, condition] of Object.entries(evaluated)) {\n if (condition) {\n classesToAdd.push(className)\n }\n }\n if (classesToAdd.length > 0) {\n const existingClasses = el.getAttribute('class') || ''\n const newClasses = existingClasses\n ? `${existingClasses} ${classesToAdd.join(' ')}`\n : classesToAdd.join(' ')\n el.setAttribute('class', newClasses)\n }\n } else if (\n evaluated !== null &&\n evaluated !== undefined &&\n evaluated !== false\n ) {\n // For boolean true, just set the attribute without value\n if (evaluated === true) {\n el.setAttribute(realAttrName, '')\n } else {\n el.setAttribute(realAttrName, String(evaluated))\n }\n }\n\n // Remove the dynamic binding attribute\n el.removeAttribute(attr.name)\n } catch (err) {\n logger.errorWithContext(\n `Error evaluating dynamic attribute \"${attr.name}\"`,\n { attributeName: attr.name, expression: expr },\n err,\n )\n }\n continue\n }\n\n if (attr.value.includes('{{')) {\n try {\n let updated = replaceTemplateString(attr.value, state)\n // Normalize whitespace for class attributes only\n if (attr.name === 'class') {\n updated = updated.replace(/\\s+/g, ' ').trim()\n }\n if (updated !== attr.value) el.setAttribute(attr.name, updated)\n } catch (err) {\n logger.errorWithContext(\n `Error replacing attribute \"${attr.name}\"`,\n { attributeName: attr.name },\n err,\n )\n }\n }\n }\n\n // Don't traverse into custom elements\n if (el.tagName.includes('-')) {\n current = skipNode(walker) || walker.nextNode()\n continue\n }\n } else if (current.nodeType === Node.TEXT_NODE && current instanceof Text) {\n // Skip text nodes inside custom elements\n let parent = current.parentElement\n let isInsideCustomElement = false\n while (parent) {\n if (parent.tagName.includes('-')) {\n isInsideCustomElement = true\n break\n }\n parent = parent.parentElement\n }\n if (!isInsideCustomElement) {\n pending.push({ node: current, state })\n }\n }\n\n current = walker.nextNode()\n }\n\n await processNodeBatch(pending, refs)\n } catch (error) {\n logger.errorWithContext('Error processing template', {}, error)\n throw error\n }\n}\n","import { ComposeOptions } from './types'\nimport { logger } from './utils/logger'\n\n/**\n * Composes multiple objects into a single Proxy that delegates property access.\n * Properties are read from the first layer that contains them.\n * Writes go to the layer where the property exists, or to defaultWriteIndex if not found.\n * @param layers - Array of objects to compose\n * @param options - Composition options\n * @returns Proxy object that combines all layers\n * @throws Error if layers is empty or contains invalid objects\n */\nexport function composeBySource<T extends object[]>(\n layers: T,\n options: ComposeOptions = {},\n): T[number] {\n if (!Array.isArray(layers) || layers.length === 0) {\n throw new Error('composeBySource: layers must be a non-empty array')\n }\n\n if (layers.some((layer) => layer == null || typeof layer !== 'object')) {\n throw new Error('composeBySource: all layers must be objects')\n }\n\n const { defaultWriteIndex = layers.length - 1, includePrototype = false } = options\n\n const validWriteIndex =\n defaultWriteIndex >= 0 &&\n defaultWriteIndex < layers.length &&\n Number.isInteger(defaultWriteIndex)\n ? defaultWriteIndex\n : layers.length - 1\n\n if (defaultWriteIndex !== validWriteIndex) {\n logger.warnWithContext(\n `Invalid defaultWriteIndex ${defaultWriteIndex}, using ${validWriteIndex}`,\n { defaultWriteIndex, validWriteIndex, layersLength: layers.length },\n )\n }\n\n const has = (obj: object, key: PropertyKey) =>\n includePrototype ? key in obj : Object.prototype.hasOwnProperty.call(obj, key)\n\n const findLayerIndex = (key: PropertyKey): number => {\n for (let i = 0; i < layers.length; i++) {\n if (has(layers[i]!, key)) return i\n }\n return -1\n }\n\n /** Internal type for dynamic property access on composed layers */\n type LayerRecord = Record<PropertyKey, unknown>\n\n return new Proxy(layers[validWriteIndex] as object, {\n get(_target, prop) {\n const idx = findLayerIndex(prop)\n if (idx !== -1) return (layers[idx] as LayerRecord)[prop]\n return undefined\n },\n\n set(_target, prop, value) {\n const idx = findLayerIndex(prop)\n const writeTo = idx !== -1 ? idx : validWriteIndex\n ;(layers[writeTo] as LayerRecord)[prop] = value\n return true\n },\n\n deleteProperty(_target, prop) {\n const idx = findLayerIndex(prop)\n if (idx === -1) return true\n return delete (layers[idx] as LayerRecord)[prop]\n },\n\n has(_target, prop) {\n return findLayerIndex(prop) !== -1\n },\n\n ownKeys() {\n const keys = new Set<string | symbol>()\n for (const layer of layers) {\n Reflect.ownKeys(layer).forEach((k) => {\n if (typeof k !== 'number') keys.add(k)\n })\n }\n return Array.from(keys)\n },\n\n getOwnPropertyDescriptor(_target, prop) {\n for (const layer of layers) {\n const desc = Object.getOwnPropertyDescriptor(layer, prop)\n if (desc) return desc\n }\n return undefined\n },\n }) as T[number]\n}\n","import {\n bindNativeEvents,\n bindNativeEventsForComposite,\n setupEvents,\n setupEventsForComposite,\n} from './event-handler'\nimport { cleanupSubtree } from './global-event-cleaner'\nimport { createModel } from './model'\nimport { processTemplate } from './template-processor'\nimport {\n bindMethods,\n compileCode,\n createHookRegistry,\n ExtensionRegistry,\n evaluateExpression,\n getExpectedPropTypeName,\n getValueByPath,\n hasComponentInstance,\n hookEmit,\n hookOn,\n isSimplePathExpression,\n kebabToCamel,\n setValueByPath,\n bindOnce,\n logger,\n reconcileDOM,\n} from './utils'\n\nimport { Core } from '.'\nimport {\n lifecycleHooks,\n type AnyFn,\n type ComponentInstance,\n type ComponentSource,\n type State,\n type Events,\n type HTMLElementWithInstance,\n type Props,\n type Refs,\n} from './types'\nimport { composeBySource } from './compose'\n\n/**\n * Internal type extending ComponentInstance with runtime-only properties.\n * These properties are not part of the public API but are used internally\n * for rendering coordination and state tracking.\n */\ninterface ComponentInstanceInternal extends ComponentInstance {\n /** Flag indicating if the component is currently rendering */\n isRendering?: boolean\n /** Last rendered state version for change detection */\n _lastRenderedStateVersion?: number\n}\n\n/**\n * Internal type extending State with runtime metadata.\n * Used during lifecycle hooks to pass changed paths information.\n */\ninterface StateWithMetadata extends State {\n /** Paths that changed since last render, available in lifecycle hooks */\n changedPaths?: Set<string>\n}\n\n/**\n * Gets the parent component instance for an element.\n * @param el - Element to find parent for\n * @returns Parent component instance or undefined\n */\nfunction getParentInstance(el: Element): ComponentInstance | undefined {\n const rootNode = el.getRootNode()\n const parent =\n el.parentElement ?? (rootNode instanceof ShadowRoot ? rootNode.host : undefined)\n\n if (hasComponentInstance(parent)) {\n return parent.instance\n }\n\n return undefined\n}\n\n/**\n * Processes slot elements in component template.\n * Replaces <slot> elements with content from host element.\n * @param container - Template fragment containing slot elements\n * @param host - Host element containing slot content\n */\nexport function processSlots({\n container,\n host,\n}: {\n container: DocumentFragment\n host: HTMLElement\n}): void {\n const slotContent = Array.from(host.childNodes).filter(\n (node) => node.nodeType === Node.ELEMENT_NODE || node.nodeType === Node.TEXT_NODE,\n )\n\n const slotMap: Record<string, Node[]> = {}\n\n for (const node of slotContent) {\n const slotName =\n node instanceof HTMLElement && node.hasAttribute('slot')\n ? node.getAttribute('slot')!\n : 'default'\n\n if (!slotMap[slotName]) {\n slotMap[slotName] = []\n }\n\n slotMap[slotName].push(node)\n }\n\n container.querySelectorAll('slot').forEach((slotElement) => {\n const slotName = slotElement.getAttribute('name') || 'default'\n const replacementNodes = slotMap[slotName]\n\n if (replacementNodes && replacementNodes.length > 0) {\n replacementNodes.forEach((node) => {\n slotElement.parentNode!.insertBefore(node, slotElement)\n })\n }\n\n slotElement.remove()\n })\n}\n\n/** Stage slot processing off-DOM; move the original nodes only at commit time. */\nfunction prepareSlots(container: DocumentFragment, host: HTMLElement, refs: Refs) {\n const originals = new Map<Node, Node>()\n const snapshots = new Map<\n Node,\n { attributes: Map<string, string>; children: Node[]; value: string | null }\n >()\n const remapRefs = () => {\n for (const key of Object.keys(refs)) {\n const original = originals.get(refs[key])\n if (original instanceof HTMLElement) refs[key] = original\n }\n }\n if (!container.querySelector('slot')) return { commit: () => {}, remapRefs }\n const stagedHost = document.createElement('div')\n const stage = (node: Node): Node => {\n const clone = node.cloneNode(false)\n originals.set(clone, node)\n if (!(node instanceof HTMLElement && node.tagName.includes('-'))) {\n for (const child of node.childNodes) clone.appendChild(stage(child))\n }\n snapshots.set(clone, {\n attributes: new Map(\n node instanceof HTMLElement\n ? Array.from(node.attributes, (attr) => [attr.name, attr.value])\n : [],\n ),\n children: Array.from(clone.childNodes),\n value: clone.nodeValue,\n })\n return clone\n }\n for (const node of host.childNodes) stagedHost.appendChild(stage(node))\n processSlots({ container, host: stagedHost })\n\n const commit = () => {\n const restore = (node: Node): Node => {\n const original = originals.get(node)\n const snapshot = snapshots.get(node)\n const children = Array.from(node.childNodes)\n const restoredChildren = children.map(restore)\n if (!original || !snapshot) {\n children.forEach((child, i) => {\n if (restoredChildren[i] !== child) child.replaceWith(restoredChildren[i])\n })\n return node\n }\n if (original instanceof HTMLElement && node instanceof HTMLElement) {\n // Apply processing changes only; keep modifications made through live refs in hooks.\n for (const name of snapshot.attributes.keys()) {\n if (!node.hasAttribute(name)) original.removeAttribute(name)\n }\n for (const attr of Array.from(node.attributes)) {\n if (snapshot.attributes.get(attr.name) !== attr.value) {\n original.setAttribute(attr.name, attr.value)\n }\n }\n if (\n !original.tagName.includes('-') &&\n (children.length !== snapshot.children.length ||\n children.some((child, i) => child !== snapshot.children[i]))\n ) {\n original.replaceChildren(...restoredChildren)\n }\n } else if (node.nodeValue !== snapshot.value) {\n original.nodeValue = node.nodeValue\n }\n return original\n }\n for (const child of Array.from(container.childNodes)) {\n const restored = restore(child)\n if (restored !== child) child.replaceWith(restored)\n }\n remapRefs()\n }\n return { commit, remapRefs }\n}\n\n/**\n * Validates a prop value against its definition.\n * @param propName - Name of the prop\n * @param propValue - Value to validate\n * @param props - Props definition object\n * @returns True if prop is valid, false otherwise\n */\nexport function validateProp({\n propName,\n propValue,\n props,\n}: {\n propName: string\n propValue: unknown\n props: Props\n}): boolean {\n const propOptions = props[propName]\n const pValue = propValue ?? propOptions?.default\n\n if (!propOptions) return true\n\n const expectedType = getExpectedPropTypeName(propOptions.type)\n const actualType = Array.isArray(pValue) ? 'array' : typeof pValue\n\n const typeChecks: Record<string, boolean> = {\n string: actualType === 'string',\n number: actualType === 'number',\n boolean: actualType === 'boolean',\n array: Array.isArray(pValue),\n object: actualType === 'object' && pValue !== null && !Array.isArray(pValue),\n function: actualType === 'function',\n }\n\n // If expected type is unknown, skip runtime type validation\n const typeMatches =\n expectedType === 'unknown' ? true : (typeChecks[expectedType] ?? false)\n\n if (!typeMatches) {\n logger.error(\n `Prop \"${propName}\" should be of type \"${expectedType}\", but got \"${actualType}\".`,\n pValue,\n )\n return false\n }\n\n if (\n propOptions.regex &&\n typeof pValue === 'string' &&\n !new RegExp(propOptions.regex).test(pValue)\n ) {\n logger.error(`Prop \"${propName}\" does not match regex \"${propOptions.regex}\".`)\n return false\n }\n\n return true\n}\n\n/**\n * Processes component props from element attributes.\n * Handles static props, dynamic props, and two-way bindings.\n * @param ele - Component element\n * @param parent - Parent component instance\n * @param props - Props definition\n * @param state - Component state to populate\n */\nfunction processProps({\n ele,\n parent,\n props,\n state,\n}: {\n ele: HTMLElement\n parent: ComponentInstance | undefined\n props: Props\n state: State\n}) {\n const hasDefinedProps = Object.keys(props).length > 0\n\n const defineBoundProp = (propName: string, parentPath: string) => {\n Object.defineProperty(state, propName, {\n enumerable: true,\n configurable: true,\n get() {\n if (!parent) return undefined\n return getValueByPath(parent.state, parentPath)\n },\n set(next) {\n if (!parent || !parent.state) return\n\n try {\n setValueByPath(parent.state, parentPath, next)\n } catch (error) {\n logger.errorWithContext(\n `Failed to set bound prop \"${propName}\" → \"${parentPath}\"`,\n { propName, parentPath },\n error,\n )\n }\n },\n })\n }\n\n for (const attr of ele.attributes) {\n const isDynamic = attr.name.startsWith(':')\n const propName = kebabToCamel(attr.name.substring(isDynamic ? 1 : 0))\n\n // ignore \":\" without parent (SSR, standalone, etc.)\n if (isDynamic && !parent) continue\n\n // If component declares props, validate against it (as far as possible)\n const isAllowed =\n !hasDefinedProps || (props[propName] && props[propName] !== undefined)\n\n if (!isAllowed) continue\n\n // STATIC\n if (!isDynamic) {\n const value = attr.value !== '' ? attr.value : true\n\n if (!hasDefinedProps || validateProp({ propName, propValue: value, props })) {\n state[propName] = value\n }\n\n continue\n }\n\n // DYNAMIC\n const expr = attr.value?.trim() ?? ''\n\n // If it's a simple path, create a true binding (two-way)\n if (expr && isSimplePathExpression(expr)) {\n // validate based on current value (read)\n const currentValue = getValueByPath(parent!.state, expr)\n\n if (\n !hasDefinedProps ||\n validateProp({ propName, propValue: currentValue, props })\n ) {\n defineBoundProp(propName, expr)\n }\n\n continue\n }\n\n // Otherwise: evaluate expression one-way (read-only)\n const evaluated = expr ? evaluateExpression(expr, parent!.state) : undefined\n\n if (!hasDefinedProps || validateProp({ propName, propValue: evaluated, props })) {\n state[propName] = evaluated\n }\n }\n\n // Defaults / required\n for (const [propName, propOptions] of Object.entries(props)) {\n if (!(propName in state)) {\n if (propOptions.default !== undefined) {\n state[propName] = propOptions.default\n } else if (propOptions.required) {\n logger.error(`Required prop \"${propName}\" is missing.`)\n }\n }\n }\n}\n\n/**\n * Registers a component with the custom elements registry.\n * @param componentName - Custom element tag name\n * @param source - Component source with template, script, and style\n */\nexport function registerComponent(componentName: string, source: ComponentSource): void {\n const connectedHosts = new Set<HTMLElement>()\n\n customElements.define(\n componentName,\n class extends HTMLElement {\n private template: HTMLTemplateElement\n\n /**\n * Public instance property for type compatibility with HTMLElementWithInstance.\n */\n public instance?: ComponentInstance\n\n // Cleanup state for deterministic teardown\n private _connectionVersion = 0\n private _isDisconnected = false\n private _isMounted = false // Track if component has been mounted (persists across connectedCallback calls)\n private _model?: ReturnType<typeof createModel>\n private _observerFn?: () => void\n private _renderAborted = false\n private _pendingRender: (() => Promise<void>) | null = null\n private _eventCleanup: (() => void) | null = null // Cleanup for setupEvents listeners (including window)\n\n constructor() {\n super()\n this.template = document.createElement('template')\n this.template.innerHTML = source.template\n }\n\n async connectedCallback() {\n const host = this as HTMLElementWithInstance\n const connectionVersion = ++this._connectionVersion\n this._isDisconnected = false\n this._renderAborted = false\n this._pendingRender = null\n connectedHosts.add(this)\n if (!document.head.querySelector(`style#style-${componentName}`)) {\n const style = document.createElement('style')\n style.id = `style-${componentName}`\n style.textContent = source.style\n document.head.appendChild(style)\n }\n\n // ============================================================\n // SCENARIO 1: RERENDER/RECONNECT - Reuse existing instance\n // ============================================================\n // Wenn bereits eine Instanz existiert (nach disconnect/connect),\n // wiederverwenden statt neu erstellen\n if (host.instance && this._model && this._observerFn) {\n const existingInstance = host.instance\n const parent = getParentInstance(host)\n\n // Update parent reference (kann sich geändert haben)\n existingInstance.$parent = parent\n\n // Reset disconnected state für Reconnect\n this._isDisconnected = false\n this._renderAborted = false\n this._pendingRender = null\n\n // Re-add observer in case disconnectedCallback already removed it\n this._model.addObserver(this._observerFn)\n\n // Props neu verarbeiten (können sich geändert haben)\n if (existingInstance.props && existingInstance.state) {\n processProps({\n ele: host,\n parent,\n props: existingInstance.props,\n state: existingInstance.state,\n })\n }\n\n // WICHTIG: mounted() Hook darf NICHT nochmal feuern beim Reconnect\n // mounted() geht nur einmal beim ersten Create/Render\n // Observer wird automatisch Renders triggern wenn nötig\n return\n }\n\n // ============================================================\n // SCENARIO 2: CREATE - Neue Instanz erstellen\n // ============================================================\n // Nur wenn noch keine Instanz existiert\n\n // Component type bestimmen (default: \"options\")\n const componentType = source.type || 'options'\n const useUserContext = componentType === 'options'\n\n // Parent früh ermitteln (bevor replaceChildren Children aktiviert)\n const parent = getParentInstance(host)\n\n const clonedTemplate = this.template.cloneNode(true) as HTMLTemplateElement\n\n // Resolve deps BEFORE compiling the controller script\n // This allows imports from [ts] block to be injected as local variables\n let resolvedDeps: Record<string, unknown> | undefined\n if (source.deps) {\n resolvedDeps = {}\n const depEntries = Object.entries(source.deps)\n const resolvedValues = await Promise.all(\n depEntries.map(([, importFn]) => importFn()),\n )\n for (let i = 0; i < depEntries.length; i++) {\n resolvedDeps[depEntries[i][0]] = resolvedValues[i]\n }\n }\n\n if (connectionVersion !== this._connectionVersion || this._isDisconnected) return\n\n const compiledScript = compileCode(source.script, resolvedDeps)\n\n const refs: Refs = {}\n let isRendering = false\n let lastRenderedStateVersion = -1 // Track state version instead of serialized data\n\n // Reset disconnected state for new connection\n this._isDisconnected = false\n this._renderAborted = false\n this._pendingRender = null\n\n const lifecycleRegistry = createHookRegistry()\n\n // Ready promise setup\n const ready: { promise: Promise<void>; resolve: () => void } = (() => {\n let resolve!: () => void\n const promise = new Promise<void>((res) => {\n resolve = res\n })\n return { promise, resolve }\n })()\n\n let state!: State\n let userContext!: State\n\n const take = (pluginName: string) => {\n const plugin = ExtensionRegistry.plugins[pluginName]\n\n if (!plugin || typeof plugin.setup !== 'function') {\n logger.warnWithContext(\n `Plugin \"${pluginName}\" not found or has no setup method`,\n { pluginName },\n )\n return undefined\n }\n\n try {\n // Use userContext if available and type is \"options\", otherwise use state\n const context = useUserContext && userContext ? userContext : state\n return plugin.setup.call(context)\n } catch (error) {\n logger.errorWithContext(\n `Plugin \"${pluginName}\" setup failed`,\n { pluginName },\n error,\n )\n return undefined\n }\n }\n\n // Modules attach\n const attachedModules: Record<string, unknown> = {}\n for (const [moduleName, module] of Object.entries(ExtensionRegistry.modules)) {\n if (typeof module.attach === 'function') {\n const attached = module.attach.call({\n element: host,\n parent,\n core: { take: Core.take },\n })\n\n if (attached) {\n attachedModules[`$${moduleName}`] = attached\n }\n }\n }\n\n // $emit Funktion with caching\n const handlerNameCache = new Map<string, string>()\n const getHandlerName = (eventName: string): string => {\n let cached = handlerNameCache.get(eventName)\n if (!cached) {\n cached = `on${eventName.charAt(0).toUpperCase()}${eventName.slice(1)}`\n handlerNameCache.set(eventName, cached)\n }\n return cached\n }\n\n const $emit = (eventName: string, ...args: unknown[]) => {\n const handlerName = getHandlerName(eventName)\n let current = parent\n\n while (current) {\n // Only use userContext if it exists (options type)\n const cb = current.userContext\n if (cb) {\n const handler = cb[handlerName]\n if (typeof handler === 'function') {\n // Handler is already bound via bindMethods, use directly\n ;(handler as AnyFn)(...args)\n }\n } else if (current.methods) {\n // For composite type, use methods directly without binding\n const handler = current.methods[handlerName]\n if (typeof handler === 'function') {\n handler(...args)\n }\n }\n\n current = current.$parent\n }\n }\n\n // Build component context with all $*-prefixed variables\n const componentContext = {\n $refs: refs,\n $parent: parent,\n $emit,\n $take: take,\n ...attachedModules,\n }\n\n // Script ausführen\n const controller = compiledScript(componentContext)\n\n // Model setup\n const model = createModel(controller.state ?? {})\n state = model.state\n\n // Controller Bits\n const methods = controller.methods || {}\n const props = controller.props || {}\n const events = (controller.events || []) satisfies Events\n\n let watchList = controller.watchList || []\n\n // Create userContext only for \"options\" type\n // IMPORTANT: Do NOT include $*-prefixed variables in userContext\n // They must only be available as closure variables\n if (useUserContext) {\n userContext = composeBySource([methods, state])\n }\n\n processProps({\n ele: host,\n parent,\n props,\n state,\n })\n\n // Bind methods only if userContext exists\n if (useUserContext && userContext) {\n bindMethods(methods, userContext)\n }\n\n // Hooks registrieren\n for (const hook of lifecycleHooks) {\n const fn = controller[hook]\n if (typeof fn === 'function') {\n // Bind hook only if userContext exists\n const boundFn = useUserContext && userContext ? bindOnce(fn, userContext) : fn\n hookOn(lifecycleRegistry, hook, async () => {\n const result = boundFn()\n if (result instanceof Promise) await result\n })\n }\n }\n\n // Store model reference for cleanup in disconnectedCallback\n this._model = model\n\n /**\n * render zuerst definieren (sonst TDZ wenn Observer feuert)\n */\n const render = async () => {\n // Exit early if component has been disconnected\n if (this._isDisconnected) {\n return\n }\n\n // RENDERING GUARD: Wenn bereits am Rendern, kein neuer Render-Prozess\n // Stattdessen neuen Render planen für nach dem aktuellen Render\n if (isRendering) {\n this._renderAborted = true\n this._pendingRender = render\n return\n }\n\n // State-Version Check: Nur rendern wenn sich State geändert hat\n const currentStateVersion = model.getStateVersion()\n if (lastRenderedStateVersion === currentStateVersion) {\n return\n }\n\n isRendering = true\n this._renderAborted = false\n // Set flag on instance so child components can check\n if (host.instance) {\n ;(host.instance as ComponentInstanceInternal).isRendering = true\n }\n\n try {\n const container = clonedTemplate.content.cloneNode(true) as DocumentFragment\n\n const slots = prepareSlots(container, host, refs)\n\n // Use userContext (which includes methods) for template processing\n // This allows template expressions to call component methods\n const templateContext = useUserContext && userContext ? userContext : state\n await processTemplate(container, templateContext, refs)\n slots.remapRefs()\n\n // Check if render was aborted during template processing\n if (this._renderAborted || this._model !== model) {\n // Schedule new render with latest state\n this._pendingRender = render\n return\n }\n\n const hookContext = useUserContext && userContext ? userContext : state\n await hookEmit('global', 'processed', hookContext)\n await hookEmit(lifecycleRegistry, 'processed')\n\n // Check again if render was aborted\n if (this._renderAborted || this._model !== model) {\n this._pendingRender = render\n return\n }\n\n // Flush changes and get changed paths for lifecycle hooks\n const changedPaths = model.flushChanges()\n\n // Extend hook context with changedPaths metadata\n // Use Object.defineProperty to avoid triggering the reactive proxy\n Object.defineProperty(hookContext, 'changedPaths', {\n value: changedPaths,\n writable: true,\n configurable: true,\n enumerable: false,\n })\n\n // MOUNTED GUARD: mounted() Hook darf nur einmal feuern beim ersten Render\n // Wenn bereits gemountet (_isMounted = true), dann ist es ein Update, kein Mount\n const isFirstRender = !this._isMounted\n\n await hookEmit(\n 'global',\n isFirstRender ? 'beforeMount' : 'beforeUpdate',\n hookContext,\n )\n await hookEmit(\n lifecycleRegistry,\n isFirstRender ? 'beforeMount' : 'beforeUpdate',\n hookContext,\n )\n\n // Final check before DOM update\n if (this._renderAborted || this._model !== model) {\n // Clean up ephemeral metadata before aborting\n delete (hookContext as StateWithMetadata).changedPaths\n this._pendingRender = render\n return\n }\n\n slots.commit()\n\n if (useUserContext && userContext) {\n bindNativeEvents(userContext, container)\n // Clean up previous event listeners (including window) before adding new ones\n if (this._eventCleanup) this._eventCleanup()\n this._eventCleanup = setupEvents(userContext, events, container, refs)\n } else {\n // For composite type, use methods directly without binding\n bindNativeEventsForComposite(methods, container)\n if (this._eventCleanup) this._eventCleanup()\n this._eventCleanup = setupEventsForComposite(\n methods,\n state,\n events,\n container,\n refs,\n )\n }\n\n // Use DOM reconciliation instead of replaceChildren to preserve\n // custom element instances and prevent infinite mount loops\n reconcileDOM(host, container, !this._isMounted, source.structAttr)\n\n // changedPaths is already set via defineProperty, no need to set again\n\n // Update Hook: Nur wenn bereits gemountet (nicht beim ersten Render)\n if (this._isMounted) {\n await hookEmit('global', 'updated', hookContext)\n await hookEmit(lifecycleRegistry, 'updated', hookContext)\n }\n\n // Remove ephemeral metadata after hooks complete\n delete (hookContext as StateWithMetadata).changedPaths\n\n // Update last rendered state version\n lastRenderedStateVersion = currentStateVersion\n // Store in instance for reuse\n if (host.instance) {\n ;(host.instance as ComponentInstanceInternal)._lastRenderedStateVersion =\n lastRenderedStateVersion\n }\n } catch (error) {\n logger.errorWithContext('Error during render', { componentName }, error)\n } finally {\n // Ensure ephemeral metadata is cleaned up even on error\n const hookContext = useUserContext && userContext ? userContext : state\n delete (hookContext as StateWithMetadata).changedPaths\n\n isRendering = false\n // Reset flag on instance\n if (host.instance) {\n ;(host.instance as ComponentInstanceInternal).isRendering = false\n }\n\n // Execute pending render if one was scheduled (only if still connected)\n if (this._pendingRender && !this._isDisconnected) {\n const nextRender = this._pendingRender\n this._pendingRender = null\n // Use requestAnimationFrame to ensure DOM is ready\n requestAnimationFrame(() => {\n // Double-check disconnection state in RAF callback\n if (this._isDisconnected) return\n void nextRender().catch((error) => {\n logger.errorWithContext(\n 'Error during pending render',\n { componentName },\n error,\n )\n })\n })\n }\n }\n }\n\n /**\n * Parent/Child Fix: instance VOR initial render setzen\n */\n host.instance = {\n element: host,\n template: clonedTemplate,\n state,\n userContext: useUserContext ? userContext : undefined,\n props,\n methods,\n events,\n watchList,\n $refs: refs,\n $parent: parent,\n $emit,\n $take: take,\n readyPromise: ready.promise,\n lifecycleRegistry,\n ...attachedModules,\n isRendering: false,\n } as ComponentInstanceInternal\n\n // Observer function stored in variable for later removal\n this._observerFn = () => {\n // Exit early if component has been disconnected\n if (this._isDisconnected) return\n\n // If watchList is defined, skip renders for irrelevant state changes\n if (watchList && watchList.length > 0) {\n if (!model.hasPendingChangesFor(watchList)) return\n }\n\n // Prevent child self-rendering if any ancestor is currently rendering\n // Ancestor render will update child props automatically through processTemplate\n // Check entire parent chain to see if any ancestor is rendering\n let currentParent: ComponentInstance | undefined = parent\n while (currentParent) {\n if ((currentParent as ComponentInstanceInternal).isRendering) {\n // An ancestor is rendering, so this child should not self-render\n // The ancestor's render will update this child's props automatically\n return\n }\n currentParent = currentParent.$parent\n }\n\n requestAnimationFrame(() => {\n // Double-check disconnection state in RAF callback\n if (this._isDisconnected) return\n void render().catch((error) => {\n logger.errorWithContext(\n 'Error during render (observer)',\n { componentName },\n error,\n )\n })\n })\n }\n\n // Register observer (render is already defined)\n model.addObserver(this._observerFn)\n\n // created\n const hookContext = useUserContext && userContext ? userContext : state\n await hookEmit('global', 'created', hookContext)\n await hookEmit(lifecycleRegistry, 'created')\n\n // initial render\n if (this._isDisconnected || this._model !== model) return\n await render()\n\n // MOUNTED HOOK: Nur einmal beim ersten Render, nie beim Reconnect\n // _isMounted wird nur beim ersten Render auf true gesetzt\n // Beim Reconnect wird diese Stelle nie erreicht (Early Return oben)\n if (this._isDisconnected || this._model !== model) return\n if (!this._isMounted) {\n await hookEmit('global', 'mounted', hookContext)\n if (this._isDisconnected || this._model !== model) return\n await hookEmit(lifecycleRegistry, 'mounted')\n if (this._isDisconnected || this._model !== model) return\n this._isMounted = true // Flag setzen - mounted() wird nie wieder feuern\n }\n\n ready.resolve()\n }\n\n async disconnectedCallback() {\n const host = this as HTMLElementWithInstance\n const connectionVersion = ++this._connectionVersion\n this._isDisconnected = true\n this._renderAborted = true\n this._pendingRender = null\n connectedHosts.delete(this)\n if (connectedHosts.size === 0) {\n document.head.querySelector(`style#style-${componentName}`)?.remove()\n }\n if (!host.instance) return\n\n const instance = host.instance\n\n // 1. Set disconnected flag to prevent pending/scheduled renders\n this._isDisconnected = true\n this._renderAborted = true\n this._pendingRender = null\n\n // 2. Remove model observer to stop reactive updates\n if (this._model && this._observerFn) {\n this._model.removeObserver(this._observerFn)\n }\n\n // 3. Emit beforeDestroy hooks\n const destroyContext = instance.userContext || instance.state\n await hookEmit('global', 'beforeDestroy', destroyContext)\n await hookEmit(instance.lifecycleRegistry, 'beforeDestroy')\n\n // Race guard: if reconnected during async hooks, abort teardown\n if (!this._isDisconnected || connectionVersion !== this._connectionVersion) return\n\n // 5. Cleanup DOM event listeners for this component subtree\n cleanupSubtree(this)\n\n // 5b. Cleanup setupEvents listeners (including window listeners)\n if (this._eventCleanup) {\n this._eventCleanup()\n this._eventCleanup = null\n }\n\n // 7. Emit destroyed hooks\n await hookEmit('global', 'destroyed', destroyContext)\n await hookEmit(instance.lifecycleRegistry, 'destroyed')\n\n // Race guard: if reconnected during async hooks, abort teardown\n if (!this._isDisconnected || connectionVersion !== this._connectionVersion) return\n\n // 8. Release strong references for GC\n this._isMounted = false\n this._model = undefined\n this._observerFn = undefined\n this._eventCleanup = null\n host.instance = undefined\n }\n },\n )\n}\n","// --- KoppaJS Core Public API ---\n// Only exports intended for stable, public use are exposed here.\n\nimport { logger } from './utils/logger'\nimport type { CoreCallable, CoreCtx, TakeArgs } from './types'\n\n// Public Types\nexport type {\n ComponentSource,\n ComponentInstance,\n ComponentController,\n ComponentContext,\n CoreCallable,\n CoreCtx,\n IPlugin,\n IModule,\n ModuleContext,\n TakeArgs,\n Props,\n Events,\n State,\n Refs,\n Methods,\n LifecycleHook,\n} from './types'\n\n/**\n * KoppaJS logger singleton and log level enum.\n * @public\n */\nexport { logger, LogLevel } from './utils/logger'\n\n// --- Internal implementation below ---\n// (not exported)\nimport { extend, hookOn, isComponentSource, isModule, isPlugin } from './utils'\nimport { ExtensionRegistry } from './utils/extension-registry'\nimport { registerComponent } from './component'\nimport {\n patchGlobalEventTracking,\n startGlobalDisconnectionObserver,\n} from './global-event-cleaner'\n\nlet initialized = false\nlet domInitialized = false\nlet queuedTakes: TakeArgs[] = []\n\n/**\n * Initializes the DOM environment for KoppaJS.\n *\n * - Patches global event tracking\n * - Extends HTMLElement with KoppaJS helpers\n * - Starts disconnection observer\n *\n * Safe to call multiple times (idempotent).\n */\nfunction initDomEnvironment(): void {\n if (domInitialized) return\n domInitialized = true\n\n if (typeof document === 'undefined' || typeof HTMLElement === 'undefined') {\n return\n }\n\n patchGlobalEventTracking()\n extend()\n startGlobalDisconnectionObserver()\n}\n\n/**\n * Performs the take operation for a component, plugin, or module.\n * @param args - Either [ComponentSource, name] or [IPlugin | IModule]\n */\nfunction performTake(...args: TakeArgs): void {\n const ext = args[0]\n const name = args[1]\n\n if (isComponentSource(ext)) {\n if (!name) {\n logger.error('ComponentSource requires a component name when calling take()')\n return\n }\n registerComponent(name, ext)\n return\n }\n\n if (isPlugin(ext) || isModule(ext)) {\n const ctx: CoreCtx = {\n registerHook: (hookName, callback) => {\n hookOn('global', hookName, callback)\n },\n take: Core.take,\n }\n\n try {\n ext.install(ctx)\n\n if (isPlugin(ext)) {\n ExtensionRegistry.plugins[ext.name] = ext\n } else {\n ExtensionRegistry.modules[ext.name] = ext\n }\n } catch (error) {\n logger.errorWithContext(\n 'Failed to install extension',\n { name: ext.name, type: isPlugin(ext) ? 'plugin' : 'module' },\n error,\n )\n }\n\n return\n }\n\n logger.error('Unknown extension type', ext)\n}\n\n/**\n * Initializes the core framework.\n * Processes all queued take operations and marks core as initialized.\n * Safe to call multiple times (idempotent).\n */\nfunction initialize(): void {\n if (initialized) return\n initialized = true\n\n queuedTakes.forEach((args) => performTake(...args))\n queuedTakes = []\n\n logger.info('Core initialized')\n}\n\n/**\n * Main KoppaJS Core API.\n *\n * - Call as a function to initialize the framework (processes all registrations)\n * - Use `Core.take()` to register components, plugins, or modules before initialization\n *\n * @example\n * import { Core } from '@koppajs/koppajs-core';\n * Core.take(MyComponent, 'my-component');\n * Core();\n *\n * @public\n */\nexport const Core = (() => {\n const callable = Object.assign(\n () => {\n initDomEnvironment()\n initialize()\n },\n {\n take: (...args: TakeArgs) => {\n if (initialized) performTake(...args)\n else queuedTakes.push(args)\n },\n },\n ) satisfies CoreCallable\n return callable\n})()\n"],"names":["LogLevel","EMOJIS","Logger","options","level","emoji","message","context","parts","contextStr","key","value","args","error","formatted","logger","BOUND","IS_PROXY","lifecycleHooks","bindOnce","fn","userContext","bound","bindMethods","methods","name","containsHTML","input","getValueByPath","obj","path","tokens","acc","getExpectedPropTypeName","isSimplePathExpression","expression","exp","setValueByPath","hasOwn","o","k","last","target","next","desc","domExtensions","s","classes","c","newNode","callback","siblings","sibling","attrName","attrValue","objectExtensions","kebabToCamel","x","FORBIDDEN_KEYWORDS_REGEX","expressionCache","MAX_CACHE_SIZE","sortedKeysCache","getCachedSortedKeys","state","currentKeys","fingerprint","cached","sorted","evaluateExpression","allowedVars","cacheKey","evalFunction","functionBody","firstKey","generateDepsInjectionHeader","depKeys","compileCode","strg","resolvedDeps","sanitizedCode","rawFn","createHookRegistry","globalHookRegistry","hookOn","registry","cb","hookEmit","listeners","ExtensionRegistry","isComponentSource","ext","isPlugin","isModule","hasComponentInstance","el","extend","isCustomElement","node","cleanupStructAttributes","container","structAttr","walker","getStructId","setStructId","getNodeIdentity","tagName","structId","slotId","getSlotId","isSameNodeType","nodeA","nodeB","reconcileAttributes","existing","updated","existingAttrs","updatedAttrs","attr","newValue","existingValue","reconcileChildren","existingChildren","updatedChildren","existingByIdentity","existingUsed","child","identity","i","updatedChild","existingChild","updatedIdentity","matchedNode","existingEl","updatedEl","lastChild","reconcileDOM","host","newContent","isFirstRender","tempContainer","STRUCT_ID","SLOT_ID","setNonEnumerableProp","id","setSlotId","setupEvents","events","refs","cleanupEntries","type","handler","elements","refName","rest","ref","selector","boundHandler","EVENT_ATTR_REGEX","bindNativeEvents","fragment","match","handlerName","bindNativeEventsForComposite","setupEventsForComposite","EVENT_REGISTRY","observer","patchGlobalEventTracking","g","nativeAdd","nativeRemove","listener","entries","entry","cleanupAllEventListeners","cleanupSubtree","root","startGlobalDisconnectionObserver","mutations","mutation","removedNode","globalProxyCache","globalProxyToOriginalCache","globalSlotSidecars","slotIdCounter","generateSlotId","isObject","toPropName","property","getCachedProxy","getOriginalObject","original","isProxy","getSlotIdsForArray","arr","originalArr","isPrimitive","getOrInitSlotIdsForArray","slotIds","ensureSlotSidecarInvariant","createModel","initialData","observers","objectPaths","stateVersion","changedPaths","watchers","pathMatchesPrefix","changedPath","watchPrefix","buildPath","parentPath","notifyScheduled","notifyObservers","e","diffArraysByReferenceNoDeepMerge","oldArr","newArr","hasChanges","diffArraysSimple","oldSet","newSet","item","diffArraysOptimized","mergeInPlaceObject","oldObj","newObj","basePath","oldVal","newVal","updateSlotSidecarForArrayMutation","method","newSlotIds","start","deleteCount","itemsToInsert","makeReactive","proxy","receiver","originalMethod","snapshot","result","elementToIndices","indices","element","matchIdx","isArrayElement","propName","nestedPath","oldValue","index","finalVal","reactive","isDeleted","callbacks","stopped","cbs","prefixes","prefix","callbacksToNotify","matchingPaths","existingPaths","p","paths","IDENTIFIER_REGEX","parseLoopBinding","bindingStr","trimmed","keyVar","itemVar","createFilteredTreeWalker","rootElement","filter","skipNode","current","skipSubtree","parent","stringifyTemplateValue","replaceTemplateString","template","_","applyLoop","loopDefinition","toplevelIf","collectionExp","binding","raw","isArray","idx","totalCount","localState","cloned","processTemplate","applyIfChainVueLoose","chainByParent","getChain","setChain","clearChain","ifCond","ok","elseIfCond","chain","processNodeBatch","pendingNodes","batchSize","batch","frag","processed","pending","realAttrName","expr","evaluated","classesToAdd","className","condition","existingClasses","newClasses","err","isInsideCustomElement","composeBySource","layers","layer","defaultWriteIndex","includePrototype","validWriteIndex","has","findLayerIndex","_target","prop","writeTo","keys","getParentInstance","rootNode","processSlots","slotContent","slotMap","slotName","slotElement","replacementNodes","prepareSlots","originals","snapshots","remapRefs","stagedHost","stage","clone","restore","children","restoredChildren","restored","validateProp","propValue","props","propOptions","pValue","expectedType","actualType","typeChecks","processProps","ele","hasDefinedProps","defineBoundProp","isDynamic","currentValue","registerComponent","componentName","source","connectedHosts","connectionVersion","style","existingInstance","useUserContext","clonedTemplate","depEntries","resolvedValues","importFn","compiledScript","isRendering","lastRenderedStateVersion","lifecycleRegistry","ready","resolve","res","take","pluginName","plugin","attachedModules","moduleName","module","attached","Core","handlerNameCache","getHandlerName","eventName","$emit","componentContext","controller","model","watchList","hook","boundFn","render","currentStateVersion","slots","hookContext","nextRender","currentParent","instance","destroyContext","initialized","domInitialized","queuedTakes","initDomEnvironment","performTake","ctx","hookName","initialize"],"mappings":"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"}