@elurjs/core 3.6.0 → 3.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/elur/router.cjs +1 -1
- package/dist/lib/elur/router.cjs.map +1 -1
- package/dist/lib/elur/router.js +1 -1
- package/dist/lib/elur/router.js.map +1 -1
- package/dist/lib/elur/server/index.cjs +1 -1
- package/dist/lib/elur/server/index.cjs.map +1 -1
- package/dist/lib/elur/server/index.js +5 -1
- package/dist/lib/elur/server/index.js.map +1 -1
- package/dist/lib/elur/store.cjs +1 -1
- package/dist/lib/elur/store.cjs.map +1 -1
- package/dist/lib/elur/store.js +9 -3
- package/dist/lib/elur/store.js.map +1 -1
- package/dist/lib/elur/template/bindings.cjs +1 -1
- package/dist/lib/elur/template/bindings.cjs.map +1 -1
- package/dist/lib/elur/template/bindings.js +1 -1
- package/dist/lib/elur/template/bindings.js.map +1 -1
- package/dist/lib/router.cjs +1 -1
- package/dist/lib/router.js +1 -1
- package/dist/lib/server.cjs +1 -1
- package/dist/lib/server.js +5 -1
- package/dist/lib/store.cjs +1 -1
- package/dist/lib/store.js +9 -3
- package/package.json +12 -1
|
@@ -136,7 +136,7 @@ function v(o, s, c, l, u) {
|
|
|
136
136
|
let v = u[o];
|
|
137
137
|
if (p.type === "event") {
|
|
138
138
|
let e = _.name, t = m, n = p.modifiers;
|
|
139
|
-
if (g(e) && !n.includes("capture") && !n.includes("once")) d.push(h(v, e, n, t));
|
|
139
|
+
if (g(e) && !n.includes("capture") && !n.includes("once") && !n.includes("passive")) d.push(h(v, e, n, t));
|
|
140
140
|
else {
|
|
141
141
|
let r = {
|
|
142
142
|
once: n.includes("once"),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bindings.js","names":[],"sources":["../../../../src/elur/template/bindings.ts"],"sourcesContent":["import { effect } from \"../reactivity.js\";\nimport type { ElurRef, TemplateBindingContext } from \"./types.js\";\nimport { activateNodeBinding } from \"./node-binding.js\";\nimport { queueDOMWrite } from \"./dom-write.js\";\nimport { isUrlAttrName, isExecutableAttrName, sanitizeUrl } from \"./sanitize.js\";\n\n// =============================================================================\n// --- show / hide ---\n// =============================================================================\n\n/** Toggles element visibility via `display: none` without unmounting. */\nexport function showWhen(el: HTMLElement, condition: boolean): void {\n if (!condition) {\n if (el.style.display !== \"none\") el.style.display = \"none\";\n } else {\n if (el.style.display === \"none\") el.style.display = \"\";\n }\n}\n\n// =============================================================================\n// --- Binding context ---\n// =============================================================================\n\nexport type BindingContext = TemplateBindingContext;\n\n/**\n * Determines the binding context (node, event, or attribute) for an interpolated\n * value based on the preceding template string.\n */\nexport function detectContext(prevString: string): BindingContext {\n const lastClose = prevString.lastIndexOf(\">\");\n const lastOpen = prevString.lastIndexOf(\"<\");\n\n if (lastOpen <= lastClose) {\n return { type: \"node\" };\n }\n\n const tagContent = prevString.slice(lastOpen + 1);\n\n const eqIdx = tagContent.lastIndexOf(\"=\");\n if (eqIdx === -1) {\n return { type: \"node\" };\n }\n\n const hadOpenQuote =\n tagContent.endsWith('\"') ||\n tagContent.endsWith(\"'\") ||\n tagContent[tagContent.length - 1] === '\"' ||\n tagContent[tagContent.length - 1] === \"'\";\n\n let startIdx = eqIdx - 1;\n while (startIdx >= 0 && /\\S/.test(tagContent[startIdx])) {\n startIdx--;\n }\n startIdx++;\n\n const fullAttr = tagContent.slice(startIdx, eqIdx);\n\n if (fullAttr[0] === \"@\") {\n const parts = fullAttr.slice(1).split(\".\");\n return {\n type: \"event\",\n eventName: parts[0],\n modifiers: parts.slice(1),\n hadOpenQuote,\n };\n }\n\n return {\n type: \"attr\",\n attrName: fullAttr,\n hadOpenQuote,\n // Precomputed once per template (compile time). Read as a cheap boolean\n // in the render/update hot path.\n url: isUrlAttrName(fullAttr),\n executable: isExecutableAttrName(fullAttr),\n };\n}\n\n// =============================================================================\n// --- Keyboard modifier map ---\n// =============================================================================\n\nconst KEY_MAP: Readonly<Record<string, string>> = {\n enter: \"Enter\",\n escape: \"Escape\",\n space: \" \",\n tab: \"Tab\",\n delete: \"Delete\",\n backspace: \"Backspace\",\n up: \"ArrowUp\",\n down: \"ArrowDown\",\n left: \"ArrowLeft\",\n right: \"ArrowRight\",\n};\n\n// =============================================================================\n// --- Global Event Delegation ---\n// =============================================================================\n\nconst DELEGABLE_EVENTS = new Set([\n \"click\", \"dblclick\", \"mousedown\", \"mouseup\",\n \"keydown\", \"keyup\", \"input\", \"change\", \"submit\"\n]);\nconst _delegatedRegistry = new Set<string>();\n\nfunction _globalEventHandlerCore(e: Event, propName: string, modsName: string): void {\n let target = e.target as Node | null;\n\n const originalStop = e.stopPropagation;\n let stopped = false;\n e.stopPropagation = () => {\n stopped = true;\n originalStop.call(e);\n };\n\n while (target && target !== document) {\n const handler = (target as any)[propName] as EventListener | undefined;\n if (handler) {\n const mods = (target as any)[modsName] as string[] | undefined;\n if (mods) {\n if (mods.includes(\"prevent\")) e.preventDefault();\n if (mods.includes(\"stop\")) e.stopPropagation();\n if (mods.includes(\"self\") && e.target !== target) {\n target = target.parentNode;\n continue;\n }\n if (\"key\" in e) {\n const ke = e as KeyboardEvent;\n let keyMatch = true;\n for (const mod of mods) {\n const mapped = KEY_MAP[mod];\n if (mapped !== undefined && ke.key !== mapped) { keyMatch = false; break; }\n if (!mapped && mod.length === 1 && ke.key.toLowerCase() !== mod) { keyMatch = false; break; }\n }\n if (!keyMatch) {\n target = target.parentNode;\n continue;\n }\n }\n }\n handler(e);\n if (stopped) break;\n }\n target = target.parentNode;\n }\n\n e.stopPropagation = originalStop;\n}\n\n// NOTE: entries are intentionally permanent — delegated listeners on document\n// live for the application lifetime.\nconst _delegatedHandlers = new Map<string, (e: Event) => void>();\n\n/**\n * Activates a delegated event on an element, using the same global registry\n * as mount-time bindings. Used by both `activateBindings` (mount) and the\n * hydrator to ensure consistent event delegation.\n *\n * @returns A dispose function that removes the handler from the element.\n */\nexport function _ensureDelegatedEvent(eventName: string): void {\n if (!_delegatedRegistry.has(eventName)) {\n const propName = `__elur_${eventName}`;\n const modsName = `__elur_${eventName}_mods`;\n const boundHandler = (e: Event) => _globalEventHandlerCore(e, propName, modsName);\n _delegatedHandlers.set(eventName, boundHandler);\n document.addEventListener(eventName, boundHandler);\n _delegatedRegistry.add(eventName);\n }\n}\n\nexport function _setDelegatedEvent(\n el: Element,\n eventName: string,\n modifiers: readonly string[],\n rawHandler: EventListener,\n): void {\n _ensureDelegatedEvent(eventName);\n const nodePropName = `__elur_${eventName}`;\n const nodeModsName = `__elur_${eventName}_mods`;\n (el as any)[nodePropName] = rawHandler;\n if (modifiers.length > 0) (el as any)[nodeModsName] = modifiers;\n}\n\nexport function activateDelegatedEvent(\n el: Element,\n eventName: string,\n modifiers: readonly string[],\n rawHandler: EventListener,\n): () => void {\n _setDelegatedEvent(el, eventName, modifiers, rawHandler);\n const nodePropName = `__elur_${eventName}`;\n const nodeModsName = `__elur_${eventName}_mods`;\n return () => {\n (el as any)[nodePropName] = null;\n (el as any)[nodeModsName] = null;\n };\n}\n\n/** Returns true if an event name is in the delegable set. */\nexport function isDelegableEvent(eventName: string): boolean {\n return DELEGABLE_EVENTS.has(eventName);\n}\n\n// =============================================================================\n// --- Binding activation ---\n// =============================================================================\n\n/** Activates all bindings on the cloned fragment. Returns dispose/postMount. */\nexport function activateBindings(\n fragment: DocumentFragment,\n contexts: BindingContext[],\n values: unknown[],\n pathMap: Array<{ nodeIndex: number; name?: string } | null>,\n): { disposes: Array<() => void>; postMountHooks: Array<() => void> } {\n // PHASE 1: READ — single-pass TreeWalker O(N)\n const resolvedNodes = new Array<Node | null>(contexts.length);\n\n let maxNodeIndex = -1;\n for (let i = 0; i < contexts.length; i++) {\n if (pathMap[i] && pathMap[i]!.nodeIndex > maxNodeIndex) {\n maxNodeIndex = pathMap[i]!.nodeIndex;\n }\n }\n\n const flatNodes = new Array<Node>(maxNodeIndex + 1);\n flatNodes[0] = fragment;\n if (maxNodeIndex > 0) {\n const walker = document.createTreeWalker(fragment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT);\n let fi = 1;\n let currentNode: Node | null;\n while (fi <= maxNodeIndex && (currentNode = walker.nextNode())) {\n flatNodes[fi++] = currentNode;\n }\n }\n\n for (let i = 0; i < contexts.length; i++) {\n const info = pathMap[i];\n resolvedNodes[i] = info ? flatNodes[info.nodeIndex] : null;\n }\n\n // PHASE 2: MUTATE (delegated to _activateBindingsWithNodes)\n return _activateBindingsWithNodes(fragment, contexts, values, pathMap, resolvedNodes);\n}\n\n/**\n * Activates bindings using pre-resolved nodes — skips the TreeWalker phase.\n * Used by the compiler's __elurCompiledTemplate to eliminate the second TreeWalker.\n */\nexport function _activateBindingsWithNodes(\n _fragment: DocumentFragment,\n contexts: BindingContext[],\n values: unknown[],\n pathMap: Array<{ nodeIndex: number; name?: string } | null>,\n resolvedNodes: Array<Node | null>,\n): { disposes: Array<() => void>; postMountHooks: Array<() => void> } {\n const disposes: Array<() => void> = [];\n const postMountHooks: Array<() => void> = [];\n\n for (let i = 0; i < contexts.length; i++) {\n const ctx = contexts[i];\n const value = values[i];\n const info = pathMap[i];\n if (!info) continue;\n\n const el = resolvedNodes[i]!;\n\n // --- Events ---\n if (ctx.type === \"event\") {\n const eventName = info.name!;\n const rawHandler = value as EventListener;\n const mods = ctx.modifiers;\n\n const canDelegate =\n isDelegableEvent(eventName) &&\n !mods.includes(\"capture\") &&\n !mods.includes(\"once\");\n\n if (canDelegate) {\n disposes.push(activateDelegatedEvent(el as Element, eventName, mods, rawHandler));\n } else {\n const listenerOpts: AddEventListenerOptions = {\n once: mods.includes(\"once\"),\n capture: mods.includes(\"capture\"),\n passive: mods.includes(\"passive\")\n };\n const handler = (e: Event) => {\n if (mods.includes(\"prevent\")) e.preventDefault();\n if (mods.includes(\"stop\")) e.stopPropagation();\n if (mods.includes(\"self\") && e.target !== e.currentTarget) return;\n rawHandler(e);\n };\n el.addEventListener(eventName, handler, listenerOpts);\n disposes.push(() => el.removeEventListener(eventName, handler, listenerOpts));\n }\n continue;\n }\n\n // --- Attributes ---\n if (ctx.type === \"attr\") {\n const attrName = info.name!;\n const element = el as Element;\n\n if (attrName === \"ref\") {\n (value as ElurRef<Element>).el = element;\n disposes.push(() => { (value as ElurRef<Element>).el = null; });\n continue;\n }\n\n if (attrName === \"show\" || attrName === \"hide\") {\n const htmlEl = element as HTMLElement;\n let originalDisplay: string | null = null;\n\n if (typeof value === \"function\") {\n let queued = false;\n let pendingVisible = false;\n let isFirstRun = true;\n\n const dispose = effect(() => {\n pendingVisible = Boolean((value as () => unknown)());\n const update = () => {\n queued = false;\n const shouldShow = attrName === \"show\" ? pendingVisible : !pendingVisible;\n if (originalDisplay === null) {\n originalDisplay = htmlEl.style.display || \"\";\n }\n htmlEl.style.display = shouldShow ? originalDisplay : \"none\";\n };\n\n if (isFirstRun) {\n isFirstRun = false;\n update();\n } else if (!queued) {\n queued = true;\n queueDOMWrite(update);\n }\n });\n disposes.push(dispose);\n } else {\n const shouldShow = attrName === \"show\" ? Boolean(value) : !Boolean(value);\n if (!shouldShow) htmlEl.style.display = \"none\";\n }\n continue;\n }\n\n // on*/srcdoc bindings are non-idiomatic in Elur (events use @click) and\n // turn an untrusted value into executable code. Warn the developer but\n // do not block — the attribute name is developer-authored.\n if (ctx.executable ?? isExecutableAttrName(attrName)) {\n console.warn(\n `[elur] Dynamic binding on executable attribute \"${attrName}\". Use @event for handlers; avoid binding untrusted values here.`,\n );\n }\n\n // Precomputed at compile time. Only URL attributes pay the sanitizer;\n // class/style/aria-*/data-*/custom attributes skip it entirely.\n const isUrl = ctx.url ?? isUrlAttrName(attrName);\n\n const isDomProp = (attrName === \"value\" || attrName === \"checked\" || attrName === \"selected\") && attrName in element;\n\n if (typeof value === \"function\") {\n let queued = false;\n let pendingValue: unknown;\n let isFirstRun = true;\n\n const dispose = effect(() => {\n pendingValue = (value as () => unknown)();\n const update = () => {\n queued = false;\n const v = pendingValue;\n if (isDomProp) {\n (element as any)[attrName] = v ?? \"\";\n } else if (v == null || v === false) {\n element.removeAttribute(attrName);\n } else {\n const s = String(v);\n element.setAttribute(attrName, isUrl ? sanitizeUrl(s) : s);\n }\n };\n\n if (isFirstRun) {\n isFirstRun = false;\n update();\n } else if (!queued) {\n queued = true;\n queueDOMWrite(update);\n }\n });\n disposes.push(dispose);\n } else {\n if (isDomProp) {\n (element as any)[attrName] = value ?? \"\";\n } else if (value != null && value !== false) {\n const s = String(value);\n element.setAttribute(attrName, isUrl ? sanitizeUrl(s) : s);\n }\n }\n continue;\n }\n\n // --- Nodes — delegate to node-binding.ts ---\n const originalAnchor = el as Comment;\n if (!originalAnchor) continue;\n\n const anchor = document.createTextNode(\"\");\n originalAnchor.parentNode!.replaceChild(anchor, originalAnchor);\n\n activateNodeBinding(anchor, value, disposes, postMountHooks);\n }\n\n return { disposes, postMountHooks };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"bindings.js","names":[],"sources":["../../../../src/elur/template/bindings.ts"],"sourcesContent":["import { effect } from \"../reactivity.js\";\nimport type { ElurRef, TemplateBindingContext } from \"./types.js\";\nimport { activateNodeBinding } from \"./node-binding.js\";\nimport { queueDOMWrite } from \"./dom-write.js\";\nimport { isUrlAttrName, isExecutableAttrName, sanitizeUrl } from \"./sanitize.js\";\n\n// =============================================================================\n// --- show / hide ---\n// =============================================================================\n\n/** Toggles element visibility via `display: none` without unmounting. */\nexport function showWhen(el: HTMLElement, condition: boolean): void {\n if (!condition) {\n if (el.style.display !== \"none\") el.style.display = \"none\";\n } else {\n if (el.style.display === \"none\") el.style.display = \"\";\n }\n}\n\n// =============================================================================\n// --- Binding context ---\n// =============================================================================\n\nexport type BindingContext = TemplateBindingContext;\n\n/**\n * Determines the binding context (node, event, or attribute) for an interpolated\n * value based on the preceding template string.\n */\nexport function detectContext(prevString: string): BindingContext {\n const lastClose = prevString.lastIndexOf(\">\");\n const lastOpen = prevString.lastIndexOf(\"<\");\n\n if (lastOpen <= lastClose) {\n return { type: \"node\" };\n }\n\n const tagContent = prevString.slice(lastOpen + 1);\n\n const eqIdx = tagContent.lastIndexOf(\"=\");\n if (eqIdx === -1) {\n return { type: \"node\" };\n }\n\n const hadOpenQuote =\n tagContent.endsWith('\"') ||\n tagContent.endsWith(\"'\") ||\n tagContent[tagContent.length - 1] === '\"' ||\n tagContent[tagContent.length - 1] === \"'\";\n\n let startIdx = eqIdx - 1;\n while (startIdx >= 0 && /\\S/.test(tagContent[startIdx])) {\n startIdx--;\n }\n startIdx++;\n\n const fullAttr = tagContent.slice(startIdx, eqIdx);\n\n if (fullAttr[0] === \"@\") {\n const parts = fullAttr.slice(1).split(\".\");\n return {\n type: \"event\",\n eventName: parts[0],\n modifiers: parts.slice(1),\n hadOpenQuote,\n };\n }\n\n return {\n type: \"attr\",\n attrName: fullAttr,\n hadOpenQuote,\n // Precomputed once per template (compile time). Read as a cheap boolean\n // in the render/update hot path.\n url: isUrlAttrName(fullAttr),\n executable: isExecutableAttrName(fullAttr),\n };\n}\n\n// =============================================================================\n// --- Keyboard modifier map ---\n// =============================================================================\n\nconst KEY_MAP: Readonly<Record<string, string>> = {\n enter: \"Enter\",\n escape: \"Escape\",\n space: \" \",\n tab: \"Tab\",\n delete: \"Delete\",\n backspace: \"Backspace\",\n up: \"ArrowUp\",\n down: \"ArrowDown\",\n left: \"ArrowLeft\",\n right: \"ArrowRight\",\n};\n\n// =============================================================================\n// --- Global Event Delegation ---\n// =============================================================================\n\nconst DELEGABLE_EVENTS = new Set([\n \"click\", \"dblclick\", \"mousedown\", \"mouseup\",\n \"keydown\", \"keyup\", \"input\", \"change\", \"submit\"\n]);\nconst _delegatedRegistry = new Set<string>();\n\nfunction _globalEventHandlerCore(e: Event, propName: string, modsName: string): void {\n let target = e.target as Node | null;\n\n const originalStop = e.stopPropagation;\n let stopped = false;\n e.stopPropagation = () => {\n stopped = true;\n originalStop.call(e);\n };\n\n while (target && target !== document) {\n const handler = (target as any)[propName] as EventListener | undefined;\n if (handler) {\n const mods = (target as any)[modsName] as string[] | undefined;\n if (mods) {\n if (mods.includes(\"prevent\")) e.preventDefault();\n if (mods.includes(\"stop\")) e.stopPropagation();\n if (mods.includes(\"self\") && e.target !== target) {\n target = target.parentNode;\n continue;\n }\n if (\"key\" in e) {\n const ke = e as KeyboardEvent;\n let keyMatch = true;\n for (const mod of mods) {\n const mapped = KEY_MAP[mod];\n if (mapped !== undefined && ke.key !== mapped) { keyMatch = false; break; }\n if (!mapped && mod.length === 1 && ke.key.toLowerCase() !== mod) { keyMatch = false; break; }\n }\n if (!keyMatch) {\n target = target.parentNode;\n continue;\n }\n }\n }\n handler(e);\n if (stopped) break;\n }\n target = target.parentNode;\n }\n\n e.stopPropagation = originalStop;\n}\n\n// NOTE: entries are intentionally permanent — delegated listeners on document\n// live for the application lifetime.\nconst _delegatedHandlers = new Map<string, (e: Event) => void>();\n\n/**\n * Activates a delegated event on an element, using the same global registry\n * as mount-time bindings. Used by both `activateBindings` (mount) and the\n * hydrator to ensure consistent event delegation.\n *\n * @returns A dispose function that removes the handler from the element.\n */\nexport function _ensureDelegatedEvent(eventName: string): void {\n if (!_delegatedRegistry.has(eventName)) {\n const propName = `__elur_${eventName}`;\n const modsName = `__elur_${eventName}_mods`;\n const boundHandler = (e: Event) => _globalEventHandlerCore(e, propName, modsName);\n _delegatedHandlers.set(eventName, boundHandler);\n document.addEventListener(eventName, boundHandler);\n _delegatedRegistry.add(eventName);\n }\n}\n\nexport function _setDelegatedEvent(\n el: Element,\n eventName: string,\n modifiers: readonly string[],\n rawHandler: EventListener,\n): void {\n _ensureDelegatedEvent(eventName);\n const nodePropName = `__elur_${eventName}`;\n const nodeModsName = `__elur_${eventName}_mods`;\n (el as any)[nodePropName] = rawHandler;\n if (modifiers.length > 0) (el as any)[nodeModsName] = modifiers;\n}\n\nexport function activateDelegatedEvent(\n el: Element,\n eventName: string,\n modifiers: readonly string[],\n rawHandler: EventListener,\n): () => void {\n _setDelegatedEvent(el, eventName, modifiers, rawHandler);\n const nodePropName = `__elur_${eventName}`;\n const nodeModsName = `__elur_${eventName}_mods`;\n return () => {\n (el as any)[nodePropName] = null;\n (el as any)[nodeModsName] = null;\n };\n}\n\n/** Returns true if an event name is in the delegable set. */\nexport function isDelegableEvent(eventName: string): boolean {\n return DELEGABLE_EVENTS.has(eventName);\n}\n\n// =============================================================================\n// --- Binding activation ---\n// =============================================================================\n\n/** Activates all bindings on the cloned fragment. Returns dispose/postMount. */\nexport function activateBindings(\n fragment: DocumentFragment,\n contexts: BindingContext[],\n values: unknown[],\n pathMap: Array<{ nodeIndex: number; name?: string } | null>,\n): { disposes: Array<() => void>; postMountHooks: Array<() => void> } {\n // PHASE 1: READ — single-pass TreeWalker O(N)\n const resolvedNodes = new Array<Node | null>(contexts.length);\n\n let maxNodeIndex = -1;\n for (let i = 0; i < contexts.length; i++) {\n if (pathMap[i] && pathMap[i]!.nodeIndex > maxNodeIndex) {\n maxNodeIndex = pathMap[i]!.nodeIndex;\n }\n }\n\n const flatNodes = new Array<Node>(maxNodeIndex + 1);\n flatNodes[0] = fragment;\n if (maxNodeIndex > 0) {\n const walker = document.createTreeWalker(fragment, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT);\n let fi = 1;\n let currentNode: Node | null;\n while (fi <= maxNodeIndex && (currentNode = walker.nextNode())) {\n flatNodes[fi++] = currentNode;\n }\n }\n\n for (let i = 0; i < contexts.length; i++) {\n const info = pathMap[i];\n resolvedNodes[i] = info ? flatNodes[info.nodeIndex] : null;\n }\n\n // PHASE 2: MUTATE (delegated to _activateBindingsWithNodes)\n return _activateBindingsWithNodes(fragment, contexts, values, pathMap, resolvedNodes);\n}\n\n/**\n * Activates bindings using pre-resolved nodes — skips the TreeWalker phase.\n * Used by the compiler's __elurCompiledTemplate to eliminate the second TreeWalker.\n */\nexport function _activateBindingsWithNodes(\n _fragment: DocumentFragment,\n contexts: BindingContext[],\n values: unknown[],\n pathMap: Array<{ nodeIndex: number; name?: string } | null>,\n resolvedNodes: Array<Node | null>,\n): { disposes: Array<() => void>; postMountHooks: Array<() => void> } {\n const disposes: Array<() => void> = [];\n const postMountHooks: Array<() => void> = [];\n\n for (let i = 0; i < contexts.length; i++) {\n const ctx = contexts[i];\n const value = values[i];\n const info = pathMap[i];\n if (!info) continue;\n\n const el = resolvedNodes[i]!;\n\n // --- Events ---\n if (ctx.type === \"event\") {\n const eventName = info.name!;\n const rawHandler = value as EventListener;\n const mods = ctx.modifiers;\n\n const canDelegate =\n isDelegableEvent(eventName) &&\n !mods.includes(\"capture\") &&\n !mods.includes(\"once\") &&\n !mods.includes(\"passive\");\n\n if (canDelegate) {\n disposes.push(activateDelegatedEvent(el as Element, eventName, mods, rawHandler));\n } else {\n const listenerOpts: AddEventListenerOptions = {\n once: mods.includes(\"once\"),\n capture: mods.includes(\"capture\"),\n passive: mods.includes(\"passive\")\n };\n const handler = (e: Event) => {\n if (mods.includes(\"prevent\")) e.preventDefault();\n if (mods.includes(\"stop\")) e.stopPropagation();\n if (mods.includes(\"self\") && e.target !== e.currentTarget) return;\n rawHandler(e);\n };\n el.addEventListener(eventName, handler, listenerOpts);\n disposes.push(() => el.removeEventListener(eventName, handler, listenerOpts));\n }\n continue;\n }\n\n // --- Attributes ---\n if (ctx.type === \"attr\") {\n const attrName = info.name!;\n const element = el as Element;\n\n if (attrName === \"ref\") {\n (value as ElurRef<Element>).el = element;\n disposes.push(() => { (value as ElurRef<Element>).el = null; });\n continue;\n }\n\n if (attrName === \"show\" || attrName === \"hide\") {\n const htmlEl = element as HTMLElement;\n let originalDisplay: string | null = null;\n\n if (typeof value === \"function\") {\n let queued = false;\n let pendingVisible = false;\n let isFirstRun = true;\n\n const dispose = effect(() => {\n pendingVisible = Boolean((value as () => unknown)());\n const update = () => {\n queued = false;\n const shouldShow = attrName === \"show\" ? pendingVisible : !pendingVisible;\n if (originalDisplay === null) {\n originalDisplay = htmlEl.style.display || \"\";\n }\n htmlEl.style.display = shouldShow ? originalDisplay : \"none\";\n };\n\n if (isFirstRun) {\n isFirstRun = false;\n update();\n } else if (!queued) {\n queued = true;\n queueDOMWrite(update);\n }\n });\n disposes.push(dispose);\n } else {\n const shouldShow = attrName === \"show\" ? Boolean(value) : !Boolean(value);\n if (!shouldShow) htmlEl.style.display = \"none\";\n }\n continue;\n }\n\n // on*/srcdoc bindings are non-idiomatic in Elur (events use @click) and\n // turn an untrusted value into executable code. Warn the developer but\n // do not block — the attribute name is developer-authored.\n if (ctx.executable ?? isExecutableAttrName(attrName)) {\n console.warn(\n `[elur] Dynamic binding on executable attribute \"${attrName}\". Use @event for handlers; avoid binding untrusted values here.`,\n );\n }\n\n // Precomputed at compile time. Only URL attributes pay the sanitizer;\n // class/style/aria-*/data-*/custom attributes skip it entirely.\n const isUrl = ctx.url ?? isUrlAttrName(attrName);\n\n const isDomProp = (attrName === \"value\" || attrName === \"checked\" || attrName === \"selected\") && attrName in element;\n\n if (typeof value === \"function\") {\n let queued = false;\n let pendingValue: unknown;\n let isFirstRun = true;\n\n const dispose = effect(() => {\n pendingValue = (value as () => unknown)();\n const update = () => {\n queued = false;\n const v = pendingValue;\n if (isDomProp) {\n (element as any)[attrName] = v ?? \"\";\n } else if (v == null || v === false) {\n element.removeAttribute(attrName);\n } else {\n const s = String(v);\n element.setAttribute(attrName, isUrl ? sanitizeUrl(s) : s);\n }\n };\n\n if (isFirstRun) {\n isFirstRun = false;\n update();\n } else if (!queued) {\n queued = true;\n queueDOMWrite(update);\n }\n });\n disposes.push(dispose);\n } else {\n if (isDomProp) {\n (element as any)[attrName] = value ?? \"\";\n } else if (value != null && value !== false) {\n const s = String(value);\n element.setAttribute(attrName, isUrl ? sanitizeUrl(s) : s);\n }\n }\n continue;\n }\n\n // --- Nodes — delegate to node-binding.ts ---\n const originalAnchor = el as Comment;\n if (!originalAnchor) continue;\n\n const anchor = document.createTextNode(\"\");\n originalAnchor.parentNode!.replaceChild(anchor, originalAnchor);\n\n activateNodeBinding(anchor, value, disposes, postMountHooks);\n }\n\n return { disposes, postMountHooks };\n}\n"],"mappings":"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"}
|
package/dist/lib/router.cjs
CHANGED
|
@@ -7,6 +7,6 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
|
|
|
7
7
|
`;let a=i.route.chain[e];return a?a():r.html`
|
|
8
8
|
<span></span>
|
|
9
9
|
`}}</div>`}},O=class extends t.ElurComponent{_to;_label;_router;constructor(e,t,n){super(),this._to=e,this._label=t,this._router=n}render(){let e=this._to,t=this._label,n=this._router??T(),i=e.startsWith(`/`)?e:`/`+e,a=(n._base?n._base+i:i).replace(/\/+/g,`/`);return r.html`
|
|
10
|
-
<a href=${n._mode===`hash`?`#`+a:a} style=${()=>n.current.value===
|
|
10
|
+
<a href=${n._mode===`hash`?`#`+a:a} style=${()=>n.current.value===i?`color:#38bdf8;font-weight:700;text-decoration:none;cursor:pointer;padding:4px 10px;border-radius:4px;background:#0c2a3a`:`color:#a3a3a3;text-decoration:none;cursor:pointer;padding:4px 10px;border-radius:4px`} @click=${t=>{t.preventDefault(),n.navigate(e)}}>${t}</a>
|
|
11
11
|
`}};function k(){let e=i._mountedRouters.length?i._mountedRouters[i._mountedRouters.length-1]:a;if(!e)return null;let t=e,n=t.current.value,r=x(n,t._flat),o=r?.route.beforeEnter,s=t._guards.map((e,t)=>e.name||`beforeEach#${t+1}`);return o&&s.push(o.name||`beforeEnter`),{mode:t._mode,base:t._base||`/`,currentPath:n,params:{...t.params.value},query:{...t.query.value},matchedPath:r?.route.fullPath??null,activeGuards:{globalCount:t._guards.length,hasRouteGuard:!!o,names:s}}}exports.Link=O,exports.RouterKey=i.RouterKey,exports.RouterView=D,exports._debugGetRouterInternal=k,exports._debugRegisterRouter=i._debugRegisterRouter,exports._debugUnregisterRouter=i._debugUnregisterRouter,exports._hasActiveRouter=u,exports._resetRouter=E,exports.createRouter=w,exports.elurRouter=T;
|
|
12
12
|
//# sourceMappingURL=router.cjs.map
|
package/dist/lib/router.js
CHANGED
|
@@ -476,7 +476,7 @@ var j = class extends t {
|
|
|
476
476
|
render() {
|
|
477
477
|
let e = this._to, t = this._label, n = this._router ?? k(), i = e.startsWith("/") ? e : "/" + e, a = (n._base ? n._base + i : i).replace(/\/+/g, "/");
|
|
478
478
|
return r`
|
|
479
|
-
<a href=${n._mode === "hash" ? "#" + a : a} style=${() => n.current.value ===
|
|
479
|
+
<a href=${n._mode === "hash" ? "#" + a : a} style=${() => n.current.value === i ? "color:#38bdf8;font-weight:700;text-decoration:none;cursor:pointer;padding:4px 10px;border-radius:4px;background:#0c2a3a" : "color:#a3a3a3;text-decoration:none;cursor:pointer;padding:4px 10px;border-radius:4px"} @click=${(t) => {
|
|
480
480
|
t.preventDefault(), n.navigate(e);
|
|
481
481
|
}}>${t}</a>
|
|
482
482
|
`;
|
package/dist/lib/server.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./elur/template/types.cjs`),t=require(`./lifecycle.cjs`),n=require(`./context.cjs`),r=require(`./elur/template/keyed.cjs`),i=require(`./elur/template/sanitize.cjs`);let a=require(`node:async_hooks`);var o=e.isElurTemplate,s=e.isKeyedList,c=new a.AsyncLocalStorage;n._setContextScopeResolver(()=>c.getStore());function l(e={}){let t=new AbortController,n={markers:e.markers===`hydration`,context:e.context,onError:e.onError},r=e=>Promise.resolve(c.run([],e));return{signal:t.signal,async render(e,i){let a={...n,markers:i?.markers??n.markers,signal:t.signal},o=``;return await r(()=>(async()=>{for await(let t of p(e,a))o+=t.value})()),o},renderToChunks(e,r){return u(e,{...n,markers:r?.markers??n.markers,signal:t.signal})},abort(e){t.abort(e)}}}function u(e,t){return{async*[Symbol.asyncIterator](){let n=[],r=[],i=!1,a,o=()=>{r.shift()?.()},s=c.run([],async()=>{try{for await(let r of p(e,t))n.push(r),o()}catch(e){a=e}finally{i=!0,o()}});for(;;){for(;n.length===0&&!i;)await new Promise(e=>r.push(e));if(n.length===0)break;let e=n.shift();e&&(yield e)}if(a)throw a;yield{type:`done`,value:``,index:-1},await s}}}async function d(e,t={}){let n={markers:t.markers===`hydration`,signal:t.signal,context:t.context,onError:t.onError},r=``;return await Promise.resolve(c.run([],async()=>{for await(let t of p(e,n))r+=t.value})),r}function f(e,t={}){return u(e,{markers:t.markers===`hydration`,signal:t.signal,context:t.context,onError:t.onError})}async function*p(n,i){if(_(i),n instanceof Promise){yield*p(await n,i);return}if(!(n==null||n===!1||n===!0)){if(typeof n==`string`||typeof n==`number`||typeof n==`bigint`){yield{type:`markup`,value:b(String(n)),index:-1};return}if(Array.isArray(n)){let e=await Promise.all(n.map(e=>v(e)));_(i);for(let t of e)i.markers&&(yield{type:`markup`,value:`<!--elur-ai-->`,index:-1}),yield*p(t,i),i.markers&&(yield{type:`markup`,value:`<!--elur-aiend-->`,index:-1});return}if((typeof n==`object`||typeof n==`function`)&&n!==null){let t=n[e.ELUR_RENDER_PROTOCOL];if(t?.renderServer){let e=await t.renderServer({markers:i.markers,signal:i.signal,context:i.context,render:(e,t)=>g(e,{...i,markers:t?.markers??i.markers})});_(i),yield{type:`markup`,value:e,index:-1};return}}if(t.isElurComponent(n)){yield*m(n,i);return}if(s(n)){if(!i.markers){yield{type:`markup`,value:(await Promise.all(n.items.map((e,t)=>g(n.renderFn(e,t),i)))).join(``),index:-1};return}let e=new Set;for(let t=0;t<n.items.length;t++){let a=n.items[t],o=r.normalizeRepeatKey(n.keyFn(a,t),t),s=r.serializeRepeatKey(o);e.has(s)&&console.warn(`[elur] repeat(): duplicate key "${o}" during server render. Keys must be unique; entries after the first will leak during hydration.`),e.add(s),yield{type:`markup`,value:`<!--elur-ki:${s}-->`,index:-1},yield*p(n.renderFn(a,t),i),yield{type:`markup`,value:`<!--elur-ke-->`,index:-1}}return}if(o(n)){let t=n[e.ELUR_TEMPLATE_DESCRIPTOR];if(!t)throw TypeError(`[elur] Template does not support server rendering`);yield*h(t,i);return}yield{type:`markup`,value:b(String(n)),index:-1}}}async function*m(e,t){n._pushComponentContext();let r={index:-1,context:`component`,cause:void 0,component:e._debugName};try{try{e.onInit?.(),e.onServerRender?.()}catch(t){if(e.onError)e.onError(t);else throw t}try{yield*p(e.render(),t)}catch(t){if(e.onError){e.onError(t);return}throw t}}catch(e){throw t.onError?.(e,{...r,cause:e}),e}finally{n._popComponentContext()}}async function*h(e,t){let n=new Uint8Array(e.strings.length);for(let r=0;r<e.strings.length;r++){if(t.signal?.aborted)throw t.signal.reason??new DOMException(`Render aborted`,`AbortError`);let a=e.strings[r];if(n[r]===1&&(a[0]===`"`||a[0]===`'`)&&(a=a.slice(1)),r>=e.contexts.length){yield{type:`markup`,value:a,index:r};continue}let o=e.contexts[r],s=e.values[r];if(o.type===`node`){yield{type:`markup`,value:a,index:r},t.markers&&(yield{type:`boundary-start`,value:`<!--elur-${r}-->`,index:r});try{let e=await v(s);_(t),yield*p(e,t)}catch(e){throw t.onError?.(e,{index:r,context:`node`,cause:e}),e}t.markers&&(yield{type:`boundary-end`,value:`<!--elur-end-${r}-->`,index:r});continue}let c=y(o),l=a.slice(0,-c);if(o.hadOpenQuote&&(n[r+1]=1),o.type===`event`){t.markers?yield{type:`markup`,value:`${l}${/\s$/.test(l)?``:` `}data-elur-e-${r}="${x(o.eventName)}"`,index:r}:yield{type:`markup`,value:l.replace(/\s+$/,``),index:r};continue}yield{type:`markup`,value:l,index:r};let u=await v(s);if(_(t),o.attrName!==`ref`&&u!=null&&u!==!1){let e=o.url?i.sanitizeUrl(String(u)):String(u);yield{type:`markup`,value:`${/\s$/.test(l)?``:` `}${o.attrName}="${x(e)}"`,index:r}}t.markers&&(yield{type:`markup`,value:` data-elur-a-${r}="${x(o.attrName)}"`,index:r})}}async function g(e,t){let n=``;for await(let r of p(e,t))n+=r.value;return n}function _(e){if(e.signal?.aborted)throw e.signal.reason??new DOMException(`Render aborted`,`AbortError`)}async function v(e){let t=typeof e==`function`?e():e;return t instanceof Promise?await t:t}function y(e){return e.type===`event`?`@${e.modifiers.length?`${e.eventName}.${e.modifiers.join(`.`)}`:e.eventName}=`.length+ +!!e.hadOpenQuote:`${e.attrName}=`.length+ +!!e.hadOpenQuote}function b(e){return e.replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`)}function x(e){return b(e).replace(/"/g,`"`)}exports.createServerRenderScope=l,exports.renderToChunks=f,exports.renderToString=d;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./elur/template/types.cjs`),t=require(`./lifecycle.cjs`),n=require(`./context.cjs`),r=require(`./elur/template/keyed.cjs`),i=require(`./elur/template/sanitize.cjs`);let a=require(`node:async_hooks`);var o=e.isElurTemplate,s=e.isKeyedList,c=new a.AsyncLocalStorage;n._setContextScopeResolver(()=>c.getStore());function l(e={}){let t=new AbortController,n={markers:e.markers===`hydration`,context:e.context,onError:e.onError},r=e=>Promise.resolve(c.run([],e));return{signal:t.signal,async render(e,i){let a={...n,markers:i?.markers??n.markers,signal:t.signal},o=``;return await r(()=>(async()=>{for await(let t of p(e,a))o+=t.value})()),o},renderToChunks(e,r){return u(e,{...n,markers:r?.markers??n.markers,signal:t.signal})},abort(e){t.abort(e)}}}function u(e,t){return{async*[Symbol.asyncIterator](){let n=[],r=[],i=!1,a,o=()=>{r.shift()?.()},s=c.run([],async()=>{try{for await(let r of p(e,t))n.push(r),o()}catch(e){a=e}finally{i=!0,o()}});for(;;){for(;n.length===0&&!i;)await new Promise(e=>r.push(e));if(n.length===0)break;let e=n.shift();e&&(yield e)}if(a)throw yield{type:`error`,value:a instanceof Error?a.message:String(a),index:-1},a;yield{type:`done`,value:``,index:-1},await s}}}async function d(e,t={}){let n={markers:t.markers===`hydration`,signal:t.signal,context:t.context,onError:t.onError},r=``;return await Promise.resolve(c.run([],async()=>{for await(let t of p(e,n))r+=t.value})),r}function f(e,t={}){return u(e,{markers:t.markers===`hydration`,signal:t.signal,context:t.context,onError:t.onError})}async function*p(n,i){if(_(i),n instanceof Promise){yield*p(await n,i);return}if(!(n==null||n===!1||n===!0)){if(typeof n==`string`||typeof n==`number`||typeof n==`bigint`){yield{type:`markup`,value:b(String(n)),index:-1};return}if(Array.isArray(n)){let e=await Promise.all(n.map(e=>v(e)));_(i);for(let t of e)i.markers&&(yield{type:`markup`,value:`<!--elur-ai-->`,index:-1}),yield*p(t,i),i.markers&&(yield{type:`markup`,value:`<!--elur-aiend-->`,index:-1});return}if((typeof n==`object`||typeof n==`function`)&&n!==null){let t=n[e.ELUR_RENDER_PROTOCOL];if(t?.renderServer){let e=await t.renderServer({markers:i.markers,signal:i.signal,context:i.context,render:(e,t)=>g(e,{...i,markers:t?.markers??i.markers})});_(i),yield{type:`markup`,value:e,index:-1};return}}if(t.isElurComponent(n)){yield*m(n,i);return}if(s(n)){if(!i.markers){yield{type:`markup`,value:(await Promise.all(n.items.map((e,t)=>g(n.renderFn(e,t),i)))).join(``),index:-1};return}let e=new Set;for(let t=0;t<n.items.length;t++){let a=n.items[t],o=r.normalizeRepeatKey(n.keyFn(a,t),t),s=r.serializeRepeatKey(o);e.has(s)&&console.warn(`[elur] repeat(): duplicate key "${o}" during server render. Keys must be unique; entries after the first will leak during hydration.`),e.add(s),yield{type:`markup`,value:`<!--elur-ki:${s}-->`,index:-1},yield*p(n.renderFn(a,t),i),yield{type:`markup`,value:`<!--elur-ke-->`,index:-1}}return}if(o(n)){let t=n[e.ELUR_TEMPLATE_DESCRIPTOR];if(!t)throw TypeError(`[elur] Template does not support server rendering`);yield*h(t,i);return}yield{type:`markup`,value:b(String(n)),index:-1}}}async function*m(e,t){n._pushComponentContext();let r={index:-1,context:`component`,cause:void 0,component:e._debugName};try{try{e.onInit?.(),e.onServerRender?.()}catch(t){if(e.onError)e.onError(t);else throw t}try{yield*p(e.render(),t)}catch(t){if(e.onError){e.onError(t);return}throw t}}catch(e){throw t.onError?.(e,{...r,cause:e}),e}finally{n._popComponentContext()}}async function*h(e,t){let n=new Uint8Array(e.strings.length);for(let r=0;r<e.strings.length;r++){if(t.signal?.aborted)throw t.signal.reason??new DOMException(`Render aborted`,`AbortError`);let a=e.strings[r];if(n[r]===1&&(a[0]===`"`||a[0]===`'`)&&(a=a.slice(1)),r>=e.contexts.length){yield{type:`markup`,value:a,index:r};continue}let o=e.contexts[r],s=e.values[r];if(o.type===`node`){yield{type:`markup`,value:a,index:r},t.markers&&(yield{type:`boundary-start`,value:`<!--elur-${r}-->`,index:r});try{let e=await v(s);_(t),yield*p(e,t)}catch(e){throw t.onError?.(e,{index:r,context:`node`,cause:e}),e}t.markers&&(yield{type:`boundary-end`,value:`<!--elur-end-${r}-->`,index:r});continue}let c=y(o),l=a.slice(0,-c);if(o.hadOpenQuote&&(n[r+1]=1),o.type===`event`){t.markers?yield{type:`markup`,value:`${l}${/\s$/.test(l)?``:` `}data-elur-e-${r}="${x(o.eventName)}"`,index:r}:yield{type:`markup`,value:l.replace(/\s+$/,``),index:r};continue}yield{type:`markup`,value:l,index:r};let u=await v(s);if(_(t),o.attrName!==`ref`&&u!=null&&u!==!1){let e=o.url?i.sanitizeUrl(String(u)):String(u);yield{type:`markup`,value:`${/\s$/.test(l)?``:` `}${o.attrName}="${x(e)}"`,index:r}}t.markers&&(yield{type:`markup`,value:` data-elur-a-${r}="${x(o.attrName)}"`,index:r})}}async function g(e,t){let n=``;for await(let r of p(e,t))n+=r.value;return n}function _(e){if(e.signal?.aborted)throw e.signal.reason??new DOMException(`Render aborted`,`AbortError`)}async function v(e){let t=typeof e==`function`?e():e;return t instanceof Promise?await t:t}function y(e){return e.type===`event`?`@${e.modifiers.length?`${e.eventName}.${e.modifiers.join(`.`)}`:e.eventName}=`.length+ +!!e.hadOpenQuote:`${e.attrName}=`.length+ +!!e.hadOpenQuote}function b(e){return e.replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`)}function x(e){return b(e).replace(/"/g,`"`)}exports.createServerRenderScope=l,exports.renderToChunks=f,exports.renderToString=d;
|
|
2
2
|
//# sourceMappingURL=server.cjs.map
|
package/dist/lib/server.js
CHANGED
package/dist/lib/store.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./signals.cjs`);var t=class extends e.Signal{label;constructor(e,t=`ReadonlySignal`){super(e.peek()),this.label=t,Object.defineProperty(this,`value`,{get:()=>e.value,set:()=>{throw Error(`[elur] "${this.label}" is read-only.`)},configurable:!1}),this.update=()=>{throw Error(`[elur] "${this.label}" is read-only.`)},this.dispose=()=>{throw Error(`[elur] Cannot dispose "${this.label}" directly.`)}}},n=new Set([`$id`,`$state`,`$stateSignal`,`$snapshot`,`$reset`,`$patch`,`$watch`,`$dispose`]);function r(e){if(e===`__proto__`||e===`constructor`||e===`prototype`)throw Error(`[elur] Store key "${e}" is not allowed for security reasons.`);if(n.has(e))throw Error(`[elur] Store key "${e}" is reserved.`)}function i(e,t){return n.has(e)?(console.warn(`[elur] Store ${t} "${e}" is reserved and will be ignored.`),!1):!0}function a(e,n){return new t(e,n)}function o(t,o){let{name:s=`store`,actions:c,getters:l,plugins:u=[],serialize:d}=o??{},f=Object.keys(t),p={};for(let n of f)r(n),p[n]=e.signal(t[n]);let m=p,h=e.computed(()=>{let e={};for(let t of f)e[t]=p[t].value;return e}),g=a(h,`store "${s}".$stateSignal`),_;try{_=d?d(t):structuredClone(t)}catch(e){throw Error(`[elur] Store "${s}" initialState contains non-serializable data (functions, DOM nodes, Symbols, or WeakRefs). Provide a custom \`serialize\` option or remove these before creating the store. Original error: ${e}`)}let v=[];function y(){let t=x();for(let e of v)e(
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./signals.cjs`);var t=class extends e.Signal{label;constructor(e,t=`ReadonlySignal`){super(e.peek()),this.label=t,Object.defineProperty(this,`value`,{get:()=>e.value,set:()=>{throw Error(`[elur] "${this.label}" is read-only.`)},configurable:!1}),this.update=()=>{throw Error(`[elur] "${this.label}" is read-only.`)},this.dispose=()=>{throw Error(`[elur] Cannot dispose "${this.label}" directly.`)}}},n=new Set([`$id`,`$state`,`$stateSignal`,`$snapshot`,`$reset`,`$patch`,`$watch`,`$dispose`]);function r(e){if(e===`__proto__`||e===`constructor`||e===`prototype`)throw Error(`[elur] Store key "${e}" is not allowed for security reasons.`);if(n.has(e))throw Error(`[elur] Store key "${e}" is reserved.`)}function i(e,t){return n.has(e)?(console.warn(`[elur] Store ${t} "${e}" is reserved and will be ignored.`),!1):!0}function a(e,n){return new t(e,n)}function o(t,o){let{name:s=`store`,actions:c,getters:l,plugins:u=[],serialize:d}=o??{},f=Object.keys(t),p={};for(let n of f)r(n),p[n]=e.signal(t[n]);let m=p,h=e.computed(()=>{let e={};for(let t of f)e[t]=p[t].value;return e}),g=a(h,`store "${s}".$stateSignal`),_;try{_=d?d(t):structuredClone(t)}catch(e){throw Error(`[elur] Store "${s}" initialState contains non-serializable data (functions, DOM nodes, Symbols, or WeakRefs). Provide a custom \`serialize\` option or remove these before creating the store. Original error: ${e}`)}let v=[];function y(){let t=x(),n=_;for(let e of v){let r=e(n,t);r!==void 0&&(n={...n,...r})}e.batch(()=>{for(let e of f)p[e].value=n[e]})}function b(t){let n=t,r=x();for(let e of v){let t=e(n,r);t!==void 0&&(n=t)}e.batch(()=>{for(let e of Object.keys(n))Object.prototype.hasOwnProperty.call(p,e)&&(p[e].value=n[e])})}function x(){let e={};for(let t of f)e[t]=p[t].peek();return e}function S(t,n){return e.watch(h,t,n)}let C=Object.assign(Object.create(null),m,{$reset:y,$patch:b,$watch:S,$snapshot:x});Object.defineProperty(C,`$id`,{value:s,writable:!1,enumerable:!1,configurable:!1}),Object.defineProperty(C,`$state`,{get(){return h.value},enumerable:!0,configurable:!1}),Object.defineProperty(C,`$stateSignal`,{value:g,writable:!1,enumerable:!1,configurable:!1}),Object.defineProperty(C,`_guardFns`,{value:v,writable:!1,enumerable:!1,configurable:!1});let w=new Set([...f,...Array.from(n)]);if(c){let e=c(m);for(let t of Object.keys(e))if(i(t,`action`)){if(w.has(t)){console.warn(`[elur] Store "${s}": action "${t}" collides with an existing signal or getter and will be ignored.`);continue}w.add(t),C[t]=e[t]}}if(l){let t=l(m);for(let n of Object.keys(t)){if(!i(n,`getter`))continue;if(w.has(n)){console.warn(`[elur] Store "${s}": getter "${n}" collides with an existing signal or action and will be ignored.`);continue}let r=t[n];if(!(r instanceof e.Signal))throw TypeError(`[elur] Store "${s}": getter "${n}" must return a Signal (wrap it with computed()). Got: ${typeof r}`);w.add(n),C[n]=a(r,`getter "${n}" in store "${s}"`)}}let T=[()=>h.dispose()];for(let e of u)try{let t=e(C);typeof t==`function`&&T.push(t)}catch(e){console.error(`[elur] Plugin initialization failed for store "${s}":`,e)}return C.$dispose=()=>{for(let e of T)e()},C}exports.ReadonlySignal=t,exports.createStore=o;
|
|
2
2
|
//# sourceMappingURL=store.cjs.map
|
package/dist/lib/store.js
CHANGED
|
@@ -50,10 +50,16 @@ function u(a, u) {
|
|
|
50
50
|
}
|
|
51
51
|
let S = [];
|
|
52
52
|
function C() {
|
|
53
|
-
let e = T();
|
|
54
|
-
for (let t of S)
|
|
53
|
+
let e = T(), n = x;
|
|
54
|
+
for (let t of S) {
|
|
55
|
+
let r = t(n, e);
|
|
56
|
+
r !== void 0 && (n = {
|
|
57
|
+
...n,
|
|
58
|
+
...r
|
|
59
|
+
});
|
|
60
|
+
}
|
|
55
61
|
t(() => {
|
|
56
|
-
for (let e of g) _[e].value =
|
|
62
|
+
for (let e of g) _[e].value = n[e];
|
|
57
63
|
});
|
|
58
64
|
}
|
|
59
65
|
function w(e) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elurjs/core",
|
|
3
|
-
"version": "3.6.
|
|
3
|
+
"version": "3.6.2",
|
|
4
4
|
"description": "A lightweight, fully reactive framework — no virtual DOM, no compiler, just signals and tagged templates.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Deiver Vasquez",
|
|
@@ -61,6 +61,14 @@
|
|
|
61
61
|
"import": "./dist/lib/store.js",
|
|
62
62
|
"require": "./dist/lib/store.cjs"
|
|
63
63
|
},
|
|
64
|
+
"./plugins": {
|
|
65
|
+
"types": {
|
|
66
|
+
"import": "./dist/lib/elur/plugins.d.ts",
|
|
67
|
+
"require": "./dist/lib/elur/plugins.d.cts"
|
|
68
|
+
},
|
|
69
|
+
"import": "./dist/lib/plugins.js",
|
|
70
|
+
"require": "./dist/lib/plugins.cjs"
|
|
71
|
+
},
|
|
64
72
|
"./async": {
|
|
65
73
|
"types": {
|
|
66
74
|
"import": "./dist/lib/elur/async.d.ts",
|
|
@@ -140,6 +148,9 @@
|
|
|
140
148
|
"store": [
|
|
141
149
|
"./dist/lib/elur/store.d.ts"
|
|
142
150
|
],
|
|
151
|
+
"plugins": [
|
|
152
|
+
"./dist/lib/elur/plugins.d.ts"
|
|
153
|
+
],
|
|
143
154
|
"async": [
|
|
144
155
|
"./dist/lib/elur/async.d.ts"
|
|
145
156
|
],
|