nuclo 0.2.36 → 0.2.37

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.
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../Element-BUdteOsZ.cjs");var t=class{nodeType=3;nodeName=`#text`;data;textContent;parentNode=null;constructor(e){this.data=e,this.textContent=e}get nodeValue(){return this.data}set nodeValue(e){this.data=e,this.textContent=e}},n=class{nodeType=11;nodeName=`#document-fragment`;childNodes=[];children=[];textContent=``;get firstChild(){return this.childNodes.length>0?this.childNodes[0]:null}get lastChild(){return this.childNodes.length>0?this.childNodes[this.childNodes.length-1]:null}appendChild(e){return this.childNodes.push(e),e.nodeType===1&&this.children.push(e),e.parentNode=this,e}insertBefore(e,t){if(!t)return this.appendChild(e);let n=this.childNodes.indexOf(t);if(n!==-1&&(this.childNodes.splice(n,0,e),e.nodeType===1)){let n=this.children.indexOf(t);n!==-1&&this.children.splice(n,0,e)}return e.parentNode=this,e}removeChild(e){let t=this.childNodes.indexOf(e);if(t!==-1&&this.childNodes.splice(t,1),e.nodeType===1){let t=this.children.indexOf(e);t!==-1&&this.children.splice(t,1)}return e.parentNode=null,e}replaceChild(e,t){let n=this.childNodes.indexOf(t);if(n!==-1&&(this.childNodes[n]=e,t.nodeType===1&&e.nodeType===1)){let n=this.children.indexOf(t);n!==-1&&(this.children[n]=e)}return e.parentNode=this,t.parentNode=null,e}querySelector(){return null}querySelectorAll(){return[]}},r=class{head;body;_listeners;constructor(){this.head=new e.t(`head`),this.body=new e.t(`body`),this._listeners=/* @__PURE__ */ new Map}createElement(t,n){return new e.t(t)}createElementNS(t,n,r){let i=new e.t(n);return i.namespaceURI=t,i}createTextNode(e){return new t(e)}createComment(e){return{nodeType:8,nodeName:`#comment`,data:e,textContent:e,nodeValue:e,parentNode:null,nextSibling:null,previousSibling:null}}createDocumentFragment(){return new n}querySelector(e){if(e.startsWith(`#`)){let t=e.slice(1);if(t===`nuclo-styles`&&this.head.children){for(let e of this.head.children)if(e.id===t)return e}}return null}querySelectorAll(e){return[]}addEventListener(e,t,n){this._listeners.has(e)||this._listeners.set(e,/* @__PURE__ */ new Map),this._listeners.get(e).set(t,{listener:t,options:n})}removeEventListener(e,t,n){let r=this._listeners.get(e);r&&(r.delete(t),r.size===0&&this._listeners.delete(e))}dispatchEvent(e){let t=this._listeners.get(e.type);if(t){let n=Array.from(t.values());for(let t=0;t<n.length;t++){let{listener:r}=n[t];try{r(e)}catch(e){console.error(`Error in event listener:`,e)}}}return!0}contains(e){return!1}};const i=globalThis.document||new r;var a=class{type;bubbles;cancelable;composed;currentTarget=null;defaultPrevented=!1;eventPhase=0;isTrusted=!1;target=null;timeStamp;AT_TARGET=2;BUBBLING_PHASE=3;CAPTURING_PHASE=1;NONE=0;returnValue=!0;srcElement=null;cancelBubble=!1;constructor(e,t){this.type=e,this.bubbles=t?.bubbles||!1,this.cancelable=t?.cancelable||!1,this.composed=t?.composed||!1,this.timeStamp=Date.now()}composedPath(){return[]}initEvent(e,t,n){}preventDefault(){this.cancelable&&(this.defaultPrevented=!0)}stopImmediatePropagation(){this.cancelBubble=!0}stopPropagation(){this.cancelBubble=!0}},o=class extends a{detail;constructor(e,t){super(e,t),this.detail=t?.detail}initCustomEvent(e,t,n,r){}};const s=globalThis.Event||a,c=globalThis.CustomEvent||o,l=e.n,u=e.t,d=e.t;if(typeof window>`u`&&typeof globalThis<`u`){let t=globalThis;t.document||=i,t.Event||=s,t.CustomEvent||=c,t.Node||=e.n,t.Element||=e.t,t.HTMLElement||=e.t}exports.CustomEvent=c,exports.Element=u,exports.Event=s,exports.HTMLElement=d,exports.Node=l,exports.NucloCustomEvent=o,exports.NucloDocument=r,exports.NucloElement=e.t,exports.NucloEvent=a,exports.NucloNode=e.n,exports.NucloText=t,exports.document=i;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../Element-DfxBbUgD.cjs");var t=class{nodeType=3;nodeName=`#text`;data;textContent;parentNode=null;constructor(e){this.data=e,this.textContent=e}get nodeValue(){return this.data}set nodeValue(e){this.data=e,this.textContent=e}},n=class{nodeType=11;nodeName=`#document-fragment`;childNodes=[];children=[];textContent=``;get firstChild(){return this.childNodes.length>0?this.childNodes[0]:null}get lastChild(){return this.childNodes.length>0?this.childNodes[this.childNodes.length-1]:null}appendChild(e){return this.childNodes.push(e),e.nodeType===1&&this.children.push(e),e.parentNode=this,e}insertBefore(e,t){if(!t)return this.appendChild(e);let n=this.childNodes.indexOf(t);if(n!==-1&&(this.childNodes.splice(n,0,e),e.nodeType===1)){let n=this.children.indexOf(t);n!==-1&&this.children.splice(n,0,e)}return e.parentNode=this,e}removeChild(e){let t=this.childNodes.indexOf(e);if(t!==-1&&this.childNodes.splice(t,1),e.nodeType===1){let t=this.children.indexOf(e);t!==-1&&this.children.splice(t,1)}return e.parentNode=null,e}replaceChild(e,t){let n=this.childNodes.indexOf(t);if(n!==-1&&(this.childNodes[n]=e,t.nodeType===1&&e.nodeType===1)){let n=this.children.indexOf(t);n!==-1&&(this.children[n]=e)}return e.parentNode=this,t.parentNode=null,e}querySelector(){return null}querySelectorAll(){return[]}},r=class{head;body;constructor(){this.head=new e.t(`head`),this.body=new e.t(`body`)}createElement(t,n){return new e.t(t)}createElementNS(t,n,r){let i=new e.t(n);return i.namespaceURI=t,i}createTextNode(e){return new t(e)}createComment(e){return{nodeType:8,nodeName:`#comment`,data:e,textContent:e,nodeValue:e,parentNode:null,nextSibling:null,previousSibling:null}}createDocumentFragment(){return new n}querySelector(e){return null}querySelectorAll(e){return[]}addEventListener(e,t,n){}removeEventListener(e,t,n){}dispatchEvent(e){return!0}contains(e){return!1}};const i=globalThis.document||new r,a=globalThis.Event,o=globalThis.CustomEvent,s=e.n,c=e.t,l=e.t;if(typeof window>`u`){let t=globalThis;t.document??=i,t.Node??=e.n,t.Element??=e.t,t.HTMLElement??=e.t}exports.CustomEvent=o,exports.Element=c,exports.Event=a,exports.HTMLElement=l,exports.Node=s,exports.NucloDocument=r,exports.NucloElement=e.t,exports.NucloNode=e.n,exports.NucloText=t,exports.document=i;
2
2
  //# sourceMappingURL=nuclo.polyfill.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"nuclo.polyfill.cjs","names":["NucloElement","NucloNode","NucloElement"],"sources":["../../src/polyfill/Text.ts","../../src/polyfill/Document.ts","../../src/polyfill/Event.ts","../../src/polyfill/index.ts"],"sourcesContent":["export class NucloText {\n nodeType = 3; // Node.TEXT_NODE\n nodeName = '#text';\n data: string;\n textContent: string;\n parentNode: unknown = null;\n \n constructor(data: string) {\n this.data = data;\n this.textContent = data;\n }\n \n get nodeValue(): string {\n return this.data;\n }\n \n set nodeValue(value: string) {\n this.data = value;\n this.textContent = value;\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { NucloElement } from './Element';\nimport { NucloText } from './Text';\n\n/**\n * Lightweight DocumentFragment for SSR — prototype methods instead of per-instance closures.\n */\nclass SSRDocumentFragment {\n nodeType: number = 11;\n nodeName: string = '#document-fragment';\n childNodes: Node[] = [];\n children: Element[] = [];\n textContent: string = '';\n\n get firstChild(): Node | null {\n return this.childNodes.length > 0 ? this.childNodes[0] : null;\n }\n\n get lastChild(): Node | null {\n return this.childNodes.length > 0 ? this.childNodes[this.childNodes.length - 1] : null;\n }\n\n appendChild<T extends Node>(child: T): T {\n this.childNodes.push(child);\n if ((child as any).nodeType === 1) {\n this.children.push(child as unknown as Element);\n }\n (child as any).parentNode = this;\n return child;\n }\n\n insertBefore<T extends Node>(newNode: T, refNode: Node | null): T {\n if (!refNode) return this.appendChild(newNode);\n const index = this.childNodes.indexOf(refNode);\n if (index !== -1) {\n this.childNodes.splice(index, 0, newNode);\n if ((newNode as any).nodeType === 1) {\n const elementIndex = this.children.indexOf(refNode as Element);\n if (elementIndex !== -1) {\n this.children.splice(elementIndex, 0, newNode as unknown as Element);\n }\n }\n }\n (newNode as any).parentNode = this;\n return newNode;\n }\n\n removeChild<T extends Node>(child: T): T {\n const index = this.childNodes.indexOf(child);\n if (index !== -1) this.childNodes.splice(index, 1);\n if ((child as any).nodeType === 1) {\n const elementIndex = this.children.indexOf(child as unknown as Element);\n if (elementIndex !== -1) this.children.splice(elementIndex, 1);\n }\n (child as any).parentNode = null;\n return child;\n }\n\n replaceChild<T extends Node>(newChild: T, oldChild: Node): T {\n const index = this.childNodes.indexOf(oldChild);\n if (index !== -1) {\n this.childNodes[index] = newChild;\n if ((oldChild as any).nodeType === 1 && (newChild as any).nodeType === 1) {\n const elementIndex = this.children.indexOf(oldChild as Element);\n if (elementIndex !== -1) {\n this.children[elementIndex] = newChild as unknown as Element;\n }\n }\n }\n (newChild as any).parentNode = this;\n (oldChild as any).parentNode = null;\n return newChild;\n }\n\n querySelector(): null { return null; }\n querySelectorAll(): NodeListOf<Element> { return [] as unknown as NodeListOf<Element>; }\n}\n\nexport class NucloDocument {\n head: ExpandedElement;\n body: ExpandedElement;\n private _listeners: Map<string, Map<EventListener, { listener: EventListener; options?: boolean | AddEventListenerOptions }>>;\n \n constructor() {\n this.head = new NucloElement('head') as unknown as ExpandedElement;\n this.body = new NucloElement('body') as unknown as ExpandedElement;\n this._listeners = new Map();\n }\n \n createElement(tagName: string, _options?: unknown): ExpandedElement {\n return new NucloElement(tagName) as unknown as ExpandedElement;\n }\n \n createElementNS(namespace: string, tagName: string, _options?: unknown): ExpandedElement {\n const element = new NucloElement(tagName) as unknown as ExpandedElement;\n (element as any).namespaceURI = namespace;\n return element;\n }\n \n createTextNode(data: string): Text {\n return new NucloText(data) as unknown as Text;\n }\n \n createComment(data: string): Comment {\n const comment = {\n nodeType: 8,\n nodeName: '#comment',\n data,\n textContent: data,\n nodeValue: data,\n parentNode: null,\n nextSibling: null,\n previousSibling: null\n };\n return comment as unknown as Comment;\n }\n \n createDocumentFragment(): DocumentFragment {\n return new SSRDocumentFragment() as unknown as DocumentFragment;\n }\n \n querySelector(selector: string): Element | null {\n // Simple implementation - only supports ID selector for #nuclo-styles\n if (selector.startsWith('#')) {\n const id = selector.slice(1);\n if (id === 'nuclo-styles' && this.head.children) {\n for (const child of this.head.children) {\n if ((child as any).id === id) {\n return child as unknown as Element;\n }\n }\n }\n }\n return null;\n }\n \n querySelectorAll(_selector: string): NodeListOf<Element> {\n return [] as unknown as NodeListOf<Element>;\n }\n \n addEventListener(type: string, listener: EventListener, options?: boolean | AddEventListenerOptions): void {\n if (!this._listeners.has(type)) {\n this._listeners.set(type, new Map());\n }\n const listenersMap = this._listeners.get(type)!;\n listenersMap.set(listener, { listener, options });\n }\n \n removeEventListener(type: string, listener: EventListener, _options?: boolean | AddEventListenerOptions): void {\n const listeners = this._listeners.get(type);\n if (listeners) {\n listeners.delete(listener);\n // Clean up empty maps to prevent memory leaks\n if (listeners.size === 0) {\n this._listeners.delete(type);\n }\n }\n }\n \n dispatchEvent(event: Event): boolean {\n const listeners = this._listeners.get(event.type);\n if (listeners) {\n // Create a copy to avoid issues if listeners are modified during dispatch\n const listenersCopy = Array.from(listeners.values());\n for (let i = 0; i < listenersCopy.length; i++) {\n const { listener } = listenersCopy[i];\n try {\n listener(event);\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('Error in event listener:', error);\n }\n }\n }\n return true;\n }\n \n contains(_node: Node): boolean {\n return false;\n }\n}\n\nexport const document = globalThis.document || new NucloDocument();","/* eslint-disable @typescript-eslint/no-explicit-any */\nexport class NucloEvent implements Event {\n type: string;\n bubbles: boolean;\n cancelable: boolean;\n composed: boolean;\n currentTarget: EventTarget | null = null;\n defaultPrevented: boolean = false;\n eventPhase: number = 0;\n isTrusted: boolean = false;\n target: EventTarget | null = null;\n timeStamp: number;\n readonly AT_TARGET = 2;\n readonly BUBBLING_PHASE = 3;\n readonly CAPTURING_PHASE = 1;\n readonly NONE = 0;\n returnValue: boolean = true;\n srcElement: EventTarget | null = null;\n cancelBubble: boolean = false;\n \n constructor(type: string, eventInitDict?: EventInit) {\n this.type = type;\n this.bubbles = eventInitDict?.bubbles || false;\n this.cancelable = eventInitDict?.cancelable || false;\n this.composed = eventInitDict?.composed || false;\n this.timeStamp = Date.now();\n }\n \n composedPath(): EventTarget[] {\n return [];\n }\n \n initEvent(_type: string, _bubbles?: boolean, _cancelable?: boolean): void {\n // Legacy method - no-op\n }\n \n preventDefault(): void {\n if (this.cancelable) {\n this.defaultPrevented = true;\n }\n }\n \n stopImmediatePropagation(): void {\n this.cancelBubble = true;\n }\n \n stopPropagation(): void {\n this.cancelBubble = true;\n }\n}\n\nexport class NucloCustomEvent<T = any> extends NucloEvent implements CustomEvent<T> {\n detail: T;\n \n constructor(type: string, eventInitDict?: CustomEventInit<T>) {\n super(type, eventInitDict);\n this.detail = eventInitDict?.detail as T;\n }\n \n initCustomEvent(_type: string, _bubbles?: boolean, _cancelable?: boolean, _detail?: T): void {\n // Legacy method - no-op\n }\n}\n\n// Export polyfills if browser globals don't exist\nexport const Event = globalThis.Event || NucloEvent;\nexport const CustomEvent = globalThis.CustomEvent || NucloCustomEvent;\n","/**\n * Polyfills for Node.js environments\n * \n * This module provides minimal browser API polyfills to allow Nuclo to run in Node.js\n * for server-side rendering (SSR) scenarios.\n * \n * To use in Node.js:\n * ```typescript\n * import 'nuclo/polyfill';\n * // or\n * import { document, Event, CustomEvent } from 'nuclo/polyfill';\n * ```\n */\n\nexport { NucloDocument, document } from './Document';\nexport { NucloElement } from './Element';\nexport { NucloText } from './Text';\nexport { NucloEvent, NucloCustomEvent, Event, CustomEvent } from './Event';\nexport { NucloNode } from './Node';\n\n// Import for local use\nimport { NucloElement } from './Element';\nimport { NucloNode } from './Node';\nimport { document } from './Document';\nimport { Event, CustomEvent } from './Event';\n\nexport const Node = NucloNode;\nexport const Element = NucloElement;\nexport const HTMLElement = NucloElement;\n\n// Auto-apply polyfills to globalThis if in Node environment (synchronous — no top-level await)\nif (typeof window === 'undefined' && typeof globalThis !== 'undefined') {\n interface GlobalWithPolyfills {\n document?: typeof document;\n Event?: typeof Event;\n CustomEvent?: typeof CustomEvent;\n Node?: typeof NucloNode;\n Element?: typeof NucloElement;\n HTMLElement?: typeof NucloElement;\n }\n\n const g = globalThis as unknown as GlobalWithPolyfills;\n\n if (!g.document) g.document = document;\n if (!g.Event) g.Event = Event;\n if (!g.CustomEvent) g.CustomEvent = CustomEvent;\n if (!g.Node) g.Node = NucloNode;\n if (!g.Element) g.Element = NucloElement;\n if (!g.HTMLElement) g.HTMLElement = NucloElement;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"nuclo.polyfill.cjs","names":["NucloElement","NucloNode","NucloElement"],"sources":["../../src/polyfill/Text.ts","../../src/polyfill/Document.ts","../../src/polyfill/index.ts"],"sourcesContent":["export class NucloText {\n nodeType = 3; // Node.TEXT_NODE\n nodeName = '#text';\n data: string;\n textContent: string;\n parentNode: unknown = null;\n \n constructor(data: string) {\n this.data = data;\n this.textContent = data;\n }\n \n get nodeValue(): string {\n return this.data;\n }\n \n set nodeValue(value: string) {\n this.data = value;\n this.textContent = value;\n }\n}\n","import { NucloElement } from './Element';\nimport { NucloText } from './Text';\n\n/**\n * Lightweight DocumentFragment for SSR — prototype methods instead of per-instance closures.\n */\nclass SSRDocumentFragment {\n nodeType: number = 11;\n nodeName: string = '#document-fragment';\n childNodes: Node[] = [];\n children: Element[] = [];\n textContent: string = '';\n\n get firstChild(): Node | null {\n return this.childNodes.length > 0 ? this.childNodes[0] : null;\n }\n\n get lastChild(): Node | null {\n return this.childNodes.length > 0 ? this.childNodes[this.childNodes.length - 1] : null;\n }\n\n appendChild<T extends Node>(child: T): T {\n this.childNodes.push(child);\n if ((child as any).nodeType === 1) {\n this.children.push(child as unknown as Element);\n }\n (child as any).parentNode = this;\n return child;\n }\n\n insertBefore<T extends Node>(newNode: T, refNode: Node | null): T {\n if (!refNode) return this.appendChild(newNode);\n const index = this.childNodes.indexOf(refNode);\n if (index !== -1) {\n this.childNodes.splice(index, 0, newNode);\n if ((newNode as any).nodeType === 1) {\n const elementIndex = this.children.indexOf(refNode as Element);\n if (elementIndex !== -1) {\n this.children.splice(elementIndex, 0, newNode as unknown as Element);\n }\n }\n }\n (newNode as any).parentNode = this;\n return newNode;\n }\n\n removeChild<T extends Node>(child: T): T {\n const index = this.childNodes.indexOf(child);\n if (index !== -1) this.childNodes.splice(index, 1);\n if ((child as any).nodeType === 1) {\n const elementIndex = this.children.indexOf(child as unknown as Element);\n if (elementIndex !== -1) this.children.splice(elementIndex, 1);\n }\n (child as any).parentNode = null;\n return child;\n }\n\n replaceChild<T extends Node>(newChild: T, oldChild: Node): T {\n const index = this.childNodes.indexOf(oldChild);\n if (index !== -1) {\n this.childNodes[index] = newChild;\n if ((oldChild as any).nodeType === 1 && (newChild as any).nodeType === 1) {\n const elementIndex = this.children.indexOf(oldChild as Element);\n if (elementIndex !== -1) {\n this.children[elementIndex] = newChild as unknown as Element;\n }\n }\n }\n (newChild as any).parentNode = this;\n (oldChild as any).parentNode = null;\n return newChild;\n }\n\n querySelector(): null { return null; }\n querySelectorAll(): NodeListOf<Element> { return [] as unknown as NodeListOf<Element>; }\n}\n\nexport class NucloDocument {\n head: ExpandedElement;\n body: ExpandedElement;\n\n constructor() {\n this.head = new NucloElement('head') as unknown as ExpandedElement;\n this.body = new NucloElement('body') as unknown as ExpandedElement;\n }\n \n createElement(tagName: string, _options?: unknown): ExpandedElement {\n return new NucloElement(tagName) as unknown as ExpandedElement;\n }\n \n createElementNS(namespace: string, tagName: string, _options?: unknown): ExpandedElement {\n const element = new NucloElement(tagName) as unknown as ExpandedElement;\n (element as any).namespaceURI = namespace;\n return element;\n }\n \n createTextNode(data: string): Text {\n return new NucloText(data) as unknown as Text;\n }\n \n createComment(data: string): Comment {\n const comment = {\n nodeType: 8,\n nodeName: '#comment',\n data,\n textContent: data,\n nodeValue: data,\n parentNode: null,\n nextSibling: null,\n previousSibling: null\n };\n return comment as unknown as Comment;\n }\n \n createDocumentFragment(): DocumentFragment {\n return new SSRDocumentFragment() as unknown as DocumentFragment;\n }\n \n // SSR never dispatches events: listeners are accepted and dropped, and\n // queries find nothing.\n querySelector(_selector: string): Element | null {\n return null;\n }\n\n querySelectorAll(_selector: string): NodeListOf<Element> {\n return [] as unknown as NodeListOf<Element>;\n }\n\n addEventListener(_type: string, _listener: EventListener, _options?: boolean | AddEventListenerOptions): void {}\n\n removeEventListener(_type: string, _listener: EventListener, _options?: boolean | AddEventListenerOptions): void {}\n\n dispatchEvent(_event: Event): boolean {\n return true;\n }\n\n contains(_node: Node): boolean {\n return false;\n }\n}\n\nexport const document = globalThis.document || new NucloDocument();","/**\n * Polyfills for Node.js environments\n *\n * This module provides minimal browser API polyfills to allow Nuclo to run in Node.js\n * for server-side rendering (SSR).\n *\n * To use in Node.js:\n * ```typescript\n * import 'nuclo/polyfill';\n * // or\n * import { document, Event, CustomEvent } from 'nuclo/polyfill';\n * ```\n */\n\nexport { NucloDocument, document } from './Document';\nexport { NucloElement } from './Element';\nexport { NucloText } from './Text';\nexport { NucloNode } from './Node';\n\nimport { NucloElement } from './Element';\nimport { NucloNode } from './Node';\nimport { document } from './Document';\n\n// Event and CustomEvent are built into every supported runtime (Node >= 19,\n// Bun, Deno); re-exported for the documented named imports.\nexport const Event = globalThis.Event;\nexport const CustomEvent = globalThis.CustomEvent;\nexport const Node = NucloNode;\nexport const Element = NucloElement;\nexport const HTMLElement = NucloElement;\n\n// Auto-apply polyfills to globalThis if in Node environment (synchronous — no top-level await)\nif (typeof window === 'undefined') {\n const g = globalThis as unknown as {\n document?: typeof document;\n Node?: typeof NucloNode;\n Element?: typeof NucloElement;\n HTMLElement?: typeof NucloElement;\n };\n g.document ??= document;\n g.Node ??= NucloNode;\n g.Element ??= NucloElement;\n g.HTMLElement ??= NucloElement;\n}\n"],"mappings":"8GAAA,IAAa,EAAb,KAAuB,CACrB,SAAW,EACX,SAAW,QACX,KACA,YACA,WAAsB,KAEtB,YAAY,EAAc,CACxB,KAAK,KAAO,EACZ,KAAK,YAAc,CACrB,CAEA,IAAI,WAAoB,CACtB,OAAO,KAAK,IACd,CAEA,IAAI,UAAU,EAAe,CAC3B,KAAK,KAAO,EACZ,KAAK,YAAc,CACrB,CACF,ECdM,EAAN,KAA0B,CACxB,SAAmB,GACnB,SAAmB,qBACnB,WAAqB,CAAC,EACtB,SAAsB,CAAC,EACvB,YAAsB,GAEtB,IAAI,YAA0B,CAC5B,OAAO,KAAK,WAAW,OAAS,EAAI,KAAK,WAAW,GAAK,IAC3D,CAEA,IAAI,WAAyB,CAC3B,OAAO,KAAK,WAAW,OAAS,EAAI,KAAK,WAAW,KAAK,WAAW,OAAS,GAAK,IACpF,CAEA,YAA4B,EAAa,CAMvC,OALA,KAAK,WAAW,KAAK,CAAK,EACrB,EAAc,WAAa,GAC9B,KAAK,SAAS,KAAK,CAA2B,EAEhD,EAAe,WAAa,KACrB,CACT,CAEA,aAA6B,EAAY,EAAyB,CAChE,GAAI,CAAC,EAAS,OAAO,KAAK,YAAY,CAAO,EAC7C,IAAM,EAAQ,KAAK,WAAW,QAAQ,CAAO,EAC7C,GAAI,IAAU,KACZ,KAAK,WAAW,OAAO,EAAO,EAAG,CAAO,EACnC,EAAgB,WAAa,GAAG,CACnC,IAAM,EAAe,KAAK,SAAS,QAAQ,CAAkB,EACzD,IAAiB,IACnB,KAAK,SAAS,OAAO,EAAc,EAAG,CAA6B,CAEvE,CAGF,MADA,GAAiB,WAAa,KACvB,CACT,CAEA,YAA4B,EAAa,CACvC,IAAM,EAAQ,KAAK,WAAW,QAAQ,CAAK,EAE3C,GADI,IAAU,IAAI,KAAK,WAAW,OAAO,EAAO,CAAC,EAC5C,EAAc,WAAa,EAAG,CACjC,IAAM,EAAe,KAAK,SAAS,QAAQ,CAA2B,EAClE,IAAiB,IAAI,KAAK,SAAS,OAAO,EAAc,CAAC,CAC/D,CAEA,MADA,GAAe,WAAa,KACrB,CACT,CAEA,aAA6B,EAAa,EAAmB,CAC3D,IAAM,EAAQ,KAAK,WAAW,QAAQ,CAAQ,EAC9C,GAAI,IAAU,KACZ,KAAK,WAAW,GAAS,EACpB,EAAiB,WAAa,GAAM,EAAiB,WAAa,GAAG,CACxE,IAAM,EAAe,KAAK,SAAS,QAAQ,CAAmB,EAC1D,IAAiB,KACnB,KAAK,SAAS,GAAgB,EAElC,CAIF,MAFA,GAAkB,WAAa,KAC/B,EAAkB,WAAa,KACxB,CACT,CAEA,eAAsB,CAAE,OAAO,IAAM,CACrC,kBAAwC,CAAE,MAAO,CAAC,CAAqC,CACzF,EAEa,EAAb,KAA2B,CACzB,KACA,KAEA,aAAc,CACZ,KAAK,KAAO,IAAIA,EAAAA,EAAa,MAAM,EACnC,KAAK,KAAO,IAAIA,EAAAA,EAAa,MAAM,CACrC,CAEA,cAAc,EAAiB,EAAqC,CAClE,OAAO,IAAIA,EAAAA,EAAa,CAAO,CACjC,CAEA,gBAAgB,EAAmB,EAAiB,EAAqC,CACvF,IAAM,EAAU,IAAIA,EAAAA,EAAa,CAAO,EAExC,MADA,GAAiB,aAAe,EACzB,CACT,CAEA,eAAe,EAAoB,CACjC,OAAO,IAAI,EAAU,CAAI,CAC3B,CAEA,cAAc,EAAuB,CAWnC,MAAO,CATL,SAAU,EACV,SAAU,WACV,OACA,YAAa,EACb,UAAW,EACX,WAAY,KACZ,YAAa,KACb,gBAAiB,IAEN,CACf,CAEA,wBAA2C,CACzC,OAAO,IAAI,CACb,CAIA,cAAc,EAAmC,CAC/C,OAAO,IACT,CAEA,iBAAiB,EAAwC,CACvD,MAAO,CAAC,CACV,CAEA,iBAAiB,EAAe,EAA0B,EAAoD,CAAC,CAE/G,oBAAoB,EAAe,EAA0B,EAAoD,CAAC,CAElH,cAAc,EAAwB,CACpC,MAAO,EACT,CAEA,SAAS,EAAsB,CAC7B,MAAO,EACT,CACF,EAEA,MAAa,EAAW,WAAW,UAAY,IAAI,ECpHtC,EAAQ,WAAW,MACnB,EAAc,WAAW,YACzB,EAAOC,EAAAA,EACP,EAAUC,EAAAA,EACV,EAAcA,EAAAA,EAG3B,GAAI,OAAO,OAAW,IAAa,CACjC,IAAM,EAAI,WAMV,EAAE,WAAa,EACf,EAAE,OAASD,EAAAA,EACX,EAAE,UAAYC,EAAAA,EACd,EAAE,cAAgBA,EAAAA,CACpB"}
@@ -1,2 +1,2 @@
1
- import{n as e,t}from"../Element-Djosl17E.mjs";var n=class{nodeType=3;nodeName=`#text`;data;textContent;parentNode=null;constructor(e){this.data=e,this.textContent=e}get nodeValue(){return this.data}set nodeValue(e){this.data=e,this.textContent=e}},r=class{nodeType=11;nodeName=`#document-fragment`;childNodes=[];children=[];textContent=``;get firstChild(){return this.childNodes.length>0?this.childNodes[0]:null}get lastChild(){return this.childNodes.length>0?this.childNodes[this.childNodes.length-1]:null}appendChild(e){return this.childNodes.push(e),e.nodeType===1&&this.children.push(e),e.parentNode=this,e}insertBefore(e,t){if(!t)return this.appendChild(e);let n=this.childNodes.indexOf(t);if(n!==-1&&(this.childNodes.splice(n,0,e),e.nodeType===1)){let n=this.children.indexOf(t);n!==-1&&this.children.splice(n,0,e)}return e.parentNode=this,e}removeChild(e){let t=this.childNodes.indexOf(e);if(t!==-1&&this.childNodes.splice(t,1),e.nodeType===1){let t=this.children.indexOf(e);t!==-1&&this.children.splice(t,1)}return e.parentNode=null,e}replaceChild(e,t){let n=this.childNodes.indexOf(t);if(n!==-1&&(this.childNodes[n]=e,t.nodeType===1&&e.nodeType===1)){let n=this.children.indexOf(t);n!==-1&&(this.children[n]=e)}return e.parentNode=this,t.parentNode=null,e}querySelector(){return null}querySelectorAll(){return[]}},i=class{head;body;_listeners;constructor(){this.head=new t(`head`),this.body=new t(`body`),this._listeners=/* @__PURE__ */ new Map}createElement(e,n){return new t(e)}createElementNS(e,n,r){let i=new t(n);return i.namespaceURI=e,i}createTextNode(e){return new n(e)}createComment(e){return{nodeType:8,nodeName:`#comment`,data:e,textContent:e,nodeValue:e,parentNode:null,nextSibling:null,previousSibling:null}}createDocumentFragment(){return new r}querySelector(e){if(e.startsWith(`#`)){let t=e.slice(1);if(t===`nuclo-styles`&&this.head.children){for(let e of this.head.children)if(e.id===t)return e}}return null}querySelectorAll(e){return[]}addEventListener(e,t,n){this._listeners.has(e)||this._listeners.set(e,/* @__PURE__ */ new Map),this._listeners.get(e).set(t,{listener:t,options:n})}removeEventListener(e,t,n){let r=this._listeners.get(e);r&&(r.delete(t),r.size===0&&this._listeners.delete(e))}dispatchEvent(e){let t=this._listeners.get(e.type);if(t){let n=Array.from(t.values());for(let t=0;t<n.length;t++){let{listener:r}=n[t];try{r(e)}catch(e){console.error(`Error in event listener:`,e)}}}return!0}contains(e){return!1}};const a=globalThis.document||new i;var o=class{type;bubbles;cancelable;composed;currentTarget=null;defaultPrevented=!1;eventPhase=0;isTrusted=!1;target=null;timeStamp;AT_TARGET=2;BUBBLING_PHASE=3;CAPTURING_PHASE=1;NONE=0;returnValue=!0;srcElement=null;cancelBubble=!1;constructor(e,t){this.type=e,this.bubbles=t?.bubbles||!1,this.cancelable=t?.cancelable||!1,this.composed=t?.composed||!1,this.timeStamp=Date.now()}composedPath(){return[]}initEvent(e,t,n){}preventDefault(){this.cancelable&&(this.defaultPrevented=!0)}stopImmediatePropagation(){this.cancelBubble=!0}stopPropagation(){this.cancelBubble=!0}},s=class extends o{detail;constructor(e,t){super(e,t),this.detail=t?.detail}initCustomEvent(e,t,n,r){}};const c=globalThis.Event||o,l=globalThis.CustomEvent||s,u=e,d=t,f=t;if(typeof window>`u`&&typeof globalThis<`u`){let n=globalThis;n.document||=a,n.Event||=c,n.CustomEvent||=l,n.Node||=e,n.Element||=t,n.HTMLElement||=t}export{l as CustomEvent,d as Element,c as Event,f as HTMLElement,u as Node,s as NucloCustomEvent,i as NucloDocument,t as NucloElement,o as NucloEvent,e as NucloNode,n as NucloText,a as document};
1
+ import{n as e,t}from"../Element-DLSdmoqX.mjs";var n=class{nodeType=3;nodeName=`#text`;data;textContent;parentNode=null;constructor(e){this.data=e,this.textContent=e}get nodeValue(){return this.data}set nodeValue(e){this.data=e,this.textContent=e}},r=class{nodeType=11;nodeName=`#document-fragment`;childNodes=[];children=[];textContent=``;get firstChild(){return this.childNodes.length>0?this.childNodes[0]:null}get lastChild(){return this.childNodes.length>0?this.childNodes[this.childNodes.length-1]:null}appendChild(e){return this.childNodes.push(e),e.nodeType===1&&this.children.push(e),e.parentNode=this,e}insertBefore(e,t){if(!t)return this.appendChild(e);let n=this.childNodes.indexOf(t);if(n!==-1&&(this.childNodes.splice(n,0,e),e.nodeType===1)){let n=this.children.indexOf(t);n!==-1&&this.children.splice(n,0,e)}return e.parentNode=this,e}removeChild(e){let t=this.childNodes.indexOf(e);if(t!==-1&&this.childNodes.splice(t,1),e.nodeType===1){let t=this.children.indexOf(e);t!==-1&&this.children.splice(t,1)}return e.parentNode=null,e}replaceChild(e,t){let n=this.childNodes.indexOf(t);if(n!==-1&&(this.childNodes[n]=e,t.nodeType===1&&e.nodeType===1)){let n=this.children.indexOf(t);n!==-1&&(this.children[n]=e)}return e.parentNode=this,t.parentNode=null,e}querySelector(){return null}querySelectorAll(){return[]}},i=class{head;body;constructor(){this.head=new t(`head`),this.body=new t(`body`)}createElement(e,n){return new t(e)}createElementNS(e,n,r){let i=new t(n);return i.namespaceURI=e,i}createTextNode(e){return new n(e)}createComment(e){return{nodeType:8,nodeName:`#comment`,data:e,textContent:e,nodeValue:e,parentNode:null,nextSibling:null,previousSibling:null}}createDocumentFragment(){return new r}querySelector(e){return null}querySelectorAll(e){return[]}addEventListener(e,t,n){}removeEventListener(e,t,n){}dispatchEvent(e){return!0}contains(e){return!1}};const a=globalThis.document||new i,o=globalThis.Event,s=globalThis.CustomEvent,c=e,l=t,u=t;if(typeof window>`u`){let n=globalThis;n.document??=a,n.Node??=e,n.Element??=t,n.HTMLElement??=t}export{s as CustomEvent,l as Element,o as Event,u as HTMLElement,c as Node,i as NucloDocument,t as NucloElement,e as NucloNode,n as NucloText,a as document};
2
2
  //# sourceMappingURL=nuclo.polyfill.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"nuclo.polyfill.mjs","names":[],"sources":["../../src/polyfill/Text.ts","../../src/polyfill/Document.ts","../../src/polyfill/Event.ts","../../src/polyfill/index.ts"],"sourcesContent":["export class NucloText {\n nodeType = 3; // Node.TEXT_NODE\n nodeName = '#text';\n data: string;\n textContent: string;\n parentNode: unknown = null;\n \n constructor(data: string) {\n this.data = data;\n this.textContent = data;\n }\n \n get nodeValue(): string {\n return this.data;\n }\n \n set nodeValue(value: string) {\n this.data = value;\n this.textContent = value;\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { NucloElement } from './Element';\nimport { NucloText } from './Text';\n\n/**\n * Lightweight DocumentFragment for SSR — prototype methods instead of per-instance closures.\n */\nclass SSRDocumentFragment {\n nodeType: number = 11;\n nodeName: string = '#document-fragment';\n childNodes: Node[] = [];\n children: Element[] = [];\n textContent: string = '';\n\n get firstChild(): Node | null {\n return this.childNodes.length > 0 ? this.childNodes[0] : null;\n }\n\n get lastChild(): Node | null {\n return this.childNodes.length > 0 ? this.childNodes[this.childNodes.length - 1] : null;\n }\n\n appendChild<T extends Node>(child: T): T {\n this.childNodes.push(child);\n if ((child as any).nodeType === 1) {\n this.children.push(child as unknown as Element);\n }\n (child as any).parentNode = this;\n return child;\n }\n\n insertBefore<T extends Node>(newNode: T, refNode: Node | null): T {\n if (!refNode) return this.appendChild(newNode);\n const index = this.childNodes.indexOf(refNode);\n if (index !== -1) {\n this.childNodes.splice(index, 0, newNode);\n if ((newNode as any).nodeType === 1) {\n const elementIndex = this.children.indexOf(refNode as Element);\n if (elementIndex !== -1) {\n this.children.splice(elementIndex, 0, newNode as unknown as Element);\n }\n }\n }\n (newNode as any).parentNode = this;\n return newNode;\n }\n\n removeChild<T extends Node>(child: T): T {\n const index = this.childNodes.indexOf(child);\n if (index !== -1) this.childNodes.splice(index, 1);\n if ((child as any).nodeType === 1) {\n const elementIndex = this.children.indexOf(child as unknown as Element);\n if (elementIndex !== -1) this.children.splice(elementIndex, 1);\n }\n (child as any).parentNode = null;\n return child;\n }\n\n replaceChild<T extends Node>(newChild: T, oldChild: Node): T {\n const index = this.childNodes.indexOf(oldChild);\n if (index !== -1) {\n this.childNodes[index] = newChild;\n if ((oldChild as any).nodeType === 1 && (newChild as any).nodeType === 1) {\n const elementIndex = this.children.indexOf(oldChild as Element);\n if (elementIndex !== -1) {\n this.children[elementIndex] = newChild as unknown as Element;\n }\n }\n }\n (newChild as any).parentNode = this;\n (oldChild as any).parentNode = null;\n return newChild;\n }\n\n querySelector(): null { return null; }\n querySelectorAll(): NodeListOf<Element> { return [] as unknown as NodeListOf<Element>; }\n}\n\nexport class NucloDocument {\n head: ExpandedElement;\n body: ExpandedElement;\n private _listeners: Map<string, Map<EventListener, { listener: EventListener; options?: boolean | AddEventListenerOptions }>>;\n \n constructor() {\n this.head = new NucloElement('head') as unknown as ExpandedElement;\n this.body = new NucloElement('body') as unknown as ExpandedElement;\n this._listeners = new Map();\n }\n \n createElement(tagName: string, _options?: unknown): ExpandedElement {\n return new NucloElement(tagName) as unknown as ExpandedElement;\n }\n \n createElementNS(namespace: string, tagName: string, _options?: unknown): ExpandedElement {\n const element = new NucloElement(tagName) as unknown as ExpandedElement;\n (element as any).namespaceURI = namespace;\n return element;\n }\n \n createTextNode(data: string): Text {\n return new NucloText(data) as unknown as Text;\n }\n \n createComment(data: string): Comment {\n const comment = {\n nodeType: 8,\n nodeName: '#comment',\n data,\n textContent: data,\n nodeValue: data,\n parentNode: null,\n nextSibling: null,\n previousSibling: null\n };\n return comment as unknown as Comment;\n }\n \n createDocumentFragment(): DocumentFragment {\n return new SSRDocumentFragment() as unknown as DocumentFragment;\n }\n \n querySelector(selector: string): Element | null {\n // Simple implementation - only supports ID selector for #nuclo-styles\n if (selector.startsWith('#')) {\n const id = selector.slice(1);\n if (id === 'nuclo-styles' && this.head.children) {\n for (const child of this.head.children) {\n if ((child as any).id === id) {\n return child as unknown as Element;\n }\n }\n }\n }\n return null;\n }\n \n querySelectorAll(_selector: string): NodeListOf<Element> {\n return [] as unknown as NodeListOf<Element>;\n }\n \n addEventListener(type: string, listener: EventListener, options?: boolean | AddEventListenerOptions): void {\n if (!this._listeners.has(type)) {\n this._listeners.set(type, new Map());\n }\n const listenersMap = this._listeners.get(type)!;\n listenersMap.set(listener, { listener, options });\n }\n \n removeEventListener(type: string, listener: EventListener, _options?: boolean | AddEventListenerOptions): void {\n const listeners = this._listeners.get(type);\n if (listeners) {\n listeners.delete(listener);\n // Clean up empty maps to prevent memory leaks\n if (listeners.size === 0) {\n this._listeners.delete(type);\n }\n }\n }\n \n dispatchEvent(event: Event): boolean {\n const listeners = this._listeners.get(event.type);\n if (listeners) {\n // Create a copy to avoid issues if listeners are modified during dispatch\n const listenersCopy = Array.from(listeners.values());\n for (let i = 0; i < listenersCopy.length; i++) {\n const { listener } = listenersCopy[i];\n try {\n listener(event);\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('Error in event listener:', error);\n }\n }\n }\n return true;\n }\n \n contains(_node: Node): boolean {\n return false;\n }\n}\n\nexport const document = globalThis.document || new NucloDocument();","/* eslint-disable @typescript-eslint/no-explicit-any */\nexport class NucloEvent implements Event {\n type: string;\n bubbles: boolean;\n cancelable: boolean;\n composed: boolean;\n currentTarget: EventTarget | null = null;\n defaultPrevented: boolean = false;\n eventPhase: number = 0;\n isTrusted: boolean = false;\n target: EventTarget | null = null;\n timeStamp: number;\n readonly AT_TARGET = 2;\n readonly BUBBLING_PHASE = 3;\n readonly CAPTURING_PHASE = 1;\n readonly NONE = 0;\n returnValue: boolean = true;\n srcElement: EventTarget | null = null;\n cancelBubble: boolean = false;\n \n constructor(type: string, eventInitDict?: EventInit) {\n this.type = type;\n this.bubbles = eventInitDict?.bubbles || false;\n this.cancelable = eventInitDict?.cancelable || false;\n this.composed = eventInitDict?.composed || false;\n this.timeStamp = Date.now();\n }\n \n composedPath(): EventTarget[] {\n return [];\n }\n \n initEvent(_type: string, _bubbles?: boolean, _cancelable?: boolean): void {\n // Legacy method - no-op\n }\n \n preventDefault(): void {\n if (this.cancelable) {\n this.defaultPrevented = true;\n }\n }\n \n stopImmediatePropagation(): void {\n this.cancelBubble = true;\n }\n \n stopPropagation(): void {\n this.cancelBubble = true;\n }\n}\n\nexport class NucloCustomEvent<T = any> extends NucloEvent implements CustomEvent<T> {\n detail: T;\n \n constructor(type: string, eventInitDict?: CustomEventInit<T>) {\n super(type, eventInitDict);\n this.detail = eventInitDict?.detail as T;\n }\n \n initCustomEvent(_type: string, _bubbles?: boolean, _cancelable?: boolean, _detail?: T): void {\n // Legacy method - no-op\n }\n}\n\n// Export polyfills if browser globals don't exist\nexport const Event = globalThis.Event || NucloEvent;\nexport const CustomEvent = globalThis.CustomEvent || NucloCustomEvent;\n","/**\n * Polyfills for Node.js environments\n * \n * This module provides minimal browser API polyfills to allow Nuclo to run in Node.js\n * for server-side rendering (SSR) scenarios.\n * \n * To use in Node.js:\n * ```typescript\n * import 'nuclo/polyfill';\n * // or\n * import { document, Event, CustomEvent } from 'nuclo/polyfill';\n * ```\n */\n\nexport { NucloDocument, document } from './Document';\nexport { NucloElement } from './Element';\nexport { NucloText } from './Text';\nexport { NucloEvent, NucloCustomEvent, Event, CustomEvent } from './Event';\nexport { NucloNode } from './Node';\n\n// Import for local use\nimport { NucloElement } from './Element';\nimport { NucloNode } from './Node';\nimport { document } from './Document';\nimport { Event, CustomEvent } from './Event';\n\nexport const Node = NucloNode;\nexport const Element = NucloElement;\nexport const HTMLElement = NucloElement;\n\n// Auto-apply polyfills to globalThis if in Node environment (synchronous — no top-level await)\nif (typeof window === 'undefined' && typeof globalThis !== 'undefined') {\n interface GlobalWithPolyfills {\n document?: typeof document;\n Event?: typeof Event;\n CustomEvent?: typeof CustomEvent;\n Node?: typeof NucloNode;\n Element?: typeof NucloElement;\n HTMLElement?: typeof NucloElement;\n }\n\n const g = globalThis as unknown as GlobalWithPolyfills;\n\n if (!g.document) g.document = document;\n if (!g.Event) g.Event = Event;\n if (!g.CustomEvent) g.CustomEvent = CustomEvent;\n if (!g.Node) g.Node = NucloNode;\n if (!g.Element) g.Element = NucloElement;\n if (!g.HTMLElement) g.HTMLElement = NucloElement;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"nuclo.polyfill.mjs","names":[],"sources":["../../src/polyfill/Text.ts","../../src/polyfill/Document.ts","../../src/polyfill/index.ts"],"sourcesContent":["export class NucloText {\n nodeType = 3; // Node.TEXT_NODE\n nodeName = '#text';\n data: string;\n textContent: string;\n parentNode: unknown = null;\n \n constructor(data: string) {\n this.data = data;\n this.textContent = data;\n }\n \n get nodeValue(): string {\n return this.data;\n }\n \n set nodeValue(value: string) {\n this.data = value;\n this.textContent = value;\n }\n}\n","import { NucloElement } from './Element';\nimport { NucloText } from './Text';\n\n/**\n * Lightweight DocumentFragment for SSR — prototype methods instead of per-instance closures.\n */\nclass SSRDocumentFragment {\n nodeType: number = 11;\n nodeName: string = '#document-fragment';\n childNodes: Node[] = [];\n children: Element[] = [];\n textContent: string = '';\n\n get firstChild(): Node | null {\n return this.childNodes.length > 0 ? this.childNodes[0] : null;\n }\n\n get lastChild(): Node | null {\n return this.childNodes.length > 0 ? this.childNodes[this.childNodes.length - 1] : null;\n }\n\n appendChild<T extends Node>(child: T): T {\n this.childNodes.push(child);\n if ((child as any).nodeType === 1) {\n this.children.push(child as unknown as Element);\n }\n (child as any).parentNode = this;\n return child;\n }\n\n insertBefore<T extends Node>(newNode: T, refNode: Node | null): T {\n if (!refNode) return this.appendChild(newNode);\n const index = this.childNodes.indexOf(refNode);\n if (index !== -1) {\n this.childNodes.splice(index, 0, newNode);\n if ((newNode as any).nodeType === 1) {\n const elementIndex = this.children.indexOf(refNode as Element);\n if (elementIndex !== -1) {\n this.children.splice(elementIndex, 0, newNode as unknown as Element);\n }\n }\n }\n (newNode as any).parentNode = this;\n return newNode;\n }\n\n removeChild<T extends Node>(child: T): T {\n const index = this.childNodes.indexOf(child);\n if (index !== -1) this.childNodes.splice(index, 1);\n if ((child as any).nodeType === 1) {\n const elementIndex = this.children.indexOf(child as unknown as Element);\n if (elementIndex !== -1) this.children.splice(elementIndex, 1);\n }\n (child as any).parentNode = null;\n return child;\n }\n\n replaceChild<T extends Node>(newChild: T, oldChild: Node): T {\n const index = this.childNodes.indexOf(oldChild);\n if (index !== -1) {\n this.childNodes[index] = newChild;\n if ((oldChild as any).nodeType === 1 && (newChild as any).nodeType === 1) {\n const elementIndex = this.children.indexOf(oldChild as Element);\n if (elementIndex !== -1) {\n this.children[elementIndex] = newChild as unknown as Element;\n }\n }\n }\n (newChild as any).parentNode = this;\n (oldChild as any).parentNode = null;\n return newChild;\n }\n\n querySelector(): null { return null; }\n querySelectorAll(): NodeListOf<Element> { return [] as unknown as NodeListOf<Element>; }\n}\n\nexport class NucloDocument {\n head: ExpandedElement;\n body: ExpandedElement;\n\n constructor() {\n this.head = new NucloElement('head') as unknown as ExpandedElement;\n this.body = new NucloElement('body') as unknown as ExpandedElement;\n }\n \n createElement(tagName: string, _options?: unknown): ExpandedElement {\n return new NucloElement(tagName) as unknown as ExpandedElement;\n }\n \n createElementNS(namespace: string, tagName: string, _options?: unknown): ExpandedElement {\n const element = new NucloElement(tagName) as unknown as ExpandedElement;\n (element as any).namespaceURI = namespace;\n return element;\n }\n \n createTextNode(data: string): Text {\n return new NucloText(data) as unknown as Text;\n }\n \n createComment(data: string): Comment {\n const comment = {\n nodeType: 8,\n nodeName: '#comment',\n data,\n textContent: data,\n nodeValue: data,\n parentNode: null,\n nextSibling: null,\n previousSibling: null\n };\n return comment as unknown as Comment;\n }\n \n createDocumentFragment(): DocumentFragment {\n return new SSRDocumentFragment() as unknown as DocumentFragment;\n }\n \n // SSR never dispatches events: listeners are accepted and dropped, and\n // queries find nothing.\n querySelector(_selector: string): Element | null {\n return null;\n }\n\n querySelectorAll(_selector: string): NodeListOf<Element> {\n return [] as unknown as NodeListOf<Element>;\n }\n\n addEventListener(_type: string, _listener: EventListener, _options?: boolean | AddEventListenerOptions): void {}\n\n removeEventListener(_type: string, _listener: EventListener, _options?: boolean | AddEventListenerOptions): void {}\n\n dispatchEvent(_event: Event): boolean {\n return true;\n }\n\n contains(_node: Node): boolean {\n return false;\n }\n}\n\nexport const document = globalThis.document || new NucloDocument();","/**\n * Polyfills for Node.js environments\n *\n * This module provides minimal browser API polyfills to allow Nuclo to run in Node.js\n * for server-side rendering (SSR).\n *\n * To use in Node.js:\n * ```typescript\n * import 'nuclo/polyfill';\n * // or\n * import { document, Event, CustomEvent } from 'nuclo/polyfill';\n * ```\n */\n\nexport { NucloDocument, document } from './Document';\nexport { NucloElement } from './Element';\nexport { NucloText } from './Text';\nexport { NucloNode } from './Node';\n\nimport { NucloElement } from './Element';\nimport { NucloNode } from './Node';\nimport { document } from './Document';\n\n// Event and CustomEvent are built into every supported runtime (Node >= 19,\n// Bun, Deno); re-exported for the documented named imports.\nexport const Event = globalThis.Event;\nexport const CustomEvent = globalThis.CustomEvent;\nexport const Node = NucloNode;\nexport const Element = NucloElement;\nexport const HTMLElement = NucloElement;\n\n// Auto-apply polyfills to globalThis if in Node environment (synchronous — no top-level await)\nif (typeof window === 'undefined') {\n const g = globalThis as unknown as {\n document?: typeof document;\n Node?: typeof NucloNode;\n Element?: typeof NucloElement;\n HTMLElement?: typeof NucloElement;\n };\n g.document ??= document;\n g.Node ??= NucloNode;\n g.Element ??= NucloElement;\n g.HTMLElement ??= NucloElement;\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../Element-BUdteOsZ.cjs");function t(e){let t=0;for(;t<e.length;t++){let n=e.charCodeAt(t);if(n>=65&&n<=90)break}if(t===e.length)return e;let n=e.slice(0,t);for(let r=t;r<e.length;r++){let t=e.charCodeAt(r);t>=65&&t<=90?(r>0&&(n+=`-`),n+=String.fromCharCode(t+32)):n+=e[r]}return n}const n=/[&<>"']/,r=/[&<>]/;function i(e){let t=n.exec(e);if(!t)return e;let r=``,i=0;for(let n=t.index;n<e.length;n++){let t;switch(e.charCodeAt(n)){case 38:t=`&amp;`;break;case 60:t=`&lt;`;break;case 62:t=`&gt;`;break;case 34:t=`&quot;`;break;case 39:t=`&#039;`;break;default:continue}r+=e.slice(i,n)+t,i=n+1}return r+e.slice(i)}function a(e){let t=r.exec(e);if(!t)return e;let n=``,i=0;for(let r=t.index;r<e.length;r++){let t;switch(e.charCodeAt(r)){case 38:t=`&amp;`;break;case 60:t=`&lt;`;break;case 62:t=`&gt;`;break;default:continue}n+=e.slice(i,r)+t,i=r+1}return n+e.slice(i)}let o=!1;function s(e){let t=o;o=!0;try{return e()}finally{o=t}}const c=/* @__PURE__ */ new Set;typeof FinalizationRegistry<`u`&&new FinalizationRegistry(e=>{c.delete(e)});function l(e){return globalThis.document?document.createElement(e):null}const u=/* @__PURE__ */ new Set(/* @__PURE__ */ `viewBox.preserveAspectRatio.markerWidth.markerHeight.gradientTransform.patternTransform.clipPathUnits.gradientUnits.patternUnits.pathLength.refX.refY.stdDeviation.baseFrequency.numOctaves.kernelMatrix.tableValues.targetX.targetY.specularExponent.specularConstant.diffuseConstant.surfaceScale.xChannelSelector.yChannelSelector.edgeMode.stitchTiles.spreadMethod.patternContentUnits.markerUnits.startOffset.textLength.lengthAdjust`.split(`.`)),d=/* @__PURE__ */ new Set([`allowfullscreen`,`async`,`autofocus`,`autoplay`,`checked`,`controls`,`default`,`defer`,`disabled`,`formnovalidate`,`hidden`,`ismap`,`loop`,`multiple`,`muted`,`nomodule`,`novalidate`,`open`,`readonly`,`required`,`reversed`,`selected`]);function f(e,n){if(n==null||n===!1)return``;if(n===!0)return` ${e}`;if(d.has(e)){if(n===`false`)return``;if(n===`true`||n===``||n===e)return` ${e}`}if(e===`style`&&typeof n==`object`){let e=``;for(let r in n){let i=n[r];i!=null&&i!==``&&(e+=(e?` `:``)+t(r)+`: `+String(i)+`;`)}return e?` style="${i(e)}"`:``}return` ${e}="${i(String(n))}"`}function p(e,n){let r=``;if(n){let n=e,a=n._attributes;n.id&&!a?.has(`id`)&&(r+=f(`id`,n.id)),n.className&&!a?.has(`class`)&&(r+=f(`class`,n.className));let o=n._style;if(!a?.has(`style`)&&o){let e=o.cssText||``;if(e){let n=e.split(`;`).map(e=>e.trim()).filter(Boolean).map(e=>{let n=e.indexOf(`:`);if(n===-1)return e;let r=e.slice(0,n).trim(),i=e.slice(n+1).trim();return i?`${t(r)}: ${i};`:``}).filter(Boolean).join(` `);n&&(r+=` style="${i(n)}"`)}}if(a)for(let[e,n]of a){let i=u.has(e)?e:t(e);r+=f(i,n)}return r}if(e.attributes&&e.attributes.length)for(let t=0;t<e.attributes.length;t++){let n=e.attributes[t];n&&n.name&&(r+=f(n.name,n.value))}return r}const m=Object.assign(Object.create(null),{area:1,base:1,br:1,col:1,embed:1,hr:1,img:1,input:1,link:1,meta:1,param:1,source:1,track:1,wbr:1,script:2,style:2});function h(e,t){return t.replace(RegExp(`</(`+e+`)`,`gi`),`<\\/$1`)}function g(e){if(`tagName`in e&&`children`in e){let t=e.children;if(Array.isArray(t))return t}if(`childNodes`in e){let t=e.childNodes;if(t&&(Array.isArray(t)||t.length!==void 0))return t}return[]}function _(t){if(t.nodeType===3)return a(t.textContent||``);if(t.nodeType===8)return`<!--${t.textContent||``}-->`;if(t.nodeType===1){let n=t,r=n.tagName,i=Array.isArray(n.children),o=n instanceof e.t?r:r.toLowerCase(),s=p(n,i),c=m[o];if(c===1)return`<${o}${s} />`;let l=i?n.children:g(n);if(c===2){let e=``,n=l;if(n&&n.length>0)for(let t=0;t<n.length;t++){let r=n[t];r&&r.nodeType===3&&(e+=r.textContent||``)}else{let n=t.textContent;typeof n==`string`&&(e=n)}return`<${o}${s}>${h(o,e)}</${o}>`}let u=``;if(l&&l.length>0)for(let e=0;e<l.length;e++){let t=l[e];t&&(u+=_(t))}else{let e=t.textContent;typeof e==`string`&&e&&(u=a(e))}return`<${o}${s}>${u}</${o}>`}if(t.nodeType===11){let e=``,n=g(t);if(n&&n.length>0)for(let t=0;t<n.length;t++){let r=n[t];r&&(e+=_(r))}return e}return``}function v(e){if(!e)return``;if(typeof e==`function`)try{let t=s(()=>{let t=l(`div`);if(!t)throw Error(`Document is not available. Make sure polyfills are loaded.`);return e(t,0)});return t&&typeof t==`object`&&`nodeType`in t?_(t):``}catch(e){return console.error(`Error rendering component to string:`,e),``}return`nodeType`in e?_(e):``}function y(e){return e.map(e=>v(e))}function b(e,t=`div`,n={}){let r=v(e);return`<${t}${Object.entries(n).map(([e,t])=>f(e,t)).join(``)}>${r}</${t}>`}function x(){return{ssrCollector:null,atomCache:/* @__PURE__ */ new Map,atomMeta:/* @__PURE__ */ new Map,rawKeys:/* @__PURE__ */ new Set,baseRules:[],queryRules:/* @__PURE__ */ new Map,styleEpoch:0,cssTextCache:null,sheet:null,sheetDocument:null,baseRuleCount:0,groupRules:/* @__PURE__ */ new Map,externalRules:null,hasExternalGroups:!1}}const S=Symbol.for(`nuclo.style.engine.v1`),C=globalThis;let w;function T(){return w??=C[S]??(C[S]=x())}function E(e){let t=T();t.ssrCollector=e}function D(){let e=T();if(e.cssTextCache!==null)return e.cssTextCache;let t=e.baseRules.join(``);for(let[n,r]of e.queryRules)r.length>0&&(t+=n+`{`+r.join(``)+`}`);return e.cssTextCache=t,t}exports.getCssText=D,exports.renderManyToString=y,exports.renderToString=v,exports.renderToStringWithContainer=b,exports.setSSRCollector=E;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../Element-DfxBbUgD.cjs");function t(e){let t=0;for(;t<e.length;t++){let n=e.charCodeAt(t);if(n>=65&&n<=90)break}if(t===e.length)return e;let n=e.slice(0,t);for(let r=t;r<e.length;r++){let t=e.charCodeAt(r);n+=t>=65&&t<=90?`-`+String.fromCharCode(t+32):e[r]}return n}const n=/[&<>"']/,r=/[&<>]/;function i(e){let t=n.exec(e);if(!t)return e;let r=``,i=0;for(let n=t.index;n<e.length;n++){let t;switch(e.charCodeAt(n)){case 38:t=`&amp;`;break;case 60:t=`&lt;`;break;case 62:t=`&gt;`;break;case 34:t=`&quot;`;break;case 39:t=`&#039;`;break;default:continue}r+=e.slice(i,n)+t,i=n+1}return r+e.slice(i)}function a(e){let t=r.exec(e);if(!t)return e;let n=``,i=0;for(let r=t.index;r<e.length;r++){let t;switch(e.charCodeAt(r)){case 38:t=`&amp;`;break;case 60:t=`&lt;`;break;case 62:t=`&gt;`;break;default:continue}n+=e.slice(i,r)+t,i=r+1}return n+e.slice(i)}let o=!1;function s(e){let t=o;o=!0;try{return e()}finally{o=t}}const c=/* @__PURE__ */ new Set(/* @__PURE__ */ `viewBox.preserveAspectRatio.markerWidth.markerHeight.gradientTransform.patternTransform.clipPathUnits.gradientUnits.patternUnits.pathLength.refX.refY.stdDeviation.baseFrequency.numOctaves.kernelMatrix.tableValues.targetX.targetY.specularExponent.specularConstant.diffuseConstant.surfaceScale.xChannelSelector.yChannelSelector.edgeMode.stitchTiles.spreadMethod.patternContentUnits.markerUnits.startOffset.textLength.lengthAdjust`.split(`.`)),l=/* @__PURE__ */ new Set([`allowfullscreen`,`async`,`autofocus`,`autoplay`,`checked`,`controls`,`default`,`defer`,`disabled`,`formnovalidate`,`hidden`,`ismap`,`loop`,`multiple`,`muted`,`nomodule`,`novalidate`,`open`,`readonly`,`required`,`reversed`,`selected`]);function u(e,n){if(n==null||n===!1)return``;if(n===!0)return` ${e}`;if(l.has(e)){if(n===`false`)return``;if(n===`true`||n===``||n===e)return` ${e}`}if(e===`style`&&typeof n==`object`){let e=``;for(let r in n){let i=n[r];i!=null&&i!==``&&(e+=(e?` `:``)+t(r)+`: `+String(i)+`;`)}return e?` style="${i(e)}"`:``}return` ${e}="${i(String(n))}"`}function d(e,n){let r=``;if(n){let n=e,a=n._attributes;n.id&&!a?.has(`id`)&&(r+=u(`id`,n.id)),n.className&&!a?.has(`class`)&&(r+=u(`class`,n.className));let o=n._style;if(o&&!a?.has(`style`)){let e=``;for(let n in o){let r=o[n];r!=null&&r!==``&&(e+=(e?` `:``)+t(n)+`: `+String(r)+`;`)}e&&(r+=` style="${i(e)}"`)}if(a)for(let[e,n]of a){let i=c.has(e)?e:t(e);r+=u(i,n)}return r}if(e.attributes&&e.attributes.length)for(let t=0;t<e.attributes.length;t++){let n=e.attributes[t];n&&n.name&&(r+=u(n.name,n.value))}return r}const f=Object.assign(Object.create(null),{area:1,base:1,br:1,col:1,embed:1,hr:1,img:1,input:1,link:1,meta:1,param:1,source:1,track:1,wbr:1,script:2,style:2});function p(e,t){return t.replace(RegExp(`</(`+e+`)`,`gi`),`<\\/$1`)}function m(t){if(t.nodeType===3)return a(t.textContent||``);if(t.nodeType===8)return`<!--${t.textContent||``}-->`;if(t.nodeType===1){let n=t,r=n.tagName,i=Array.isArray(n.children),o=n instanceof e.t?r:r.toLowerCase(),s=d(n,i),c=f[o];if(c===1)return`<${o}${s} />`;let l=i?n.children:n.childNodes;if(c===2){let e=``,n=l;if(n&&n.length>0)for(let t=0;t<n.length;t++){let r=n[t];r&&r.nodeType===3&&(e+=r.textContent||``)}else{let n=t.textContent;typeof n==`string`&&(e=n)}return`<${o}${s}>${p(o,e)}</${o}>`}let u=``;if(l&&l.length>0)for(let e=0;e<l.length;e++){let t=l[e];t&&(u+=m(t))}else{let e=t.textContent;typeof e==`string`&&e&&(u=a(e))}return`<${o}${s}>${u}</${o}>`}if(t.nodeType===11){let e=``,n=t.childNodes??[];if(n.length>0)for(let t=0;t<n.length;t++){let r=n[t];r&&(e+=m(r))}return e}return``}function h(e){if(!e)return``;if(typeof e==`function`)try{let t=s(()=>{if(typeof document>`u`)throw Error(`Document is not available. Make sure polyfills are loaded.`);return e(document.createElement(`div`),0)});return t&&typeof t==`object`&&`nodeType`in t?m(t):``}catch(e){return console.error(`Error rendering component to string:`,e),``}return`nodeType`in e?m(e):``}function g(e){return e.map(e=>h(e))}function _(e,t=`div`,n={}){let r=h(e);return`<${t}${Object.entries(n).map(([e,t])=>u(e,t)).join(``)}>${r}</${t}>`}function v(){return{atomCache:/* @__PURE__ */ new Map,atomMeta:/* @__PURE__ */ new Map,rawKeys:/* @__PURE__ */ new Set,baseRules:[],queryRules:/* @__PURE__ */ new Map,styleEpoch:0,cssTextCache:null,sheet:null,sheetDocument:null,baseRuleCount:0,groupRules:/* @__PURE__ */ new Map,externalRules:null,hasExternalGroups:!1}}const y=Symbol.for(`nuclo.style.engine.v1`),b=globalThis;let x;function S(){return x??=b[y]??(b[y]=v())}function C(){let e=S();if(e.cssTextCache!==null)return e.cssTextCache;let t=e.baseRules.join(``);for(let[n,r]of e.queryRules)r.length>0&&(t+=n+`{`+r.join(``)+`}`);return e.cssTextCache=t,t}exports.getCssText=C,exports.renderManyToString=g,exports.renderToString=h,exports.renderToStringWithContainer=_;
2
2
  //# sourceMappingURL=nuclo.ssr.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"nuclo.ssr.cjs","names":["NucloElement"],"sources":["../../src/shared/strings.ts","../../src/hydration.ts","../../src/update/registry.ts","../../src/shared/dom.ts","../../src/ssr/render-to-string.ts","../../src/style/engine.ts"],"sourcesContent":["/**\n * String utility functions\n */\n\n/**\n * Converts camelCase to kebab-case (optimized for performance)\n * Uses direct character code manipulation for maximum speed\n * @example camelToKebab('backgroundColor') => 'background-color'\n */\nexport function camelToKebab(str: string): string {\n // Fast path: attribute/property names are usually already lowercase.\n let firstUpper = 0;\n for (; firstUpper < str.length; firstUpper++) {\n const code = str.charCodeAt(firstUpper);\n if (code >= 65 && code <= 90) break;\n }\n if (firstUpper === str.length) return str;\n\n let result = str.slice(0, firstUpper);\n for (let i = firstUpper; i < str.length; i++) {\n const code = str.charCodeAt(i);\n // A-Z is 65-90, a-z is 97-122 (difference of 32)\n if (code >= 65 && code <= 90) {\n if (i > 0) result += '-';\n result += String.fromCharCode(code + 32);\n } else {\n result += str[i];\n }\n }\n return result;\n}\n\nconst ATTR_ESCAPE_RE = /[&<>\"']/;\nconst TEXT_ESCAPE_RE = /[&<>]/;\n\n/**\n * Escapes HTML special characters in attribute values (includes \" and ')\n */\nexport function escapeHtml(text: string): string {\n // Fast path: most strings contain no special characters at all.\n const first = ATTR_ESCAPE_RE.exec(text);\n if (!first) return text;\n\n let result = '';\n let last = 0;\n for (let i = first.index; i < text.length; i++) {\n let escaped: string;\n switch (text.charCodeAt(i)) {\n case 38: escaped = '&amp;'; break; // &\n case 60: escaped = '&lt;'; break; // <\n case 62: escaped = '&gt;'; break; // >\n case 34: escaped = '&quot;'; break; // \"\n case 39: escaped = '&#039;'; break; // '\n default: continue;\n }\n result += text.slice(last, i) + escaped;\n last = i + 1;\n }\n return result + text.slice(last);\n}\n\n/**\n * Escapes HTML special characters in text node content.\n * Only &, < and > need escaping — quotes are safe inside text nodes.\n */\nexport function escapeText(text: string): string {\n const first = TEXT_ESCAPE_RE.exec(text);\n if (!first) return text;\n\n let result = '';\n let last = 0;\n for (let i = first.index; i < text.length; i++) {\n let escaped: string;\n switch (text.charCodeAt(i)) {\n case 38: escaped = '&amp;'; break; // &\n case 60: escaped = '&lt;'; break; // <\n case 62: escaped = '&gt;'; break; // >\n default: continue;\n }\n result += text.slice(last, i) + escaped;\n last = i + 1;\n }\n return result + text.slice(last);\n}\n","/**\n * Hydration context — tracks global hydration state and per-parent cursor positions.\n *\n * During hydration the component tree is built against an existing DOM tree\n * (produced by SSR). Instead of creating new nodes, factories claim existing\n * children from their parent element by advancing a cursor.\n *\n * The cursor is a *node pointer* (the next unclaimed child), not an index.\n * Indexed childNodes access is O(n) after any tree/attribute mutation in\n * jsdom (live NodeList re-materialization) which made hydration O(n²);\n * firstChild/nextSibling pointers are O(1) in every DOM implementation.\n */\n\nlet _hydrating = false;\n// True while renderToString() is building a tree destined for serialization.\nlet _serializing = false;\n// Missing entry = cursor at parent.firstChild; null = past the last child.\nlet _cursors = new WeakMap<Node, Node | null>();\n\nexport function isHydrating(): boolean {\n return _hydrating;\n}\n\n/**\n * True while a tree is being built for SSR serialization (inside\n * renderToString). Text children must keep their `<!-- text-N -->` markers in\n * this mode so the emitted HTML stays hydratable — even when `isBrowser` is\n * true (SSR running under jsdom, or an isomorphic worker that provides a DOM).\n * A pure client render leaves this false and skips the markers.\n */\nexport function isSerializing(): boolean {\n return _serializing;\n}\n\n/**\n * Runs `fn` with serialization mode enabled, restoring the previous state\n * afterwards (so nested/re-entrant renderToString calls behave correctly).\n */\nexport function runSerializing<T>(fn: () => T): T {\n const previous = _serializing;\n _serializing = true;\n try {\n return fn();\n } finally {\n _serializing = previous;\n }\n}\n\nexport function startHydration(): void {\n _hydrating = true;\n // Each hydration pass starts with a clean cursor slate. Stale cursors from\n // a previous pass would desynchronize claims when a container's content is\n // replaced and re-hydrated (HMR, islands re-mounting).\n _cursors = new WeakMap<Node, Node | null>();\n}\n\nexport function endHydration(): void {\n _hydrating = false;\n}\n\n/**\n * Runs a callback with hydration temporarily disabled, restoring the previous\n * state afterwards. Used when a server/client mismatch forces a subtree to be\n * rendered fresh in the middle of a hydration pass — fresh rendering must not\n * claim nodes from the surrounding SSR DOM.\n */\nexport function runWithoutHydration<T>(fn: () => T): T {\n const wasHydrating = _hydrating;\n _hydrating = false;\n try {\n return fn();\n } finally {\n _hydrating = wasHydrating;\n }\n}\n\n/**\n * Returns the next unclaimed child of a parent node (or null at the end)\n * without advancing the cursor.\n */\nexport function peekChild(parent: Node): Node | null {\n const entry = _cursors.get(parent);\n return entry === undefined ? parent.firstChild : entry;\n}\n\n/**\n * Sets the cursor to a specific child node (or null for \"past the end\").\n */\nexport function setCursor(parent: Node, node: Node | null): void {\n _cursors.set(parent, node);\n}\n\nfunction isWhitespaceText(node: Node): boolean {\n return node.nodeType === 3 && !/\\S/.test(node.textContent || '');\n}\n\n/**\n * Advances the cursor past whitespace-only text nodes.\n *\n * Nuclo's own SSR output never produces bare whitespace text nodes (text\n * children are always preceded by a `<!-- text-N -->` marker), so unmarked\n * whitespace comes from the surrounding template or an HTML\n * formatter/minifier. Skipping (without removing) keeps the cursor aligned\n * while leaving the document's visual whitespace untouched.\n */\nexport function skipWhitespaceText(parent: Node): void {\n let child = peekChild(parent);\n let advanced = false;\n while (child && isWhitespaceText(child)) {\n child = child.nextSibling;\n advanced = true;\n }\n if (advanced) {\n setCursor(parent, child);\n }\n}\n\n/**\n * Claims the next child node from parent at the current cursor position.\n * Advances the cursor by one.\n */\nexport function claimChild(parent: Node): Node | null {\n const child = peekChild(parent);\n if (child) {\n setCursor(parent, child.nextSibling);\n }\n return child;\n}\n\n/**\n * Attempts to claim an existing element from the parent during hydration.\n * Returns the claimed element if the next child matches the expected tag, or null.\n */\nexport function claimElement(parent: Node, tagName: string): Element | null {\n if (!_hydrating) return null;\n skipWhitespaceText(parent);\n const candidate = peekChild(parent);\n if (candidate && candidate.nodeType === 1 && (candidate as Element).tagName.toLowerCase() === tagName) {\n return claimChild(parent) as Element;\n }\n return null;\n}\n\n/**\n * Removes unclaimed SSR children from a hydrated element.\n * Must be called after modifiers have been applied to a claimed element.\n * Removes nodes from the cursor through `lastOriginalChild` (the element's\n * last child before modifiers ran) — nodes appended by modifiers come after\n * that boundary and are preserved.\n */\nexport function cleanupUnclaimedChildren(node: Node, lastOriginalChild: Node | null): void {\n if (!lastOriginalChild) return;\n let current = peekChild(node);\n while (current) {\n const next = current === lastOriginalChild ? null : current.nextSibling;\n node.removeChild(current);\n current = next;\n }\n setCursor(node, null);\n}\n","/**\n * Shared types and registries for reactive nodes.\n * Single source of truth — imported by reactiveText.ts and reactiveAttributes.ts.\n *\n * Registry structure: the iteration sets only hold WeakRefs; the actual info\n * records live in WeakMaps keyed by the node. Info records may strongly\n * reference the node (e.g. attribute applyValue closures capture the\n * element), so storing them in a strongly-held map would pin the node in\n * memory forever. With WeakMap storage the whole record is collectible as\n * soon as the node is unreachable.\n *\n * Dead WeakRefs left in the iteration sets are pruned by the notify passes as\n * they iterate (deref() === undefined, or node disconnected). Registration is\n * the hottest path in list-heavy renders (one text node + often one element\n * per row), so no per-node FinalizationRegistry is used here: its register()\n * cost per row outweighs keeping the sets tidy between updates, and a stale\n * husk is just an empty WeakRef until the next update() sweeps it.\n */\n\nexport type TextResolver = () => Primitive;\n\nexport interface ReactiveTextNodeInfo {\n resolver: TextResolver;\n lastValue: string;\n /**\n * DSL semantics: nullish and non-primitive resolver results render as \"\"\n * (instead of String(value)). Set by the tag-builder text path so it can\n * register the user's resolver directly rather than allocating a\n * sanitizing wrapper closure per text node.\n */\n sanitize?: boolean;\n}\n\nexport type AttributeResolver = () => unknown;\n\nexport interface AttributeResolverRecord {\n key: string;\n resolver: AttributeResolver;\n applyValue: (value: unknown) => void;\n lastValue: unknown;\n}\n\nexport interface ReactiveElementInfo {\n /**\n * Flat keyed array rather than a Map: elements almost always carry one or\n * two reactive attributes, so linear key lookup on registration beats a Map\n * allocation per element, and the per-update flush iterates with a plain\n * index loop (no iterator/destructuring allocations).\n */\n attributeResolvers: AttributeResolverRecord[];\n}\n\n/**\n * Iteration set of weak references to reactive text nodes.\n */\nexport const reactiveTextNodes = new Set<WeakRef<Text>>();\n\n/**\n * WeakMap for O(1) lookups of reactive text node info by node reference.\n */\nexport const reactiveTextNodesByNode = new WeakMap<Text, { ref: WeakRef<Text>; info: ReactiveTextNodeInfo }>();\n\n/**\n * Iteration set of weak references to reactive elements.\n */\nexport const reactiveElements = new Set<WeakRef<Element>>();\n\n/**\n * WeakMap for O(1) lookups of reactive element info by element reference.\n */\nexport const reactiveElementsByNode = new WeakMap<Element, { ref: WeakRef<Element>; info: ReactiveElementInfo }>();\n\n/**\n * Registers a reactive text node in both lookup structures.\n */\nexport function registerReactiveTextNode(node: Text, info: ReactiveTextNodeInfo): void {\n const existing = reactiveTextNodesByNode.get(node);\n if (existing) {\n // Re-registration (e.g. repeated hydration): replace the info in place.\n existing.info.resolver = info.resolver;\n existing.info.lastValue = info.lastValue;\n existing.info.sanitize = info.sanitize;\n return;\n }\n const ref = new WeakRef(node);\n reactiveTextNodes.add(ref);\n reactiveTextNodesByNode.set(node, { ref, info });\n}\n\n/**\n * Registers a reactive element in both lookup structures.\n */\nexport function registerReactiveElement(element: Element, info: ReactiveElementInfo): void {\n const existing = reactiveElementsByNode.get(element);\n if (existing) {\n existing.info = info;\n return;\n }\n const ref = new WeakRef(element);\n reactiveElements.add(ref);\n reactiveElementsByNode.set(element, { ref, info });\n}\n\n/**\n * Removes a reactive text node's WeakRef entry from the iteration set.\n */\nexport function removeReactiveTextNodeRef(ref: WeakRef<Text>): void {\n reactiveTextNodes.delete(ref);\n}\n\n/**\n * Removes a reactive element's WeakRef entry from the iteration set.\n */\nexport function removeReactiveElementRef(ref: WeakRef<Element>): void {\n reactiveElements.delete(ref);\n}\n\n/**\n * Manually removes reactive text node info for a specific text node.\n * This should be called when a text node is removed from the DOM to prevent memory leaks.\n */\nexport function cleanupReactiveTextNode(node: Text): void {\n const entry = reactiveTextNodesByNode.get(node);\n if (entry) {\n reactiveTextNodes.delete(entry.ref);\n reactiveTextNodesByNode.delete(node);\n }\n}\n\n/**\n * Manually removes reactive element info for a specific element.\n * This should be called when an element is removed from the DOM to prevent memory leaks.\n */\nexport function cleanupReactiveElement(element: Element): void {\n const entry = reactiveElementsByNode.get(element);\n if (entry) {\n reactiveElements.delete(entry.ref);\n reactiveElementsByNode.delete(element);\n }\n}\n\n// ─── Conditional elements ────────────────────────────────────────────────────\n// Same idea as above, but for nodes created by conditional rendering: the\n// registry remembers each node's condition + modifiers so update() can\n// re-evaluate and swap the element in place.\n\nexport interface ConditionalInfo<TTagName extends ElementTagName = ElementTagName> {\n\tcondition: () => boolean;\n\ttagName: TTagName;\n\tmodifiers: Array<NodeMod<TTagName> | NodeModFn<TTagName>>;\n\tisSvg: boolean;\n}\n\n// WeakMap replaces the _conditionalInfo expando property — zero `any`, no DOM pollution, auto-GC.\nconst conditionalInfoMap = new WeakMap<Node, ConditionalInfo<ElementTagName>>();\n\n/**\n * Registry of all nodes that have conditional info attached.\n * Uses WeakRef to prevent memory leaks — allows garbage collection of removed nodes.\n * This enables O(nConditionals) updates instead of a full DOM tree walk.\n */\nconst activeConditionalNodes = new Set<WeakRef<Node>>();\n\n/**\n * Reverse lookup for O(1) unregister — maps node to its WeakRef in the active set.\n */\nconst refByNode = new WeakMap<Node, WeakRef<Node>>();\n\n/**\n * Prunes dead WeakRefs from the active set as soon as their node is\n * collected, instead of waiting for the next getActiveConditionalNodes() pass.\n */\nconst conditionalNodeFinalizer = typeof FinalizationRegistry !== \"undefined\"\n\t? new FinalizationRegistry<WeakRef<Node>>((ref) => { activeConditionalNodes.delete(ref); })\n\t: null;\n\n/**\n * Attach conditional info to a node and register it.\n */\nexport function storeConditionalInfo<TTagName extends ElementTagName>(\n\tnode: Node,\n\tinfo: ConditionalInfo<TTagName>\n): void {\n\tconditionalInfoMap.set(node, info as ConditionalInfo<ElementTagName>);\n\tif (refByNode.has(node)) return;\n\tconst ref = new WeakRef(node);\n\tactiveConditionalNodes.add(ref);\n\trefByNode.set(node, ref);\n\tconditionalNodeFinalizer?.register(node, ref, ref);\n}\n\n/**\n * Explicit unregister helper (optional use on teardown if needed).\n * O(1) via reverse lookup WeakMap.\n */\nexport function unregisterConditionalNode(node: Node): void {\n\tconditionalInfoMap.delete(node);\n\tconst ref = refByNode.get(node);\n\tif (ref) {\n\t\tactiveConditionalNodes.delete(ref);\n\t\tconditionalNodeFinalizer?.unregister(ref);\n\t\trefByNode.delete(node);\n\t}\n}\n\n/**\n * Returns an array of currently tracked conditional nodes that are still alive.\n * Automatically cleans up garbage-collected nodes.\n */\nexport function getActiveConditionalNodes(): Node[] {\n\tconst nodes: Node[] = [];\n\n\tfor (const ref of activeConditionalNodes) {\n\t\tconst node = ref.deref();\n\t\tif (node === undefined) {\n\t\t\tactiveConditionalNodes.delete(ref);\n\t\t} else {\n\t\t\tnodes.push(node);\n\t\t}\n\t}\n\n\treturn nodes;\n}\n\nexport function getConditionalInfo(node: Node): ConditionalInfo<ElementTagName> | null {\n\treturn conditionalInfoMap.get(node) ?? null;\n}\n","import { logError } from \"./errors\";\nimport { removeAllListeners } from \"../element/events\";\nimport { cleanupReactiveTextNode, cleanupReactiveElement, unregisterConditionalNode } from \"../update/registry\";\nimport { disposeElementLifecycle, hasActiveLifecycleRegistrations } from \"../element/lifecycle\";\n\nexport const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';\n\n/**\n * Creates an HTML element.\n * Wrapper for document.createElement with type safety.\n */\nexport function createElement<K extends keyof HTMLElementTagNameMap>(\n tagName: K\n): HTMLElementTagNameMap[K] | null;\nexport function createElement(tagName: string): ExpandedElement | null;\nexport function createElement(tagName: string): ExpandedElement | null {\n return globalThis.document ? document.createElement(tagName) as ExpandedElement : null;\n}\n\n/**\n * Creates an element in the given namespace (typically for SVG elements).\n * Wrapper for document.createElementNS with type safety.\n */\nexport function createElementNS(\n namespace: string,\n tagName: string\n): ExpandedElement | null {\n return globalThis.document ? document.createElementNS(namespace, tagName) as ExpandedElement : null;\n}\n\n/**\n * Creates a text node with the given content.\n * Wrapper for document.createTextNode.\n */\nexport function createTextNode(text: string): Text | null {\n return globalThis.document ? document.createTextNode(text) : null;\n}\n\n/**\n * Creates a document fragment.\n * Wrapper for document.createDocumentFragment.\n */\nexport function createDocumentFragment(): DocumentFragment | null {\n return globalThis.document ? document.createDocumentFragment() : null;\n}\n\nfunction safeAppendChild(parent: Element | Node, child: Node): boolean {\n try {\n parent.appendChild(child);\n return true;\n } catch (error) {\n logError('Failed to append child node', error);\n return false;\n }\n}\n\n/**\n * Recursively removes all event listeners and reactive subscriptions from a node and its descendants\n * to prevent memory leaks when elements are removed from the DOM.\n */\nfunction cleanupNodeTree(node: Node): void {\n // Clean up the node itself based on its type. Order-independent bookkeeping\n // (listeners, reactive registrations) runs up front; onDestroy is fired\n // below, after descendants — see the comment there.\n if (node.nodeType === Node.ELEMENT_NODE) {\n const element = node as HTMLElement;\n // Remove all event listeners\n removeAllListeners(element);\n // Remove reactive attribute resolvers\n cleanupReactiveElement(element);\n // Remove conditional info\n unregisterConditionalNode(element);\n } else if (node.nodeType === Node.TEXT_NODE) {\n // Remove reactive text node info\n cleanupReactiveTextNode(node as Text);\n } else if (node.nodeType === Node.COMMENT_NODE) {\n // Remove conditional info from comment nodes (used by when/list)\n unregisterConditionalNode(node);\n }\n\n // Recursively clean up all child nodes\n // Destroy callbacks can mutate the live childNodes collection. Snapshot\n // only when hooks exist; ordinary cleanup needs no additional allocation.\n const children = hasActiveLifecycleRegistrations() ? Array.from(node.childNodes) : node.childNodes;\n for (let i = 0; i < children.length; i++) {\n cleanupNodeTree(children[i]);\n }\n\n // Fire onDestroy last — after every descendant's onDestroy has already run\n // (post-order) — so a parent's teardown can rely on its children having\n // already released whatever they were using (e.g. a subscription or timer\n // the parent owns and children only read from). This mirrors onMount's own\n // order, which is naturally parent-before-child (registration order is\n // construction order: a parent's own onMount/{onMount} modifier is applied\n // before its child factories are even invoked) — so mount is top-down,\n // destroy is bottom-up, the same LIFO discipline nested resource scopes\n // always use. No-op unless this exact element registered a callback.\n if (node.nodeType === Node.ELEMENT_NODE) {\n disposeElementLifecycle(node as HTMLElement);\n }\n}\n\n/**\n * Fires onDestroy for a subtree that a fast removal path (list()'s bulk\n * clear/replace, the single-element when()/else() swap) is about to drop\n * without walking through cleanupNodeTree()/safeRemoveChild(). Short-circuits\n * to a single comparison when nothing on the page has ever registered a\n * lifecycle callback — the common case — so those fast paths stay fast.\n *\n * Same post-order (children, then self) as cleanupNodeTree() above, for the\n * same reason — see the comment there.\n */\nexport function disposeLifecyclesInSubtree(node: Node): void {\n if (!hasActiveLifecycleRegistrations()) return;\n const children = Array.from(node.childNodes);\n for (let i = 0; i < children.length; i++) {\n disposeLifecyclesInSubtree(children[i]);\n }\n if (node.nodeType === Node.ELEMENT_NODE) {\n disposeElementLifecycle(node as Element);\n }\n}\n\nexport function safeRemoveChild(child: Node): boolean {\n if (!child?.parentNode) return false;\n try {\n // Clean up all event listeners before removing the element\n cleanupNodeTree(child);\n // A destroy callback may already have removed the node.\n child.parentNode?.removeChild(child);\n return true;\n } catch (error) {\n logError('Failed to remove child node', error);\n return false;\n }\n}\n\nfunction safeInsertBefore(parent: Node, newNode: Node, referenceNode: Node | null): boolean {\n try {\n parent.insertBefore(newNode, referenceNode);\n return true;\n } catch (error) {\n logError('Failed to insert node before reference', error);\n return false;\n }\n}\n\nexport function createComment(text: string): Comment | null {\n return globalThis.document ? globalThis.document.createComment(text) : null;\n}\n\nexport function createConditionalComment(tagName: string, suffix = \"hidden\"): Comment | null {\n return globalThis.document ? globalThis.document.createComment(`conditional-${tagName}-${suffix}`) : null;\n}\n\nexport function createMarkerPair(prefix: string, id: number | string): { start: Comment; end: Comment } {\n const endComment = createComment(`${prefix}-end`);\n if (!endComment) throw new Error(\"Failed to create comment: document not available\");\n const startComment = createComment(`${prefix}-start-${id}`);\n if (!startComment) throw new Error(\"Failed to create comment: document not available\");\n return { start: startComment, end: endComment };\n}\n\nexport function clearBetweenMarkers(startMarker: Comment, endMarker: Comment): void {\n let current = startMarker.nextSibling;\n while (current && current !== endMarker) {\n const next = current.nextSibling;\n safeRemoveChild(current);\n current = next;\n }\n}\n\nexport function insertNodesBefore(nodes: Node[], referenceNode: Node): void {\n const parent = referenceNode.parentNode;\n if (parent) {\n for (let i = 0; i < nodes.length; i++) {\n safeInsertBefore(parent, nodes[i], referenceNode);\n }\n }\n}\n\nexport function appendChildren(\n parent: Element | Node,\n ...children: Array<Element | Node | string | null | undefined>\n): Element | Node {\n if (!parent) return parent;\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n if (child != null) {\n let nodeToAppend: Node;\n\n if (typeof child === \"string\") {\n const textNode = createTextNode(child);\n if (textNode) {\n nodeToAppend = textNode;\n } else {\n continue;\n }\n } else {\n nodeToAppend = child as Node;\n }\n\n safeAppendChild(parent, nodeToAppend);\n }\n }\n\n return parent;\n}\n\nexport function isNodeConnected(node: Node | null | undefined): boolean {\n return node?.isConnected === true;\n}\n\n/**\n * Safely replaces an old node with a new node in the DOM.\n * Returns true on success, false on failure (and logs the error).\n */\nexport function replaceNodeSafely(oldNode: Node, newNode: Node): boolean {\n if (!oldNode?.parentNode) return false;\n try {\n oldNode.parentNode.replaceChild(newNode, oldNode);\n return true;\n } catch (error) {\n logError(\"Error replacing conditional node\", error);\n return false;\n }\n}\n\n// ─── Type-safe DOM helpers ───────────────────────────────────────────────────\n\n/**\n * Safely casts an Element-like object to Node & ParentNode interface.\n * This is a common pattern needed when working with DOM manipulation.\n *\n * @param element - The element to cast\n * @returns The element typed as Node & ParentNode\n */\nexport function asParentNode<T extends Element | object>(element: T): Node & ParentNode {\n return element as unknown as Node & ParentNode;\n}\n\n/**\n * Creates a scoped DOM insertion context that temporarily redirects appendChild\n * to insertBefore at a specific reference node. This is useful for inserting\n * content at specific positions in the DOM tree.\n *\n * @param host - The host element\n * @param referenceNode - The node before which new nodes should be inserted\n * @param callback - Function to execute with the scoped context\n * @returns The result of the callback\n */\nexport function withScopedInsertion<T, THost extends Element | object>(\n host: THost,\n referenceNode: Node,\n callback: () => T\n): T {\n const parent = asParentNode(host);\n const originalAppend = Object.getOwnPropertyDescriptor(parent, \"appendChild\");\n const originalInsert = parent.insertBefore;\n\n // Temporarily override appendChild to insert before the reference node\n // TypeScript doesn't like this override but it's safe at runtime\n (parent as unknown as Record<string, unknown>).appendChild = function(node: Node): Node {\n return originalInsert.call(parent, node, referenceNode);\n };\n\n try {\n return callback();\n } finally {\n // Restore original method\n if (originalAppend) Object.defineProperty(parent, \"appendChild\", originalAppend);\n else Reflect.deleteProperty(parent, \"appendChild\");\n }\n}\n\n/**\n * Type-safe wrapper for setting CSS style properties.\n * Provides better error handling than direct CSSStyleDeclaration access.\n * Supports both camelCase and kebab-case property names.\n *\n * @param element - The element to apply styles to\n * @param property - The CSS property name (camelCase or kebab-case)\n * @param value - The value to set (string, number, or null to remove)\n * @returns true if the style was applied successfully, false otherwise\n */\nexport function setStyleProperty(\n element: HTMLElement,\n property: string,\n value: string | number | null\n): boolean {\n try {\n if (value === null || value === undefined || value === '') {\n // Use bracket notation to remove property (works with camelCase)\n (element.style as unknown as Record<string, string>)[property] = '';\n return true;\n }\n\n // Convert value to string first (might throw if toString() throws)\n const stringValue = String(value);\n // Use bracket notation to set property (works with camelCase)\n (element.style as unknown as Record<string, string>)[property] = stringValue;\n return true;\n } catch {\n return false;\n }\n}\n","/**\n * Server-Side Rendering (SSR) utilities for Nuclo\n * Renders Nuclo components to HTML strings in Node.js environment\n */\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { escapeHtml, escapeText, camelToKebab } from '../shared/strings';\nimport { createElement } from '../shared/dom';\nimport { runSerializing } from '../hydration';\nimport { NucloElement } from '../polyfill/Element';\n\ntype RenderableInput =\n | NodeModFn<ElementTagName>\n | Element\n | Node\n | null\n | undefined;\n\n/**\n * SVG attributes that are natively camelCase and must NOT be converted to kebab-case.\n * Most SVG attributes are already kebab-case (stroke-width, fill-rule, etc.), but a\n * handful are defined as camelCase in the SVG spec and must be preserved.\n */\nconst SVG_PRESERVE_CASE_ATTRS = new Set([\n 'viewBox', 'preserveAspectRatio', 'markerWidth', 'markerHeight',\n 'gradientTransform', 'patternTransform', 'clipPathUnits', 'gradientUnits',\n 'patternUnits', 'pathLength', 'refX', 'refY', 'stdDeviation',\n 'baseFrequency', 'numOctaves', 'kernelMatrix', 'tableValues',\n 'targetX', 'targetY', 'specularExponent', 'specularConstant',\n 'diffuseConstant', 'surfaceScale', 'xChannelSelector', 'yChannelSelector',\n 'edgeMode', 'stitchTiles', 'spreadMethod', 'patternContentUnits',\n 'markerUnits', 'startOffset', 'textLength', 'lengthAdjust',\n]);\n\n/**\n * HTML boolean attributes — presence means true, absence means false.\n * When the stored value is the string \"true\" or \"false\" (from setAttribute),\n * we must re-apply boolean semantics instead of outputting the raw string.\n */\nconst HTML_BOOLEAN_ATTRIBUTES = new Set([\n 'allowfullscreen', 'async', 'autofocus', 'autoplay', 'checked', 'controls',\n 'default', 'defer', 'disabled', 'formnovalidate', 'hidden', 'ismap', 'loop',\n 'multiple', 'muted', 'nomodule', 'novalidate', 'open', 'readonly', 'required',\n 'reversed', 'selected',\n]);\n\n/**\n * Serializes a DOM attribute value\n */\nfunction serializeAttribute(name: string, value: unknown): string {\n if (value === null || value === undefined || value === false) {\n return '';\n }\n\n if (value === true) {\n return ` ${name}`;\n }\n\n // Boolean attributes stored as strings via setAttribute() need special handling\n if (HTML_BOOLEAN_ATTRIBUTES.has(name)) {\n if (value === 'false') return '';\n if (value === 'true' || value === '' || value === name) return ` ${name}`;\n }\n\n if (name === 'style' && typeof value === 'object') {\n let styleStr = '';\n for (const key in value as Record<string, unknown>) {\n const val = (value as Record<string, unknown>)[key];\n if (val == null || val === '') continue;\n styleStr += (styleStr ? ' ' : '') + camelToKebab(key) + ': ' + String(val) + ';';\n }\n return styleStr ? ` style=\"${escapeHtml(styleStr)}\"` : '';\n }\n\n return ` ${name}=\"${escapeHtml(String(value))}\"`;\n}\n\n/**\n * Serializes DOM element attributes to HTML string\n *\n * `isPolyfill` is passed in by the caller (serializeNode already computed it\n * to decide whether tagName needs lowercasing) so this doesn't repeat the\n * same `Array.isArray` discriminator check per element.\n */\nfunction serializeAttributes(element: Element, isPolyfill: boolean): string {\n let result = '';\n\n // Handle polyfill elements. NucloElement keeps every child in a plain Array\n // (`children`), which a real DOM element never does (HTMLCollection) — this is\n // the same allocation-free discriminator getChildNodes() uses. Reading\n // `el.attributes` directly would lazily allocate an empty Map for every\n // element being serialized, so the backing `_attributes` field is read instead.\n if (isPolyfill) {\n const el = element as any;\n const attrs = el._attributes as Map<string, string> | undefined;\n\n // id — may live on the property rather than in the Map\n if (el.id && !attrs?.has('id')) {\n result += serializeAttribute('id', el.id);\n }\n\n // class — kept on .className, mirrored to Map only when setAttribute is used\n if (el.className && !attrs?.has('class')) {\n result += serializeAttribute('class', el.className);\n }\n\n // style — lives on the backing _style object, not in the attributes Map.\n // Read the field directly (never `el.style`) so elements that never set a\n // style are not forced to lazily allocate an empty SSRStyle just to serialize.\n // cssText returns camelCase keys (\"backgroundColor: red\"), so convert them.\n const styleObj = el._style;\n if (!attrs?.has('style') && styleObj) {\n const rawCssText: string = styleObj.cssText || '';\n if (rawCssText) {\n const kebabStyle = rawCssText\n .split(';')\n .map((decl: string) => decl.trim())\n .filter(Boolean)\n .map((decl: string) => {\n const colonIdx = decl.indexOf(':');\n if (colonIdx === -1) return decl;\n const key = decl.slice(0, colonIdx).trim();\n const val = decl.slice(colonIdx + 1).trim();\n // Skip declarations with empty values (e.g. reactive styles that resolved to undefined)\n if (!val) return '';\n return `${camelToKebab(key)}: ${val};`;\n })\n .filter(Boolean)\n .join(' ');\n if (kebabStyle) {\n result += ` style=\"${escapeHtml(kebabStyle)}\"`;\n }\n }\n }\n\n // All remaining attributes from the Map\n // Convert camelCase ARIA/HTML attribute names (e.g. ariaLabel → aria-label) that the\n // polyfill stores as-is because NucloElement lacks the browser property mappings.\n // SVG attributes that are natively camelCase (e.g. viewBox, preserveAspectRatio) must\n // NOT be converted — they are stored via setAttribute() as-is.\n if (attrs) {\n for (const [name, value] of attrs) {\n const htmlName = SVG_PRESERVE_CASE_ATTRS.has(name) ? name : camelToKebab(name);\n result += serializeAttribute(htmlName, value);\n }\n }\n return result;\n }\n\n // Handle browser elements with NamedNodeMap attributes\n if (element.attributes && element.attributes.length) {\n for (let i = 0; i < element.attributes.length; i++) {\n const attr = element.attributes[i];\n if (attr && attr.name) {\n result += serializeAttribute(attr.name, attr.value);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Tag-category lookup, keyed by lowercase tag name. Every element in a tree\n * hits this once, so void + raw-text elements are folded into a single\n * dictionary lookup instead of two separate `Set.has()` probes (one of which\n * would always miss for the other category).\n */\nconst TAG_VOID = 1;\nconst TAG_RAW_TEXT = 2;\nconst TAG_CATEGORY: Record<string, 1 | 2> = Object.assign(Object.create(null), {\n // Self-closing HTML tags that don't have closing tags\n area: TAG_VOID, base: TAG_VOID, br: TAG_VOID, col: TAG_VOID, embed: TAG_VOID,\n hr: TAG_VOID, img: TAG_VOID, input: TAG_VOID, link: TAG_VOID, meta: TAG_VOID,\n param: TAG_VOID, source: TAG_VOID, track: TAG_VOID, wbr: TAG_VOID,\n // Raw-text elements — browsers never decode entities inside them, so their\n // text content must be emitted verbatim (escaping would corrupt inline\n // JS/CSS, e.g. `a < b` becoming `a &lt; b` inside a script). A closing-tag\n // sequence in the content would terminate the element early, so it is\n // neutralized (see escapeRawText).\n script: TAG_RAW_TEXT, style: TAG_RAW_TEXT,\n});\n\nfunction escapeRawText(tagName: string, text: string): string {\n // \"</script\" (any case) inside a script would close it — break the sequence\n // the same way JSON serializers do (\"<\\/script\").\n return text.replace(new RegExp('</(' + tagName + ')', 'gi'), '<\\\\/$1');\n}\n\n/**\n * Get child nodes from a node (handles both browser and polyfill elements).\n *\n * NucloElement stores ALL children (elements, text, comments) in a plain Array\n * called `children` — it is the authoritative list. DocumentFragments in the\n * polyfill also have a `children` array, but it only holds Element children;\n * their full set of nodes lives in `childNodes`. We therefore only prefer\n * `children` when the node is an actual element (has `tagName`).\n */\nfunction getChildNodes(node: Node): ArrayLike<Node> {\n // NucloElement: tagName exists and children is a plain Array containing every node type\n if ('tagName' in node && 'children' in node) {\n const children = (node as any).children;\n if (Array.isArray(children)) {\n return children as ArrayLike<Node>;\n }\n }\n // DocumentFragments and browser elements: use childNodes\n if ('childNodes' in node) {\n const childNodes = (node as any).childNodes;\n if (childNodes && (Array.isArray(childNodes) || childNodes.length !== undefined)) {\n return childNodes;\n }\n }\n return [] as ArrayLike<Node>;\n}\n\n/**\n * Serializes a DOM node to HTML string\n */\nfunction serializeNode(node: Node): string {\n // Text node — only & < > need escaping; quotes are safe in text content\n if (node.nodeType === 3) { // Node.TEXT_NODE\n return escapeText(node.textContent || '');\n }\n\n // Comment node\n if (node.nodeType === 8) { // Node.COMMENT_NODE\n return `<!--${node.textContent || ''}-->`;\n }\n\n // Element node\n if (node.nodeType === 1) { // Node.ELEMENT_NODE\n const element = node as Element;\n const rawTagName = element.tagName;\n // Duck-typed polyfill discriminator (also used by serializeAttributes /\n // getChildNodes): a plain Array `children` field never occurs on a real\n // DOM element (HTMLCollection), only on NucloElement — and on hand-rolled\n // polyfill-shaped test doubles, which is why this alone isn't enough to\n // skip re-lowercasing tagName below.\n const isPolyfillShape = Array.isArray((element as any).children);\n // Only a *real* NucloElement is guaranteed to have pre-lowercased tagName\n // (done once in its constructor) — re-lowercasing it here on every\n // element would be pure waste, since this is the hottest function in\n // renderToString. Anything else (browser Element, or a polyfill-shaped\n // object that didn't go through `new NucloElement()`) still needs it.\n const tagName = element instanceof NucloElement ? rawTagName : rawTagName.toLowerCase();\n const attributes = serializeAttributes(element, isPolyfillShape);\n const category = TAG_CATEGORY[tagName];\n\n // Self-closing tags\n if (category === TAG_VOID) {\n return `<${tagName}${attributes} />`;\n }\n\n const childNodes = isPolyfillShape ? ((element as any).children as ArrayLike<Node>) : getChildNodes(element);\n\n // Raw-text elements: emit text verbatim (no entity escaping, no Nuclo\n // text markers — `<!--` would act as a line comment inside a script).\n if (category === TAG_RAW_TEXT) {\n let rawContent = '';\n const rawChildren = childNodes;\n if (rawChildren && rawChildren.length > 0) {\n for (let i = 0; i < rawChildren.length; i++) {\n const child = rawChildren[i];\n if (child && child.nodeType === 3) {\n rawContent += child.textContent || '';\n }\n }\n } else {\n const tc = (node as { textContent?: unknown }).textContent;\n if (typeof tc === 'string') rawContent = tc;\n }\n return `<${tagName}${attributes}>${escapeRawText(tagName, rawContent)}</${tagName}>`;\n }\n\n // Regular elements with children\n let childrenHtml = '';\n if (childNodes && childNodes.length > 0) {\n for (let i = 0; i < childNodes.length; i++) {\n const child = childNodes[i];\n if (child) {\n childrenHtml += serializeNode(child);\n }\n }\n } else {\n // Fallback: textContent set directly on the element (e.g. el.textContent = \"...\")\n const tc = (node as any).textContent;\n if (typeof tc === 'string' && tc) {\n childrenHtml = escapeText(tc);\n }\n }\n\n return `<${tagName}${attributes}>${childrenHtml}</${tagName}>`;\n }\n\n // Document fragment\n if (node.nodeType === 11) { // Node.DOCUMENT_FRAGMENT_NODE\n let result = '';\n const childNodes = getChildNodes(node);\n if (childNodes && childNodes.length > 0) {\n for (let i = 0; i < childNodes.length; i++) {\n const child = childNodes[i];\n if (child) {\n result += serializeNode(child);\n }\n }\n }\n return result;\n }\n\n return '';\n}\n\n/**\n * Renders a Nuclo component to an HTML string for server-side rendering\n *\n * @param input - A Nuclo component function, DOM element, or node\n * @returns HTML string representation of the component\n *\n * @example\n * ```ts\n * import { renderToString } from 'nuclo/ssr';\n * import { div } from 'nuclo';\n *\n * const html = renderToString(\n * div(\"Hello, World!\")\n * );\n * // Returns: '<div>Hello, World!</div>'\n * ```\n */\nexport function renderToString(input: RenderableInput): string {\n if (!input) return '';\n\n if (typeof input === 'function') {\n try {\n // Build the tree in serialization mode so text children keep their\n // <!-- text-N --> markers (needed for hydration) even when isBrowser is\n // true, e.g. SSR running under jsdom.\n const element = runSerializing(() => {\n const container = createElement('div');\n if (!container) throw new Error('Document is not available. Make sure polyfills are loaded.');\n return input(container as ExpandedElement<ElementTagName>, 0);\n });\n return element && typeof element === 'object' && 'nodeType' in element ? serializeNode(element as Node) : '';\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('Error rendering component to string:', error);\n return '';\n }\n }\n\n if ('nodeType' in input) {\n return serializeNode(input as Node);\n }\n\n return '';\n}\n\n/**\n * Renders multiple Nuclo components to HTML strings\n *\n * @param inputs - Array of Nuclo components\n * @returns Array of HTML strings\n */\nexport function renderManyToString(inputs: RenderableInput[]): string[] {\n return inputs.map(input => renderToString(input));\n}\n\n/**\n * Renders a Nuclo component and wraps it in a container element\n *\n * @param input - A Nuclo component\n * @param containerTag - The tag name for the container (default: 'div')\n * @param containerAttrs - Attributes for the container element\n * @returns HTML string with container wrapper\n */\nexport function renderToStringWithContainer(\n input: RenderableInput,\n containerTag: string = 'div',\n containerAttrs: Record<string, string> = {}\n): string {\n const content = renderToString(input);\n const attrs = Object.entries(containerAttrs)\n .map(([key, value]) => serializeAttribute(key, value))\n .join('');\n\n return `<${containerTag}${attrs}>${content}</${containerTag}>`;\n}\n","/**\n * Shared generated-CSS engine state.\n *\n * One stylesheet, one rule registry, shared by every `createCss` instance so\n * identical declarations dedupe globally and cascade order stays deterministic:\n * base rules first (insertion order), then one grouping rule per at-rule query\n * in registration order (theme `screens` order).\n *\n * Browser: rules are injected through CSSOM with O(1) appends — no rescans.\n * SSR: rules accumulate in the registry; `getCssText()` serializes them.\n *\n * The state below lives on `globalThis`, keyed by a `Symbol.for(...)` (the\n * global symbol registry, shared by every realm-local copy of this module).\n * `nuclo` publishes `.`, `./ssr`, and `./polyfill` as independently built\n * bundle files (see tsdown.config.ts) — a consumer that resolves them\n * through normal package resolution (any bundler/runtime that doesn't\n * alias every subpath to this same source file) loads two or three\n * separate copies of this module, each with its own module-scope\n * variables. Without a realm-wide singleton, `css()` (from `nuclo`) would\n * mint rules into one copy's registry while `getCssText()`/\n * `setSSRCollector()` (from `nuclo/ssr`) read an entirely different,\n * always-empty one — SSR output would render the right classes with no\n * matching CSS at all. Storing the registry on `globalThis` instead makes\n * every copy of this module share the same state regardless of how many\n * times it ends up bundled.\n *\n * The registry never shrinks on its own: atomCache/atomMeta/rawKeys/\n * baseRules/queryRules retain every rule for the life of the process —\n * content-addressed dedup needs a durable record of what each class means,\n * and the engine has no way to know whether a minted class still backs a\n * live DOM node (it's deliberately decoupled from element/list lifecycle),\n * so it can't safely evict. Only resetStyles() (a manual test helper)\n * clears it. This is fine for the intended use — a bounded design-token\n * vocabulary — but a caller piping truly per-instance dynamic values\n * through css({ raw: {...} }) (e.g. per-row data in a list) mints one\n * permanent class per unique value; prefer the `style` prop\n * (element/inline-style.ts) for values that vary per instance rather than\n * per design token. See test/style/registry-growth.test.ts.\n */\n\n// SSR collector — optional hook that receives every newly minted rule string\n// (wrapped in its at-rule, if any). Installed once at server startup.\ntype SSRCollector = (rule: string) => void;\n\nexport interface BlockMeta {\n\treadonly query: string | undefined;\n\treadonly suffix: string;\n\treadonly decls: ReadonlyArray<readonly [string, string]>;\n\t/** Author-supplied identity from `css(name, …)`; inherited by cx() merges. */\n\treadonly name: string | undefined;\n}\n\ninterface EngineState {\n\tssrCollector: SSRCollector | null;\n\n\t// Registry — the source of truth for all generated CSS.\n\t// atomCache: declaration-block key -> class name (dedup)\n\t// atomMeta: class name -> what the class means (its selector context and its\n\t// declarations). This is what lets cx() merge two same-context classes at the\n\t// declaration level instead of guessing: the engine can always recover the\n\t// exact content of any class it minted.\n\tatomCache: Map<string, string>;\n\tatomMeta: Map<string, BlockMeta>;\n\trawKeys: Set<string>;\n\tbaseRules: string[];\n\tqueryRules: Map<string, string[]>;\n\tstyleEpoch: number;\n\n\t// Memoized getCssText() output. SSR calls getCssText() once per request, but the\n\t// rule set is stable after warmup — so the serialized sheet is recomputed only\n\t// when a new rule is actually recorded. Invalidated in record() and resetStyles().\n\tcssTextCache: string | null;\n\n\t// Browser CSSOM state. Base rules occupy [0, baseRuleCount); grouping rules\n\t// (one per query, created in registration order) live after them. CSSRule\n\t// references stay live when indices shift, so insertion never rescans.\n\tsheet: CSSStyleSheet | null;\n\tsheetDocument: Document | null;\n\tbaseRuleCount: number;\n\tgroupRules: Map<string, CSSGroupingRule>;\n\n\t// Normalized rules already sitting in a freshly-adopted stylesheet that this\n\t// module didn't insert itself — e.g. server-rendered CSS being hydrated.\n\t// Rebuilt on every fresh bind in ensureSheet(); null when there is nothing\n\t// external to guard against.\n\texternalRules: Map<string, Set<string>> | null;\n\thasExternalGroups: boolean;\n}\n\nfunction createState(): EngineState {\n\treturn {\n\t\tssrCollector: null,\n\t\tatomCache: new Map(),\n\t\tatomMeta: new Map(),\n\t\trawKeys: new Set(),\n\t\tbaseRules: [],\n\t\tqueryRules: new Map(),\n\t\tstyleEpoch: 0,\n\t\tcssTextCache: null,\n\t\tsheet: null,\n\t\tsheetDocument: null,\n\t\tbaseRuleCount: 0,\n\t\tgroupRules: new Map(),\n\t\texternalRules: null,\n\t\thasExternalGroups: false,\n\t};\n}\n\nconst ENGINE_STATE_KEY = Symbol.for(\"nuclo.style.engine.v1\");\nconst globalScope = globalThis as unknown as Record<symbol, EngineState>;\n// Importing the runtime does not allocate the registry until styling is used.\nlet cachedState: EngineState | undefined;\nfunction getState(): EngineState {\n\treturn cachedState ??= globalScope[ENGINE_STATE_KEY] ?? (globalScope[ENGINE_STATE_KEY] = createState());\n}\n\nexport function setSSRCollector(fn: SSRCollector | null): void {\n\tconst state = getState();\n\tstate.ssrCollector = fn;\n}\n\n/** Pre-register at-rule queries so their cascade order follows theme order. */\nexport function registerQueries(queries: Iterable<string>): void {\n\tfor (const query of queries) {\n\t\tconst state = getState();\n\t\tif (!state.queryRules.has(query)) state.queryRules.set(query, []);\n\t}\n}\n\nfunction createGroup(s: CSSStyleSheet, query: string): CSSGroupingRule | null {\n\tconst state = getState();\n\ttry {\n\t\tconst idx = s.cssRules.length;\n\t\ts.insertRule(query + \"{}\", idx);\n\t\tconst group = s.cssRules[idx] as CSSGroupingRule;\n\t\tstate.groupRules.set(query, group);\n\t\tstate.groupRules.set(groupQueryOf(group), group);\n\t\treturn group;\n\t} catch {\n\t\treturn null; // unsupported at-rule in this environment\n\t}\n}\n\n// A group prelude is stable while its children grow. Reading cssText on each\n// insertion would serialize all previous children and make loading quadratic.\n// Weak keys allow detached stylesheets to be collected after reset/rebinding.\nconst groupQueries = new WeakMap<CSSRule, string>();\nfunction groupQueryOf(rule: CSSRule): string {\n\tconst cached = groupQueries.get(rule);\n\tif (cached !== undefined) return cached;\n\tconst text = rule.cssText;\n\tconst brace = text.indexOf(\"{\");\n\tconst query = (brace === -1 ? text : text.slice(0, brace)).trim();\n\tgroupQueries.set(rule, query);\n\treturn query;\n}\n\nfunction ruleIdentity(rule: CSSRule): string {\n\treturn rule instanceof CSSStyleRule ? rule.selectorText : groupQueryOf(rule);\n}\n\nfunction scopedRuleKey(query: string | undefined, identity: string): string {\n\tconst scope = query === undefined ? \"-\" : \"+\" + query.length + \":\" + query;\n\treturn scope + identity.length + \":\" + identity;\n}\n\nfunction rememberExternalRule(rule: CSSRule, query: string | undefined): void {\n\tconst state = getState();\n\tif (!state.externalRules) return;\n\tconst key = scopedRuleKey(query, ruleIdentity(rule));\n\tlet texts = state.externalRules.get(key);\n\tif (!texts) {\n\t\ttexts = new Set();\n\t\tstate.externalRules.set(key, texts);\n\t}\n\ttexts.add(rule.cssText);\n}\n\nfunction consumeExternalRule(rule: CSSRule, query: string | undefined): boolean {\n\tconst state = getState();\n\tif (!state.externalRules) return false;\n\tconst key = scopedRuleKey(query, ruleIdentity(rule));\n\tconst texts = state.externalRules.get(key);\n\tif (!texts?.delete(rule.cssText)) return false;\n\tif (texts.size === 0) state.externalRules.delete(key);\n\tif (state.externalRules.size === 0) state.externalRules = null;\n\treturn true;\n}\n\n/**\n * Index an already-populated stylesheet found on adopt (SSR output, most\n * commonly): every top-level conditional grouping rule (@media/@container/…)\n * is registered into groupRules (by its reconstructed at-rule text) so later\n * record() calls append into it instead of creating a sibling duplicate. The\n * other rules are indexed by scope, selector/prelude, and normalized cssText\n * so exact server/client matches can be skipped without hiding a changed\n * named or global rule that happens to reuse the same selector.\n */\nfunction indexExternalRules(rules: CSSRuleList): void {\n\tconst state = getState();\n\tfor (let i = 0; i < rules.length; i++) {\n\t\tconst rule = rules[i];\n\t\tif (rule instanceof CSSStyleRule) {\n\t\t\trememberExternalRule(rule, undefined);\n\t\t\tcontinue;\n\t\t}\n\t\tconst prelude = groupQueryOf(rule);\n\t\tif (\"cssRules\" in rule && !prelude.startsWith(\"@keyframes\")) {\n\t\t\tconst group = rule as CSSGroupingRule;\n\t\t\tstate.hasExternalGroups = true;\n\t\t\tstate.groupRules.set(prelude, group);\n\t\t\tfor (let j = 0; j < group.cssRules.length; j++) {\n\t\t\t\trememberExternalRule(group.cssRules[j], prelude);\n\t\t\t}\n\t\t} else {\n\t\t\t// @keyframes, @font-face, … — one-shot rules matched by prelude.\n\t\t\trememberExternalRule(rule, undefined);\n\t\t}\n\t}\n}\n\nfunction insertBase(s: CSSStyleSheet, rule: string): void {\n\tconst state = getState();\n\ttry {\n\t\ts.insertRule(rule, state.baseRuleCount);\n\t\tconst inserted = s.cssRules[state.baseRuleCount];\n\t\tif (consumeExternalRule(inserted, undefined)) {\n\t\t\ts.deleteRule(state.baseRuleCount);\n\t\t\treturn;\n\t\t}\n\t\tstate.baseRuleCount++;\n\t} catch {\n\t\t// Invalid value/selector: drop the declaration, like browsers do for bad CSS.\n\t}\n}\n\nfunction insertGrouped(group: CSSGroupingRule, rule: string): void {\n\tconst state = getState();\n\ttry {\n\t\tconst index = group.cssRules.length;\n\t\tgroup.insertRule(rule, index);\n\t\tconst inserted = group.cssRules[index];\n\t\tif (state.externalRules && consumeExternalRule(inserted, groupQueryOf(group))) group.deleteRule(index);\n\t} catch {\n\t\t// Invalid value/selector: drop the declaration, like browsers do for bad CSS.\n\t}\n}\n\nfunction getOrCreateGroup(s: CSSStyleSheet, query: string): CSSGroupingRule | null {\n\tconst state = getState();\n\tconst direct = state.groupRules.get(query);\n\tif (direct) return direct;\n\tif (!state.hasExternalGroups) return createGroup(s, query);\n\n\t// CSSOM may normalize whitespace in an at-rule prelude. Normalize the\n\t// authored query through a temporary empty group before deciding that an\n\t// adopted SSR group is missing.\n\ttry {\n\t\tconst index = s.cssRules.length;\n\t\ts.insertRule(query + \"{}\", index);\n\t\tconst normalized = groupQueryOf(s.cssRules[index]);\n\t\ts.deleteRule(index);\n\t\tconst existing = state.groupRules.get(normalized);\n\t\tif (existing) {\n\t\t\tstate.groupRules.set(query, existing);\n\t\t\treturn existing;\n\t\t}\n\t} catch {\n\t\treturn null;\n\t}\n\treturn createGroup(s, query);\n}\n\n/**\n * Returns the live stylesheet, (re)binding when the document changes — e.g.\n * fresh jsdom documents between tests. Rebinding replays the whole registry,\n * which replaces v1's per-call classExistsInDOM() DOM scans with a single\n * replay per document.\n */\nexport function ensureSheet(): CSSStyleSheet | null {\n\tconst state = getState();\n\tif (typeof document === \"undefined\") return null;\n\t// The nuclo SSR polyfill provides a document without getElementById — in\n\t// that context rules accumulate in the registry for getCssText() only.\n\tif (typeof document.getElementById !== \"function\") return null;\n\tif (\n\t\tstate.sheet &&\n\t\tstate.sheetDocument === document &&\n\t\tstate.sheet.ownerNode &&\n\t\t(state.sheet.ownerNode as Element).isConnected\n\t) {\n\t\treturn state.sheet;\n\t}\n\tconst existing = document.getElementById(\"nuclo-styles\");\n\tlet el: HTMLStyleElement;\n\tif (existing?.tagName === \"STYLE\") {\n\t\tel = existing as HTMLStyleElement;\n\t} else {\n\t\tel = document.createElement(\"style\");\n\t\tel.id = \"nuclo-styles\";\n\t\tif (existing) existing.replaceWith(el);\n\t\telse document.head.appendChild(el);\n\t}\n\tstate.sheet = el.sheet;\n\tstate.sheetDocument = document;\n\tstate.groupRules.clear();\n\tstate.baseRuleCount = 0;\n\tstate.externalRules = null;\n\tstate.hasExternalGroups = false;\n\tif (!state.sheet) return null;\n\tif (state.sheet.cssRules.length > 0) {\n\t\t// Leading top-level non-group rules (style rules, @keyframes — before\n\t\t// the first @media/@container group) are this element's existing\n\t\t// \"base\" region — count them so insertBase() keeps inserting new base\n\t\t// rules right after them, still ahead of every group.\n\t\tlet i = 0;\n\t\twhile (i < state.sheet.cssRules.length) {\n\t\t\tconst r = state.sheet.cssRules[i];\n\t\t\tif (!(r instanceof CSSStyleRule) && \"cssRules\" in r && !groupQueryOf(r).startsWith(\"@keyframes\")) break;\n\t\t\ti++;\n\t\t}\n\t\tstate.baseRuleCount = i;\n\t\tstate.externalRules = new Map();\n\t\tindexExternalRules(state.sheet.cssRules);\n\t}\n\tfor (const rule of state.baseRules) insertBase(state.sheet, rule);\n\tfor (const [query, rules] of state.queryRules) {\n\t\tconst group = getOrCreateGroup(state.sheet, query);\n\t\tif (group) for (const rule of rules) insertGrouped(group, rule);\n\t}\n\treturn state.sheet;\n}\n\nfunction record(rule: string, query: string | undefined): void {\n\tconst state = getState();\n\t// Bind/replay *before* this rule joins the registry, so a fresh bind's\n\t// replay only ever covers previously-known rules — never this one twice.\n\tconst s = ensureSheet();\n\n\tif (query === undefined) {\n\t\tstate.baseRules.push(rule);\n\t} else {\n\t\tlet bucket = state.queryRules.get(query);\n\t\tif (!bucket) {\n\t\t\tbucket = [];\n\t\t\tstate.queryRules.set(query, bucket);\n\t\t}\n\t\tbucket.push(rule);\n\t}\n\tstate.cssTextCache = null; // a new rule changes the serialized sheet\n\n\tif (s) {\n\t\tif (query === undefined) {\n\t\t\tinsertBase(s, rule);\n\t\t} else {\n\t\t\tconst group = getOrCreateGroup(s, query);\n\t\t\tif (group) insertGrouped(group, rule);\n\t\t}\n\t}\n\tstate.ssrCollector?.(query === undefined ? rule : query + \"{\" + rule + \"}\");\n}\n\n/**\n * Content-addressed ~42-bit hash (two interleaved FNV-1a style passes). Class\n * names must match between server and client for SSR hydration, so a counter\n * is not an option; 42 bits keeps collision odds low (~1e-5 at 10k\n * unique declaration blocks).\n */\nexport function hash(input: string): string {\n\tlet a = 0x811c9dc5;\n\tlet b = 0x7ee3623b;\n\tfor (let i = 0; i < input.length; i++) {\n\t\tconst c = input.charCodeAt(i);\n\t\ta = Math.imul(a ^ c, 0x01000193);\n\t\tb = Math.imul(b ^ c, 0x85ebca6b);\n\t}\n\treturn (a >>> 0).toString(36) + ((b >>> 9) % 1296).toString(36);\n}\n\nfunction contextKeyOf(query: string | undefined, suffix: string): string {\n\tconst queryPart = query === undefined ? \"-\" : \"+\" + query.length + \":\" + query;\n\treturn queryPart + suffix.length + \":\" + suffix;\n}\n\nfunction appendKeyPart(key: string, value: string): string {\n\treturn key + value.length + \":\" + value;\n}\n\nexport function expandAmpersands(input: string, replacement: string): string {\n\tlet expanded = \"\";\n\tlet quote = 0;\n\tfor (let i = 0; i < input.length; i++) {\n\t\tconst code = input.charCodeAt(i);\n\t\tif (code === 92 /* \\\\ */ && i + 1 < input.length) {\n\t\t\texpanded += input[i] + input[++i];\n\t\t\tcontinue;\n\t\t}\n\t\tif (quote !== 0) {\n\t\t\texpanded += input[i];\n\t\t\tif (code === quote) quote = 0;\n\t\t\tcontinue;\n\t\t}\n\t\tif (code === 34 /* \" */ || code === 39 /* ' */) {\n\t\t\tquote = code;\n\t\t\texpanded += input[i];\n\t\t} else {\n\t\t\texpanded += code === 38 /* & */ ? replacement : input[i];\n\t\t}\n\t}\n\treturn expanded;\n}\n\nfunction selectorFor(className: string, suffix: string): string {\n\tconst selector = \".\" + className;\n\treturn selector + expandAmpersands(suffix, selector);\n}\n\n/**\n * True for strings usable verbatim as an unescaped CSS class selector:\n * letters/digits/`-`/`_`, not starting with a digit or `-`+digit.\n * Char-code loop rather than a RegExp — this runs on the cold mint path but\n * stays allocation-free either way.\n */\nfunction isValidClassName(name: string): boolean {\n\tif (name.length === 0 || name === \"-\") return false;\n\tfor (let i = 0; i < name.length; i++) {\n\t\tconst c = name.charCodeAt(i);\n\t\tconst ok =\n\t\t\t(c >= 97 && c <= 122) || // a-z\n\t\t\t(c >= 65 && c <= 90) || // A-Z\n\t\t\tc === 45 || c === 95 || // - _\n\t\t\t(i > 0 && c >= 48 && c <= 57); // 0-9, never leading\n\t\tif (!ok) return false;\n\t}\n\t// \"-9foo\" is not a valid identifier start either.\n\tif (name.charCodeAt(0) === 45 && name.length > 1) {\n\t\tconst second = name.charCodeAt(1);\n\t\tif (second >= 48 && second <= 57) return false;\n\t}\n\treturn true;\n}\n\n/**\n * Mint (or reuse) the class for a declaration block in a selector context.\n *\n * Declarations keep their authored order — CSS resolves shorthand/longhand\n * and repeated-property conflicts by declaration order, so reordering (e.g.\n * alphabetical sorting) would silently change what `{ pt: 20, p: 16 }` means.\n * The cost is that the same declarations authored in a different order mint a\n * second, content-identical class — harmless, and rare in practice.\n *\n * `name` is the author's identity for the style (`css(\"app-root\", …)`). It\n * becomes part of the cache key, so two different names never share a class\n * even with identical declarations. With `exactName`, this block *is* the\n * named one and takes the name verbatim; otherwise the name is only a\n * readable prefix on a content-addressed prefix (`app-root-1a2b3c`), which is\n * how a named style's non-base contexts and its cx() merges stay identifiable\n * in devtools without ever colliding with the base class.\n */\nfunction mintBlock(\n\tquery: string | undefined,\n\tsuffix: string,\n\tdecls: ReadonlyArray<readonly [string, string]>,\n\tname?: string,\n\texactName = false,\n): string {\n\tconst state = getState();\n\tlet contextKey = contextKeyOf(query, suffix);\n\tfor (const [prop, value] of decls) {\n\t\tcontextKey = appendKeyPart(appendKeyPart(contextKey, prop), value);\n\t}\n\tif (name !== undefined && !isValidClassName(name)) {\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.warn(\n\t\t\t`[nuclo] css() name ${JSON.stringify(name)} is not a valid CSS class name ` +\n\t\t\t\t\"(letters, digits, - and _ only, not starting with a digit); falling back to a generated name.\",\n\t\t);\n\t\tname = undefined;\n\t}\n\tconst declKey = name === undefined ? \"a\" + contextKey : \"n\" + appendKeyPart(\"\", name) + contextKey;\n\tlet className = state.atomCache.get(declKey);\n\tif (className !== undefined) {\n\t\t// Touch the sheet so a swapped document (tests) gets the replayed rules.\n\t\tensureSheet();\n\t\treturn className;\n\t}\n\n\tif (name === undefined) {\n\t\tclassName = \"n\" + hash(declKey);\n\t} else {\n\t\tclassName = exactName ? name : name + \"-\" + hash(declKey);\n\t\tif (state.atomMeta.has(className)) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn(\n\t\t\t\t`[nuclo] css() name ${JSON.stringify(className)} is already used by a different style. ` +\n\t\t\t\t\t\"Both rules are emitted under the same class, so they will override each other — rename one.\",\n\t\t\t);\n\t\t}\n\t}\n\n\tlet body = \"\";\n\tfor (const [prop, value] of decls) body += (body ? \";\" : \"\") + prop + \":\" + value;\n\tstate.atomCache.set(declKey, className);\n\tstate.atomMeta.set(className, { query, suffix, decls, name });\n\trecord(selectorFor(className, suffix) + \"{\" + body + \"}\", query);\n\treturn className;\n}\n\n/**\n * One class per (query, selector-suffix) — every declaration that shares that\n * context compiles into a single rule under a single generated class name,\n * rather than one class per individual property. Pass `name` to give the\n * style a stable, readable identity (see mintBlock).\n */\nexport function atomBlock(\n\tquery: string | undefined,\n\tsuffix: string,\n\tdecls: ReadonlyArray<readonly [string, string]>,\n\tname?: string,\n\texactName = false,\n): string {\n\treturn mintBlock(query, suffix, decls, name, exactName);\n}\n\n/**\n * Merge two same-context generated classes into one: `second`'s declarations\n * override `first`'s per exact property (shorthand/longhand interplay is left\n * to CSS order), and the combined block mints its own content-addressed class\n * — so cx(base, override) keeps base's untouched properties instead of\n * dropping the whole base class. Deterministic: the same pair always yields\n * the same class name, on server and client alike. A named base passes its\n * name down as a prefix, so `cx(appRoot, active)` reads as `app-root-1a2b3c`.\n */\nexport function mergeBlocks(first: string, second: string): string {\n\tconst state = getState();\n\tconst a = state.atomMeta.get(first);\n\tconst b = state.atomMeta.get(second);\n\tif (!a || !b) return second; // unknown input — nothing to merge with\n\tconst concat = [...a.decls, ...b.decls];\n\t// Keep only the last occurrence of each exact property, at its position —\n\t// so a later `padding` still fully resets an earlier `padding-top`.\n\tconst lastIndex = new Map<string, number>();\n\tfor (let i = 0; i < concat.length; i++) lastIndex.set(concat[i][0], i);\n\tconst merged = concat.filter((decl, i) => lastIndex.get(decl[0]) === i);\n\treturn mintBlock(a.query, a.suffix, merged, a.name ?? b.name);\n}\n\n/** Conflict key (query|suffix) for a generated class — lets cx() group classes by selector context. */\nexport function conflictKeyOf(className: string): string | undefined {\n\tconst state = getState();\n\tconst meta = state.atomMeta.get(className);\n\treturn meta === undefined ? undefined : contextKeyOf(meta.query, meta.suffix);\n}\n\n/** Current registry generation, used to invalidate per-instance WeakMap hits after resetStyles(). */\nexport function getStyleEpoch(): number {\n\treturn (cachedState ?? globalScope[ENGINE_STATE_KEY])?.styleEpoch ?? 0;\n}\n\n/** Register a non-atomic rule (keyframes, global styles) once per dedupe key. */\nexport function addRawRule(dedupeKey: string, rule: string): void {\n\tconst state = getState();\n\tif (state.rawKeys.has(dedupeKey)) {\n\t\tensureSheet();\n\t\treturn;\n\t}\n\tstate.rawKeys.add(dedupeKey);\n\trecord(rule, undefined);\n}\n\n/** All generated CSS — base rules first, then at-rule groups in registration order. */\nexport function getCssText(): string {\n\tconst state = getState();\n\tif (state.cssTextCache !== null) return state.cssTextCache;\n\tlet out = state.baseRules.join(\"\");\n\tfor (const [query, rules] of state.queryRules) {\n\t\tif (rules.length > 0) out += query + \"{\" + rules.join(\"\") + \"}\";\n\t}\n\tstate.cssTextCache = out;\n\treturn out;\n}\n\n/** Clear all engine state (test helper). Removes the injected style element. */\nexport function resetStyles(): void {\n\tconst state = getState();\n\tstate.atomCache.clear();\n\tstate.atomMeta.clear();\n\tstate.rawKeys.clear();\n\tstate.baseRules.length = 0;\n\tstate.queryRules.clear();\n\tstate.groupRules.clear();\n\tstate.cssTextCache = null;\n\tstate.baseRuleCount = 0;\n\tstate.sheet = null;\n\tstate.sheetDocument = null;\n\tstate.externalRules = null;\n\tstate.hasExternalGroups = false;\n\tstate.styleEpoch++;\n\tif (typeof document !== \"undefined\") {\n\t\tdocument.getElementById(\"nuclo-styles\")?.remove();\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"nuclo.ssr.cjs","names":["NucloElement"],"sources":["../../src/shared/strings.ts","../../src/hydration.ts","../../src/ssr/render-to-string.ts","../../src/style/engine.ts"],"sourcesContent":["/**\n * camelCase → kebab-case for CSS property (and attribute) names. A leading\n * capital becomes a leading dash, as vendor prefixes need\n * (WebkitTransition → -webkit-transition). Char-code loop with a\n * no-uppercase fast path: SSR runs this per style declaration.\n */\nexport function camelToKebab(str: string): string {\n let firstUpper = 0;\n for (; firstUpper < str.length; firstUpper++) {\n const code = str.charCodeAt(firstUpper);\n if (code >= 65 && code <= 90) break;\n }\n if (firstUpper === str.length) return str;\n\n let result = str.slice(0, firstUpper);\n for (let i = firstUpper; i < str.length; i++) {\n const code = str.charCodeAt(i);\n // A-Z is 65-90, a-z is 97-122 (difference of 32)\n result += code >= 65 && code <= 90 ? '-' + String.fromCharCode(code + 32) : str[i];\n }\n return result;\n}\n\nconst ATTR_ESCAPE_RE = /[&<>\"']/;\nconst TEXT_ESCAPE_RE = /[&<>]/;\n\n/**\n * Escapes HTML special characters in attribute values (includes \" and ')\n */\nexport function escapeHtml(text: string): string {\n // Fast path: most strings contain no special characters at all.\n const first = ATTR_ESCAPE_RE.exec(text);\n if (!first) return text;\n\n let result = '';\n let last = 0;\n for (let i = first.index; i < text.length; i++) {\n let escaped: string;\n switch (text.charCodeAt(i)) {\n case 38: escaped = '&amp;'; break; // &\n case 60: escaped = '&lt;'; break; // <\n case 62: escaped = '&gt;'; break; // >\n case 34: escaped = '&quot;'; break; // \"\n case 39: escaped = '&#039;'; break; // '\n default: continue;\n }\n result += text.slice(last, i) + escaped;\n last = i + 1;\n }\n return result + text.slice(last);\n}\n\n/**\n * Escapes HTML special characters in text node content.\n * Only &, < and > need escaping — quotes are safe inside text nodes.\n */\nexport function escapeText(text: string): string {\n const first = TEXT_ESCAPE_RE.exec(text);\n if (!first) return text;\n\n let result = '';\n let last = 0;\n for (let i = first.index; i < text.length; i++) {\n let escaped: string;\n switch (text.charCodeAt(i)) {\n case 38: escaped = '&amp;'; break; // &\n case 60: escaped = '&lt;'; break; // <\n case 62: escaped = '&gt;'; break; // >\n default: continue;\n }\n result += text.slice(last, i) + escaped;\n last = i + 1;\n }\n return result + text.slice(last);\n}\n","/**\n * Hydration context — tracks global hydration state and per-parent cursor positions.\n *\n * During hydration the component tree is built against an existing DOM tree\n * (produced by SSR). Instead of creating new nodes, factories claim existing\n * children from their parent element by advancing a cursor.\n *\n * The cursor is a *node pointer* (the next unclaimed child), not an index.\n * Indexed childNodes access is O(n) after any tree/attribute mutation in\n * jsdom (live NodeList re-materialization) which made hydration O(n²);\n * firstChild/nextSibling pointers are O(1) in every DOM implementation.\n */\n\nlet _hydrating = false;\n// True while renderToString() is building a tree destined for serialization.\nlet _serializing = false;\n// Missing entry = cursor at parent.firstChild; null = past the last child.\nlet _cursors = new WeakMap<Node, Node | null>();\n\nexport function isHydrating(): boolean {\n return _hydrating;\n}\n\n/**\n * True while a tree is being built for SSR serialization (inside\n * renderToString). Text children must keep their `<!-- text-N -->` markers in\n * this mode so the emitted HTML stays hydratable — even when `isBrowser` is\n * true (SSR running under jsdom, or an isomorphic worker that provides a DOM).\n * A pure client render leaves this false and skips the markers.\n */\nexport function isSerializing(): boolean {\n return _serializing;\n}\n\n/**\n * Runs `fn` with serialization mode enabled, restoring the previous state\n * afterwards (so nested/re-entrant renderToString calls behave correctly).\n */\nexport function runSerializing<T>(fn: () => T): T {\n const previous = _serializing;\n _serializing = true;\n try {\n return fn();\n } finally {\n _serializing = previous;\n }\n}\n\nexport function startHydration(): void {\n _hydrating = true;\n // Each hydration pass starts with a clean cursor slate. Stale cursors from\n // a previous pass would desynchronize claims when a container's content is\n // replaced and re-hydrated (HMR, islands re-mounting).\n _cursors = new WeakMap<Node, Node | null>();\n}\n\nexport function endHydration(): void {\n _hydrating = false;\n}\n\n/**\n * Runs a callback with hydration temporarily disabled, restoring the previous\n * state afterwards. Used when a server/client mismatch forces a subtree to be\n * rendered fresh in the middle of a hydration pass — fresh rendering must not\n * claim nodes from the surrounding SSR DOM.\n */\nexport function runWithoutHydration<T>(fn: () => T): T {\n const wasHydrating = _hydrating;\n _hydrating = false;\n try {\n return fn();\n } finally {\n _hydrating = wasHydrating;\n }\n}\n\n/**\n * Returns the next unclaimed child of a parent node (or null at the end)\n * without advancing the cursor.\n */\nexport function peekChild(parent: Node): Node | null {\n const entry = _cursors.get(parent);\n return entry === undefined ? parent.firstChild : entry;\n}\n\n/**\n * Sets the cursor to a specific child node (or null for \"past the end\").\n */\nexport function setCursor(parent: Node, node: Node | null): void {\n _cursors.set(parent, node);\n}\n\nfunction isWhitespaceText(node: Node): boolean {\n return node.nodeType === 3 && !/\\S/.test(node.textContent || '');\n}\n\n/**\n * Advances the cursor past whitespace-only text nodes.\n *\n * Nuclo's own SSR output never produces bare whitespace text nodes (text\n * children are always preceded by a `<!-- text-N -->` marker), so unmarked\n * whitespace comes from the surrounding template or an HTML\n * formatter/minifier. Skipping (without removing) keeps the cursor aligned\n * while leaving the document's visual whitespace untouched.\n */\nexport function skipWhitespaceText(parent: Node): void {\n let child = peekChild(parent);\n let advanced = false;\n while (child && isWhitespaceText(child)) {\n child = child.nextSibling;\n advanced = true;\n }\n if (advanced) {\n setCursor(parent, child);\n }\n}\n\n/**\n * Claims the next child node from parent at the current cursor position.\n * Advances the cursor by one.\n */\nexport function claimChild(parent: Node): Node | null {\n const child = peekChild(parent);\n if (child) {\n setCursor(parent, child.nextSibling);\n }\n return child;\n}\n\n/**\n * Claims a server-rendered `<!--{prefix}-start-…-->` … `<!--{prefix}-end-->`\n * block (list()/when()) at the cursor, leaving the cursor just after the start\n * marker. Returns null, claiming nothing, when the next child isn't a start\n * marker. Pairs are depth-counted because directly nested blocks share a\n * host. A missing end marker (corrupt/truncated SSR output) is recreated right\n * after the start marker and reported as `recreated`.\n */\nexport function claimMarkerPair(\n parent: Node,\n prefix: \"list\" | \"when\",\n): { start: Comment; end: Comment; recreated: boolean } | null {\n skipWhitespaceText(parent);\n const start = peekChild(parent);\n const startPrefix = prefix + \"-start-\";\n if (!start || start.nodeType !== 8 || !start.textContent?.startsWith(startPrefix)) return null;\n claimChild(parent);\n const endText = prefix + \"-end\";\n let depth = 0;\n for (let node = start.nextSibling; node; node = node.nextSibling) {\n if (node.nodeType !== 8) continue;\n const text = node.textContent;\n if (text === endText) {\n if (depth === 0) return { start: start as Comment, end: node as Comment, recreated: false };\n depth--;\n } else if (text?.startsWith(startPrefix)) {\n depth++;\n }\n }\n const end = document.createComment(endText);\n parent.insertBefore(end, start.nextSibling);\n return { start: start as Comment, end, recreated: true };\n}\n\n/**\n * Attempts to claim an existing element from the parent during hydration.\n * Returns the claimed element if the next child matches the expected tag, or null.\n */\nexport function claimElement(parent: Node, tagName: string): Element | null {\n if (!_hydrating) return null;\n skipWhitespaceText(parent);\n const candidate = peekChild(parent);\n if (candidate && candidate.nodeType === 1 && (candidate as Element).tagName.toLowerCase() === tagName) {\n return claimChild(parent) as Element;\n }\n return null;\n}\n\n/**\n * Removes unclaimed SSR children from a hydrated element.\n * Must be called after modifiers have been applied to a claimed element.\n * Removes nodes from the cursor through `lastOriginalChild` (the element's\n * last child before modifiers ran) — nodes appended by modifiers come after\n * that boundary and are preserved.\n */\nexport function cleanupUnclaimedChildren(node: Node, lastOriginalChild: Node | null): void {\n if (!lastOriginalChild) return;\n let current = peekChild(node);\n while (current) {\n const next = current === lastOriginalChild ? null : current.nextSibling;\n node.removeChild(current);\n current = next;\n }\n setCursor(node, null);\n}\n","/**\n * Server-Side Rendering (SSR) utilities for Nuclo\n * Renders Nuclo components to HTML strings in Node.js environment\n */\n\nimport { escapeHtml, escapeText, camelToKebab } from '../shared/strings';\nimport { runSerializing } from '../hydration';\nimport { NucloElement } from '../polyfill/Element';\n\ntype RenderableInput =\n | NodeModFn<ElementTagName>\n | Element\n | Node\n | null\n | undefined;\n\n/**\n * SVG attributes that are natively camelCase and must NOT be converted to kebab-case.\n * Most SVG attributes are already kebab-case (stroke-width, fill-rule, etc.), but a\n * handful are defined as camelCase in the SVG spec and must be preserved.\n */\nconst SVG_PRESERVE_CASE_ATTRS = new Set([\n 'viewBox', 'preserveAspectRatio', 'markerWidth', 'markerHeight',\n 'gradientTransform', 'patternTransform', 'clipPathUnits', 'gradientUnits',\n 'patternUnits', 'pathLength', 'refX', 'refY', 'stdDeviation',\n 'baseFrequency', 'numOctaves', 'kernelMatrix', 'tableValues',\n 'targetX', 'targetY', 'specularExponent', 'specularConstant',\n 'diffuseConstant', 'surfaceScale', 'xChannelSelector', 'yChannelSelector',\n 'edgeMode', 'stitchTiles', 'spreadMethod', 'patternContentUnits',\n 'markerUnits', 'startOffset', 'textLength', 'lengthAdjust',\n]);\n\n/**\n * HTML boolean attributes — presence means true, absence means false.\n * When the stored value is the string \"true\" or \"false\" (from setAttribute),\n * we must re-apply boolean semantics instead of outputting the raw string.\n */\nconst HTML_BOOLEAN_ATTRIBUTES = new Set([\n 'allowfullscreen', 'async', 'autofocus', 'autoplay', 'checked', 'controls',\n 'default', 'defer', 'disabled', 'formnovalidate', 'hidden', 'ismap', 'loop',\n 'multiple', 'muted', 'nomodule', 'novalidate', 'open', 'readonly', 'required',\n 'reversed', 'selected',\n]);\n\n/**\n * Serializes a DOM attribute value\n */\nfunction serializeAttribute(name: string, value: unknown): string {\n if (value === null || value === undefined || value === false) {\n return '';\n }\n\n if (value === true) {\n return ` ${name}`;\n }\n\n // Boolean attributes stored as strings via setAttribute() need special handling\n if (HTML_BOOLEAN_ATTRIBUTES.has(name)) {\n if (value === 'false') return '';\n if (value === 'true' || value === '' || value === name) return ` ${name}`;\n }\n\n // A style object (e.g. renderToStringWithContainer's containerAttrs from\n // untyped JS): serialize its declarations, skipping nullish/empty values.\n if (name === 'style' && typeof value === 'object') {\n let styleStr = '';\n for (const key in value as Record<string, unknown>) {\n const val = (value as Record<string, unknown>)[key];\n if (val == null || val === '') continue;\n styleStr += (styleStr ? ' ' : '') + camelToKebab(key) + ': ' + String(val) + ';';\n }\n return styleStr ? ` style=\"${escapeHtml(styleStr)}\"` : '';\n }\n\n return ` ${name}=\"${escapeHtml(String(value))}\"`;\n}\n\n/**\n * Serializes DOM element attributes to HTML string\n *\n * `isPolyfill` is passed in by the caller (serializeNode already computed it\n * to decide whether tagName needs lowercasing) so this doesn't repeat the\n * same `Array.isArray` discriminator check per element.\n */\nfunction serializeAttributes(element: Element, isPolyfill: boolean): string {\n let result = '';\n\n // Handle polyfill elements. NucloElement keeps every child in a plain Array\n // (`children`), which a real DOM element never does (HTMLCollection) — this is\n // the same allocation-free discriminator serializeNode() uses. Reading\n // `el.attributes` directly would lazily allocate an empty Map for every\n // element being serialized, so the backing `_attributes` field is read instead.\n if (isPolyfill) {\n const el = element as any;\n const attrs = el._attributes as Map<string, string> | undefined;\n\n // id — may live on the property rather than in the Map\n if (el.id && !attrs?.has('id')) {\n result += serializeAttribute('id', el.id);\n }\n\n // class — kept on .className, mirrored to Map only when setAttribute is used\n if (el.className && !attrs?.has('class')) {\n result += serializeAttribute('class', el.className);\n }\n\n // style — lives on the backing _style object (its own properties are the\n // declarations), not in the attributes Map. Read the field directly (never\n // `el.style`) so elements that never set a style are not forced to lazily\n // allocate an empty SSRStyle just to serialize. Empty values (e.g. reactive\n // styles that resolved to undefined) are skipped.\n const styleObj = el._style as Record<string, unknown> | undefined;\n if (styleObj && !attrs?.has('style')) {\n let css = '';\n for (const key in styleObj) {\n const val = styleObj[key];\n if (val == null || val === '') continue;\n css += (css ? ' ' : '') + camelToKebab(key) + ': ' + String(val) + ';';\n }\n if (css) result += ` style=\"${escapeHtml(css)}\"`;\n }\n\n // All remaining attributes from the Map\n // Convert camelCase ARIA/HTML attribute names (e.g. ariaLabel → aria-label) that the\n // polyfill stores as-is because NucloElement lacks the browser property mappings.\n // SVG attributes that are natively camelCase (e.g. viewBox, preserveAspectRatio) must\n // NOT be converted — they are stored via setAttribute() as-is.\n if (attrs) {\n for (const [name, value] of attrs) {\n const htmlName = SVG_PRESERVE_CASE_ATTRS.has(name) ? name : camelToKebab(name);\n result += serializeAttribute(htmlName, value);\n }\n }\n return result;\n }\n\n // Handle browser elements with NamedNodeMap attributes\n if (element.attributes && element.attributes.length) {\n for (let i = 0; i < element.attributes.length; i++) {\n const attr = element.attributes[i];\n if (attr && attr.name) {\n result += serializeAttribute(attr.name, attr.value);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Tag-category lookup, keyed by lowercase tag name. Every element in a tree\n * hits this once, so void + raw-text elements are folded into a single\n * dictionary lookup instead of two separate `Set.has()` probes (one of which\n * would always miss for the other category).\n */\nconst TAG_VOID = 1;\nconst TAG_RAW_TEXT = 2;\nconst TAG_CATEGORY: Record<string, 1 | 2> = Object.assign(Object.create(null), {\n // Self-closing HTML tags that don't have closing tags\n area: TAG_VOID, base: TAG_VOID, br: TAG_VOID, col: TAG_VOID, embed: TAG_VOID,\n hr: TAG_VOID, img: TAG_VOID, input: TAG_VOID, link: TAG_VOID, meta: TAG_VOID,\n param: TAG_VOID, source: TAG_VOID, track: TAG_VOID, wbr: TAG_VOID,\n // Raw-text elements — browsers never decode entities inside them, so their\n // text content must be emitted verbatim (escaping would corrupt inline\n // JS/CSS, e.g. `a < b` becoming `a &lt; b` inside a script). A closing-tag\n // sequence in the content would terminate the element early, so it is\n // neutralized (see escapeRawText).\n script: TAG_RAW_TEXT, style: TAG_RAW_TEXT,\n});\n\nfunction escapeRawText(tagName: string, text: string): string {\n // \"</script\" (any case) inside a script would close it — break the sequence\n // the same way JSON serializers do (\"<\\/script\").\n return text.replace(new RegExp('</(' + tagName + ')', 'gi'), '<\\\\/$1');\n}\n\n/**\n * Serializes a DOM node to HTML string\n */\nfunction serializeNode(node: Node): string {\n // Text node — only & < > need escaping; quotes are safe in text content\n if (node.nodeType === 3) { // Node.TEXT_NODE\n return escapeText(node.textContent || '');\n }\n\n // Comment node\n if (node.nodeType === 8) { // Node.COMMENT_NODE\n return `<!--${node.textContent || ''}-->`;\n }\n\n // Element node\n if (node.nodeType === 1) { // Node.ELEMENT_NODE\n const element = node as Element;\n const rawTagName = element.tagName;\n // Duck-typed polyfill discriminator (also used by serializeAttributes): a\n // plain Array `children` field never occurs on a real\n // DOM element (HTMLCollection), only on NucloElement — and on hand-rolled\n // polyfill-shaped test doubles, which is why this alone isn't enough to\n // skip re-lowercasing tagName below.\n const isPolyfillShape = Array.isArray((element as any).children);\n // Only a *real* NucloElement is guaranteed to have pre-lowercased tagName\n // (done once in its constructor) — re-lowercasing it here on every\n // element would be pure waste, since this is the hottest function in\n // renderToString. Anything else (browser Element, or a polyfill-shaped\n // object that didn't go through `new NucloElement()`) still needs it.\n const tagName = element instanceof NucloElement ? rawTagName : rawTagName.toLowerCase();\n const attributes = serializeAttributes(element, isPolyfillShape);\n const category = TAG_CATEGORY[tagName];\n\n // Self-closing tags\n if (category === TAG_VOID) {\n return `<${tagName}${attributes} />`;\n }\n\n const childNodes: ArrayLike<Node> = isPolyfillShape ? (element as any).children : element.childNodes;\n\n // Raw-text elements: emit text verbatim (no entity escaping, no Nuclo\n // text markers — `<!--` would act as a line comment inside a script).\n if (category === TAG_RAW_TEXT) {\n let rawContent = '';\n const rawChildren = childNodes;\n if (rawChildren && rawChildren.length > 0) {\n for (let i = 0; i < rawChildren.length; i++) {\n const child = rawChildren[i];\n if (child && child.nodeType === 3) {\n rawContent += child.textContent || '';\n }\n }\n } else {\n const tc = (node as { textContent?: unknown }).textContent;\n if (typeof tc === 'string') rawContent = tc;\n }\n return `<${tagName}${attributes}>${escapeRawText(tagName, rawContent)}</${tagName}>`;\n }\n\n // Regular elements with children\n let childrenHtml = '';\n if (childNodes && childNodes.length > 0) {\n for (let i = 0; i < childNodes.length; i++) {\n const child = childNodes[i];\n if (child) {\n childrenHtml += serializeNode(child);\n }\n }\n } else {\n // Fallback: textContent set directly on the element (e.g. el.textContent = \"...\")\n const tc = (node as any).textContent;\n if (typeof tc === 'string' && tc) {\n childrenHtml = escapeText(tc);\n }\n }\n\n return `<${tagName}${attributes}>${childrenHtml}</${tagName}>`;\n }\n\n // Document fragment\n if (node.nodeType === 11) { // Node.DOCUMENT_FRAGMENT_NODE\n let result = '';\n const childNodes: ArrayLike<Node> = (node as any).childNodes ?? [];\n if (childNodes.length > 0) {\n for (let i = 0; i < childNodes.length; i++) {\n const child = childNodes[i];\n if (child) {\n result += serializeNode(child);\n }\n }\n }\n return result;\n }\n\n return '';\n}\n\n/**\n * Renders a Nuclo component to an HTML string for server-side rendering\n *\n * @param input - A Nuclo component function, DOM element, or node\n * @returns HTML string representation of the component\n *\n * @example\n * ```ts\n * import { renderToString } from 'nuclo/ssr';\n * import { div } from 'nuclo';\n *\n * const html = renderToString(\n * div(\"Hello, World!\")\n * );\n * // Returns: '<div>Hello, World!</div>'\n * ```\n */\nexport function renderToString(input: RenderableInput): string {\n if (!input) return '';\n\n if (typeof input === 'function') {\n try {\n // Build the tree in serialization mode so text children keep their\n // <!-- text-N --> markers (needed for hydration) even when isBrowser is\n // true, e.g. SSR running under jsdom.\n const element = runSerializing(() => {\n if (typeof document === 'undefined') throw new Error('Document is not available. Make sure polyfills are loaded.');\n return input(document.createElement('div') as unknown as ExpandedElement<ElementTagName>, 0);\n });\n return element && typeof element === 'object' && 'nodeType' in element ? serializeNode(element as Node) : '';\n } catch (error) {\n console.error('Error rendering component to string:', error);\n return '';\n }\n }\n\n if ('nodeType' in input) {\n return serializeNode(input as Node);\n }\n\n return '';\n}\n\n/**\n * Renders multiple Nuclo components to HTML strings\n *\n * @param inputs - Array of Nuclo components\n * @returns Array of HTML strings\n */\nexport function renderManyToString(inputs: RenderableInput[]): string[] {\n return inputs.map(input => renderToString(input));\n}\n\n/**\n * Renders a Nuclo component and wraps it in a container element\n *\n * @param input - A Nuclo component\n * @param containerTag - The tag name for the container (default: 'div')\n * @param containerAttrs - Attributes for the container element\n * @returns HTML string with container wrapper\n */\nexport function renderToStringWithContainer(\n input: RenderableInput,\n containerTag: string = 'div',\n containerAttrs: Record<string, string> = {}\n): string {\n const content = renderToString(input);\n const attrs = Object.entries(containerAttrs)\n .map(([key, value]) => serializeAttribute(key, value))\n .join('');\n\n return `<${containerTag}${attrs}>${content}</${containerTag}>`;\n}\n","/**\n * Shared generated-CSS engine state.\n *\n * One stylesheet, one rule registry, shared by every `createCss` instance so\n * identical declarations dedupe globally and cascade order stays deterministic:\n * base rules first (insertion order), then one grouping rule per at-rule query\n * in registration order (theme `screens` order).\n *\n * Browser: rules are injected through CSSOM with O(1) appends — no rescans.\n * SSR: rules accumulate in the registry; `getCssText()` serializes them.\n *\n * The state below lives on `globalThis`, keyed by a `Symbol.for(...)` (the\n * global symbol registry, shared by every realm-local copy of this module).\n * `nuclo` publishes `.`, `./ssr`, and `./polyfill` as independently built\n * bundle files (see tsdown.config.ts) — a consumer that resolves them\n * through normal package resolution (any bundler/runtime that doesn't\n * alias every subpath to this same source file) loads two or three\n * separate copies of this module, each with its own module-scope\n * variables. Without a realm-wide singleton, `css()` (from `nuclo`) would\n * mint rules into one copy's registry while `getCssText()` (from\n * `nuclo/ssr`) reads an entirely different, always-empty one — SSR output\n * would render the right classes with no matching CSS at all. Storing the registry on `globalThis` instead makes\n * every copy of this module share the same state regardless of how many\n * times it ends up bundled.\n *\n * The registry never shrinks on its own: atomCache/atomMeta/rawKeys/\n * baseRules/queryRules retain every rule for the life of the process —\n * content-addressed dedup needs a durable record of what each class means,\n * and the engine has no way to know whether a minted class still backs a\n * live DOM node (it's deliberately decoupled from element/list lifecycle),\n * so it can't safely evict. Only resetStyles() (a manual test helper)\n * clears it. This is fine for the intended use — a bounded design-token\n * vocabulary — but a caller piping truly per-instance dynamic values\n * through css({ raw: {...} }) (e.g. per-row data in a list) mints one\n * permanent class per unique value; prefer the `style` prop\n * (element/inline-style.ts) for values that vary per instance rather than\n * per design token. See test/style/registry-growth.test.ts.\n */\n\nexport interface BlockMeta {\n\treadonly query: string | undefined;\n\treadonly suffix: string;\n\treadonly decls: ReadonlyArray<readonly [string, string]>;\n\t/** Author-supplied identity from `css(name, …)`; inherited by cx() merges. */\n\treadonly name: string | undefined;\n}\n\ninterface EngineState {\n\t// Registry — the source of truth for all generated CSS.\n\t// atomCache: declaration-block key -> class name (dedup)\n\t// atomMeta: class name -> what the class means (its selector context and its\n\t// declarations). This is what lets cx() merge two same-context classes at the\n\t// declaration level instead of guessing: the engine can always recover the\n\t// exact content of any class it minted.\n\tatomCache: Map<string, string>;\n\tatomMeta: Map<string, BlockMeta>;\n\trawKeys: Set<string>;\n\tbaseRules: string[];\n\tqueryRules: Map<string, string[]>;\n\tstyleEpoch: number;\n\n\t// Memoized getCssText() output. SSR calls getCssText() once per request, but the\n\t// rule set is stable after warmup — so the serialized sheet is recomputed only\n\t// when a new rule is actually recorded. Invalidated in record() and resetStyles().\n\tcssTextCache: string | null;\n\n\t// Browser CSSOM state. Base rules occupy [0, baseRuleCount); grouping rules\n\t// (one per query, created in registration order) live after them. CSSRule\n\t// references stay live when indices shift, so insertion never rescans.\n\tsheet: CSSStyleSheet | null;\n\tsheetDocument: Document | null;\n\tbaseRuleCount: number;\n\tgroupRules: Map<string, CSSGroupingRule>;\n\n\t// Normalized rules already sitting in a freshly-adopted stylesheet that this\n\t// module didn't insert itself — e.g. server-rendered CSS being hydrated.\n\t// Rebuilt on every fresh bind in ensureSheet(); null when there is nothing\n\t// external to guard against.\n\texternalRules: Map<string, Set<string>> | null;\n\thasExternalGroups: boolean;\n}\n\nfunction createState(): EngineState {\n\treturn {\n\t\tatomCache: new Map(),\n\t\tatomMeta: new Map(),\n\t\trawKeys: new Set(),\n\t\tbaseRules: [],\n\t\tqueryRules: new Map(),\n\t\tstyleEpoch: 0,\n\t\tcssTextCache: null,\n\t\tsheet: null,\n\t\tsheetDocument: null,\n\t\tbaseRuleCount: 0,\n\t\tgroupRules: new Map(),\n\t\texternalRules: null,\n\t\thasExternalGroups: false,\n\t};\n}\n\nconst ENGINE_STATE_KEY = Symbol.for(\"nuclo.style.engine.v1\");\nconst globalScope = globalThis as unknown as Record<symbol, EngineState>;\n// Importing the runtime does not allocate the registry until styling is used.\nlet cachedState: EngineState | undefined;\nfunction getState(): EngineState {\n\treturn cachedState ??= globalScope[ENGINE_STATE_KEY] ?? (globalScope[ENGINE_STATE_KEY] = createState());\n}\n\n/** Pre-register at-rule queries so their cascade order follows theme order. */\nexport function registerQueries(queries: Iterable<string>): void {\n\tfor (const query of queries) {\n\t\tconst state = getState();\n\t\tif (!state.queryRules.has(query)) state.queryRules.set(query, []);\n\t}\n}\n\nfunction createGroup(s: CSSStyleSheet, query: string): CSSGroupingRule | null {\n\tconst state = getState();\n\ttry {\n\t\tconst idx = s.cssRules.length;\n\t\ts.insertRule(query + \"{}\", idx);\n\t\tconst group = s.cssRules[idx] as CSSGroupingRule;\n\t\tstate.groupRules.set(query, group);\n\t\tstate.groupRules.set(groupQueryOf(group), group);\n\t\treturn group;\n\t} catch {\n\t\treturn null; // unsupported at-rule in this environment\n\t}\n}\n\n// A group prelude is stable while its children grow. Reading cssText on each\n// insertion would serialize all previous children and make loading quadratic.\n// Weak keys allow detached stylesheets to be collected after reset/rebinding.\nconst groupQueries = new WeakMap<CSSRule, string>();\nfunction groupQueryOf(rule: CSSRule): string {\n\tconst cached = groupQueries.get(rule);\n\tif (cached !== undefined) return cached;\n\tconst text = rule.cssText;\n\tconst brace = text.indexOf(\"{\");\n\tconst query = (brace === -1 ? text : text.slice(0, brace)).trim();\n\tgroupQueries.set(rule, query);\n\treturn query;\n}\n\nfunction ruleIdentity(rule: CSSRule): string {\n\treturn rule instanceof CSSStyleRule ? rule.selectorText : groupQueryOf(rule);\n}\n\nfunction rememberExternalRule(rule: CSSRule, query: string | undefined): void {\n\tconst state = getState();\n\tif (!state.externalRules) return;\n\tconst key = contextKeyOf(query, ruleIdentity(rule));\n\tlet texts = state.externalRules.get(key);\n\tif (!texts) {\n\t\ttexts = new Set();\n\t\tstate.externalRules.set(key, texts);\n\t}\n\ttexts.add(rule.cssText);\n}\n\nfunction consumeExternalRule(rule: CSSRule, query: string | undefined): boolean {\n\tconst state = getState();\n\tif (!state.externalRules) return false;\n\tconst key = contextKeyOf(query, ruleIdentity(rule));\n\tconst texts = state.externalRules.get(key);\n\tif (!texts?.delete(rule.cssText)) return false;\n\tif (texts.size === 0) state.externalRules.delete(key);\n\tif (state.externalRules.size === 0) state.externalRules = null;\n\treturn true;\n}\n\n/**\n * Index an already-populated stylesheet found on adopt (SSR output, most\n * commonly): every top-level conditional grouping rule (@media/@container/…)\n * is registered into groupRules (by its reconstructed at-rule text) so later\n * record() calls append into it instead of creating a sibling duplicate. The\n * other rules are indexed by scope, selector/prelude, and normalized cssText\n * so exact server/client matches can be skipped without hiding a changed\n * named or global rule that happens to reuse the same selector.\n */\nfunction indexExternalRules(rules: CSSRuleList): void {\n\tconst state = getState();\n\tfor (let i = 0; i < rules.length; i++) {\n\t\tconst rule = rules[i];\n\t\tif (rule instanceof CSSStyleRule) {\n\t\t\trememberExternalRule(rule, undefined);\n\t\t\tcontinue;\n\t\t}\n\t\tconst prelude = groupQueryOf(rule);\n\t\tif (\"cssRules\" in rule && !prelude.startsWith(\"@keyframes\")) {\n\t\t\tconst group = rule as CSSGroupingRule;\n\t\t\tstate.hasExternalGroups = true;\n\t\t\tstate.groupRules.set(prelude, group);\n\t\t\tfor (let j = 0; j < group.cssRules.length; j++) {\n\t\t\t\trememberExternalRule(group.cssRules[j], prelude);\n\t\t\t}\n\t\t} else {\n\t\t\t// @keyframes, @font-face, … — one-shot rules matched by prelude.\n\t\t\trememberExternalRule(rule, undefined);\n\t\t}\n\t}\n}\n\nfunction insertBase(s: CSSStyleSheet, rule: string): void {\n\tconst state = getState();\n\ttry {\n\t\ts.insertRule(rule, state.baseRuleCount);\n\t\tconst inserted = s.cssRules[state.baseRuleCount];\n\t\tif (consumeExternalRule(inserted, undefined)) {\n\t\t\ts.deleteRule(state.baseRuleCount);\n\t\t\treturn;\n\t\t}\n\t\tstate.baseRuleCount++;\n\t} catch {\n\t\t// Invalid value/selector: drop the declaration, like browsers do for bad CSS.\n\t}\n}\n\nfunction insertGrouped(group: CSSGroupingRule, rule: string): void {\n\tconst state = getState();\n\ttry {\n\t\tconst index = group.cssRules.length;\n\t\tgroup.insertRule(rule, index);\n\t\tconst inserted = group.cssRules[index];\n\t\tif (state.externalRules && consumeExternalRule(inserted, groupQueryOf(group))) group.deleteRule(index);\n\t} catch {\n\t\t// Invalid value/selector: drop the declaration, like browsers do for bad CSS.\n\t}\n}\n\nfunction getOrCreateGroup(s: CSSStyleSheet, query: string): CSSGroupingRule | null {\n\tconst state = getState();\n\tconst direct = state.groupRules.get(query);\n\tif (direct) return direct;\n\tif (!state.hasExternalGroups) return createGroup(s, query);\n\n\t// CSSOM may normalize whitespace in an at-rule prelude. Normalize the\n\t// authored query through a temporary empty group before deciding that an\n\t// adopted SSR group is missing.\n\ttry {\n\t\tconst index = s.cssRules.length;\n\t\ts.insertRule(query + \"{}\", index);\n\t\tconst normalized = groupQueryOf(s.cssRules[index]);\n\t\ts.deleteRule(index);\n\t\tconst existing = state.groupRules.get(normalized);\n\t\tif (existing) {\n\t\t\tstate.groupRules.set(query, existing);\n\t\t\treturn existing;\n\t\t}\n\t} catch {\n\t\treturn null;\n\t}\n\treturn createGroup(s, query);\n}\n\n/**\n * Returns the live stylesheet, (re)binding when the document changes — e.g.\n * fresh jsdom documents between tests. Rebinding replays the whole registry,\n * which replaces v1's per-call classExistsInDOM() DOM scans with a single\n * replay per document.\n */\nexport function ensureSheet(): CSSStyleSheet | null {\n\tconst state = getState();\n\tif (typeof document === \"undefined\") return null;\n\t// The nuclo SSR polyfill provides a document without getElementById — in\n\t// that context rules accumulate in the registry for getCssText() only.\n\tif (typeof document.getElementById !== \"function\") return null;\n\tif (\n\t\tstate.sheet &&\n\t\tstate.sheetDocument === document &&\n\t\tstate.sheet.ownerNode &&\n\t\t(state.sheet.ownerNode as Element).isConnected\n\t) {\n\t\treturn state.sheet;\n\t}\n\tconst existing = document.getElementById(\"nuclo-styles\");\n\tlet el: HTMLStyleElement;\n\tif (existing?.tagName === \"STYLE\") {\n\t\tel = existing as HTMLStyleElement;\n\t} else {\n\t\tel = document.createElement(\"style\");\n\t\tel.id = \"nuclo-styles\";\n\t\tif (existing) existing.replaceWith(el);\n\t\telse document.head.appendChild(el);\n\t}\n\tstate.sheet = el.sheet;\n\tstate.sheetDocument = document;\n\tstate.groupRules.clear();\n\tstate.baseRuleCount = 0;\n\tstate.externalRules = null;\n\tstate.hasExternalGroups = false;\n\tif (!state.sheet) return null;\n\tif (state.sheet.cssRules.length > 0) {\n\t\t// Leading top-level non-group rules (style rules, @keyframes — before\n\t\t// the first @media/@container group) are this element's existing\n\t\t// \"base\" region — count them so insertBase() keeps inserting new base\n\t\t// rules right after them, still ahead of every group.\n\t\tlet i = 0;\n\t\twhile (i < state.sheet.cssRules.length) {\n\t\t\tconst r = state.sheet.cssRules[i];\n\t\t\tif (!(r instanceof CSSStyleRule) && \"cssRules\" in r && !groupQueryOf(r).startsWith(\"@keyframes\")) break;\n\t\t\ti++;\n\t\t}\n\t\tstate.baseRuleCount = i;\n\t\tstate.externalRules = new Map();\n\t\tindexExternalRules(state.sheet.cssRules);\n\t}\n\tfor (const rule of state.baseRules) insertBase(state.sheet, rule);\n\tfor (const [query, rules] of state.queryRules) {\n\t\tconst group = getOrCreateGroup(state.sheet, query);\n\t\tif (group) for (const rule of rules) insertGrouped(group, rule);\n\t}\n\treturn state.sheet;\n}\n\nfunction record(rule: string, query: string | undefined): void {\n\tconst state = getState();\n\t// Bind/replay *before* this rule joins the registry, so a fresh bind's\n\t// replay only ever covers previously-known rules — never this one twice.\n\tconst s = ensureSheet();\n\n\tif (query === undefined) {\n\t\tstate.baseRules.push(rule);\n\t} else {\n\t\tlet bucket = state.queryRules.get(query);\n\t\tif (!bucket) {\n\t\t\tbucket = [];\n\t\t\tstate.queryRules.set(query, bucket);\n\t\t}\n\t\tbucket.push(rule);\n\t}\n\tstate.cssTextCache = null; // a new rule changes the serialized sheet\n\n\tif (s) {\n\t\tif (query === undefined) {\n\t\t\tinsertBase(s, rule);\n\t\t} else {\n\t\t\tconst group = getOrCreateGroup(s, query);\n\t\t\tif (group) insertGrouped(group, rule);\n\t\t}\n\t}\n}\n\n/**\n * Content-addressed ~42-bit hash (two interleaved FNV-1a style passes). Class\n * names must match between server and client for SSR hydration, so a counter\n * is not an option; 42 bits keeps collision odds low (~1e-5 at 10k\n * unique declaration blocks).\n */\nexport function hash(input: string): string {\n\tlet a = 0x811c9dc5;\n\tlet b = 0x7ee3623b;\n\tfor (let i = 0; i < input.length; i++) {\n\t\tconst c = input.charCodeAt(i);\n\t\ta = Math.imul(a ^ c, 0x01000193);\n\t\tb = Math.imul(b ^ c, 0x85ebca6b);\n\t}\n\treturn (a >>> 0).toString(36) + ((b >>> 9) % 1296).toString(36);\n}\n\n/** Length-prefixed (query, selector-suffix) key — unambiguous for any strings. */\nexport function contextKeyOf(query: string | undefined, suffix: string): string {\n\tconst queryPart = query === undefined ? \"-\" : \"+\" + query.length + \":\" + query;\n\treturn queryPart + suffix.length + \":\" + suffix;\n}\n\nfunction appendKeyPart(key: string, value: string): string {\n\treturn key + value.length + \":\" + value;\n}\n\nexport function expandAmpersands(input: string, replacement: string): string {\n\tlet expanded = \"\";\n\tlet quote = 0;\n\tfor (let i = 0; i < input.length; i++) {\n\t\tconst code = input.charCodeAt(i);\n\t\tif (code === 92 /* \\\\ */ && i + 1 < input.length) {\n\t\t\texpanded += input[i] + input[++i];\n\t\t\tcontinue;\n\t\t}\n\t\tif (quote !== 0) {\n\t\t\texpanded += input[i];\n\t\t\tif (code === quote) quote = 0;\n\t\t\tcontinue;\n\t\t}\n\t\tif (code === 34 /* \" */ || code === 39 /* ' */) {\n\t\t\tquote = code;\n\t\t\texpanded += input[i];\n\t\t} else {\n\t\t\texpanded += code === 38 /* & */ ? replacement : input[i];\n\t\t}\n\t}\n\treturn expanded;\n}\n\nfunction selectorFor(className: string, suffix: string): string {\n\tconst selector = \".\" + className;\n\treturn selector + expandAmpersands(suffix, selector);\n}\n\n/**\n * True for strings usable verbatim as an unescaped CSS class selector:\n * letters/digits/`-`/`_`, not starting with a digit or `-`+digit.\n * Char-code loop rather than a RegExp — this runs on the cold mint path but\n * stays allocation-free either way.\n */\nfunction isValidClassName(name: string): boolean {\n\tif (name.length === 0 || name === \"-\") return false;\n\tfor (let i = 0; i < name.length; i++) {\n\t\tconst c = name.charCodeAt(i);\n\t\tconst ok =\n\t\t\t(c >= 97 && c <= 122) || // a-z\n\t\t\t(c >= 65 && c <= 90) || // A-Z\n\t\t\tc === 45 || c === 95 || // - _\n\t\t\t(i > 0 && c >= 48 && c <= 57); // 0-9, never leading\n\t\tif (!ok) return false;\n\t}\n\t// \"-9foo\" is not a valid identifier start either.\n\tif (name.charCodeAt(0) === 45 && name.length > 1) {\n\t\tconst second = name.charCodeAt(1);\n\t\tif (second >= 48 && second <= 57) return false;\n\t}\n\treturn true;\n}\n\n/**\n * Mint (or reuse) the class for a declaration block in a selector context.\n *\n * Declarations keep their authored order — CSS resolves shorthand/longhand\n * and repeated-property conflicts by declaration order, so reordering (e.g.\n * alphabetical sorting) would silently change what `{ pt: 20, p: 16 }` means.\n * The cost is that the same declarations authored in a different order mint a\n * second, content-identical class — harmless, and rare in practice.\n *\n * `name` is the author's identity for the style (`css(\"app-root\", …)`). It\n * becomes part of the cache key, so two different names never share a class\n * even with identical declarations. With `exactName`, this block *is* the\n * named one and takes the name verbatim; otherwise the name is only a\n * readable prefix on a content-addressed prefix (`app-root-1a2b3c`), which is\n * how a named style's non-base contexts and its cx() merges stay identifiable\n * in devtools without ever colliding with the base class.\n */\nexport function atomBlock(\n\tquery: string | undefined,\n\tsuffix: string,\n\tdecls: ReadonlyArray<readonly [string, string]>,\n\tname?: string,\n\texactName = false,\n): string {\n\tconst state = getState();\n\tlet contextKey = contextKeyOf(query, suffix);\n\tfor (const [prop, value] of decls) {\n\t\tcontextKey = appendKeyPart(appendKeyPart(contextKey, prop), value);\n\t}\n\tif (name !== undefined && !isValidClassName(name)) {\n\t\tconsole.warn(\n\t\t\t`[nuclo] css() name ${JSON.stringify(name)} is not a valid CSS class name ` +\n\t\t\t\t\"(letters, digits, - and _ only, not starting with a digit); falling back to a generated name.\",\n\t\t);\n\t\tname = undefined;\n\t}\n\tconst declKey = name === undefined ? \"a\" + contextKey : \"n\" + appendKeyPart(\"\", name) + contextKey;\n\tlet className = state.atomCache.get(declKey);\n\tif (className !== undefined) {\n\t\t// Touch the sheet so a swapped document (tests) gets the replayed rules.\n\t\tensureSheet();\n\t\treturn className;\n\t}\n\n\tif (name === undefined) {\n\t\tclassName = \"n\" + hash(declKey);\n\t} else {\n\t\tclassName = exactName ? name : name + \"-\" + hash(declKey);\n\t\tif (state.atomMeta.has(className)) {\n\t\t\tconsole.warn(\n\t\t\t\t`[nuclo] css() name ${JSON.stringify(className)} is already used by a different style. ` +\n\t\t\t\t\t\"Both rules are emitted under the same class, so they will override each other — rename one.\",\n\t\t\t);\n\t\t}\n\t}\n\n\tlet body = \"\";\n\tfor (const [prop, value] of decls) body += (body ? \";\" : \"\") + prop + \":\" + value;\n\tstate.atomCache.set(declKey, className);\n\tstate.atomMeta.set(className, { query, suffix, decls, name });\n\trecord(selectorFor(className, suffix) + \"{\" + body + \"}\", query);\n\treturn className;\n}\n\n/**\n * Merge two same-context generated classes into one: `second`'s declarations\n * override `first`'s per exact property (shorthand/longhand interplay is left\n * to CSS order), and the combined block mints its own content-addressed class\n * — so cx(base, override) keeps base's untouched properties instead of\n * dropping the whole base class. Deterministic: the same pair always yields\n * the same class name, on server and client alike. A named base passes its\n * name down as a prefix, so `cx(appRoot, active)` reads as `app-root-1a2b3c`.\n */\nexport function mergeBlocks(first: string, second: string): string {\n\tconst state = getState();\n\tconst a = state.atomMeta.get(first);\n\tconst b = state.atomMeta.get(second);\n\tif (!a || !b) return second; // unknown input — nothing to merge with\n\tconst concat = [...a.decls, ...b.decls];\n\t// Keep only the last occurrence of each exact property, at its position —\n\t// so a later `padding` still fully resets an earlier `padding-top`.\n\tconst lastIndex = new Map<string, number>();\n\tfor (let i = 0; i < concat.length; i++) lastIndex.set(concat[i][0], i);\n\tconst merged = concat.filter((decl, i) => lastIndex.get(decl[0]) === i);\n\treturn atomBlock(a.query, a.suffix, merged, a.name ?? b.name);\n}\n\n/** Conflict key (query|suffix) for a generated class — lets cx() group classes by selector context. */\nexport function conflictKeyOf(className: string): string | undefined {\n\tconst state = getState();\n\tconst meta = state.atomMeta.get(className);\n\treturn meta === undefined ? undefined : contextKeyOf(meta.query, meta.suffix);\n}\n\n/** Current registry generation, used to invalidate per-instance WeakMap hits after resetStyles(). */\nexport function getStyleEpoch(): number {\n\treturn (cachedState ?? globalScope[ENGINE_STATE_KEY])?.styleEpoch ?? 0;\n}\n\n/** Register a non-atomic rule (keyframes, global styles) once per dedupe key. */\nexport function addRawRule(dedupeKey: string, rule: string): void {\n\tconst state = getState();\n\tif (state.rawKeys.has(dedupeKey)) {\n\t\tensureSheet();\n\t\treturn;\n\t}\n\tstate.rawKeys.add(dedupeKey);\n\trecord(rule, undefined);\n}\n\n/** All generated CSS — base rules first, then at-rule groups in registration order. */\nexport function getCssText(): string {\n\tconst state = getState();\n\tif (state.cssTextCache !== null) return state.cssTextCache;\n\tlet out = state.baseRules.join(\"\");\n\tfor (const [query, rules] of state.queryRules) {\n\t\tif (rules.length > 0) out += query + \"{\" + rules.join(\"\") + \"}\";\n\t}\n\tstate.cssTextCache = out;\n\treturn out;\n}\n\n/** Clear all engine state (test helper). Removes the injected style element. */\nexport function resetStyles(): void {\n\tconst state = getState();\n\tstate.atomCache.clear();\n\tstate.atomMeta.clear();\n\tstate.rawKeys.clear();\n\tstate.baseRules.length = 0;\n\tstate.queryRules.clear();\n\tstate.groupRules.clear();\n\tstate.cssTextCache = null;\n\tstate.baseRuleCount = 0;\n\tstate.sheet = null;\n\tstate.sheetDocument = null;\n\tstate.externalRules = null;\n\tstate.hasExternalGroups = false;\n\tstate.styleEpoch++;\n\tif (typeof document !== \"undefined\") {\n\t\tdocument.getElementById(\"nuclo-styles\")?.remove();\n\t}\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{t as e}from"../Element-Djosl17E.mjs";function t(e){let t=0;for(;t<e.length;t++){let n=e.charCodeAt(t);if(n>=65&&n<=90)break}if(t===e.length)return e;let n=e.slice(0,t);for(let r=t;r<e.length;r++){let t=e.charCodeAt(r);t>=65&&t<=90?(r>0&&(n+=`-`),n+=String.fromCharCode(t+32)):n+=e[r]}return n}const n=/[&<>"']/,r=/[&<>]/;function i(e){let t=n.exec(e);if(!t)return e;let r=``,i=0;for(let n=t.index;n<e.length;n++){let t;switch(e.charCodeAt(n)){case 38:t=`&amp;`;break;case 60:t=`&lt;`;break;case 62:t=`&gt;`;break;case 34:t=`&quot;`;break;case 39:t=`&#039;`;break;default:continue}r+=e.slice(i,n)+t,i=n+1}return r+e.slice(i)}function a(e){let t=r.exec(e);if(!t)return e;let n=``,i=0;for(let r=t.index;r<e.length;r++){let t;switch(e.charCodeAt(r)){case 38:t=`&amp;`;break;case 60:t=`&lt;`;break;case 62:t=`&gt;`;break;default:continue}n+=e.slice(i,r)+t,i=r+1}return n+e.slice(i)}let o=!1;function s(e){let t=o;o=!0;try{return e()}finally{o=t}}const c=/* @__PURE__ */ new Set;typeof FinalizationRegistry<`u`&&new FinalizationRegistry(e=>{c.delete(e)});function l(e){return globalThis.document?document.createElement(e):null}const u=/* @__PURE__ */ new Set(/* @__PURE__ */ `viewBox.preserveAspectRatio.markerWidth.markerHeight.gradientTransform.patternTransform.clipPathUnits.gradientUnits.patternUnits.pathLength.refX.refY.stdDeviation.baseFrequency.numOctaves.kernelMatrix.tableValues.targetX.targetY.specularExponent.specularConstant.diffuseConstant.surfaceScale.xChannelSelector.yChannelSelector.edgeMode.stitchTiles.spreadMethod.patternContentUnits.markerUnits.startOffset.textLength.lengthAdjust`.split(`.`)),d=/* @__PURE__ */ new Set([`allowfullscreen`,`async`,`autofocus`,`autoplay`,`checked`,`controls`,`default`,`defer`,`disabled`,`formnovalidate`,`hidden`,`ismap`,`loop`,`multiple`,`muted`,`nomodule`,`novalidate`,`open`,`readonly`,`required`,`reversed`,`selected`]);function f(e,n){if(n==null||n===!1)return``;if(n===!0)return` ${e}`;if(d.has(e)){if(n===`false`)return``;if(n===`true`||n===``||n===e)return` ${e}`}if(e===`style`&&typeof n==`object`){let e=``;for(let r in n){let i=n[r];i!=null&&i!==``&&(e+=(e?` `:``)+t(r)+`: `+String(i)+`;`)}return e?` style="${i(e)}"`:``}return` ${e}="${i(String(n))}"`}function p(e,n){let r=``;if(n){let n=e,a=n._attributes;n.id&&!a?.has(`id`)&&(r+=f(`id`,n.id)),n.className&&!a?.has(`class`)&&(r+=f(`class`,n.className));let o=n._style;if(!a?.has(`style`)&&o){let e=o.cssText||``;if(e){let n=e.split(`;`).map(e=>e.trim()).filter(Boolean).map(e=>{let n=e.indexOf(`:`);if(n===-1)return e;let r=e.slice(0,n).trim(),i=e.slice(n+1).trim();return i?`${t(r)}: ${i};`:``}).filter(Boolean).join(` `);n&&(r+=` style="${i(n)}"`)}}if(a)for(let[e,n]of a){let i=u.has(e)?e:t(e);r+=f(i,n)}return r}if(e.attributes&&e.attributes.length)for(let t=0;t<e.attributes.length;t++){let n=e.attributes[t];n&&n.name&&(r+=f(n.name,n.value))}return r}const m=Object.assign(Object.create(null),{area:1,base:1,br:1,col:1,embed:1,hr:1,img:1,input:1,link:1,meta:1,param:1,source:1,track:1,wbr:1,script:2,style:2});function h(e,t){return t.replace(RegExp(`</(`+e+`)`,`gi`),`<\\/$1`)}function g(e){if(`tagName`in e&&`children`in e){let t=e.children;if(Array.isArray(t))return t}if(`childNodes`in e){let t=e.childNodes;if(t&&(Array.isArray(t)||t.length!==void 0))return t}return[]}function _(t){if(t.nodeType===3)return a(t.textContent||``);if(t.nodeType===8)return`<!--${t.textContent||``}-->`;if(t.nodeType===1){let n=t,r=n.tagName,i=Array.isArray(n.children),o=n instanceof e?r:r.toLowerCase(),s=p(n,i),c=m[o];if(c===1)return`<${o}${s} />`;let l=i?n.children:g(n);if(c===2){let e=``,n=l;if(n&&n.length>0)for(let t=0;t<n.length;t++){let r=n[t];r&&r.nodeType===3&&(e+=r.textContent||``)}else{let n=t.textContent;typeof n==`string`&&(e=n)}return`<${o}${s}>${h(o,e)}</${o}>`}let u=``;if(l&&l.length>0)for(let e=0;e<l.length;e++){let t=l[e];t&&(u+=_(t))}else{let e=t.textContent;typeof e==`string`&&e&&(u=a(e))}return`<${o}${s}>${u}</${o}>`}if(t.nodeType===11){let e=``,n=g(t);if(n&&n.length>0)for(let t=0;t<n.length;t++){let r=n[t];r&&(e+=_(r))}return e}return``}function v(e){if(!e)return``;if(typeof e==`function`)try{let t=s(()=>{let t=l(`div`);if(!t)throw Error(`Document is not available. Make sure polyfills are loaded.`);return e(t,0)});return t&&typeof t==`object`&&`nodeType`in t?_(t):``}catch(e){return console.error(`Error rendering component to string:`,e),``}return`nodeType`in e?_(e):``}function y(e){return e.map(e=>v(e))}function b(e,t=`div`,n={}){let r=v(e);return`<${t}${Object.entries(n).map(([e,t])=>f(e,t)).join(``)}>${r}</${t}>`}function x(){return{ssrCollector:null,atomCache:/* @__PURE__ */ new Map,atomMeta:/* @__PURE__ */ new Map,rawKeys:/* @__PURE__ */ new Set,baseRules:[],queryRules:/* @__PURE__ */ new Map,styleEpoch:0,cssTextCache:null,sheet:null,sheetDocument:null,baseRuleCount:0,groupRules:/* @__PURE__ */ new Map,externalRules:null,hasExternalGroups:!1}}const S=Symbol.for(`nuclo.style.engine.v1`),C=globalThis;let w;function T(){return w??=C[S]??(C[S]=x())}function E(e){let t=T();t.ssrCollector=e}function D(){let e=T();if(e.cssTextCache!==null)return e.cssTextCache;let t=e.baseRules.join(``);for(let[n,r]of e.queryRules)r.length>0&&(t+=n+`{`+r.join(``)+`}`);return e.cssTextCache=t,t}export{D as getCssText,y as renderManyToString,v as renderToString,b as renderToStringWithContainer,E as setSSRCollector};
1
+ import{t as e}from"../Element-DLSdmoqX.mjs";function t(e){let t=0;for(;t<e.length;t++){let n=e.charCodeAt(t);if(n>=65&&n<=90)break}if(t===e.length)return e;let n=e.slice(0,t);for(let r=t;r<e.length;r++){let t=e.charCodeAt(r);n+=t>=65&&t<=90?`-`+String.fromCharCode(t+32):e[r]}return n}const n=/[&<>"']/,r=/[&<>]/;function i(e){let t=n.exec(e);if(!t)return e;let r=``,i=0;for(let n=t.index;n<e.length;n++){let t;switch(e.charCodeAt(n)){case 38:t=`&amp;`;break;case 60:t=`&lt;`;break;case 62:t=`&gt;`;break;case 34:t=`&quot;`;break;case 39:t=`&#039;`;break;default:continue}r+=e.slice(i,n)+t,i=n+1}return r+e.slice(i)}function a(e){let t=r.exec(e);if(!t)return e;let n=``,i=0;for(let r=t.index;r<e.length;r++){let t;switch(e.charCodeAt(r)){case 38:t=`&amp;`;break;case 60:t=`&lt;`;break;case 62:t=`&gt;`;break;default:continue}n+=e.slice(i,r)+t,i=r+1}return n+e.slice(i)}let o=!1;function s(e){let t=o;o=!0;try{return e()}finally{o=t}}const c=/* @__PURE__ */ new Set(/* @__PURE__ */ `viewBox.preserveAspectRatio.markerWidth.markerHeight.gradientTransform.patternTransform.clipPathUnits.gradientUnits.patternUnits.pathLength.refX.refY.stdDeviation.baseFrequency.numOctaves.kernelMatrix.tableValues.targetX.targetY.specularExponent.specularConstant.diffuseConstant.surfaceScale.xChannelSelector.yChannelSelector.edgeMode.stitchTiles.spreadMethod.patternContentUnits.markerUnits.startOffset.textLength.lengthAdjust`.split(`.`)),l=/* @__PURE__ */ new Set([`allowfullscreen`,`async`,`autofocus`,`autoplay`,`checked`,`controls`,`default`,`defer`,`disabled`,`formnovalidate`,`hidden`,`ismap`,`loop`,`multiple`,`muted`,`nomodule`,`novalidate`,`open`,`readonly`,`required`,`reversed`,`selected`]);function u(e,n){if(n==null||n===!1)return``;if(n===!0)return` ${e}`;if(l.has(e)){if(n===`false`)return``;if(n===`true`||n===``||n===e)return` ${e}`}if(e===`style`&&typeof n==`object`){let e=``;for(let r in n){let i=n[r];i!=null&&i!==``&&(e+=(e?` `:``)+t(r)+`: `+String(i)+`;`)}return e?` style="${i(e)}"`:``}return` ${e}="${i(String(n))}"`}function d(e,n){let r=``;if(n){let n=e,a=n._attributes;n.id&&!a?.has(`id`)&&(r+=u(`id`,n.id)),n.className&&!a?.has(`class`)&&(r+=u(`class`,n.className));let o=n._style;if(o&&!a?.has(`style`)){let e=``;for(let n in o){let r=o[n];r!=null&&r!==``&&(e+=(e?` `:``)+t(n)+`: `+String(r)+`;`)}e&&(r+=` style="${i(e)}"`)}if(a)for(let[e,n]of a){let i=c.has(e)?e:t(e);r+=u(i,n)}return r}if(e.attributes&&e.attributes.length)for(let t=0;t<e.attributes.length;t++){let n=e.attributes[t];n&&n.name&&(r+=u(n.name,n.value))}return r}const f=Object.assign(Object.create(null),{area:1,base:1,br:1,col:1,embed:1,hr:1,img:1,input:1,link:1,meta:1,param:1,source:1,track:1,wbr:1,script:2,style:2});function p(e,t){return t.replace(RegExp(`</(`+e+`)`,`gi`),`<\\/$1`)}function m(t){if(t.nodeType===3)return a(t.textContent||``);if(t.nodeType===8)return`<!--${t.textContent||``}-->`;if(t.nodeType===1){let n=t,r=n.tagName,i=Array.isArray(n.children),o=n instanceof e?r:r.toLowerCase(),s=d(n,i),c=f[o];if(c===1)return`<${o}${s} />`;let l=i?n.children:n.childNodes;if(c===2){let e=``,n=l;if(n&&n.length>0)for(let t=0;t<n.length;t++){let r=n[t];r&&r.nodeType===3&&(e+=r.textContent||``)}else{let n=t.textContent;typeof n==`string`&&(e=n)}return`<${o}${s}>${p(o,e)}</${o}>`}let u=``;if(l&&l.length>0)for(let e=0;e<l.length;e++){let t=l[e];t&&(u+=m(t))}else{let e=t.textContent;typeof e==`string`&&e&&(u=a(e))}return`<${o}${s}>${u}</${o}>`}if(t.nodeType===11){let e=``,n=t.childNodes??[];if(n.length>0)for(let t=0;t<n.length;t++){let r=n[t];r&&(e+=m(r))}return e}return``}function h(e){if(!e)return``;if(typeof e==`function`)try{let t=s(()=>{if(typeof document>`u`)throw Error(`Document is not available. Make sure polyfills are loaded.`);return e(document.createElement(`div`),0)});return t&&typeof t==`object`&&`nodeType`in t?m(t):``}catch(e){return console.error(`Error rendering component to string:`,e),``}return`nodeType`in e?m(e):``}function g(e){return e.map(e=>h(e))}function _(e,t=`div`,n={}){let r=h(e);return`<${t}${Object.entries(n).map(([e,t])=>u(e,t)).join(``)}>${r}</${t}>`}function v(){return{atomCache:/* @__PURE__ */ new Map,atomMeta:/* @__PURE__ */ new Map,rawKeys:/* @__PURE__ */ new Set,baseRules:[],queryRules:/* @__PURE__ */ new Map,styleEpoch:0,cssTextCache:null,sheet:null,sheetDocument:null,baseRuleCount:0,groupRules:/* @__PURE__ */ new Map,externalRules:null,hasExternalGroups:!1}}const y=Symbol.for(`nuclo.style.engine.v1`),b=globalThis;let x;function S(){return x??=b[y]??(b[y]=v())}function C(){let e=S();if(e.cssTextCache!==null)return e.cssTextCache;let t=e.baseRules.join(``);for(let[n,r]of e.queryRules)r.length>0&&(t+=n+`{`+r.join(``)+`}`);return e.cssTextCache=t,t}export{C as getCssText,g as renderManyToString,h as renderToString,_ as renderToStringWithContainer};
2
2
  //# sourceMappingURL=nuclo.ssr.mjs.map