@vielzeug/ore 26.11.5 → 26.11.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/base-element.cjs +1 -1
  2. package/dist/base-element.cjs.map +1 -1
  3. package/dist/base-element.js +1 -1
  4. package/dist/define.cjs +1 -1
  5. package/dist/define.cjs.map +1 -1
  6. package/dist/define.js +1 -1
  7. package/dist/directives/each.cjs +1 -1
  8. package/dist/directives/each.cjs.map +1 -1
  9. package/dist/directives/each.js +1 -1
  10. package/dist/directives/unsafe-html.cjs +1 -1
  11. package/dist/directives/unsafe-html.cjs.map +1 -1
  12. package/dist/directives/unsafe-html.js +1 -1
  13. package/dist/directives/when.cjs +1 -1
  14. package/dist/directives/when.cjs.map +1 -1
  15. package/dist/directives/when.js +1 -1
  16. package/dist/host-bind.cjs +1 -1
  17. package/dist/host-bind.cjs.map +1 -1
  18. package/dist/host-bind.js +1 -1
  19. package/dist/index.cjs +1 -1
  20. package/dist/index.js +1 -1
  21. package/dist/ore.js +12 -25
  22. package/dist/ore.js.map +1 -1
  23. package/dist/props.cjs +1 -1
  24. package/dist/props.cjs.map +1 -1
  25. package/dist/props.js +1 -1
  26. package/dist/template/bindings.cjs +1 -1
  27. package/dist/template/bindings.cjs.map +1 -1
  28. package/dist/template/bindings.js +1 -1
  29. package/dist/template/instantiator.cjs +1 -1
  30. package/dist/template/instantiator.cjs.map +1 -1
  31. package/dist/template/instantiator.js +1 -1
  32. package/dist/testing/mount.cjs +1 -1
  33. package/dist/testing/mount.cjs.map +1 -1
  34. package/dist/testing/mount.js +1 -1
  35. package/dist/testing/render-hook.cjs +1 -1
  36. package/dist/testing/render-hook.cjs.map +1 -1
  37. package/dist/testing/render-hook.js +1 -1
  38. package/dist/testing.cjs +1 -1
  39. package/dist/testing.cjs.map +1 -1
  40. package/dist/testing.js +1 -1
  41. package/package.json +11 -11
@@ -1,2 +1,2 @@
1
- const e=require("./errors.cjs"),t=require("./runtime.cjs"),n=require("./props.cjs"),r=require("./utils/css.cjs");let i=require("@vielzeug/ripple");var a={SETUP_DONE:`setup_done`,SETUP_RUNNING:`setup_running`,UNINITIALIZED:`uninitialized`,UNMOUNTED:`unmounted`},o=()=>({formResetCallbacks:[],generation:0,mountCallbacks:[],phase:a.UNINITIALIZED,scope:(0,i.createScope)(),templateResult:null}),s=e=>(typeof e==`object`||typeof e==`function`)&&e!==null&&`then`in e&&typeof e.then==`function`,c=class extends HTMLElement{static _definition;static _normalizedPropDefs;static formAssociated=!1;static observedAttributes=[];_component;constructor(){super();let e=this.constructor._definition;e?.shadow!==!1&&this.attachShadow({mode:`open`,...e?.shadow}),this._component=o()}connectedCallback(){(0,i.untrack)(()=>{this._component.phase===a.UNINITIALIZED&&this._runSetup(),this._init()})}attributeChangedCallback(e,t,r){if(t===r)return;let a=n.getPropMeta(this,e);if(!a)return;let o=a.parse(r);Object.is((0,i.untrack)(()=>a.signal.value),o)||(a.signal.value=o)}disconnectedCallback(){this._component.generation++,this._component.phase=a.UNMOUNTED,this._resetSetupState()}_resetSetupState(){this._component.scope.dispose(),this._component.formResetCallbacks=[],this._component.mountCallbacks=[],this._component.phase=a.UNINITIALIZED,this._component.scope=(0,i.createScope)(),this._component.templateResult=null}formResetCallback(){for(let e of this._component.formResetCallbacks)try{e()}catch(e){this._reportLifecycleError(e,`form-reset`)}}_reportLifecycleError(t,n){let r=t instanceof Error?t:Error(String(t)),i=new e.OreLifecycleError(`<${this.localName}> failed during ${this._component.phase} (${n})`,{cause:r,component:this.localName,phase:n});e.reportRuntimeError(i,this)}_runSetup(){this._component.phase=a.SETUP_RUNNING;let r=this.constructor._definition,i=this.constructor._normalizedPropDefs,o=t.createRuntimeContext(this);try{let c;if(this._component.scope.run(()=>{c=t.runWithContext(o,()=>{let e=i?n.createProps(this,i):{};return r.setup(e)})}),this._component.mountCallbacks.push(...o.mountCallbacks),this._component.formResetCallbacks.push(...o.formResetCallbacks),s(c))throw new e.OreApiError(e.ORE_ERRORS.asyncSetupUnsupported);this._component.templateResult=c??null,this._component.phase=a.SETUP_DONE}catch(e){throw this._reportLifecycleError(e,`setup`),this._resetSetupState(),e}}_isStale(e){return this._component.generation!==e||!this.isConnected}_applyResult(e){if(!e)return;let n=this.shadowRoot??this,r=t.createRuntimeContext(this);n.replaceChildren(),this._component.scope.run(()=>{t.runWithContext(r,()=>{e.mount(n,null,t.onCleanup)})})}_init(){this._applyStyles(),this._mountTemplate(),this._component.phase===a.SETUP_DONE&&this._scheduleMountCallbacks()}_applyStyles(){let e=this.constructor._definition;this.shadowRoot&&e?.styles?.length&&(this.shadowRoot.adoptedStyleSheets=e.styles.map(r.loadStylesheet))}_mountTemplate(){let e=this._component.templateResult;e&&this._applyResult(e)}_scheduleMountCallbacks(){if(this._component.mountCallbacks.length===0)return;let e=this._component.generation,n=t.beginPendingWork();queueMicrotask(()=>{try{if(this._isStale(e))return;let n=this._component.mountCallbacks.splice(0);for(let e=0;e<n.length;e++){let r=n[e];try{let e=t.createRuntimeContext(this);this._component.scope.run(()=>{t.runWithContext(e,()=>{let e=r();typeof e==`function`&&t.onCleanup(e)})}),e.mountCallbacks.length>0&&n.push(...e.mountCallbacks),e.formResetCallbacks.length>0&&this._component.formResetCallbacks.push(...e.formResetCallbacks)}catch(e){this._reportLifecycleError(e,`mounted`)}}}finally{n()}})}};exports.BaseElement=c;
1
+ const e=require("./errors.cjs"),t=require("./props.cjs"),n=require("./runtime.cjs"),r=require("./utils/css.cjs");let i=require("@vielzeug/ripple");var a={SETUP_DONE:`setup_done`,SETUP_RUNNING:`setup_running`,UNINITIALIZED:`uninitialized`,UNMOUNTED:`unmounted`},o=()=>({formResetCallbacks:[],generation:0,mountCallbacks:[],phase:a.UNINITIALIZED,scope:(0,i.createScope)(),templateResult:null}),s=e=>(typeof e==`object`||typeof e==`function`)&&e!==null&&`then`in e&&typeof e.then==`function`,c=class extends HTMLElement{static _definition;static _normalizedPropDefs;static formAssociated=!1;static observedAttributes=[];_component;constructor(){super();let e=this.constructor._definition;e?.shadow!==!1&&this.attachShadow({mode:`open`,...e?.shadow}),this._component=o()}connectedCallback(){(0,i.untrack)(()=>{this._component.phase===a.UNINITIALIZED&&this._runSetup(),this._init()})}attributeChangedCallback(e,n,r){if(n===r)return;let a=t.getPropMeta(this,e);if(!a)return;let o=a.parse(r);Object.is((0,i.untrack)(()=>a.signal.value),o)||(a.signal.value=o)}disconnectedCallback(){this._component.generation++,this._component.phase=a.UNMOUNTED,this._resetSetupState()}_resetSetupState(){this._component.scope.dispose(),this._component.formResetCallbacks=[],this._component.mountCallbacks=[],this._component.phase=a.UNINITIALIZED,this._component.scope=(0,i.createScope)(),this._component.templateResult=null}formResetCallback(){for(let e of this._component.formResetCallbacks)try{e()}catch(e){this._reportLifecycleError(e,`form-reset`)}}_reportLifecycleError(t,n){let r=t instanceof Error?t:Error(String(t)),i=new e.OreLifecycleError(`<${this.localName}> failed during ${this._component.phase} (${n})`,{cause:r,component:this.localName,phase:n});e.reportRuntimeError(i,this)}_runSetup(){this._component.phase=a.SETUP_RUNNING;let r=this.constructor._definition,i=this.constructor._normalizedPropDefs,o=n.createRuntimeContext(this);try{let c;if(this._component.scope.run(()=>{c=n.runWithContext(o,()=>{let e=i?t.createProps(this,i):{};return r.setup(e)})}),this._component.mountCallbacks.push(...o.mountCallbacks),this._component.formResetCallbacks.push(...o.formResetCallbacks),s(c))throw new e.OreApiError(e.ORE_ERRORS.asyncSetupUnsupported);this._component.templateResult=c??null,this._component.phase=a.SETUP_DONE}catch(e){throw this._reportLifecycleError(e,`setup`),this._resetSetupState(),e}}_isStale(e){return this._component.generation!==e||!this.isConnected}_applyResult(e){if(!e)return;let t=this.shadowRoot??this,r=n.createRuntimeContext(this);t.replaceChildren(),this._component.scope.run(()=>{n.runWithContext(r,()=>{e.mount(t,null,n.onCleanup)})})}_init(){this._applyStyles(),this._mountTemplate(),this._component.phase===a.SETUP_DONE&&this._scheduleMountCallbacks()}_applyStyles(){let e=this.constructor._definition;this.shadowRoot&&e?.styles?.length&&(this.shadowRoot.adoptedStyleSheets=e.styles.map(r.loadStylesheet))}_mountTemplate(){let e=this._component.templateResult;e&&this._applyResult(e)}_scheduleMountCallbacks(){if(this._component.mountCallbacks.length===0)return;let e=this._component.generation,t=n.beginPendingWork();queueMicrotask(()=>{try{if(this._isStale(e))return;let t=this._component.mountCallbacks.splice(0);for(let e=0;e<t.length;e++){let r=t[e];try{let e=n.createRuntimeContext(this);this._component.scope.run(()=>{n.runWithContext(e,()=>{let e=r();typeof e==`function`&&n.onCleanup(e)})}),e.mountCallbacks.length>0&&t.push(...e.mountCallbacks),e.formResetCallbacks.length>0&&this._component.formResetCallbacks.push(...e.formResetCallbacks)}catch(e){this._reportLifecycleError(e,`mounted`)}}}finally{t()}})}};exports.BaseElement=c;
2
2
  //# sourceMappingURL=base-element.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"base-element.cjs","names":["createScope","getPropMeta","untrack","OreLifecycleError","createRuntimeContext","runWithContext","createProps","OreApiError","ORE_ERRORS","onCleanup","loadStylesheet","beginPendingWork","require_errors","require_runtime","require_props","require_css","_vielzeug_ripple","ComponentPhase","createComponentState","isPromiseLike","value","BaseElement","def","oldValue","newValue","propMeta","name","parsed","callback","error","err","oreError","phase","normalizedPropDefs","ctx","setupResult","setupProps","capturedGeneration","result","host","context","endWork","batch","i","nestedCtx","cleanup"],"sources":["../src/base-element.ts"],"sourcesContent":["import { createScope, type Scope, untrack } from '@vielzeug/ripple';\n\nimport type { ComponentDefinition } from './component-types';\n\nimport { ORE_ERRORS, OreApiError, type OreErrorPhase, OreLifecycleError, reportRuntimeError } from './errors';\nimport { createProps, getPropMeta, type InferProps, type PropInputDefs, type PropsDef } from './props';\nimport {\n beginPendingWork,\n createRuntimeContext,\n type OnFormResetCallback,\n type OnMountedCallback,\n onCleanup,\n runWithContext,\n} from './runtime';\nimport type { HTMLResult } from './template/result';\nimport { loadStylesheet } from './utils/css';\n\n// ─── Component phases ─────────────────────────────────────────────────────────\n// Internal to BaseElement: the only state machine in the package.\n\nconst ComponentPhase = {\n SETUP_DONE: 'setup_done',\n SETUP_RUNNING: 'setup_running',\n UNINITIALIZED: 'uninitialized',\n UNMOUNTED: 'unmounted',\n} as const;\n\ntype ComponentPhase = (typeof ComponentPhase)[keyof typeof ComponentPhase];\n\n// ─── Internal component state ─────────────────────────────────────────────────\n\ntype ComponentState = {\n /** Registered via `onFormReset()`: persists across mount callbacks, unlike `mountCallbacks`. */\n formResetCallbacks: OnFormResetCallback[];\n /** Incremented on every disconnect: invalidates queued mount callbacks. */\n generation: number;\n mountCallbacks: OnMountedCallback[];\n phase: ComponentPhase;\n scope: Scope;\n templateResult: HTMLResult | null;\n};\n\nconst createComponentState = (): ComponentState => ({\n formResetCallbacks: [],\n generation: 0,\n mountCallbacks: [],\n phase: ComponentPhase.UNINITIALIZED,\n scope: createScope(),\n templateResult: null,\n});\n\nconst isPromiseLike = (value: unknown): value is PromiseLike<unknown> =>\n (typeof value === 'object' || typeof value === 'function') &&\n value !== null &&\n 'then' in value &&\n typeof value.then === 'function';\n\n// ─── BaseElement ──────────────────────────────────────────────────────────────\n\n/**\n * Phase transitions:\n *\n * ```\n * UNINITIALIZED ──_runSetup()──► SETUP_DONE\n * SETUP_DONE ──disconnectedCallback()──► UNMOUNTED ──(reset)──► UNINITIALIZED\n * ```\n *\n * `generation` increments on every disconnect. Scheduled mount callbacks capture\n * it so callbacks belonging to a disconnected instance cannot run after a\n * reconnect (see `_isStale`).\n *\n * Why this lives on the class instead of a standalone pure reducer: every\n * transition here is triggered by running actual user code (`def.setup()`,\n * `onMounted` callbacks) inside a reactive `scope.run()` + `runWithContext()`\n *: there is no meaningful \"decide the next phase\" step that can be separated\n * from \"run the side-effecting thing that produces the phase change\" without\n * introducing a data-only effect-description layer that this package has no\n * other use for. That's why the methods below stay as direct, readable\n * procedural steps instead of a reducer + effect interpreter.\n */\nexport class BaseElement extends HTMLElement {\n static _definition: ComponentDefinition;\n static _normalizedPropDefs: PropsDef<Record<never, never>> | undefined;\n static formAssociated = false;\n static observedAttributes: string[] = [];\n\n private _component: ComponentState;\n\n constructor() {\n super();\n\n const def = (this.constructor as typeof BaseElement)._definition;\n\n if (def?.shadow !== false) {\n this.attachShadow({ mode: 'open', ...(def?.shadow as Partial<ShadowRootInit> | undefined) });\n }\n\n this._component = createComponentState();\n }\n\n connectedCallback(): void {\n untrack(() => {\n if (this._component.phase === ComponentPhase.UNINITIALIZED) this._runSetup();\n\n this._init();\n });\n }\n\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n if (oldValue === newValue) return;\n\n const propMeta = getPropMeta(this, name);\n\n if (!propMeta) return;\n\n const parsed = propMeta.parse(newValue);\n\n if (\n !Object.is(\n untrack(() => propMeta.signal.value),\n parsed,\n )\n )\n propMeta.signal.value = parsed as never;\n }\n\n disconnectedCallback(): void {\n this._component.generation++;\n this._component.phase = ComponentPhase.UNMOUNTED;\n this._resetSetupState();\n }\n\n /** Dispose one connection's resources before its state can be rebuilt. */\n private _resetSetupState(): void {\n this._component.scope.dispose();\n // Reset mutable fields for next connection, keeping the same object for stable references.\n this._component.formResetCallbacks = [];\n this._component.mountCallbacks = [];\n this._component.phase = ComponentPhase.UNINITIALIZED;\n this._component.scope = createScope();\n this._component.templateResult = null;\n }\n\n /**\n * Native form-association lifecycle callback: the browser calls this on every\n * `formAssociated: true` element inside a `<form>` when that form is reset.\n * Runs every `onFormReset()` callback registered during `setup()`.\n */\n formResetCallback(): void {\n for (const callback of this._component.formResetCallbacks) {\n try {\n callback();\n } catch (error) {\n this._reportLifecycleError(error, 'form-reset');\n }\n }\n }\n\n private _reportLifecycleError(error: unknown, phase: OreErrorPhase): void {\n const err = error instanceof Error ? error : new Error(String(error));\n const oreError = new OreLifecycleError(`<${this.localName}> failed during ${this._component.phase} (${phase})`, {\n cause: err,\n component: this.localName,\n phase,\n });\n\n reportRuntimeError(oreError, this);\n }\n\n private _runSetup(): void {\n this._component.phase = ComponentPhase.SETUP_RUNNING;\n\n const def = (this.constructor as typeof BaseElement)._definition;\n const normalizedPropDefs = (this.constructor as typeof BaseElement)._normalizedPropDefs;\n const ctx = createRuntimeContext(this);\n\n try {\n let setupResult: HTMLResult | null | undefined;\n\n this._component.scope.run(() => {\n setupResult = runWithContext(ctx, () => {\n const setupProps = normalizedPropDefs\n ? createProps(this, normalizedPropDefs)\n : ({} as InferProps<PropInputDefs>);\n\n return def.setup(setupProps as InferProps<PropInputDefs>);\n });\n });\n this._component.mountCallbacks.push(...ctx.mountCallbacks);\n this._component.formResetCallbacks.push(...ctx.formResetCallbacks);\n\n if (isPromiseLike(setupResult)) throw new OreApiError(ORE_ERRORS.asyncSetupUnsupported);\n\n this._component.templateResult = setupResult ?? null;\n this._component.phase = ComponentPhase.SETUP_DONE;\n } catch (error) {\n this._reportLifecycleError(error, 'setup');\n // Setup is atomic: a failed run must not leave partial effects or cleanups\n // live until a later disconnect.\n this._resetSetupState();\n throw error;\n }\n }\n\n private _isStale(capturedGeneration: number): boolean {\n return this._component.generation !== capturedGeneration || !this.isConnected;\n }\n\n private _applyResult(result: HTMLResult | null): void {\n if (!result) return;\n\n const host: Element | ShadowRoot = this.shadowRoot ?? this;\n\n // Mounting can register component cleanup, so preserve a runtime context here too.\n const context = createRuntimeContext(this);\n\n host.replaceChildren();\n this._component.scope.run(() => {\n runWithContext(context, () => {\n result.mount(host, null, onCleanup);\n });\n });\n }\n\n private _init(): void {\n this._applyStyles();\n this._mountTemplate();\n\n // Setup completes before the template mounts, so callbacks always observe live DOM.\n if (this._component.phase === ComponentPhase.SETUP_DONE) this._scheduleMountCallbacks();\n }\n\n private _applyStyles(): void {\n const def = (this.constructor as typeof BaseElement)._definition;\n\n if (this.shadowRoot && def?.styles?.length) {\n this.shadowRoot.adoptedStyleSheets = def.styles.map(loadStylesheet);\n }\n }\n\n private _mountTemplate(): void {\n const result = this._component.templateResult;\n\n if (!result) return;\n\n this._applyResult(result);\n }\n\n private _scheduleMountCallbacks(): void {\n if (this._component.mountCallbacks.length === 0) return;\n\n const capturedGeneration = this._component.generation;\n // Tracked as pending work for the duration of this microtask: ended in a `finally`\n // so a thrown callback (already caught per-callback below, but defensive here too)\n // never leaves the counter stuck above zero. See runtime.ts's beginPendingWork().\n const endWork = beginPendingWork();\n\n queueMicrotask(() => {\n try {\n if (this._isStale(capturedGeneration)) return;\n\n // Snapshot callbacks so in-loop registrations don't extend this iteration.\n // Nested onMounted registrations are appended to `batch` and run in the same\n // microtask: no recursive scheduling. Index-based loop because the array\n // grows as nested callbacks are discovered.\n const batch = this._component.mountCallbacks.splice(0);\n\n for (let i = 0; i < batch.length; i++) {\n const callback = batch[i];\n\n try {\n const nestedCtx = createRuntimeContext(this);\n\n this._component.scope.run(() => {\n runWithContext(nestedCtx, () => {\n const cleanup = callback();\n\n if (typeof cleanup === 'function') onCleanup(cleanup);\n });\n });\n\n if (nestedCtx.mountCallbacks.length > 0) {\n batch.push(...nestedCtx.mountCallbacks);\n }\n\n if (nestedCtx.formResetCallbacks.length > 0) {\n this._component.formResetCallbacks.push(...nestedCtx.formResetCallbacks);\n }\n } catch (error) {\n this._reportLifecycleError(error, 'mounted');\n }\n }\n } finally {\n endWork();\n }\n });\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"base-element.cjs","names":["createScope","getPropMeta","untrack","OreLifecycleError","createRuntimeContext","runWithContext","createProps","OreApiError","ORE_ERRORS","onCleanup","loadStylesheet","beginPendingWork","require_errors","require_props","require_runtime","require_css","_vielzeug_ripple","ComponentPhase","createComponentState","isPromiseLike","value","BaseElement","def","oldValue","newValue","propMeta","name","parsed","callback","error","err","oreError","phase","normalizedPropDefs","ctx","setupResult","setupProps","capturedGeneration","result","host","context","endWork","batch","i","nestedCtx","cleanup"],"sources":["../src/base-element.ts"],"sourcesContent":["import { createScope, type Scope, untrack } from '@vielzeug/ripple';\n\nimport type { ComponentDefinition } from './component-types';\n\nimport { ORE_ERRORS, OreApiError, type OreErrorPhase, OreLifecycleError, reportRuntimeError } from './errors';\nimport { createProps, getPropMeta, type InferProps, type PropInputDefs, type PropsDef } from './props';\nimport {\n beginPendingWork,\n createRuntimeContext,\n type OnFormResetCallback,\n type OnMountedCallback,\n onCleanup,\n runWithContext,\n} from './runtime';\nimport type { HTMLResult } from './template/result';\nimport { loadStylesheet } from './utils/css';\n\n// ─── Component phases ─────────────────────────────────────────────────────────\n// Internal to BaseElement: the only state machine in the package.\n\nconst ComponentPhase = {\n SETUP_DONE: 'setup_done',\n SETUP_RUNNING: 'setup_running',\n UNINITIALIZED: 'uninitialized',\n UNMOUNTED: 'unmounted',\n} as const;\n\ntype ComponentPhase = (typeof ComponentPhase)[keyof typeof ComponentPhase];\n\n// ─── Internal component state ─────────────────────────────────────────────────\n\ntype ComponentState = {\n /** Registered via `onFormReset()`: persists across mount callbacks, unlike `mountCallbacks`. */\n formResetCallbacks: OnFormResetCallback[];\n /** Incremented on every disconnect: invalidates queued mount callbacks. */\n generation: number;\n mountCallbacks: OnMountedCallback[];\n phase: ComponentPhase;\n scope: Scope;\n templateResult: HTMLResult | null;\n};\n\nconst createComponentState = (): ComponentState => ({\n formResetCallbacks: [],\n generation: 0,\n mountCallbacks: [],\n phase: ComponentPhase.UNINITIALIZED,\n scope: createScope(),\n templateResult: null,\n});\n\nconst isPromiseLike = (value: unknown): value is PromiseLike<unknown> =>\n (typeof value === 'object' || typeof value === 'function') &&\n value !== null &&\n 'then' in value &&\n typeof value.then === 'function';\n\n// ─── BaseElement ──────────────────────────────────────────────────────────────\n\n/**\n * Phase transitions:\n *\n * ```\n * UNINITIALIZED ──_runSetup()──► SETUP_DONE\n * SETUP_DONE ──disconnectedCallback()──► UNMOUNTED ──(reset)──► UNINITIALIZED\n * ```\n *\n * `generation` increments on every disconnect. Scheduled mount callbacks capture\n * it so callbacks belonging to a disconnected instance cannot run after a\n * reconnect (see `_isStale`).\n *\n * Why this lives on the class instead of a standalone pure reducer: every\n * transition here is triggered by running actual user code (`def.setup()`,\n * `onMounted` callbacks) inside a reactive `scope.run()` + `runWithContext()`\n *: there is no meaningful \"decide the next phase\" step that can be separated\n * from \"run the side-effecting thing that produces the phase change\" without\n * introducing a data-only effect-description layer that this package has no\n * other use for. That's why the methods below stay as direct, readable\n * procedural steps instead of a reducer + effect interpreter.\n */\nexport class BaseElement extends HTMLElement {\n static _definition: ComponentDefinition;\n static _normalizedPropDefs: PropsDef<Record<never, never>> | undefined;\n static formAssociated = false;\n static observedAttributes: string[] = [];\n\n private _component: ComponentState;\n\n constructor() {\n super();\n\n const def = (this.constructor as typeof BaseElement)._definition;\n\n if (def?.shadow !== false) {\n this.attachShadow({ mode: 'open', ...(def?.shadow as Partial<ShadowRootInit> | undefined) });\n }\n\n this._component = createComponentState();\n }\n\n connectedCallback(): void {\n untrack(() => {\n if (this._component.phase === ComponentPhase.UNINITIALIZED) this._runSetup();\n\n this._init();\n });\n }\n\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n if (oldValue === newValue) return;\n\n const propMeta = getPropMeta(this, name);\n\n if (!propMeta) return;\n\n const parsed = propMeta.parse(newValue);\n\n if (\n !Object.is(\n untrack(() => propMeta.signal.value),\n parsed,\n )\n )\n propMeta.signal.value = parsed as never;\n }\n\n disconnectedCallback(): void {\n this._component.generation++;\n this._component.phase = ComponentPhase.UNMOUNTED;\n this._resetSetupState();\n }\n\n /** Dispose one connection's resources before its state can be rebuilt. */\n private _resetSetupState(): void {\n this._component.scope.dispose();\n // Reset mutable fields for next connection, keeping the same object for stable references.\n this._component.formResetCallbacks = [];\n this._component.mountCallbacks = [];\n this._component.phase = ComponentPhase.UNINITIALIZED;\n this._component.scope = createScope();\n this._component.templateResult = null;\n }\n\n /**\n * Native form-association lifecycle callback: the browser calls this on every\n * `formAssociated: true` element inside a `<form>` when that form is reset.\n * Runs every `onFormReset()` callback registered during `setup()`.\n */\n formResetCallback(): void {\n for (const callback of this._component.formResetCallbacks) {\n try {\n callback();\n } catch (error) {\n this._reportLifecycleError(error, 'form-reset');\n }\n }\n }\n\n private _reportLifecycleError(error: unknown, phase: OreErrorPhase): void {\n const err = error instanceof Error ? error : new Error(String(error));\n const oreError = new OreLifecycleError(`<${this.localName}> failed during ${this._component.phase} (${phase})`, {\n cause: err,\n component: this.localName,\n phase,\n });\n\n reportRuntimeError(oreError, this);\n }\n\n private _runSetup(): void {\n this._component.phase = ComponentPhase.SETUP_RUNNING;\n\n const def = (this.constructor as typeof BaseElement)._definition;\n const normalizedPropDefs = (this.constructor as typeof BaseElement)._normalizedPropDefs;\n const ctx = createRuntimeContext(this);\n\n try {\n let setupResult: HTMLResult | null | undefined;\n\n this._component.scope.run(() => {\n setupResult = runWithContext(ctx, () => {\n const setupProps = normalizedPropDefs\n ? createProps(this, normalizedPropDefs)\n : ({} as InferProps<PropInputDefs>);\n\n return def.setup(setupProps as InferProps<PropInputDefs>);\n });\n });\n this._component.mountCallbacks.push(...ctx.mountCallbacks);\n this._component.formResetCallbacks.push(...ctx.formResetCallbacks);\n\n if (isPromiseLike(setupResult)) throw new OreApiError(ORE_ERRORS.asyncSetupUnsupported);\n\n this._component.templateResult = setupResult ?? null;\n this._component.phase = ComponentPhase.SETUP_DONE;\n } catch (error) {\n this._reportLifecycleError(error, 'setup');\n // Setup is atomic: a failed run must not leave partial effects or cleanups\n // live until a later disconnect.\n this._resetSetupState();\n throw error;\n }\n }\n\n private _isStale(capturedGeneration: number): boolean {\n return this._component.generation !== capturedGeneration || !this.isConnected;\n }\n\n private _applyResult(result: HTMLResult | null): void {\n if (!result) return;\n\n const host: Element | ShadowRoot = this.shadowRoot ?? this;\n\n // Mounting can register component cleanup, so preserve a runtime context here too.\n const context = createRuntimeContext(this);\n\n host.replaceChildren();\n this._component.scope.run(() => {\n runWithContext(context, () => {\n result.mount(host, null, onCleanup);\n });\n });\n }\n\n private _init(): void {\n this._applyStyles();\n this._mountTemplate();\n\n // Setup completes before the template mounts, so callbacks always observe live DOM.\n if (this._component.phase === ComponentPhase.SETUP_DONE) this._scheduleMountCallbacks();\n }\n\n private _applyStyles(): void {\n const def = (this.constructor as typeof BaseElement)._definition;\n\n if (this.shadowRoot && def?.styles?.length) {\n this.shadowRoot.adoptedStyleSheets = def.styles.map(loadStylesheet);\n }\n }\n\n private _mountTemplate(): void {\n const result = this._component.templateResult;\n\n if (!result) return;\n\n this._applyResult(result);\n }\n\n private _scheduleMountCallbacks(): void {\n if (this._component.mountCallbacks.length === 0) return;\n\n const capturedGeneration = this._component.generation;\n // Tracked as pending work for the duration of this microtask: ended in a `finally`\n // so a thrown callback (already caught per-callback below, but defensive here too)\n // never leaves the counter stuck above zero. See runtime.ts's beginPendingWork().\n const endWork = beginPendingWork();\n\n queueMicrotask(() => {\n try {\n if (this._isStale(capturedGeneration)) return;\n\n // Snapshot callbacks so in-loop registrations don't extend this iteration.\n // Nested onMounted registrations are appended to `batch` and run in the same\n // microtask: no recursive scheduling. Index-based loop because the array\n // grows as nested callbacks are discovered.\n const batch = this._component.mountCallbacks.splice(0);\n\n for (let i = 0; i < batch.length; i++) {\n const callback = batch[i];\n\n try {\n const nestedCtx = createRuntimeContext(this);\n\n this._component.scope.run(() => {\n runWithContext(nestedCtx, () => {\n const cleanup = callback();\n\n if (typeof cleanup === 'function') onCleanup(cleanup);\n });\n });\n\n if (nestedCtx.mountCallbacks.length > 0) {\n batch.push(...nestedCtx.mountCallbacks);\n }\n\n if (nestedCtx.formResetCallbacks.length > 0) {\n this._component.formResetCallbacks.push(...nestedCtx.formResetCallbacks);\n }\n } catch (error) {\n this._reportLifecycleError(error, 'mounted');\n }\n }\n } finally {\n endWork();\n }\n });\n }\n}\n"],"mappings":"A,mJAoBA,IAAMiB,EAAiB,CACrB,WAAY,aACZ,cAAe,gBACf,cAAe,gBACf,UAAW,WACb,EAiBMC,OAA8C,CAClD,mBAAoB,CAAC,EACrB,WAAY,EACZ,eAAgB,CAAC,EACjB,MAAOD,EAAe,cACtB,OAAA,EAAOjB,EAAAA,YAAAA,CAAY,EACnB,eAAgB,IAClB,GAEMmB,EAAiB,IACpB,OAAOC,GAAU,UAAY,OAAOA,GAAU,aAC/CA,IAAU,MACV,SAAUA,GACV,OAAOA,EAAM,MAAS,WAyBXC,EAAb,cAAiC,WAAY,CAC3C,OAAO,YACP,OAAO,oBACP,OAAO,eAAiB,GACxB,OAAO,mBAA+B,CAAC,EAEvC,WAEA,aAAc,CACZ,MAAM,EAEN,IAAMC,EAAO,KAAK,YAAmC,YAEjDA,GAAK,SAAW,IAClB,KAAK,aAAa,CAAE,KAAM,OAAQ,GAAIA,GAAK,MAA+C,CAAC,EAG7F,KAAK,WAAaJ,EAAqB,CACzC,CAEA,mBAA0B,EACxB,EAAAF,EAAA,QAAA,KAAc,CACR,KAAK,WAAW,QAAUC,EAAe,eAAe,KAAK,UAAU,EAE3E,KAAK,MAAM,CACb,CAAC,CACH,CAEA,yBAAyB,EAAc,EAAyB,EAA+B,CAC7F,GAAIM,IAAaC,EAAU,OAE3B,IAAMC,EAAWxB,EAAAA,YAAY,KAAMyB,CAAI,EAEvC,GAAI,CAACD,EAAU,OAEf,IAAME,EAASF,EAAS,MAAMD,CAAQ,EAGnC,OAAO,IAAA,EACNtB,EAAAA,QAAAA,KAAcuB,EAAS,OAAO,KAAK,EACnCE,CACF,IAEA,EAAS,OAAO,MAAQA,EAC5B,CAEA,sBAA6B,CAC3B,KAAK,WAAW,aAChB,KAAK,WAAW,MAAQV,EAAe,UACvC,KAAK,iBAAiB,CACxB,CAGA,kBAAiC,CAC/B,KAAK,WAAW,MAAM,QAAQ,EAE9B,KAAK,WAAW,mBAAqB,CAAC,EACtC,KAAK,WAAW,eAAiB,CAAC,EAClC,KAAK,WAAW,MAAQA,EAAe,cACvC,KAAK,WAAW,OAAA,EAAQjB,EAAAA,YAAAA,CAAY,EACpC,KAAK,WAAW,eAAiB,IACnC,CAOA,mBAA0B,CACxB,IAAK,IAAM4B,KAAY,KAAK,WAAW,mBACrC,GAAI,CACFA,EAAS,CACX,OAASC,EAAO,CACd,KAAK,sBAAsBA,EAAO,YAAY,CAChD,CAEJ,CAEA,sBAA8B,EAAgB,EAA4B,CACxE,IAAMC,EAAMD,aAAiB,MAAQA,EAAY,MAAM,OAAOA,CAAK,CAAC,EAC9DE,EAAW,IAAI5B,EAAAA,kBAAkB,IAAI,KAAK,UAAU,kBAAkB,KAAK,WAAW,MAAM,IAAI6B,EAAM,GAAI,CAC9G,MAAOF,EACP,UAAW,KAAK,UAChB,OACF,CAAC,EAEDlB,EAAA,mBAAmBmB,EAAU,IAAI,CACnC,CAEA,WAA0B,CACxB,KAAK,WAAW,MAAQd,EAAe,cAEvC,IAAMK,EAAO,KAAK,YAAmC,YAC/CW,EAAsB,KAAK,YAAmC,oBAC9DC,EAAM9B,EAAAA,qBAAqB,IAAI,EAErC,GAAI,CACF,IAAI+B,EAcJ,GAZA,KAAK,WAAW,MAAM,QAAU,CAC9B,EAAc9B,EAAAA,eAAe6B,MAAW,CACtC,IAAME,EAAaH,EACf3B,EAAAA,YAAY,KAAM2B,CAAkB,EACnC,CAAC,EAEN,OAAOX,EAAI,MAAMc,CAAuC,CAC1D,CAAC,CACH,CAAC,EACD,KAAK,WAAW,eAAe,KAAK,GAAGF,EAAI,cAAc,EACzD,KAAK,WAAW,mBAAmB,KAAK,GAAGA,EAAI,kBAAkB,EAE7Df,EAAcgB,CAAW,EAAG,MAAM,IAAI5B,EAAAA,YAAYC,EAAAA,WAAW,qBAAqB,EAEtF,KAAK,WAAW,eAAiB2B,GAAe,KAChD,KAAK,WAAW,MAAQlB,EAAe,UACzC,OAASY,EAAO,CAKd,MAJA,KAAK,sBAAsBA,EAAO,OAAO,EAGzC,KAAK,iBAAiB,EAChBA,CACR,CACF,CAEA,SAAiB,EAAqC,CACpD,OAAO,KAAK,WAAW,aAAeQ,GAAsB,CAAC,KAAK,WACpE,CAEA,aAAqB,EAAiC,CACpD,GAAI,CAACC,EAAQ,OAEb,IAAMC,EAA6B,KAAK,YAAc,KAGhDC,EAAUpC,EAAAA,qBAAqB,IAAI,EAEzCmC,EAAK,gBAAgB,EACrB,KAAK,WAAW,MAAM,QAAU,CAC9BzB,EAAA,eAAe0B,MAAe,CAC5BF,EAAO,MAAMC,EAAM,KAAM9B,EAAAA,SAAS,CACpC,CAAC,CACH,CAAC,CACH,CAEA,OAAsB,CACpB,KAAK,aAAa,EAClB,KAAK,eAAe,EAGhB,KAAK,WAAW,QAAUQ,EAAe,YAAY,KAAK,wBAAwB,CACxF,CAEA,cAA6B,CAC3B,IAAMK,EAAO,KAAK,YAAmC,YAEjD,KAAK,YAAcA,GAAK,QAAQ,SAClC,KAAK,WAAW,mBAAqBA,EAAI,OAAO,IAAIZ,EAAAA,cAAc,EAEtE,CAEA,gBAA+B,CAC7B,IAAM4B,EAAS,KAAK,WAAW,eAE1BA,GAEL,KAAK,aAAaA,CAAM,CAC1B,CAEA,yBAAwC,CACtC,GAAI,KAAK,WAAW,eAAe,SAAW,EAAG,OAEjD,IAAMD,EAAqB,KAAK,WAAW,WAIrCI,EAAU9B,EAAAA,iBAAiB,EAEjC,mBAAqB,CACnB,GAAI,CACF,GAAI,KAAK,SAAS0B,CAAkB,EAAG,OAMvC,IAAMK,EAAQ,KAAK,WAAW,eAAe,OAAO,CAAC,EAErD,IAAK,IAAIC,EAAI,EAAGA,EAAID,EAAM,OAAQ,IAAK,CACrC,IAAMd,EAAWc,EAAMC,GAEvB,GAAI,CACF,IAAMC,EAAYxC,EAAAA,qBAAqB,IAAI,EAE3C,KAAK,WAAW,MAAM,QAAU,CAC9BU,EAAA,eAAe8B,MAAiB,CAC9B,IAAMC,EAAUjB,EAAS,EAErB,OAAOiB,GAAY,YAAY/B,EAAA,UAAU+B,CAAO,CACtD,CAAC,CACH,CAAC,EAEGD,EAAU,eAAe,OAAS,GACpCF,EAAM,KAAK,GAAGE,EAAU,cAAc,EAGpCA,EAAU,mBAAmB,OAAS,GACxC,KAAK,WAAW,mBAAmB,KAAK,GAAGA,EAAU,kBAAkB,CAE3E,OAASf,EAAO,CACd,KAAK,sBAAsBA,EAAO,SAAS,CAC7C,CACF,CACF,QAAU,CACRY,EAAQ,CACV,CACF,CAAC,CACH,CACF,E"}
@@ -1,2 +1,2 @@
1
- import{ORE_ERRORS as e,OreApiError as t,OreLifecycleError as n,reportRuntimeError as r}from"./errors.js";import{beginPendingWork as i,createRuntimeContext as a,onCleanup as o,runWithContext as s}from"./runtime.js";import{createProps as c,getPropMeta as l}from"./props.js";import{loadStylesheet as u}from"./utils/css.js";import{createScope as d,untrack as f}from"@vielzeug/ripple";var p={SETUP_DONE:`setup_done`,SETUP_RUNNING:`setup_running`,UNINITIALIZED:`uninitialized`,UNMOUNTED:`unmounted`},m=()=>({formResetCallbacks:[],generation:0,mountCallbacks:[],phase:p.UNINITIALIZED,scope:d(),templateResult:null}),h=e=>(typeof e==`object`||typeof e==`function`)&&e!==null&&`then`in e&&typeof e.then==`function`,g=class extends HTMLElement{static _definition;static _normalizedPropDefs;static formAssociated=!1;static observedAttributes=[];_component;constructor(){super();let e=this.constructor._definition;e?.shadow!==!1&&this.attachShadow({mode:`open`,...e?.shadow}),this._component=m()}connectedCallback(){f(()=>{this._component.phase===p.UNINITIALIZED&&this._runSetup(),this._init()})}attributeChangedCallback(e,t,n){if(t===n)return;let r=l(this,e);if(!r)return;let i=r.parse(n);Object.is(f(()=>r.signal.value),i)||(r.signal.value=i)}disconnectedCallback(){this._component.generation++,this._component.phase=p.UNMOUNTED,this._resetSetupState()}_resetSetupState(){this._component.scope.dispose(),this._component.formResetCallbacks=[],this._component.mountCallbacks=[],this._component.phase=p.UNINITIALIZED,this._component.scope=d(),this._component.templateResult=null}formResetCallback(){for(let e of this._component.formResetCallbacks)try{e()}catch(e){this._reportLifecycleError(e,`form-reset`)}}_reportLifecycleError(e,t){let i=e instanceof Error?e:Error(String(e)),a=new n(`<${this.localName}> failed during ${this._component.phase} (${t})`,{cause:i,component:this.localName,phase:t});r(a,this)}_runSetup(){this._component.phase=p.SETUP_RUNNING;let n=this.constructor._definition,r=this.constructor._normalizedPropDefs,i=a(this);try{let a;if(this._component.scope.run(()=>{a=s(i,()=>{let e=r?c(this,r):{};return n.setup(e)})}),this._component.mountCallbacks.push(...i.mountCallbacks),this._component.formResetCallbacks.push(...i.formResetCallbacks),h(a))throw new t(e.asyncSetupUnsupported);this._component.templateResult=a??null,this._component.phase=p.SETUP_DONE}catch(e){throw this._reportLifecycleError(e,`setup`),this._resetSetupState(),e}}_isStale(e){return this._component.generation!==e||!this.isConnected}_applyResult(e){if(!e)return;let t=this.shadowRoot??this,n=a(this);t.replaceChildren(),this._component.scope.run(()=>{s(n,()=>{e.mount(t,null,o)})})}_init(){this._applyStyles(),this._mountTemplate(),this._component.phase===p.SETUP_DONE&&this._scheduleMountCallbacks()}_applyStyles(){let e=this.constructor._definition;this.shadowRoot&&e?.styles?.length&&(this.shadowRoot.adoptedStyleSheets=e.styles.map(u))}_mountTemplate(){let e=this._component.templateResult;e&&this._applyResult(e)}_scheduleMountCallbacks(){if(this._component.mountCallbacks.length===0)return;let e=this._component.generation,t=i();queueMicrotask(()=>{try{if(this._isStale(e))return;let t=this._component.mountCallbacks.splice(0);for(let e=0;e<t.length;e++){let n=t[e];try{let e=a(this);this._component.scope.run(()=>{s(e,()=>{let e=n();typeof e==`function`&&o(e)})}),e.mountCallbacks.length>0&&t.push(...e.mountCallbacks),e.formResetCallbacks.length>0&&this._component.formResetCallbacks.push(...e.formResetCallbacks)}catch(e){this._reportLifecycleError(e,`mounted`)}}}finally{t()}})}};export{g as BaseElement};
1
+ import{ORE_ERRORS as e,OreApiError as t,OreLifecycleError as n,reportRuntimeError as r}from"./errors.js";import{createProps as i,getPropMeta as a}from"./props.js";import{beginPendingWork as o,createRuntimeContext as s,onCleanup as c,runWithContext as l}from"./runtime.js";import{loadStylesheet as u}from"./utils/css.js";import{createScope as d,untrack as f}from"@vielzeug/ripple";var p={SETUP_DONE:`setup_done`,SETUP_RUNNING:`setup_running`,UNINITIALIZED:`uninitialized`,UNMOUNTED:`unmounted`},m=()=>({formResetCallbacks:[],generation:0,mountCallbacks:[],phase:p.UNINITIALIZED,scope:d(),templateResult:null}),h=e=>(typeof e==`object`||typeof e==`function`)&&e!==null&&`then`in e&&typeof e.then==`function`,g=class extends HTMLElement{static _definition;static _normalizedPropDefs;static formAssociated=!1;static observedAttributes=[];_component;constructor(){super();let e=this.constructor._definition;e?.shadow!==!1&&this.attachShadow({mode:`open`,...e?.shadow}),this._component=m()}connectedCallback(){f(()=>{this._component.phase===p.UNINITIALIZED&&this._runSetup(),this._init()})}attributeChangedCallback(e,t,n){if(t===n)return;let r=a(this,e);if(!r)return;let i=r.parse(n);Object.is(f(()=>r.signal.value),i)||(r.signal.value=i)}disconnectedCallback(){this._component.generation++,this._component.phase=p.UNMOUNTED,this._resetSetupState()}_resetSetupState(){this._component.scope.dispose(),this._component.formResetCallbacks=[],this._component.mountCallbacks=[],this._component.phase=p.UNINITIALIZED,this._component.scope=d(),this._component.templateResult=null}formResetCallback(){for(let e of this._component.formResetCallbacks)try{e()}catch(e){this._reportLifecycleError(e,`form-reset`)}}_reportLifecycleError(e,t){let i=e instanceof Error?e:Error(String(e)),a=new n(`<${this.localName}> failed during ${this._component.phase} (${t})`,{cause:i,component:this.localName,phase:t});r(a,this)}_runSetup(){this._component.phase=p.SETUP_RUNNING;let n=this.constructor._definition,r=this.constructor._normalizedPropDefs,a=s(this);try{let o;if(this._component.scope.run(()=>{o=l(a,()=>{let e=r?i(this,r):{};return n.setup(e)})}),this._component.mountCallbacks.push(...a.mountCallbacks),this._component.formResetCallbacks.push(...a.formResetCallbacks),h(o))throw new t(e.asyncSetupUnsupported);this._component.templateResult=o??null,this._component.phase=p.SETUP_DONE}catch(e){throw this._reportLifecycleError(e,`setup`),this._resetSetupState(),e}}_isStale(e){return this._component.generation!==e||!this.isConnected}_applyResult(e){if(!e)return;let t=this.shadowRoot??this,n=s(this);t.replaceChildren(),this._component.scope.run(()=>{l(n,()=>{e.mount(t,null,c)})})}_init(){this._applyStyles(),this._mountTemplate(),this._component.phase===p.SETUP_DONE&&this._scheduleMountCallbacks()}_applyStyles(){let e=this.constructor._definition;this.shadowRoot&&e?.styles?.length&&(this.shadowRoot.adoptedStyleSheets=e.styles.map(u))}_mountTemplate(){let e=this._component.templateResult;e&&this._applyResult(e)}_scheduleMountCallbacks(){if(this._component.mountCallbacks.length===0)return;let e=this._component.generation,t=o();queueMicrotask(()=>{try{if(this._isStale(e))return;let t=this._component.mountCallbacks.splice(0);for(let e=0;e<t.length;e++){let n=t[e];try{let e=s(this);this._component.scope.run(()=>{l(e,()=>{let e=n();typeof e==`function`&&c(e)})}),e.mountCallbacks.length>0&&t.push(...e.mountCallbacks),e.formResetCallbacks.length>0&&this._component.formResetCallbacks.push(...e.formResetCallbacks)}catch(e){this._reportLifecycleError(e,`mounted`)}}}finally{t()}})}};export{g as BaseElement};
2
2
  //# sourceMappingURL=base-element.js.map
package/dist/define.cjs CHANGED
@@ -1,2 +1,2 @@
1
- const e=require("./errors.cjs"),t=require("./utils/dom.cjs"),n=require("./props.cjs"),r=require("./base-element.cjs");function i(i,a){if(!i)throw new e.OreApiError(e.ORE_ERRORS.defineRequiresTag);if(customElements.get(i))throw new e.OreApiError(e.ORE_ERRORS.defineDuplicate(i));let{props:o}=a,s=(()=>{if(!o)return;let t=n.validatePropDefs(o);if(t.length>0)throw new e.OreApiError(e.ORE_ERRORS.validationFailed(i,t));let r={};for(let[e,t]of Object.entries(o))r[e]=n.normalizePropDefinition(t,e);return r})(),c=s?Object.keys(s).map(t.toKebab):[],l=class extends r.BaseElement{static _definition=a;static _normalizedPropDefs=s;static formAssociated=a.formAssociated??!1;static observedAttributes=c};return Object.defineProperty(l,"name",{value:i}),customElements.define(i,l),l}exports.define=i;
1
+ const e=require("./base-element.cjs"),t=require("./errors.cjs"),n=require("./props.cjs"),r=require("./utils/dom.cjs");function i(i,a){if(!i)throw new t.OreApiError(t.ORE_ERRORS.defineRequiresTag);if(customElements.get(i))throw new t.OreApiError(t.ORE_ERRORS.defineDuplicate(i));let{props:o}=a,s=(()=>{if(!o)return;let e=n.validatePropDefs(o);if(e.length>0)throw new t.OreApiError(t.ORE_ERRORS.validationFailed(i,e));let r={};for(let[e,t]of Object.entries(o))r[e]=n.normalizePropDefinition(t,e);return r})(),c=s?Object.keys(s).map(r.toKebab):[],l=class extends e.BaseElement{static _definition=a;static _normalizedPropDefs=s;static formAssociated=a.formAssociated??!1;static observedAttributes=c};return Object.defineProperty(l,"name",{value:i}),customElements.define(i,l),l}exports.define=i;
2
2
  //# sourceMappingURL=define.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"define.cjs","names":["OreApiError","ORE_ERRORS","validatePropDefs","normalizePropDefinition","toKebab","BaseElement","require_errors","require_dom","require_props","require_base_element","define","tag","propDefs","definition","normalizedPropDefs","errors","normalized","key","def","observedAttrs","ComponentClass"],"sources":["../src/define.ts"],"sourcesContent":["import { BaseElement } from './base-element';\nimport type { ComponentDefinition } from './component-types';\nimport { ORE_ERRORS, OreApiError } from './errors';\nimport { normalizePropDefinition, type PropInputDefs, type PropsDef, validatePropDefs } from './props';\nimport { toKebab } from './utils/dom';\n\n/**\n * Create and register a web component.\n *\n * The `setup` function runs for each connection and returns an `HTMLResult`.\n * Disconnecting disposes its state; reconnecting rebuilds it. All reactive\n * behaviour within a connection is expressed through directives inside the\n * template: not by re-evaluating setup itself.\n *\n * Everything besides `props`: lifecycle hooks, host bindings, context, slots,\n * emit: is a free function imported from `@vielzeug/ore` and called directly\n * from inside `setup()` (or from a composable it calls):\n *\n * ```ts\n * import { define, html, prop, onMounted, useEmit, useSlots } from '@vielzeug/ore';\n *\n * define<{ count?: number }>('my-counter', {\n * props: { count: prop.number(0) },\n * setup(props) {\n * const emit = useEmit<{ increment: number }>();\n * const slots = useSlots<'header' | 'footer'>();\n *\n * onMounted(() => console.log('mounted'));\n *\n * return html`<button @click=${() => emit('increment', props.count.value + 1)}>${props.count}</button>`;\n * },\n * });\n * ```\n *\n * Returns the registered class, so callers keep a handle for `instanceof` or\n * subclassing without a follow-up `customElements.get(tag)` cast.\n */\nexport function define<Props extends Record<string, unknown> = Record<never, never>>(\n tag: string,\n definition: ComponentDefinition<Props>,\n): CustomElementConstructor {\n if (!tag) throw new OreApiError(ORE_ERRORS.defineRequiresTag);\n if (customElements.get(tag)) throw new OreApiError(ORE_ERRORS.defineDuplicate(tag));\n\n const { props: propDefs } = definition;\n\n const normalizedPropDefs: PropsDef<Props> | undefined = (() => {\n if (!propDefs) return undefined;\n\n const errors = validatePropDefs(propDefs as Record<string, unknown>);\n\n if (errors.length > 0) throw new OreApiError(ORE_ERRORS.validationFailed(tag, errors));\n\n const normalized: PropInputDefs = {};\n\n for (const [key, def] of Object.entries(propDefs)) {\n normalized[key] = normalizePropDefinition(def, key);\n }\n\n return normalized as PropsDef<Props>;\n })();\n\n const observedAttrs = normalizedPropDefs ? Object.keys(normalizedPropDefs).map(toKebab) : [];\n\n const ComponentClass = class extends BaseElement {\n static override _definition = definition as unknown as ComponentDefinition;\n static override _normalizedPropDefs = normalizedPropDefs as PropsDef<Record<never, never>> | undefined;\n static override formAssociated = definition.formAssociated ?? false;\n static override observedAttributes = observedAttrs;\n };\n\n // Prop validation and class construction above are side-effect-free; registration\n // is intentionally the last, and only global side effect of define().\n Object.defineProperty(ComponentClass, 'name', { value: tag });\n customElements.define(tag, ComponentClass);\n\n return ComponentClass;\n}\n"],"mappings":"A,sHAqCA,SAAgBU,EACd,EACA,EAC0B,CAC1B,GAAI,CAACC,EAAK,MAAM,IAAIX,EAAAA,YAAYC,EAAAA,WAAW,iBAAiB,EAC5D,GAAI,eAAe,IAAIU,CAAG,EAAG,MAAM,IAAIX,EAAAA,YAAYC,EAAAA,WAAW,gBAAgBU,CAAG,CAAC,EAElF,GAAM,CAAE,MAAOC,GAAaC,EAEtBC,OAAyD,CAC7D,GAAI,CAACF,EAAU,OAEf,IAAMG,EAASb,EAAAA,iBAAiBU,CAAmC,EAEnE,GAAIG,EAAO,OAAS,EAAG,MAAM,IAAIf,EAAAA,YAAYC,EAAAA,WAAW,iBAAiBU,EAAKI,CAAM,CAAC,EAErF,IAAMC,EAA4B,CAAC,EAEnC,IAAK,GAAM,CAACC,EAAKC,KAAQ,OAAO,QAAQN,CAAQ,EAC9C,EAAWK,GAAOd,EAAAA,wBAAwBe,EAAKD,CAAG,EAGpD,OAAOD,CACT,EAAA,CAAG,EAEGG,EAAgBL,EAAqB,OAAO,KAAKA,CAAkB,CAAC,CAAC,IAAIV,EAAAA,OAAO,EAAI,CAAC,EAErFgB,EAAiB,cAAcf,EAAAA,WAAY,CAC/C,OAAgB,YAAcQ,EAC9B,OAAgB,oBAAsBC,EACtC,OAAgB,eAAiBD,EAAW,gBAAkB,GAC9D,OAAgB,mBAAqBM,CACvC,EAOA,OAHA,OAAO,eAAeC,EAAgB,OAAQ,CAAE,MAAOT,CAAI,CAAC,EAC5D,eAAe,OAAOA,EAAKS,CAAc,EAElCA,CACT,C"}
1
+ {"version":3,"file":"define.cjs","names":["OreApiError","ORE_ERRORS","validatePropDefs","normalizePropDefinition","toKebab","BaseElement","require_base_element","require_errors","require_props","require_dom","define","tag","propDefs","definition","normalizedPropDefs","errors","normalized","key","def","observedAttrs","ComponentClass"],"sources":["../src/define.ts"],"sourcesContent":["import { BaseElement } from './base-element';\nimport type { ComponentDefinition } from './component-types';\nimport { ORE_ERRORS, OreApiError } from './errors';\nimport { normalizePropDefinition, type PropInputDefs, type PropsDef, validatePropDefs } from './props';\nimport { toKebab } from './utils/dom';\n\n/**\n * Create and register a web component.\n *\n * The `setup` function runs for each connection and returns an `HTMLResult`.\n * Disconnecting disposes its state; reconnecting rebuilds it. All reactive\n * behaviour within a connection is expressed through directives inside the\n * template: not by re-evaluating setup itself.\n *\n * Everything besides `props`: lifecycle hooks, host bindings, context, slots,\n * emit: is a free function imported from `@vielzeug/ore` and called directly\n * from inside `setup()` (or from a composable it calls):\n *\n * ```ts\n * import { define, html, prop, onMounted, useEmit, useSlots } from '@vielzeug/ore';\n *\n * define<{ count?: number }>('my-counter', {\n * props: { count: prop.number(0) },\n * setup(props) {\n * const emit = useEmit<{ increment: number }>();\n * const slots = useSlots<'header' | 'footer'>();\n *\n * onMounted(() => console.log('mounted'));\n *\n * return html`<button @click=${() => emit('increment', props.count.value + 1)}>${props.count}</button>`;\n * },\n * });\n * ```\n *\n * Returns the registered class, so callers keep a handle for `instanceof` or\n * subclassing without a follow-up `customElements.get(tag)` cast.\n */\nexport function define<Props extends Record<string, unknown> = Record<never, never>>(\n tag: string,\n definition: ComponentDefinition<Props>,\n): CustomElementConstructor {\n if (!tag) throw new OreApiError(ORE_ERRORS.defineRequiresTag);\n if (customElements.get(tag)) throw new OreApiError(ORE_ERRORS.defineDuplicate(tag));\n\n const { props: propDefs } = definition;\n\n const normalizedPropDefs: PropsDef<Props> | undefined = (() => {\n if (!propDefs) return undefined;\n\n const errors = validatePropDefs(propDefs as Record<string, unknown>);\n\n if (errors.length > 0) throw new OreApiError(ORE_ERRORS.validationFailed(tag, errors));\n\n const normalized: PropInputDefs = {};\n\n for (const [key, def] of Object.entries(propDefs)) {\n normalized[key] = normalizePropDefinition(def, key);\n }\n\n return normalized as PropsDef<Props>;\n })();\n\n const observedAttrs = normalizedPropDefs ? Object.keys(normalizedPropDefs).map(toKebab) : [];\n\n const ComponentClass = class extends BaseElement {\n static override _definition = definition as unknown as ComponentDefinition;\n static override _normalizedPropDefs = normalizedPropDefs as PropsDef<Record<never, never>> | undefined;\n static override formAssociated = definition.formAssociated ?? false;\n static override observedAttributes = observedAttrs;\n };\n\n // Prop validation and class construction above are side-effect-free; registration\n // is intentionally the last, and only global side effect of define().\n Object.defineProperty(ComponentClass, 'name', { value: tag });\n customElements.define(tag, ComponentClass);\n\n return ComponentClass;\n}\n"],"mappings":"A,sHAqCA,SAAgBU,EACd,EACA,EAC0B,CAC1B,GAAI,CAACC,EAAK,MAAM,IAAIX,EAAAA,YAAYC,EAAAA,WAAW,iBAAiB,EAC5D,GAAI,eAAe,IAAIU,CAAG,EAAG,MAAM,IAAIX,EAAAA,YAAYC,EAAAA,WAAW,gBAAgBU,CAAG,CAAC,EAElF,GAAM,CAAE,MAAOC,GAAaC,EAEtBC,OAAyD,CAC7D,GAAI,CAACF,EAAU,OAEf,IAAMG,EAASb,EAAAA,iBAAiBU,CAAmC,EAEnE,GAAIG,EAAO,OAAS,EAAG,MAAM,IAAIf,EAAAA,YAAYC,EAAAA,WAAW,iBAAiBU,EAAKI,CAAM,CAAC,EAErF,IAAMC,EAA4B,CAAC,EAEnC,IAAK,GAAM,CAACC,EAAKC,KAAQ,OAAO,QAAQN,CAAQ,EAC9C,EAAWK,GAAOd,EAAAA,wBAAwBe,EAAKD,CAAG,EAGpD,OAAOD,CACT,EAAA,CAAG,EAEGG,EAAgBL,EAAqB,OAAO,KAAKA,CAAkB,CAAC,CAAC,IAAIV,EAAAA,OAAO,EAAI,CAAC,EAErFgB,EAAiB,cAAcf,EAAAA,WAAY,CAC/C,OAAgB,YAAcQ,EAC9B,OAAgB,oBAAsBC,EACtC,OAAgB,eAAiBD,EAAW,gBAAkB,GAC9D,OAAgB,mBAAqBM,CACvC,EAOA,OAHA,OAAO,eAAeC,EAAgB,OAAQ,CAAE,MAAOT,CAAI,CAAC,EAC5D,eAAe,OAAOA,EAAKS,CAAc,EAElCA,CACT,C"}
package/dist/define.js CHANGED
@@ -1,2 +1,2 @@
1
- import{ORE_ERRORS as e,OreApiError as t}from"./errors.js";import{toKebab as n}from"./utils/dom.js";import{normalizePropDefinition as r,validatePropDefs as i}from"./props.js";import{BaseElement as a}from"./base-element.js";function o(o,s){if(!o)throw new t(e.defineRequiresTag);if(customElements.get(o))throw new t(e.defineDuplicate(o));let{props:c}=s,l=(()=>{if(!c)return;let n=i(c);if(n.length>0)throw new t(e.validationFailed(o,n));let a={};for(let[e,t]of Object.entries(c))a[e]=r(t,e);return a})(),u=l?Object.keys(l).map(n):[],d=class extends a{static _definition=s;static _normalizedPropDefs=l;static formAssociated=s.formAssociated??!1;static observedAttributes=u};return Object.defineProperty(d,"name",{value:o}),customElements.define(o,d),d}export{o as define};
1
+ import{BaseElement as e}from"./base-element.js";import{ORE_ERRORS as t,OreApiError as n}from"./errors.js";import{normalizePropDefinition as r,validatePropDefs as i}from"./props.js";import{toKebab as a}from"./utils/dom.js";function o(o,s){if(!o)throw new n(t.defineRequiresTag);if(customElements.get(o))throw new n(t.defineDuplicate(o));let{props:c}=s,l=(()=>{if(!c)return;let e=i(c);if(e.length>0)throw new n(t.validationFailed(o,e));let a={};for(let[e,t]of Object.entries(c))a[e]=r(t,e);return a})(),u=l?Object.keys(l).map(a):[],d=class extends e{static _definition=s;static _normalizedPropDefs=l;static formAssociated=s.formAssociated??!1;static observedAttributes=u};return Object.defineProperty(d,"name",{value:o}),customElements.define(o,d),d}export{o as define};
2
2
  //# sourceMappingURL=define.js.map
@@ -1,2 +1,2 @@
1
- const e=require("../errors.cjs"),t=require("../utils/dom.cjs"),n=require("../template/result.cjs");let r=require("@vielzeug/ripple");var i=(e,t,n,i,a)=>{let o=(0,r.signal)(e),s=(0,r.signal)(t),c=(0,r.createScope)(),l=[],u=[];return c.run(()=>{u=n(o,s).mount(i,a,e=>l.push(e))}),{cleanups:l,data:o,index:s,nodes:u,scope:c}},a=e=>{e.scope.dispose(),t.runAll(e.cleanups),t.removeNodes(e.nodes)},o=(t,n,o,s,c,l,u)=>{for(let e=0;e<n.length;e++){let a=o[e];if(t.has(a))continue;let d=(0,r.untrack)(()=>i(n[e],e,s,c,l));u.push(d),t.set(a,d)}let d=[];(0,r.batch)(()=>{for(let r=0;r<n.length;r++){let i=t.get(o[r]);e.invariant(i,`each() reconcile phase 2 lost an entry created in phase 1`),i.data.value=n[r],i.index.value=r,d.push(i)}});let f=l;for(let e=d.length-1;e>=0;e--){let t=d[e],n=t.nodes[0],r=t.nodes[t.nodes.length-1];if(n&&r!==f.previousSibling)for(let e of t.nodes)c.insertBefore(e,f);f=n??f}let p=new Set(o);for(let[e,n]of t)p.has(e)||(a(n),t.delete(e));return d},s=(e,t)=>{for(let n of t){a(n);for(let[t,r]of e)if(r===n){e.delete(t);break}}},c=(t,n)=>{let r=[],i=new Set;for(let a=0;a<t.length;a++){let o=n(t[a],a);if(i.has(o))throw new e.OreApiError(e.ORE_ERRORS.eachDuplicateKey(String(o),a));i.add(o),r.push(o)}return r},l=(t,n)=>{let r=t instanceof Error?t:Error(String(t));e.reportRuntimeError(new e.OreLifecycleError(`each() failed to reconcile a list update: ${r.message}`,{cause:r,component:`each()`,phase:`each-reconcile`}),n)};function u(i,u,d,f){let p=Array.isArray(i)?(0,r.signal)(i):typeof i==`function`?(0,r.computed)(i):i;return n.createDirectiveResult((n,i)=>{let m=n.parentNode;e.invariant(m,`each() anchor comment has no parent node`);let h=document.createComment(`each/end`);m.insertBefore(h,n.nextSibling);let g=new Map,_=[],v=null,y=[],b=()=>{f&&(v=f().mount(m,h,e=>y.push(e)))},x=()=>{v&&(t.runAll(y),t.removeNodes(v),v=null,y=[])},S=(0,r.effect)(()=>{let e=p.value??[];if(e.length===0){for(let e of(0,r.untrack)(()=>_))a(e);g=new Map,_=[],v||(0,r.untrack)(b);return}let t;try{t=(0,r.untrack)(()=>c(e,u))}catch(e){l(e,n);return}x();let i=[];try{_=(0,r.untrack)(()=>o(g,e,t,d,m,h,i))}catch(e){l(e,n),(0,r.untrack)(()=>s(g,i))}});i(()=>S.dispose()),i(()=>{x();for(let e of _)a(e);h.remove()})})}exports.each=u;
1
+ const e=require("../errors.cjs"),t=require("../template/result.cjs"),n=require("../utils/dom.cjs");let r=require("@vielzeug/ripple");var i=(e,t,n,i,a)=>{let o=(0,r.signal)(e),s=(0,r.signal)(t),c=(0,r.createScope)(),l=[],u=[];return c.run(()=>{u=n(o,s).mount(i,a,e=>l.push(e))}),{cleanups:l,data:o,index:s,nodes:u,scope:c}},a=e=>{e.scope.dispose(),n.runAll(e.cleanups),n.removeNodes(e.nodes)},o=(t,n,o,s,c,l,u)=>{for(let e=0;e<n.length;e++){let a=o[e];if(t.has(a))continue;let d=(0,r.untrack)(()=>i(n[e],e,s,c,l));u.push(d),t.set(a,d)}let d=[];(0,r.batch)(()=>{for(let r=0;r<n.length;r++){let i=t.get(o[r]);e.invariant(i,`each() reconcile phase 2 lost an entry created in phase 1`),i.data.value=n[r],i.index.value=r,d.push(i)}});let f=l;for(let e=d.length-1;e>=0;e--){let t=d[e],n=t.nodes[0],r=t.nodes[t.nodes.length-1];if(n&&r!==f.previousSibling)for(let e of t.nodes)c.insertBefore(e,f);f=n??f}let p=new Set(o);for(let[e,n]of t)p.has(e)||(a(n),t.delete(e));return d},s=(e,t)=>{for(let n of t){a(n);for(let[t,r]of e)if(r===n){e.delete(t);break}}},c=(t,n)=>{let r=[],i=new Set;for(let a=0;a<t.length;a++){let o=n(t[a],a);if(i.has(o))throw new e.OreApiError(e.ORE_ERRORS.eachDuplicateKey(String(o),a));i.add(o),r.push(o)}return r},l=(t,n)=>{let r=t instanceof Error?t:Error(String(t));e.reportRuntimeError(new e.OreLifecycleError(`each() failed to reconcile a list update: ${r.message}`,{cause:r,component:`each()`,phase:`each-reconcile`}),n)};function u(i,u,d,f){let p=Array.isArray(i)?(0,r.signal)(i):typeof i==`function`?(0,r.computed)(i):i;return t.createDirectiveResult((t,i)=>{let m=t.parentNode;e.invariant(m,`each() anchor comment has no parent node`);let h=document.createComment(`each/end`);m.insertBefore(h,t.nextSibling);let g=new Map,_=[],v=null,y=[],b=()=>{f&&(v=f().mount(m,h,e=>y.push(e)))},x=()=>{v&&(n.runAll(y),n.removeNodes(v),v=null,y=[])},S=(0,r.effect)(()=>{let e=p.value??[];if(e.length===0){for(let e of(0,r.untrack)(()=>_))a(e);g=new Map,_=[],v||(0,r.untrack)(b);return}let n;try{n=(0,r.untrack)(()=>c(e,u))}catch(e){l(e,t);return}x();let i=[];try{_=(0,r.untrack)(()=>o(g,e,n,d,m,h,i))}catch(e){l(e,t),(0,r.untrack)(()=>s(g,i))}});i(()=>S.dispose()),i(()=>{x();for(let e of _)a(e);h.remove()})})}exports.each=u;
2
2
  //# sourceMappingURL=each.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"each.cjs","names":["signal","createScope","untrack","OreApiError","ORE_ERRORS","OreLifecycleError","computed","createDirectiveResult","rawEffect","require_errors","require_dom","require_result","_vielzeug_ripple","createItem","dataSignal","item","indexSignal","index","scope","cleanups","nodes","render","parent","insertBefore","fn","removeItem","entry","reconcileItems","i","next","key","nextKeys","itemsMap","endMarker","createdThisPass","nextOrdered","cursor","j","firstNode","lastNode","node","nextKeySet","rollbackCreated","created","candidate","collectKeys","keys","seen","keyFn","reportEachError","cause","error","anchor","each","listSignal","list","itemsOrdered","fallbackNodes","fallbackCleanups","mountFallback","fallback","clearFallback","sub","nextList","registerCleanup"],"sources":["../../src/directives/each.ts"],"sourcesContent":["import {\n batch,\n computed,\n createScope,\n type Readable,\n effect as rawEffect,\n type Scope,\n type Signal,\n signal,\n untrack,\n} from '@vielzeug/ripple';\n\nimport { invariant, ORE_ERRORS, OreApiError, OreLifecycleError, reportRuntimeError } from '../errors';\nimport { createDirectiveResult, type DirectiveResult, type HTMLResult } from '../template/result';\nimport { type MaybeReactive, removeNodes, runAll } from '../utils/dom';\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\ntype MaybeReactiveArray<T> = MaybeReactive<T[]>;\ntype ItemKey = number | string;\n\ntype ItemEntry<T> = {\n cleanups: (() => void)[];\n data: Signal<T>;\n index: Signal<number>;\n nodes: Node[];\n scope: Scope;\n};\n\n// ─── Item lifecycle ───────────────────────────────────────────────────────────\n\nconst createItem = <T>(\n item: T,\n index: number,\n render: (item: Readable<T>, index: Readable<number>) => HTMLResult,\n parent: ParentNode,\n insertBefore: Node,\n): ItemEntry<T> => {\n const dataSignal: Signal<T> = signal(item);\n const indexSignal: Signal<number> = signal(index);\n const scope = createScope();\n const cleanups: (() => void)[] = [];\n let nodes: Node[] = [];\n\n scope.run(() => {\n const result = render(dataSignal, indexSignal);\n\n nodes = result.mount(parent, insertBefore, (fn) => cleanups.push(fn));\n });\n\n return { cleanups, data: dataSignal, index: indexSignal, nodes, scope };\n};\n\nconst removeItem = <T>(entry: ItemEntry<T>): void => {\n entry.scope.dispose();\n runAll(entry.cleanups);\n removeNodes(entry.nodes);\n};\n\n// ─── Reconciler ───────────────────────────────────────────────────────────────\n\n/**\n * Reconciles the live item map against the next array. The pass is transactional:\n * new entries are created first, existing entries are updated in-place via signal\n * writes, and stale entries are destroyed only after the whole pass has succeeded.\n * If creation throws (user render code), the caller rolls back the entries created\n * during this pass and the previous list state survives: the last good render stays\n * on screen. Returns the ordered list of entries matching nextList.\n */\nconst reconcileItems = <T>(\n itemsMap: Map<ItemKey, ItemEntry<T>>,\n next: T[],\n nextKeys: ItemKey[],\n render: (item: Readable<T>, index: Readable<number>) => HTMLResult,\n parent: ParentNode,\n endMarker: Node,\n createdThisPass: ItemEntry<T>[],\n): ItemEntry<T>[] => {\n // Phase 1: create every missing entry. This is the only step that can throw\n // (user render code), and it records what it created so a failure is undoable.\n for (let i = 0; i < next.length; i++) {\n const key = nextKeys[i];\n\n if (itemsMap.has(key)) continue;\n\n const entry = untrack(() => createItem(next[i], i, render, parent, endMarker));\n\n createdThisPass.push(entry);\n itemsMap.set(key, entry);\n }\n\n // Phase 2: ordered list + in-place updates for reused entries (signal writes).\n const nextOrdered: ItemEntry<T>[] = [];\n\n batch(() => {\n for (let i = 0; i < next.length; i++) {\n const entry = itemsMap.get(nextKeys[i]);\n\n invariant(entry, 'each() reconcile phase 2 lost an entry created in phase 1');\n\n entry.data.value = next[i];\n entry.index.value = i;\n nextOrdered.push(entry);\n }\n });\n\n // DOM ordering: right-to-left pass: move any item not already adjacent to cursor.\n // An item is in place when its last node directly precedes the cursor; items may\n // span several nodes (whitespace text around an element), so compare the last one.\n // Moving an already-placed item would disconnect and reconnect its custom elements.\n // O(n) DOM operations in the worst case; optimal for the typical small list sizes\n // encountered in UI components (tabs, options, menu items).\n let cursor: Node = endMarker;\n\n for (let j = nextOrdered.length - 1; j >= 0; j--) {\n const entry = nextOrdered[j];\n const firstNode = entry.nodes[0];\n const lastNode = entry.nodes[entry.nodes.length - 1];\n\n if (firstNode && lastNode !== cursor.previousSibling) {\n for (const node of entry.nodes) parent.insertBefore(node, cursor);\n }\n\n cursor = firstNode ?? cursor;\n }\n\n // Phase 3: commit: destroy stale entries only now that the pass has succeeded.\n const nextKeySet = new Set(nextKeys);\n\n for (const [key, entry] of itemsMap) {\n if (!nextKeySet.has(key)) {\n removeItem(entry);\n itemsMap.delete(key);\n }\n }\n\n return nextOrdered;\n};\n\n/** Undo a failed reconcile pass: destroy entries created during it, restoring the last good list. */\nconst rollbackCreated = <T>(itemsMap: Map<ItemKey, ItemEntry<T>>, created: ItemEntry<T>[]): void => {\n for (const entry of created) {\n removeItem(entry);\n\n for (const [key, candidate] of itemsMap) {\n if (candidate === entry) {\n itemsMap.delete(key);\n break;\n }\n }\n }\n};\n\nconst collectKeys = <T>(next: T[], keyFn: (item: T, index: number) => ItemKey): ItemKey[] => {\n const keys: ItemKey[] = [];\n const seen = new Set<ItemKey>();\n\n for (let i = 0; i < next.length; i++) {\n const key = keyFn(next[i], i);\n\n if (seen.has(key)) throw new OreApiError(ORE_ERRORS.eachDuplicateKey(String(key), i));\n\n seen.add(key);\n keys.push(key);\n }\n\n return keys;\n};\n\nconst reportEachError = (error: unknown, anchor: Comment): void => {\n const cause = error instanceof Error ? error : new Error(String(error));\n\n reportRuntimeError(\n new OreLifecycleError(`each() failed to reconcile a list update: ${cause.message}`, {\n cause,\n component: 'each()',\n phase: 'each-reconcile',\n }),\n anchor,\n );\n};\n\n// ─── Public API ───────────────────────────────────────────────────────────────\n\n/**\n * Renders a keyed list of items as a `DirectiveResult`.\n *\n * Each item is rendered by the provided render function.\n * Items are reused by key when the list changes; only stale items are destroyed.\n *\n * The render function receives a `Readable<T>` signal and a `Readable<number>` index\n * signal. Use `item.value` to read the current item inside reactive expressions:\n *\n * ```ts\n * html`${each(items, (item) => item.id, (item) => html`<li>${() => item.value.name}</li>`)}`\n * ```\n *\n * **Plain array:** when a plain `T[]` is passed (not a signal or getter), it is\n * treated as a one-time static render. Mutations to the original array are not\n * tracked. Pass a `Signal<T[]>` or `() => T[]` for reactive lists.\n *\n * **Optional fallback:** the fourth argument renders when the list is empty.\n *\n * **Key choice:** pass a stable item identifier (e.g. `item.id`), never the\n * array index: an index-based key reassigns to a different item whenever the\n * list is reordered or an item is inserted/removed before it, causing full\n * item teardown/recreation instead of the in-place update `each()` is built\n * for.\n *\n * **Duplicate keys:** a reconciliation failure (e.g. duplicate keys, see `eachDuplicateKey`)\n * does not throw past this function: an uncaught exception inside the reactive effect that\n * drives `each()` would risk corrupting unrelated effects scheduled in the same update batch.\n * Instead the last valid list is preserved and the failure is reported via the `ore:error` DOM event\n * (see `OreLifecycleError`, phase `'each-reconcile'`) plus a dev-only console log: listen for\n * `ore:error` on `document`/`window` to observe this in every build, including production.\n */\nexport function each<T>(\n list: MaybeReactiveArray<T>,\n keyFn: (item: T, index: number) => string | number,\n render: (item: Readable<T>, index: Readable<number>) => HTMLResult,\n fallback?: () => HTMLResult,\n): DirectiveResult {\n const listSignal = Array.isArray(list)\n ? signal(list as T[])\n : typeof list === 'function'\n ? computed(list as () => T[])\n : list;\n\n return createDirectiveResult((anchor, registerCleanup) => {\n const parent = anchor.parentNode;\n\n invariant(parent, 'each() anchor comment has no parent node');\n\n const endMarker = document.createComment('each/end');\n\n parent.insertBefore(endMarker, anchor.nextSibling);\n\n let itemsMap = new Map<ItemKey, ItemEntry<T>>();\n let itemsOrdered: ItemEntry<T>[] = [];\n let fallbackNodes: Node[] | null = null;\n let fallbackCleanups: (() => void)[] = [];\n\n const mountFallback = (): void => {\n if (!fallback) return;\n\n const result = fallback();\n\n fallbackNodes = result.mount(parent, endMarker, (fn) => fallbackCleanups.push(fn));\n };\n\n const clearFallback = (): void => {\n if (fallbackNodes) {\n runAll(fallbackCleanups);\n removeNodes(fallbackNodes);\n fallbackNodes = null;\n fallbackCleanups = [];\n }\n };\n\n const sub = rawEffect(() => {\n const nextList = listSignal.value ?? [];\n\n if (nextList.length === 0) {\n for (const entry of untrack(() => itemsOrdered)) removeItem(entry);\n itemsMap = new Map();\n itemsOrdered = [];\n\n if (!fallbackNodes) untrack(mountFallback);\n\n return;\n }\n\n let nextKeys: ItemKey[];\n\n try {\n nextKeys = untrack(() => collectKeys(nextList, keyFn));\n } catch (error) {\n reportEachError(error, anchor);\n return;\n }\n\n clearFallback();\n\n const createdThisPass: ItemEntry<T>[] = [];\n\n try {\n itemsOrdered = untrack(() =>\n reconcileItems(itemsMap, nextList, nextKeys, render, parent, endMarker, createdThisPass),\n );\n } catch (error) {\n // Undo this pass instead of tearing the list down: entries created before the\n // throw are removed, everything that was on screen stays exactly as it was.\n reportEachError(error, anchor);\n untrack(() => rollbackCreated(itemsMap, createdThisPass));\n }\n });\n\n registerCleanup(() => sub.dispose());\n registerCleanup(() => {\n clearFallback();\n for (const entry of itemsOrdered) removeItem(entry);\n endMarker.remove();\n });\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"each.cjs","names":["signal","createScope","untrack","OreApiError","ORE_ERRORS","OreLifecycleError","computed","createDirectiveResult","rawEffect","require_errors","require_result","require_dom","_vielzeug_ripple","createItem","dataSignal","item","indexSignal","index","scope","cleanups","nodes","render","parent","insertBefore","fn","removeItem","entry","reconcileItems","i","next","key","nextKeys","itemsMap","endMarker","createdThisPass","nextOrdered","cursor","j","firstNode","lastNode","node","nextKeySet","rollbackCreated","created","candidate","collectKeys","keys","seen","keyFn","reportEachError","cause","error","anchor","each","listSignal","list","itemsOrdered","fallbackNodes","fallbackCleanups","mountFallback","fallback","clearFallback","sub","nextList","registerCleanup"],"sources":["../../src/directives/each.ts"],"sourcesContent":["import {\n batch,\n computed,\n createScope,\n type Readable,\n effect as rawEffect,\n type Scope,\n type Signal,\n signal,\n untrack,\n} from '@vielzeug/ripple';\n\nimport { invariant, ORE_ERRORS, OreApiError, OreLifecycleError, reportRuntimeError } from '../errors';\nimport { createDirectiveResult, type DirectiveResult, type HTMLResult } from '../template/result';\nimport { type MaybeReactive, removeNodes, runAll } from '../utils/dom';\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\ntype MaybeReactiveArray<T> = MaybeReactive<T[]>;\ntype ItemKey = number | string;\n\ntype ItemEntry<T> = {\n cleanups: (() => void)[];\n data: Signal<T>;\n index: Signal<number>;\n nodes: Node[];\n scope: Scope;\n};\n\n// ─── Item lifecycle ───────────────────────────────────────────────────────────\n\nconst createItem = <T>(\n item: T,\n index: number,\n render: (item: Readable<T>, index: Readable<number>) => HTMLResult,\n parent: ParentNode,\n insertBefore: Node,\n): ItemEntry<T> => {\n const dataSignal: Signal<T> = signal(item);\n const indexSignal: Signal<number> = signal(index);\n const scope = createScope();\n const cleanups: (() => void)[] = [];\n let nodes: Node[] = [];\n\n scope.run(() => {\n const result = render(dataSignal, indexSignal);\n\n nodes = result.mount(parent, insertBefore, (fn) => cleanups.push(fn));\n });\n\n return { cleanups, data: dataSignal, index: indexSignal, nodes, scope };\n};\n\nconst removeItem = <T>(entry: ItemEntry<T>): void => {\n entry.scope.dispose();\n runAll(entry.cleanups);\n removeNodes(entry.nodes);\n};\n\n// ─── Reconciler ───────────────────────────────────────────────────────────────\n\n/**\n * Reconciles the live item map against the next array. The pass is transactional:\n * new entries are created first, existing entries are updated in-place via signal\n * writes, and stale entries are destroyed only after the whole pass has succeeded.\n * If creation throws (user render code), the caller rolls back the entries created\n * during this pass and the previous list state survives: the last good render stays\n * on screen. Returns the ordered list of entries matching nextList.\n */\nconst reconcileItems = <T>(\n itemsMap: Map<ItemKey, ItemEntry<T>>,\n next: T[],\n nextKeys: ItemKey[],\n render: (item: Readable<T>, index: Readable<number>) => HTMLResult,\n parent: ParentNode,\n endMarker: Node,\n createdThisPass: ItemEntry<T>[],\n): ItemEntry<T>[] => {\n // Phase 1: create every missing entry. This is the only step that can throw\n // (user render code), and it records what it created so a failure is undoable.\n for (let i = 0; i < next.length; i++) {\n const key = nextKeys[i];\n\n if (itemsMap.has(key)) continue;\n\n const entry = untrack(() => createItem(next[i], i, render, parent, endMarker));\n\n createdThisPass.push(entry);\n itemsMap.set(key, entry);\n }\n\n // Phase 2: ordered list + in-place updates for reused entries (signal writes).\n const nextOrdered: ItemEntry<T>[] = [];\n\n batch(() => {\n for (let i = 0; i < next.length; i++) {\n const entry = itemsMap.get(nextKeys[i]);\n\n invariant(entry, 'each() reconcile phase 2 lost an entry created in phase 1');\n\n entry.data.value = next[i];\n entry.index.value = i;\n nextOrdered.push(entry);\n }\n });\n\n // DOM ordering: right-to-left pass: move any item not already adjacent to cursor.\n // An item is in place when its last node directly precedes the cursor; items may\n // span several nodes (whitespace text around an element), so compare the last one.\n // Moving an already-placed item would disconnect and reconnect its custom elements.\n // O(n) DOM operations in the worst case; optimal for the typical small list sizes\n // encountered in UI components (tabs, options, menu items).\n let cursor: Node = endMarker;\n\n for (let j = nextOrdered.length - 1; j >= 0; j--) {\n const entry = nextOrdered[j];\n const firstNode = entry.nodes[0];\n const lastNode = entry.nodes[entry.nodes.length - 1];\n\n if (firstNode && lastNode !== cursor.previousSibling) {\n for (const node of entry.nodes) parent.insertBefore(node, cursor);\n }\n\n cursor = firstNode ?? cursor;\n }\n\n // Phase 3: commit: destroy stale entries only now that the pass has succeeded.\n const nextKeySet = new Set(nextKeys);\n\n for (const [key, entry] of itemsMap) {\n if (!nextKeySet.has(key)) {\n removeItem(entry);\n itemsMap.delete(key);\n }\n }\n\n return nextOrdered;\n};\n\n/** Undo a failed reconcile pass: destroy entries created during it, restoring the last good list. */\nconst rollbackCreated = <T>(itemsMap: Map<ItemKey, ItemEntry<T>>, created: ItemEntry<T>[]): void => {\n for (const entry of created) {\n removeItem(entry);\n\n for (const [key, candidate] of itemsMap) {\n if (candidate === entry) {\n itemsMap.delete(key);\n break;\n }\n }\n }\n};\n\nconst collectKeys = <T>(next: T[], keyFn: (item: T, index: number) => ItemKey): ItemKey[] => {\n const keys: ItemKey[] = [];\n const seen = new Set<ItemKey>();\n\n for (let i = 0; i < next.length; i++) {\n const key = keyFn(next[i], i);\n\n if (seen.has(key)) throw new OreApiError(ORE_ERRORS.eachDuplicateKey(String(key), i));\n\n seen.add(key);\n keys.push(key);\n }\n\n return keys;\n};\n\nconst reportEachError = (error: unknown, anchor: Comment): void => {\n const cause = error instanceof Error ? error : new Error(String(error));\n\n reportRuntimeError(\n new OreLifecycleError(`each() failed to reconcile a list update: ${cause.message}`, {\n cause,\n component: 'each()',\n phase: 'each-reconcile',\n }),\n anchor,\n );\n};\n\n// ─── Public API ───────────────────────────────────────────────────────────────\n\n/**\n * Renders a keyed list of items as a `DirectiveResult`.\n *\n * Each item is rendered by the provided render function.\n * Items are reused by key when the list changes; only stale items are destroyed.\n *\n * The render function receives a `Readable<T>` signal and a `Readable<number>` index\n * signal. Use `item.value` to read the current item inside reactive expressions:\n *\n * ```ts\n * html`${each(items, (item) => item.id, (item) => html`<li>${() => item.value.name}</li>`)}`\n * ```\n *\n * **Plain array:** when a plain `T[]` is passed (not a signal or getter), it is\n * treated as a one-time static render. Mutations to the original array are not\n * tracked. Pass a `Signal<T[]>` or `() => T[]` for reactive lists.\n *\n * **Optional fallback:** the fourth argument renders when the list is empty.\n *\n * **Key choice:** pass a stable item identifier (e.g. `item.id`), never the\n * array index: an index-based key reassigns to a different item whenever the\n * list is reordered or an item is inserted/removed before it, causing full\n * item teardown/recreation instead of the in-place update `each()` is built\n * for.\n *\n * **Duplicate keys:** a reconciliation failure (e.g. duplicate keys, see `eachDuplicateKey`)\n * does not throw past this function: an uncaught exception inside the reactive effect that\n * drives `each()` would risk corrupting unrelated effects scheduled in the same update batch.\n * Instead the last valid list is preserved and the failure is reported via the `ore:error` DOM event\n * (see `OreLifecycleError`, phase `'each-reconcile'`) plus a dev-only console log: listen for\n * `ore:error` on `document`/`window` to observe this in every build, including production.\n */\nexport function each<T>(\n list: MaybeReactiveArray<T>,\n keyFn: (item: T, index: number) => string | number,\n render: (item: Readable<T>, index: Readable<number>) => HTMLResult,\n fallback?: () => HTMLResult,\n): DirectiveResult {\n const listSignal = Array.isArray(list)\n ? signal(list as T[])\n : typeof list === 'function'\n ? computed(list as () => T[])\n : list;\n\n return createDirectiveResult((anchor, registerCleanup) => {\n const parent = anchor.parentNode;\n\n invariant(parent, 'each() anchor comment has no parent node');\n\n const endMarker = document.createComment('each/end');\n\n parent.insertBefore(endMarker, anchor.nextSibling);\n\n let itemsMap = new Map<ItemKey, ItemEntry<T>>();\n let itemsOrdered: ItemEntry<T>[] = [];\n let fallbackNodes: Node[] | null = null;\n let fallbackCleanups: (() => void)[] = [];\n\n const mountFallback = (): void => {\n if (!fallback) return;\n\n const result = fallback();\n\n fallbackNodes = result.mount(parent, endMarker, (fn) => fallbackCleanups.push(fn));\n };\n\n const clearFallback = (): void => {\n if (fallbackNodes) {\n runAll(fallbackCleanups);\n removeNodes(fallbackNodes);\n fallbackNodes = null;\n fallbackCleanups = [];\n }\n };\n\n const sub = rawEffect(() => {\n const nextList = listSignal.value ?? [];\n\n if (nextList.length === 0) {\n for (const entry of untrack(() => itemsOrdered)) removeItem(entry);\n itemsMap = new Map();\n itemsOrdered = [];\n\n if (!fallbackNodes) untrack(mountFallback);\n\n return;\n }\n\n let nextKeys: ItemKey[];\n\n try {\n nextKeys = untrack(() => collectKeys(nextList, keyFn));\n } catch (error) {\n reportEachError(error, anchor);\n return;\n }\n\n clearFallback();\n\n const createdThisPass: ItemEntry<T>[] = [];\n\n try {\n itemsOrdered = untrack(() =>\n reconcileItems(itemsMap, nextList, nextKeys, render, parent, endMarker, createdThisPass),\n );\n } catch (error) {\n // Undo this pass instead of tearing the list down: entries created before the\n // throw are removed, everything that was on screen stays exactly as it was.\n reportEachError(error, anchor);\n untrack(() => rollbackCreated(itemsMap, createdThisPass));\n }\n });\n\n registerCleanup(() => sub.dispose());\n registerCleanup(() => {\n clearFallback();\n for (const entry of itemsOrdered) removeItem(entry);\n endMarker.remove();\n });\n });\n}\n"],"mappings":"A,qIA+BA,IAAMa,GACJ,EACA,EACA,EACA,EACA,IACiB,CACjB,IAAMC,GAAA,EAAwBd,EAAAA,OAAAA,CAAOe,CAAI,EACnCC,GAAA,EAA8BhB,EAAAA,OAAAA,CAAOiB,CAAK,EAC1CC,GAAA,EAAQjB,EAAAA,YAAAA,CAAY,EACpBkB,EAA2B,CAAC,EAC9BC,EAAgB,CAAC,EAQrB,OANAF,EAAM,QAAU,CAGd,EAFeG,EAAOP,EAAYE,CAE1B,CAAA,CAAO,MAAMM,EAAQC,EAAe,GAAOJ,EAAS,KAAKK,CAAE,CAAC,CACtE,CAAC,EAEM,CAAE,WAAU,KAAMV,EAAY,MAAOE,EAAa,QAAO,OAAM,CACxE,EAEMS,EAAiB,GAA8B,CACnDC,EAAM,MAAM,QAAQ,EACpBf,EAAA,OAAOe,EAAM,QAAQ,EACrBf,EAAA,YAAYe,EAAM,KAAK,CACzB,EAYMC,GACJ,EACA,EACA,EACA,EACA,EACA,EACA,IACmB,CAGnB,IAAK,IAAIC,EAAI,EAAGA,EAAIC,EAAK,OAAQ,IAAK,CACpC,IAAMC,EAAMC,EAASH,GAErB,GAAII,EAAS,IAAIF,CAAG,EAAG,SAEvB,IAAMJ,GAAA,EAAQxB,EAAAA,QAAAA,KAAcW,EAAWgB,EAAKD,GAAIA,EAAGP,EAAQC,EAAQW,CAAS,CAAC,EAE7EC,EAAgB,KAAKR,CAAK,EAC1BM,EAAS,IAAIF,EAAKJ,CAAK,CACzB,CAGA,IAAMS,EAA8B,CAAC,GAErC,EAAAvB,EAAA,MAAA,KAAY,CACV,IAAK,IAAIgB,EAAI,EAAGA,EAAIC,EAAK,OAAQ,IAAK,CACpC,IAAMH,EAAQM,EAAS,IAAID,EAASH,EAAE,EAEtCnB,EAAA,UAAUiB,EAAO,2DAA2D,EAE5E,EAAM,KAAK,MAAQG,EAAKD,GACxB,EAAM,MAAM,MAAQA,EACpBO,EAAY,KAAKT,CAAK,CACxB,CACF,CAAC,EAQD,IAAIU,EAAeH,EAEnB,IAAK,IAAII,EAAIF,EAAY,OAAS,EAAGE,GAAK,EAAG,IAAK,CAChD,IAAMX,EAAQS,EAAYE,GACpBC,EAAYZ,EAAM,MAAM,GACxBa,EAAWb,EAAM,MAAMA,EAAM,MAAM,OAAS,GAElD,GAAIY,GAAaC,IAAaH,EAAO,gBACnC,IAAK,IAAMI,KAAQd,EAAM,MAAOJ,EAAO,aAAakB,EAAMJ,CAAM,EAGlE,EAASE,GAAaF,CACxB,CAGA,IAAMK,EAAa,IAAI,IAAIV,CAAQ,EAEnC,IAAK,GAAM,CAACD,EAAKJ,KAAUM,EACpBS,EAAW,IAAIX,CAAG,IACrBL,EAAWC,CAAK,EAChBM,EAAS,OAAOF,CAAG,GAIvB,OAAOK,CACT,EAGMO,GAAsB,EAAsC,IAAkC,CAClG,IAAK,IAAMhB,KAASiB,EAAS,CAC3BlB,EAAWC,CAAK,EAEhB,IAAK,GAAM,CAACI,EAAKc,KAAcZ,EAC7B,GAAIY,IAAclB,EAAO,CACvBM,EAAS,OAAOF,CAAG,EACnB,KACF,CAEJ,CACF,EAEMe,GAAkB,EAAW,IAA0D,CAC3F,IAAMC,EAAkB,CAAC,EACnBC,EAAO,IAAI,IAEjB,IAAK,IAAInB,EAAI,EAAGA,EAAIC,EAAK,OAAQ,IAAK,CACpC,IAAMC,EAAMkB,EAAMnB,EAAKD,GAAIA,CAAC,EAE5B,GAAImB,EAAK,IAAIjB,CAAG,EAAG,MAAM,IAAI3B,EAAAA,YAAYC,EAAAA,WAAW,iBAAiB,OAAO0B,CAAG,EAAGF,CAAC,CAAC,EAEpFmB,EAAK,IAAIjB,CAAG,EACZgB,EAAK,KAAKhB,CAAG,CACf,CAEA,OAAOgB,CACT,EAEMG,GAAmB,EAAgB,IAA0B,CACjE,IAAMC,EAAQC,aAAiB,MAAQA,EAAY,MAAM,OAAOA,CAAK,CAAC,EAEtE1C,EAAA,mBACE,IAAIJ,EAAAA,kBAAkB,6CAA6C6C,EAAM,UAAW,CAClF,QACA,UAAW,SACX,MAAO,gBACT,CAAC,EACDE,CACF,CACF,EAoCA,SAAgBC,EACd,EACA,EACA,EACA,EACiB,CACjB,IAAMC,EAAa,MAAM,QAAQC,CAAI,GAAA,EACjCvD,EAAAA,OAAAA,CAAOuD,CAAW,EAClB,OAAOA,GAAS,YAAA,EACdjD,EAAAA,SAAAA,CAASiD,CAAiB,EAC1BA,EAEN,OAAOhD,EAAAA,uBAAuB,EAAQ,IAAoB,CACxD,IAAMe,EAAS8B,EAAO,WAEtB3C,EAAA,UAAUa,EAAQ,0CAA0C,EAE5D,IAAMW,EAAY,SAAS,cAAc,UAAU,EAEnDX,EAAO,aAAaW,EAAWmB,EAAO,WAAW,EAEjD,IAAIpB,EAAW,IAAI,IACfwB,EAA+B,CAAC,EAChCC,EAA+B,KAC/BC,EAAmC,CAAC,EAElCC,MAA4B,CAC3BC,IAIL,EAFeA,EAEC,CAAA,CAAO,MAAMtC,EAAQW,EAAY,GAAOyB,EAAiB,KAAKlC,CAAE,CAAC,EACnF,EAEMqC,MAA4B,CAC5BJ,IACF9C,EAAA,OAAO+C,CAAgB,EACvB/C,EAAA,YAAY8C,CAAa,EACzB,EAAgB,KAChB,EAAmB,CAAC,EAExB,EAEMK,GAAA,EAAMtD,EAAAA,OAAAA,KAAgB,CAC1B,IAAMuD,EAAWT,EAAW,OAAS,CAAC,EAEtC,GAAIS,EAAS,SAAW,EAAG,CACzB,IAAK,IAAMrC,KAAA,EAASxB,EAAAA,QAAAA,KAAcsD,CAAY,EAAG/B,EAAWC,CAAK,EACjE,EAAW,IAAI,IACf,EAAe,CAAC,EAEX+B,IAAe,EAAA7C,EAAA,QAAA,CAAQ+C,CAAa,EAEzC,MACF,CAEA,IAAI5B,EAEJ,GAAI,CACF,GAAA,EAAW7B,EAAAA,QAAAA,KAAc2C,EAAYkB,EAAUf,CAAK,CAAC,CACvD,OAASG,EAAO,CACdF,EAAgBE,EAAOC,CAAM,EAC7B,MACF,CAEAS,EAAc,EAEd,IAAM3B,EAAkC,CAAC,EAEzC,GAAI,CACF,GAAA,EAAehC,EAAAA,QAAAA,KACbyB,EAAeK,EAAU+B,EAAUhC,EAAUV,EAAQC,EAAQW,EAAWC,CAAe,CACzF,CACF,OAASiB,EAAO,CAGdF,EAAgBE,EAAOC,CAAM,GAC7B,EAAAxC,EAAA,QAAA,KAAc8B,EAAgBV,EAAUE,CAAe,CAAC,CAC1D,CACF,CAAC,EAED8B,MAAsBF,EAAI,QAAQ,CAAC,EACnCE,MAAsB,CACpBH,EAAc,EACd,IAAK,IAAMnC,KAAS8B,EAAc/B,EAAWC,CAAK,EAClDO,EAAU,OAAO,CACnB,CAAC,CACH,CAAC,CACH,C"}
@@ -1,2 +1,2 @@
1
- import{ORE_ERRORS as e,OreApiError as t,OreLifecycleError as n,invariant as r,reportRuntimeError as i}from"../errors.js";import{removeNodes as a,runAll as o}from"../utils/dom.js";import{createDirectiveResult as s}from"../template/result.js";import{batch as c,computed as l,createScope as u,effect as d,signal as f,untrack as p}from"@vielzeug/ripple";var m=(e,t,n,r,i)=>{let a=f(e),o=f(t),s=u(),c=[],l=[];return s.run(()=>{l=n(a,o).mount(r,i,e=>c.push(e))}),{cleanups:c,data:a,index:o,nodes:l,scope:s}},h=e=>{e.scope.dispose(),o(e.cleanups),a(e.nodes)},g=(e,t,n,i,a,o,s)=>{for(let r=0;r<t.length;r++){let c=n[r];if(e.has(c))continue;let l=p(()=>m(t[r],r,i,a,o));s.push(l),e.set(c,l)}let l=[];c(()=>{for(let i=0;i<t.length;i++){let a=e.get(n[i]);r(a,`each() reconcile phase 2 lost an entry created in phase 1`),a.data.value=t[i],a.index.value=i,l.push(a)}});let u=o;for(let e=l.length-1;e>=0;e--){let t=l[e],n=t.nodes[0],r=t.nodes[t.nodes.length-1];if(n&&r!==u.previousSibling)for(let e of t.nodes)a.insertBefore(e,u);u=n??u}let d=new Set(n);for(let[t,n]of e)d.has(t)||(h(n),e.delete(t));return l},_=(e,t)=>{for(let n of t){h(n);for(let[t,r]of e)if(r===n){e.delete(t);break}}},v=(n,r)=>{let i=[],a=/* @__PURE__ */ new Set;for(let o=0;o<n.length;o++){let s=r(n[o],o);if(a.has(s))throw new t(e.eachDuplicateKey(String(s),o));a.add(s),i.push(s)}return i},y=(e,t)=>{let r=e instanceof Error?e:Error(String(e));i(new n(`each() failed to reconcile a list update: ${r.message}`,{cause:r,component:`each()`,phase:`each-reconcile`}),t)};function b(e,t,n,i){let c=Array.isArray(e)?f(e):typeof e==`function`?l(e):e;return s((e,s)=>{let l=e.parentNode;r(l,`each() anchor comment has no parent node`);let u=document.createComment(`each/end`);l.insertBefore(u,e.nextSibling);let f=/* @__PURE__ */ new Map,m=[],b=null,x=[],S=()=>{i&&(b=i().mount(l,u,e=>x.push(e)))},C=()=>{b&&(o(x),a(b),b=null,x=[])},w=d(()=>{let r=c.value??[];if(r.length===0){for(let e of p(()=>m))h(e);f=/* @__PURE__ */ new Map,m=[],b||p(S);return}let i;try{i=p(()=>v(r,t))}catch(t){y(t,e);return}C();let a=[];try{m=p(()=>g(f,r,i,n,l,u,a))}catch(t){y(t,e),p(()=>_(f,a))}});s(()=>w.dispose()),s(()=>{C();for(let e of m)h(e);u.remove()})})}export{b as each};
1
+ import{ORE_ERRORS as e,OreApiError as t,OreLifecycleError as n,invariant as r,reportRuntimeError as i}from"../errors.js";import{createDirectiveResult as a}from"../template/result.js";import{removeNodes as o,runAll as s}from"../utils/dom.js";import{batch as c,computed as l,createScope as u,effect as d,signal as f,untrack as p}from"@vielzeug/ripple";var m=(e,t,n,r,i)=>{let a=f(e),o=f(t),s=u(),c=[],l=[];return s.run(()=>{l=n(a,o).mount(r,i,e=>c.push(e))}),{cleanups:c,data:a,index:o,nodes:l,scope:s}},h=e=>{e.scope.dispose(),s(e.cleanups),o(e.nodes)},g=(e,t,n,i,a,o,s)=>{for(let r=0;r<t.length;r++){let c=n[r];if(e.has(c))continue;let l=p(()=>m(t[r],r,i,a,o));s.push(l),e.set(c,l)}let l=[];c(()=>{for(let i=0;i<t.length;i++){let a=e.get(n[i]);r(a,`each() reconcile phase 2 lost an entry created in phase 1`),a.data.value=t[i],a.index.value=i,l.push(a)}});let u=o;for(let e=l.length-1;e>=0;e--){let t=l[e],n=t.nodes[0],r=t.nodes[t.nodes.length-1];if(n&&r!==u.previousSibling)for(let e of t.nodes)a.insertBefore(e,u);u=n??u}let d=new Set(n);for(let[t,n]of e)d.has(t)||(h(n),e.delete(t));return l},_=(e,t)=>{for(let n of t){h(n);for(let[t,r]of e)if(r===n){e.delete(t);break}}},v=(n,r)=>{let i=[],a=/* @__PURE__ */ new Set;for(let o=0;o<n.length;o++){let s=r(n[o],o);if(a.has(s))throw new t(e.eachDuplicateKey(String(s),o));a.add(s),i.push(s)}return i},y=(e,t)=>{let r=e instanceof Error?e:Error(String(e));i(new n(`each() failed to reconcile a list update: ${r.message}`,{cause:r,component:`each()`,phase:`each-reconcile`}),t)};function b(e,t,n,i){let c=Array.isArray(e)?f(e):typeof e==`function`?l(e):e;return a((e,a)=>{let l=e.parentNode;r(l,`each() anchor comment has no parent node`);let u=document.createComment(`each/end`);l.insertBefore(u,e.nextSibling);let f=/* @__PURE__ */ new Map,m=[],b=null,x=[],S=()=>{i&&(b=i().mount(l,u,e=>x.push(e)))},C=()=>{b&&(s(x),o(b),b=null,x=[])},w=d(()=>{let r=c.value??[];if(r.length===0){for(let e of p(()=>m))h(e);f=/* @__PURE__ */ new Map,m=[],b||p(S);return}let i;try{i=p(()=>v(r,t))}catch(t){y(t,e);return}C();let a=[];try{m=p(()=>g(f,r,i,n,l,u,a))}catch(t){y(t,e),p(()=>_(f,a))}});a(()=>w.dispose()),a(()=>{C();for(let e of m)h(e);u.remove()})})}export{b as each};
2
2
  //# sourceMappingURL=each.js.map
@@ -1,2 +1,2 @@
1
- const e=require("../errors.cjs"),t=require("../utils/dom.cjs"),n=require("../template/result.cjs");let r=require("@vielzeug/ripple");var i=(e,t,n)=>{let r=document.createElement(`template`);r.innerHTML=e;let i=Array.from(r.content.cloneNode(!0).childNodes);for(let e of i)t.insertBefore(e,n);return i};function a(a){let o=typeof a==`function`?(0,r.computed)(a):(0,r.isReactive)(a)?a:null;return n.createDirectiveResult((n,s)=>{let c=n.parentNode;e.invariant(c,`unsafeHtml() anchor comment has no parent node`);let l=document.createComment(`unsafe-html/end`);if(c.insertBefore(l,n.nextSibling),o){let e=t.createReplaceableSlot(),n=(0,r.effect)(()=>{e.clear(),e.setNodes(i(o.value,c,l))});s(()=>n.dispose()),s(()=>{e.clear(),l.remove()})}else i(a,c,l),s(()=>l.remove())})}exports.unsafeHtml=a;
1
+ const e=require("../errors.cjs"),t=require("../template/result.cjs"),n=require("../utils/dom.cjs");let r=require("@vielzeug/ripple");var i=(e,t,n)=>{let r=document.createElement(`template`);r.innerHTML=e;let i=Array.from(r.content.cloneNode(!0).childNodes);for(let e of i)t.insertBefore(e,n);return i};function a(a){let o=typeof a==`function`?(0,r.computed)(a):(0,r.isReactive)(a)?a:null;return t.createDirectiveResult((t,s)=>{let c=t.parentNode;e.invariant(c,`unsafeHtml() anchor comment has no parent node`);let l=document.createComment(`unsafe-html/end`);if(c.insertBefore(l,t.nextSibling),o){let e=n.createReplaceableSlot(),t=(0,r.effect)(()=>{e.clear(),e.setNodes(i(o.value,c,l))});s(()=>t.dispose()),s(()=>{e.clear(),l.remove()})}else i(a,c,l),s(()=>l.remove())})}exports.unsafeHtml=a;
2
2
  //# sourceMappingURL=unsafe-html.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"unsafe-html.cjs","names":["computed","isReactive","createDirectiveResult","createReplaceableSlot","rawEffect","require_errors","require_dom","require_result","_vielzeug_ripple","parseHtml","tpl","html","nodes","node","parent","insertBefore","unsafeHtml","src","value","anchor","endMarker","slot","stop","registerCleanup"],"sources":["../../src/directives/unsafe-html.ts"],"sourcesContent":["import { computed, isReactive, type Readable, effect as rawEffect, type Signal } from '@vielzeug/ripple';\n\nimport { invariant } from '../errors';\nimport { createDirectiveResult, type DirectiveResult } from '../template/result';\nimport { createReplaceableSlot } from '../utils/dom';\n\nconst parseHtml = (html: string, parent: ParentNode, insertBefore: Node): Node[] => {\n const tpl = document.createElement('template');\n\n tpl.innerHTML = html;\n\n const nodes = Array.from(tpl.content.cloneNode(true).childNodes);\n\n for (const node of nodes) parent.insertBefore(node, insertBefore);\n\n return nodes;\n};\n\n/**\n * Renders HTML without escaping as a DirectiveResult.\n *\n * This is intentionally named `unsafeHtml`: sanitization is an application\n * boundary, not mutable process-wide framework configuration. Sanitize\n * untrusted content before passing it here.\n *\n * Supports static strings, signals, and getter functions `() => string`.\n * When reactive, the DOM is updated in-place whenever the value changes.\n */\nexport function unsafeHtml(value: (() => string) | string | Signal<string> | Readable<string>): DirectiveResult {\n const isFn = typeof value === 'function';\n const src: Readable<string> | null = isFn ? computed(value as () => string) : isReactive(value) ? value : null;\n\n return createDirectiveResult((anchor, registerCleanup) => {\n const parent = anchor.parentNode;\n\n invariant(parent, 'unsafeHtml() anchor comment has no parent node');\n\n const endMarker = document.createComment('unsafe-html/end');\n\n parent.insertBefore(endMarker, anchor.nextSibling);\n\n if (src) {\n const slot = createReplaceableSlot();\n\n const stop = rawEffect(() => {\n slot.clear();\n slot.setNodes(parseHtml(src.value, parent, endMarker));\n });\n\n registerCleanup(() => stop.dispose());\n registerCleanup(() => {\n slot.clear();\n endMarker.remove();\n });\n } else {\n parseHtml(value as string, parent, endMarker);\n\n registerCleanup(() => endMarker.remove());\n }\n });\n}\n"],"mappings":"A,qIAMA,IAAMS,GAAa,EAAc,EAAoB,IAA+B,CAClF,IAAMC,EAAM,SAAS,cAAc,UAAU,EAE7C,EAAI,UAAYC,EAEhB,IAAMC,EAAQ,MAAM,KAAKF,EAAI,QAAQ,UAAU,EAAI,CAAC,CAAC,UAAU,EAE/D,IAAK,IAAMG,KAAQD,EAAOE,EAAO,aAAaD,EAAME,CAAY,EAEhE,OAAOH,CACT,EAYA,SAAgBI,EAAW,EAAqF,CAE9G,IAAMC,EADO,OAAOC,GAAU,YAAA,EACclB,EAAAA,SAAAA,CAASkB,CAAqB,GAAA,EAAIjB,EAAAA,WAAAA,CAAWiB,CAAK,EAAIA,EAAQ,KAE1G,OAAOhB,EAAAA,uBAAuB,EAAQ,IAAoB,CACxD,IAAMY,EAASK,EAAO,WAEtBd,EAAA,UAAUS,EAAQ,gDAAgD,EAElE,IAAMM,EAAY,SAAS,cAAc,iBAAiB,EAI1D,GAFAN,EAAO,aAAaM,EAAWD,EAAO,WAAW,EAE7CF,EAAK,CACP,IAAMI,EAAOlB,EAAAA,sBAAsB,EAE7BmB,GAAA,EAAOlB,EAAAA,OAAAA,KAAgB,CAC3BiB,EAAK,MAAM,EACXA,EAAK,SAASZ,EAAUQ,EAAI,MAAOH,EAAQM,CAAS,CAAC,CACvD,CAAC,EAEDG,MAAsBD,EAAK,QAAQ,CAAC,EACpCC,MAAsB,CACpBF,EAAK,MAAM,EACXD,EAAU,OAAO,CACnB,CAAC,CACH,MACEX,EAAUS,EAAiBJ,EAAQM,CAAS,EAE5CG,MAAsBH,EAAU,OAAO,CAAC,CAE5C,CAAC,CACH,C"}
1
+ {"version":3,"file":"unsafe-html.cjs","names":["computed","isReactive","createDirectiveResult","createReplaceableSlot","rawEffect","require_errors","require_result","require_dom","_vielzeug_ripple","parseHtml","tpl","html","nodes","node","parent","insertBefore","unsafeHtml","src","value","anchor","endMarker","slot","stop","registerCleanup"],"sources":["../../src/directives/unsafe-html.ts"],"sourcesContent":["import { computed, isReactive, type Readable, effect as rawEffect, type Signal } from '@vielzeug/ripple';\n\nimport { invariant } from '../errors';\nimport { createDirectiveResult, type DirectiveResult } from '../template/result';\nimport { createReplaceableSlot } from '../utils/dom';\n\nconst parseHtml = (html: string, parent: ParentNode, insertBefore: Node): Node[] => {\n const tpl = document.createElement('template');\n\n tpl.innerHTML = html;\n\n const nodes = Array.from(tpl.content.cloneNode(true).childNodes);\n\n for (const node of nodes) parent.insertBefore(node, insertBefore);\n\n return nodes;\n};\n\n/**\n * Renders HTML without escaping as a DirectiveResult.\n *\n * This is intentionally named `unsafeHtml`: sanitization is an application\n * boundary, not mutable process-wide framework configuration. Sanitize\n * untrusted content before passing it here.\n *\n * Supports static strings, signals, and getter functions `() => string`.\n * When reactive, the DOM is updated in-place whenever the value changes.\n */\nexport function unsafeHtml(value: (() => string) | string | Signal<string> | Readable<string>): DirectiveResult {\n const isFn = typeof value === 'function';\n const src: Readable<string> | null = isFn ? computed(value as () => string) : isReactive(value) ? value : null;\n\n return createDirectiveResult((anchor, registerCleanup) => {\n const parent = anchor.parentNode;\n\n invariant(parent, 'unsafeHtml() anchor comment has no parent node');\n\n const endMarker = document.createComment('unsafe-html/end');\n\n parent.insertBefore(endMarker, anchor.nextSibling);\n\n if (src) {\n const slot = createReplaceableSlot();\n\n const stop = rawEffect(() => {\n slot.clear();\n slot.setNodes(parseHtml(src.value, parent, endMarker));\n });\n\n registerCleanup(() => stop.dispose());\n registerCleanup(() => {\n slot.clear();\n endMarker.remove();\n });\n } else {\n parseHtml(value as string, parent, endMarker);\n\n registerCleanup(() => endMarker.remove());\n }\n });\n}\n"],"mappings":"A,qIAMA,IAAMS,GAAa,EAAc,EAAoB,IAA+B,CAClF,IAAMC,EAAM,SAAS,cAAc,UAAU,EAE7C,EAAI,UAAYC,EAEhB,IAAMC,EAAQ,MAAM,KAAKF,EAAI,QAAQ,UAAU,EAAI,CAAC,CAAC,UAAU,EAE/D,IAAK,IAAMG,KAAQD,EAAOE,EAAO,aAAaD,EAAME,CAAY,EAEhE,OAAOH,CACT,EAYA,SAAgBI,EAAW,EAAqF,CAE9G,IAAMC,EADO,OAAOC,GAAU,YAAA,EACclB,EAAAA,SAAAA,CAASkB,CAAqB,GAAA,EAAIjB,EAAAA,WAAAA,CAAWiB,CAAK,EAAIA,EAAQ,KAE1G,OAAOhB,EAAAA,uBAAuB,EAAQ,IAAoB,CACxD,IAAMY,EAASK,EAAO,WAEtBd,EAAA,UAAUS,EAAQ,gDAAgD,EAElE,IAAMM,EAAY,SAAS,cAAc,iBAAiB,EAI1D,GAFAN,EAAO,aAAaM,EAAWD,EAAO,WAAW,EAE7CF,EAAK,CACP,IAAMI,EAAOlB,EAAAA,sBAAsB,EAE7BmB,GAAA,EAAOlB,EAAAA,OAAAA,KAAgB,CAC3BiB,EAAK,MAAM,EACXA,EAAK,SAASZ,EAAUQ,EAAI,MAAOH,EAAQM,CAAS,CAAC,CACvD,CAAC,EAEDG,MAAsBD,EAAK,QAAQ,CAAC,EACpCC,MAAsB,CACpBF,EAAK,MAAM,EACXD,EAAU,OAAO,CACnB,CAAC,CACH,MACEX,EAAUS,EAAiBJ,EAAQM,CAAS,EAE5CG,MAAsBH,EAAU,OAAO,CAAC,CAE5C,CAAC,CACH,C"}
@@ -1,2 +1,2 @@
1
- import{invariant as e}from"../errors.js";import{createReplaceableSlot as t}from"../utils/dom.js";import{createDirectiveResult as n}from"../template/result.js";import{computed as r,effect as i,isReactive as a}from"@vielzeug/ripple";var o=(e,t,n)=>{let r=document.createElement(`template`);r.innerHTML=e;let i=Array.from(r.content.cloneNode(!0).childNodes);for(let e of i)t.insertBefore(e,n);return i};function s(s){let c=typeof s==`function`?r(s):a(s)?s:null;return n((n,r)=>{let a=n.parentNode;e(a,`unsafeHtml() anchor comment has no parent node`);let l=document.createComment(`unsafe-html/end`);if(a.insertBefore(l,n.nextSibling),c){let e=t(),n=i(()=>{e.clear(),e.setNodes(o(c.value,a,l))});r(()=>n.dispose()),r(()=>{e.clear(),l.remove()})}else o(s,a,l),r(()=>l.remove())})}export{s as unsafeHtml};
1
+ import{invariant as e}from"../errors.js";import{createDirectiveResult as t}from"../template/result.js";import{createReplaceableSlot as n}from"../utils/dom.js";import{computed as r,effect as i,isReactive as a}from"@vielzeug/ripple";var o=(e,t,n)=>{let r=document.createElement(`template`);r.innerHTML=e;let i=Array.from(r.content.cloneNode(!0).childNodes);for(let e of i)t.insertBefore(e,n);return i};function s(s){let c=typeof s==`function`?r(s):a(s)?s:null;return t((t,r)=>{let a=t.parentNode;e(a,`unsafeHtml() anchor comment has no parent node`);let l=document.createComment(`unsafe-html/end`);if(a.insertBefore(l,t.nextSibling),c){let e=n(),t=i(()=>{e.clear(),e.setNodes(o(c.value,a,l))});r(()=>t.dispose()),r(()=>{e.clear(),l.remove()})}else o(s,a,l),r(()=>l.remove())})}export{s as unsafeHtml};
2
2
  //# sourceMappingURL=unsafe-html.js.map
@@ -1,2 +1,2 @@
1
- const e=require("../errors.cjs"),t=require("../utils/dom.cjs"),n=require("../template/result.cjs");let r=require("@vielzeug/ripple");var i=`when() anchor comment has no parent node`;function a(a,o,s){return typeof a!=`function`&&!(0,r.isReactive)(a)?n.createDirectiveResult((r,c)=>{let l=a?o():s?s():null;if(!l||!n.isHtmlResult(l))return;let u=r.parentNode;e.invariant(u,i);let d=l.mount(u,r,c);c(()=>t.removeNodes(d))}):n.createDirectiveResult((c,l)=>{let u=(typeof a==`function`?(0,r.computed)(a):null)??a,d=c.parentNode;e.invariant(d,i);let f=document.createComment(`when/end`);d.insertBefore(f,c.nextSibling);let p=t.createReplaceableSlot(),m=(0,r.effect)(()=>{let e=u.value;p.clear();let t=e?o():s?s():null;t&&n.isHtmlResult(t)&&p.setNodes((0,r.untrack)(()=>t.mount(d,f,p.registerCleanup)))});l(()=>m.dispose()),l(()=>{p.clear(),f.remove()})})}exports.when=a;
1
+ const e=require("../errors.cjs"),t=require("../template/result.cjs"),n=require("../utils/dom.cjs");let r=require("@vielzeug/ripple");var i=`when() anchor comment has no parent node`;function a(a,o,s){return typeof a!=`function`&&!(0,r.isReactive)(a)?t.createDirectiveResult((r,c)=>{let l=a?o():s?s():null;if(!l||!t.isHtmlResult(l))return;let u=r.parentNode;e.invariant(u,i);let d=l.mount(u,r,c);c(()=>n.removeNodes(d))}):t.createDirectiveResult((c,l)=>{let u=(typeof a==`function`?(0,r.computed)(a):null)??a,d=c.parentNode;e.invariant(d,i);let f=document.createComment(`when/end`);d.insertBefore(f,c.nextSibling);let p=n.createReplaceableSlot(),m=(0,r.effect)(()=>{let e=u.value;p.clear();let n=e?o():s?s():null;n&&t.isHtmlResult(n)&&p.setNodes((0,r.untrack)(()=>n.mount(d,f,p.registerCleanup)))});l(()=>m.dispose()),l(()=>{p.clear(),f.remove()})})}exports.when=a;
2
2
  //# sourceMappingURL=when.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"when.cjs","names":["isReactive","createDirectiveResult","isHtmlResult","removeNodes","computed","createReplaceableSlot","rawEffect","untrack","require_errors","require_dom","require_result","_vielzeug_ripple","NO_PARENT_MSG","when","condition","branch","truthy","falsy","parent","anchor","nodes","registerCleanup","conditionSignal","endMarker","slot","sub","next"],"sources":["../../src/directives/when.ts"],"sourcesContent":["import { computed, isReactive, type Readable, effect as rawEffect, untrack } from '@vielzeug/ripple';\n\nimport { invariant } from '../errors';\nimport { createDirectiveResult, type DirectiveResult, type HTMLResult, isHtmlResult } from '../template/result';\nimport { createReplaceableSlot, type MaybeReactive, removeNodes } from '../utils/dom';\n\ntype WhenRenderable = HTMLResult | null | undefined | false;\n\nconst NO_PARENT_MSG = 'when() anchor comment has no parent node';\n\n/**\n * Conditionally renders one of two branches as a `DirectiveResult`.\n *\n * The condition may be a boolean, signal, or getter function.\n * When the condition changes, the current branch is cleaned up and\n * the new branch is mounted in its place.\n *\n * @example\n * ```ts\n * html`${when(isLoggedIn, () => html`<p>Welcome</p>`, () => html`<p>Log in</p>`)}`\n * ```\n */\nexport function when(\n condition: MaybeReactive<boolean>,\n truthy: () => WhenRenderable,\n falsy?: () => WhenRenderable,\n): DirectiveResult {\n if (typeof condition !== 'function' && !isReactive(condition)) {\n return createDirectiveResult((anchor, registerCleanup) => {\n const branch = condition ? truthy() : falsy ? falsy() : null;\n\n if (!branch || !isHtmlResult(branch)) return;\n\n const parent = anchor.parentNode;\n\n invariant(parent, NO_PARENT_MSG);\n\n const nodes = branch.mount(parent, anchor, registerCleanup);\n\n registerCleanup(() => removeNodes(nodes));\n });\n }\n\n return createDirectiveResult((anchor, registerCleanup) => {\n const ownedComputed = typeof condition === 'function' ? computed(condition as () => boolean) : null;\n const conditionSignal = ownedComputed ?? (condition as Readable<boolean>);\n\n const parent = anchor.parentNode;\n\n invariant(parent, NO_PARENT_MSG);\n\n const endMarker = document.createComment('when/end');\n\n parent.insertBefore(endMarker, anchor.nextSibling);\n\n const slot = createReplaceableSlot();\n\n const sub = rawEffect(() => {\n const next = conditionSignal.value;\n\n slot.clear();\n\n const branch = next ? truthy() : falsy ? falsy() : null;\n\n if (!branch || !isHtmlResult(branch)) return;\n\n slot.setNodes(untrack(() => branch.mount(parent, endMarker, slot.registerCleanup)));\n });\n\n registerCleanup(() => sub.dispose());\n registerCleanup(() => {\n slot.clear();\n endMarker.remove();\n });\n });\n}\n"],"mappings":"A,qIAQA,IAAMY,EAAgB,2CActB,SAAgBC,EACd,EACA,EACA,EACiB,CAiBjB,OAhBI,OAAOC,GAAc,YAAc,EAAA,EAACd,EAAAA,WAAAA,CAAWc,CAAS,EACnDb,EAAAA,uBAAuB,EAAQ,IAAoB,CACxD,IAAMc,EAASD,EAAYE,EAAO,EAAIC,EAAQA,EAAM,EAAI,KAExD,GAAI,CAACF,GAAU,CAACb,EAAAA,aAAaa,CAAM,EAAG,OAEtC,IAAMG,EAASC,EAAO,WAEtBX,EAAA,UAAUU,EAAQN,CAAa,EAE/B,IAAMQ,EAAQL,EAAO,MAAMG,EAAQC,EAAQE,CAAe,EAE1DA,MAAsBlB,EAAAA,YAAYiB,CAAK,CAAC,CAC1C,CAAC,EAGInB,EAAAA,uBAAuB,EAAQ,IAAoB,CAExD,IAAMqB,GADgB,OAAOR,GAAc,YAAA,EAAaV,EAAAA,SAAAA,CAASU,CAA0B,EAAI,OACrDA,EAEpCI,EAASC,EAAO,WAEtBX,EAAA,UAAUU,EAAQN,CAAa,EAE/B,IAAMW,EAAY,SAAS,cAAc,UAAU,EAEnDL,EAAO,aAAaK,EAAWJ,EAAO,WAAW,EAEjD,IAAMK,EAAOnB,EAAAA,sBAAsB,EAE7BoB,GAAA,EAAMnB,EAAAA,OAAAA,KAAgB,CAC1B,IAAMoB,EAAOJ,EAAgB,MAE7BE,EAAK,MAAM,EAEX,IAAMT,EAASW,EAAOV,EAAO,EAAIC,EAAQA,EAAM,EAAI,KAE9CF,GAAWb,EAAAA,aAAaa,CAAM,GAEnCS,EAAK,UAAA,EAASjB,EAAAA,QAAAA,KAAcQ,EAAO,MAAMG,EAAQK,EAAWC,EAAK,eAAe,CAAC,CAAC,CACpF,CAAC,EAEDH,MAAsBI,EAAI,QAAQ,CAAC,EACnCJ,MAAsB,CACpBG,EAAK,MAAM,EACXD,EAAU,OAAO,CACnB,CAAC,CACH,CAAC,CACH,C"}
1
+ {"version":3,"file":"when.cjs","names":["isReactive","createDirectiveResult","isHtmlResult","removeNodes","computed","createReplaceableSlot","rawEffect","untrack","require_errors","require_result","require_dom","_vielzeug_ripple","NO_PARENT_MSG","when","condition","branch","truthy","falsy","parent","anchor","nodes","registerCleanup","conditionSignal","endMarker","slot","sub","next"],"sources":["../../src/directives/when.ts"],"sourcesContent":["import { computed, isReactive, type Readable, effect as rawEffect, untrack } from '@vielzeug/ripple';\n\nimport { invariant } from '../errors';\nimport { createDirectiveResult, type DirectiveResult, type HTMLResult, isHtmlResult } from '../template/result';\nimport { createReplaceableSlot, type MaybeReactive, removeNodes } from '../utils/dom';\n\ntype WhenRenderable = HTMLResult | null | undefined | false;\n\nconst NO_PARENT_MSG = 'when() anchor comment has no parent node';\n\n/**\n * Conditionally renders one of two branches as a `DirectiveResult`.\n *\n * The condition may be a boolean, signal, or getter function.\n * When the condition changes, the current branch is cleaned up and\n * the new branch is mounted in its place.\n *\n * @example\n * ```ts\n * html`${when(isLoggedIn, () => html`<p>Welcome</p>`, () => html`<p>Log in</p>`)}`\n * ```\n */\nexport function when(\n condition: MaybeReactive<boolean>,\n truthy: () => WhenRenderable,\n falsy?: () => WhenRenderable,\n): DirectiveResult {\n if (typeof condition !== 'function' && !isReactive(condition)) {\n return createDirectiveResult((anchor, registerCleanup) => {\n const branch = condition ? truthy() : falsy ? falsy() : null;\n\n if (!branch || !isHtmlResult(branch)) return;\n\n const parent = anchor.parentNode;\n\n invariant(parent, NO_PARENT_MSG);\n\n const nodes = branch.mount(parent, anchor, registerCleanup);\n\n registerCleanup(() => removeNodes(nodes));\n });\n }\n\n return createDirectiveResult((anchor, registerCleanup) => {\n const ownedComputed = typeof condition === 'function' ? computed(condition as () => boolean) : null;\n const conditionSignal = ownedComputed ?? (condition as Readable<boolean>);\n\n const parent = anchor.parentNode;\n\n invariant(parent, NO_PARENT_MSG);\n\n const endMarker = document.createComment('when/end');\n\n parent.insertBefore(endMarker, anchor.nextSibling);\n\n const slot = createReplaceableSlot();\n\n const sub = rawEffect(() => {\n const next = conditionSignal.value;\n\n slot.clear();\n\n const branch = next ? truthy() : falsy ? falsy() : null;\n\n if (!branch || !isHtmlResult(branch)) return;\n\n slot.setNodes(untrack(() => branch.mount(parent, endMarker, slot.registerCleanup)));\n });\n\n registerCleanup(() => sub.dispose());\n registerCleanup(() => {\n slot.clear();\n endMarker.remove();\n });\n });\n}\n"],"mappings":"A,qIAQA,IAAMY,EAAgB,2CActB,SAAgBC,EACd,EACA,EACA,EACiB,CAiBjB,OAhBI,OAAOC,GAAc,YAAc,EAAA,EAACd,EAAAA,WAAAA,CAAWc,CAAS,EACnDb,EAAAA,uBAAuB,EAAQ,IAAoB,CACxD,IAAMc,EAASD,EAAYE,EAAO,EAAIC,EAAQA,EAAM,EAAI,KAExD,GAAI,CAACF,GAAU,CAACb,EAAAA,aAAaa,CAAM,EAAG,OAEtC,IAAMG,EAASC,EAAO,WAEtBX,EAAA,UAAUU,EAAQN,CAAa,EAE/B,IAAMQ,EAAQL,EAAO,MAAMG,EAAQC,EAAQE,CAAe,EAE1DA,MAAsBlB,EAAAA,YAAYiB,CAAK,CAAC,CAC1C,CAAC,EAGInB,EAAAA,uBAAuB,EAAQ,IAAoB,CAExD,IAAMqB,GADgB,OAAOR,GAAc,YAAA,EAAaV,EAAAA,SAAAA,CAASU,CAA0B,EAAI,OACrDA,EAEpCI,EAASC,EAAO,WAEtBX,EAAA,UAAUU,EAAQN,CAAa,EAE/B,IAAMW,EAAY,SAAS,cAAc,UAAU,EAEnDL,EAAO,aAAaK,EAAWJ,EAAO,WAAW,EAEjD,IAAMK,EAAOnB,EAAAA,sBAAsB,EAE7BoB,GAAA,EAAMnB,EAAAA,OAAAA,KAAgB,CAC1B,IAAMoB,EAAOJ,EAAgB,MAE7BE,EAAK,MAAM,EAEX,IAAMT,EAASW,EAAOV,EAAO,EAAIC,EAAQA,EAAM,EAAI,KAE9CF,GAAWb,EAAAA,aAAaa,CAAM,GAEnCS,EAAK,UAAA,EAASjB,EAAAA,QAAAA,KAAcQ,EAAO,MAAMG,EAAQK,EAAWC,EAAK,eAAe,CAAC,CAAC,CACpF,CAAC,EAEDH,MAAsBI,EAAI,QAAQ,CAAC,EACnCJ,MAAsB,CACpBG,EAAK,MAAM,EACXD,EAAU,OAAO,CACnB,CAAC,CACH,CAAC,CACH,C"}
@@ -1,2 +1,2 @@
1
- import{invariant as e}from"../errors.js";import{createReplaceableSlot as t,removeNodes as n}from"../utils/dom.js";import{createDirectiveResult as r,isHtmlResult as i}from"../template/result.js";import{computed as a,effect as o,isReactive as s,untrack as c}from"@vielzeug/ripple";var l=`when() anchor comment has no parent node`;function u(u,d,f){return typeof u!=`function`&&!s(u)?r((t,r)=>{let a=u?d():f?f():null;if(!a||!i(a))return;let o=t.parentNode;e(o,l);let s=a.mount(o,t,r);r(()=>n(s))}):r((n,r)=>{let s=(typeof u==`function`?a(u):null)??u,p=n.parentNode;e(p,l);let m=document.createComment(`when/end`);p.insertBefore(m,n.nextSibling);let h=t(),g=o(()=>{let e=s.value;h.clear();let t=e?d():f?f():null;t&&i(t)&&h.setNodes(c(()=>t.mount(p,m,h.registerCleanup)))});r(()=>g.dispose()),r(()=>{h.clear(),m.remove()})})}export{u as when};
1
+ import{invariant as e}from"../errors.js";import{createDirectiveResult as t,isHtmlResult as n}from"../template/result.js";import{createReplaceableSlot as r,removeNodes as i}from"../utils/dom.js";import{computed as a,effect as o,isReactive as s,untrack as c}from"@vielzeug/ripple";var l=`when() anchor comment has no parent node`;function u(u,d,f){return typeof u!=`function`&&!s(u)?t((t,r)=>{let a=u?d():f?f():null;if(!a||!n(a))return;let o=t.parentNode;e(o,l);let s=a.mount(o,t,r);r(()=>i(s))}):t((t,i)=>{let s=(typeof u==`function`?a(u):null)??u,p=t.parentNode;e(p,l);let m=document.createComment(`when/end`);p.insertBefore(m,t.nextSibling);let h=r(),g=o(()=>{let e=s.value;h.clear();let t=e?d():f?f():null;t&&n(t)&&h.setNodes(c(()=>t.mount(p,m,h.registerCleanup)))});i(()=>g.dispose()),i(()=>{h.clear(),m.remove()})})}export{u as when};
2
2
  //# sourceMappingURL=when.js.map
@@ -1,2 +1,2 @@
1
- const e=require("./utils/dom.cjs"),t=require("./runtime.cjs"),n=require("./utils/aria.cjs");let r=require("@vielzeug/ripple");var i=(n,r)=>{let i=r?.target??t.getHost(),o=[];if(n.attr)for(let[e,t]of Object.entries(n.attr)){let n=s(i,a(e),t);n&&o.push(n)}if(n.class&&o.push(l(i,n.class)),n.style)for(let[e,t]of Object.entries(n.style)){let n=c(i,e,t);n&&o.push(n)}if(n.on){let{target:t,...a}=r??{};for(let t of Object.keys(n.on)){let r=n.on[t];r&&o.push(e.listen(i,t,r,a))}}let u=()=>{for(let e of o)e()};return t.tryRegisterCleanup(u),u},a=n.normalizeHostAttrKey,o=(e,n)=>{if(typeof e==`function`)return t.watchEffect(()=>{n(e())});if((0,r.isReactive)(e))return t.watchEffect(()=>{n(e.value)});n(e)};function s(t,n,r){return o(r,r=>e.setAttr(t,n,r))}function c(t,n,r){let i=e.cssDeclarationName(n);if(!i)return;let a=!1;return o(r,n=>{let r=e.cssDeclarationValue(n);r?(a=!0,t.style.setProperty(i,r)):a&&t.style.removeProperty(i)})}function l(n,r){let i=typeof r==`function`?r:()=>Object.fromEntries([...e.resolveClassTokens(r)].map(e=>[e,!0])),a=new Set;return t.watchEffect(()=>{let e=new Set;for(let[t,r]of Object.entries(i()))r&&(e.add(t),a.has(t)||n.classList.add(t));for(let t of a)e.has(t)||n.classList.remove(t);a=e})}exports.bind=i;
1
+ const e=require("./runtime.cjs"),t=require("./utils/aria.cjs"),n=require("./utils/dom.cjs");let r=require("@vielzeug/ripple");var i=(t,r)=>{let i=r?.target??e.getHost(),o=[];if(t.attr)for(let[e,n]of Object.entries(t.attr)){let t=s(i,a(e),n);t&&o.push(t)}if(t.class&&o.push(l(i,t.class)),t.style)for(let[e,n]of Object.entries(t.style)){let t=c(i,e,n);t&&o.push(t)}if(t.on){let{target:e,...a}=r??{};for(let e of Object.keys(t.on)){let r=t.on[e];r&&o.push(n.listen(i,e,r,a))}}let u=()=>{for(let e of o)e()};return e.tryRegisterCleanup(u),u},a=t.normalizeHostAttrKey,o=(t,n)=>{if(typeof t==`function`)return e.watchEffect(()=>{n(t())});if((0,r.isReactive)(t))return e.watchEffect(()=>{n(t.value)});n(t)};function s(e,t,r){return o(r,r=>n.setAttr(e,t,r))}function c(e,t,r){let i=n.cssDeclarationName(t);if(!i)return;let a=!1;return o(r,t=>{let r=n.cssDeclarationValue(t);r?(a=!0,e.style.setProperty(i,r)):a&&e.style.removeProperty(i)})}function l(t,r){let i=typeof r==`function`?r:()=>Object.fromEntries([...n.resolveClassTokens(r)].map(e=>[e,!0])),a=new Set;return e.watchEffect(()=>{let e=new Set;for(let[n,r]of Object.entries(i()))r&&(e.add(n),a.has(n)||t.classList.add(n));for(let n of a)e.has(n)||t.classList.remove(n);a=e})}exports.bind=i;
2
2
  //# sourceMappingURL=host-bind.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"host-bind.cjs","names":["getHost","listen","normalizeHostAttrKey","watchEffect","isReactive","setAttr","cssDeclarationName","cssDeclarationValue","resolveClassTokens","require_dom","require_runtime","require_aria","_vielzeug_ripple","bind","el","options","disposers","config","key","value","dispose","applyAttribute","toHostAttr","applyClassMap","applyStyle","_t","listenerOptions","event","listener","cleanup","applyReactiveBinding","updater","host","name","next","cssName","owned","declaration","v","getMap","cls","prev","active"],"sources":["../src/host-bind.ts"],"sourcesContent":["/**\n * Host element binding API: reactive attr, class, style, and event bindings\n * applied directly to the component's host element or any target element.\n */\n\nimport { isReactive } from '@vielzeug/ripple';\n\nimport { getHost, tryRegisterCleanup, watchEffect } from './runtime';\nimport { normalizeHostAttrKey } from './utils/aria';\nimport {\n cssDeclarationName,\n cssDeclarationValue,\n listen,\n type MaybeReactive,\n resolveClassTokens,\n setAttr,\n} from './utils/dom';\n\n/**\n * Describes a reactive or static host binding value.\n */\nexport type HostBindingValue = MaybeReactive<string | number | boolean | null | undefined>;\n\n/**\n * Configuration for host attribute bindings.\n */\nexport type AttributeBindings = Record<string, HostBindingValue>;\n\ntype HostClassBindingValue = MaybeReactive<boolean>;\n// Bivariant callback allows consumers to use narrower event types.\ntype HostEventListener = { bivarianceHack(event: Event): void }['bivarianceHack'];\n\nexport type HostBindConfig = {\n attr?: AttributeBindings;\n class?: (() => Record<string, boolean>) | Record<string, HostClassBindingValue>;\n on?: Record<string, HostEventListener | undefined>;\n style?: Record<string, HostBindingValue>;\n};\n\nexport type BindOptions = AddEventListenerOptions & {\n /**\n * Target element to bind to. Defaults to the host element when called\n * via `bind()`. Pass an explicit element to bind to any other element\n * (e.g. a slotted trigger or an internally-referenced child element).\n * When a target is provided, cleanup is always auto-registered with the\n * component scope if one is active.\n */\n target?: Element;\n};\n\n/**\n * Apply reactive or static bindings to an element's attributes, classes, styles,\n * and events. Defaults to the current component's host element; pass\n * `options.target` to bind to any other element (e.g. a slotted trigger, an\n * internally-referenced child).\n */\nexport const bind = (config: HostBindConfig, options?: BindOptions): (() => void) => {\n const el = (options?.target as HTMLElement | undefined) ?? getHost();\n const disposers: Array<() => void> = [];\n\n if (config.attr) {\n for (const [key, value] of Object.entries(config.attr)) {\n const name = toHostAttr(key);\n const dispose = applyAttribute(el, name, value);\n\n if (dispose) disposers.push(dispose);\n }\n }\n\n if (config.class) {\n disposers.push(applyClassMap(el, config.class));\n }\n\n if (config.style) {\n for (const [key, value] of Object.entries(config.style)) {\n const dispose = applyStyle(el, key, value);\n\n if (dispose) disposers.push(dispose);\n }\n }\n\n if (config.on) {\n const { target: _t, ...listenerOptions } = options ?? {};\n\n for (const event of Object.keys(config.on) as Array<keyof typeof config.on>) {\n const listener = config.on[event];\n\n if (!listener) continue;\n\n disposers.push(listen(el, event as string, listener as EventListener, listenerOptions));\n }\n }\n\n const cleanup = (): void => {\n for (const dispose of disposers) dispose();\n };\n\n tryRegisterCleanup(cleanup);\n\n return cleanup;\n};\n\nconst toHostAttr = normalizeHostAttrKey;\n\nconst applyReactiveBinding = (\n value: HostBindingValue,\n updater: (next: string | number | boolean | null | undefined) => void,\n): (() => void) | undefined => {\n if (typeof value === 'function') {\n return watchEffect(() => {\n updater(value());\n return undefined;\n });\n }\n\n if (isReactive(value)) {\n return watchEffect(() => {\n updater(value.value);\n return undefined;\n });\n }\n\n updater(value);\n};\n\nfunction applyAttribute(host: HTMLElement, name: string, value: HostBindingValue): (() => void) | undefined {\n return applyReactiveBinding(value, (next) => setAttr(host, name, next));\n}\n\nfunction applyStyle(host: HTMLElement, name: string, value: HostBindingValue): (() => void) | undefined {\n const cssName = cssDeclarationName(name);\n\n if (!cssName) return;\n\n let owned = false;\n const setStyle = (v: string | number | boolean | null | undefined): void => {\n const declaration = cssDeclarationValue(v);\n\n if (declaration) {\n owned = true;\n host.style.setProperty(cssName, declaration);\n } else if (owned) host.style.removeProperty(cssName);\n };\n\n return applyReactiveBinding(value, setStyle);\n}\n\nfunction applyClassMap(\n host: HTMLElement,\n value: (() => Record<string, boolean>) | Record<string, HostClassBindingValue>,\n): () => void {\n const getMap =\n typeof value === 'function'\n ? value\n : (): Record<string, boolean> => Object.fromEntries([...resolveClassTokens(value)].map((cls) => [cls, true]));\n\n let prev = new Set<string>();\n\n const sub = watchEffect(() => {\n const next = new Set<string>();\n\n for (const [cls, active] of Object.entries(getMap())) {\n if (!active) continue;\n\n next.add(cls);\n\n if (!prev.has(cls)) host.classList.add(cls);\n }\n for (const cls of prev) {\n if (!next.has(cls)) host.classList.remove(cls);\n }\n prev = next;\n });\n\n return sub;\n}\n"],"mappings":"A,8HAwDA,IAAaa,GAAQ,EAAwB,IAAwC,CACnF,IAAMC,EAAMC,GAAS,QAAsCf,EAAAA,QAAQ,EAC7DgB,EAA+B,CAAC,EAEtC,GAAIC,EAAO,KACT,IAAK,GAAM,CAACC,EAAKC,KAAU,OAAO,QAAQF,EAAO,IAAI,EAAG,CAEtD,IAAMG,EAAUC,EAAeP,EADlBQ,EAAWJ,CACW,EAAMC,CAAK,EAE1CC,GAASJ,EAAU,KAAKI,CAAO,CACrC,CAOF,GAJIH,EAAO,OACTD,EAAU,KAAKO,EAAcT,EAAIG,EAAO,KAAK,CAAC,EAG5CA,EAAO,MACT,IAAK,GAAM,CAACC,EAAKC,KAAU,OAAO,QAAQF,EAAO,KAAK,EAAG,CACvD,IAAMG,EAAUI,EAAWV,EAAII,EAAKC,CAAK,EAErCC,GAASJ,EAAU,KAAKI,CAAO,CACrC,CAGF,GAAIH,EAAO,GAAI,CACb,GAAM,CAAE,OAAQQ,EAAI,GAAGC,GAAoBX,GAAW,CAAC,EAEvD,IAAK,IAAMY,KAAS,OAAO,KAAKV,EAAO,EAAE,EAAoC,CAC3E,IAAMW,EAAWX,EAAO,GAAGU,GAEtBC,GAELZ,EAAU,KAAKf,EAAAA,OAAOa,EAAIa,EAAiBC,EAA2BF,CAAe,CAAC,CACxF,CACF,CAEA,IAAMG,MAAsB,CAC1B,IAAK,IAAMT,KAAWJ,EAAWI,EAAQ,CAC3C,EAIA,OAFAV,EAAA,mBAAmBmB,CAAO,EAEnBA,CACT,EAEMP,EAAapB,EAAAA,qBAEb4B,GACJ,EACA,IAC6B,CAC7B,GAAI,OAAOX,GAAU,WACnB,OAAOhB,EAAAA,gBAAkB,CACvB4B,EAAQZ,EAAM,CAAC,CAEjB,CAAC,EAGH,IAAA,EAAIf,EAAAA,WAAAA,CAAWe,CAAK,EAClB,OAAOhB,EAAAA,gBAAkB,CACvB4B,EAAQZ,EAAM,KAAK,CAErB,CAAC,EAGHY,EAAQZ,CAAK,CACf,EAEA,SAASE,EAAe,EAAmB,EAAc,EAAmD,CAC1G,OAAOS,EAAqBX,EAAQ,GAASd,EAAAA,QAAQ2B,EAAMC,EAAMC,CAAI,CAAC,CACxE,CAEA,SAASV,EAAW,EAAmB,EAAc,EAAmD,CACtG,IAAMW,EAAU7B,EAAAA,mBAAmB2B,CAAI,EAEvC,GAAI,CAACE,EAAS,OAEd,IAAIC,EAAQ,GAUZ,OAAON,EAAqBX,EATV,GAA0D,CAC1E,IAAMkB,EAAc9B,EAAAA,oBAAoB+B,CAAC,EAErCD,GACF,EAAQ,GACRL,EAAK,MAAM,YAAYG,EAASE,CAAW,GAClCD,GAAOJ,EAAK,MAAM,eAAeG,CAAO,CACrD,CAE2C,CAC7C,CAEA,SAASZ,EACP,EACA,EACY,CACZ,IAAMgB,EACJ,OAAOpB,GAAU,WACbA,MAC+B,OAAO,YAAY,CAAC,GAAGX,EAAAA,mBAAmBW,CAAK,CAAC,CAAC,CAAC,IAAK,GAAQ,CAACqB,EAAK,EAAI,CAAC,CAAC,EAE5GC,EAAO,IAAI,IAkBf,OAhBYtC,EAAAA,gBAAkB,CAC5B,IAAM+B,EAAO,IAAI,IAEjB,IAAK,GAAM,CAACM,EAAKE,KAAW,OAAO,QAAQH,EAAO,CAAC,EAC5CG,IAELR,EAAK,IAAIM,CAAG,EAEPC,EAAK,IAAID,CAAG,GAAGR,EAAK,UAAU,IAAIQ,CAAG,GAE5C,IAAK,IAAMA,KAAOC,EACXP,EAAK,IAAIM,CAAG,GAAGR,EAAK,UAAU,OAAOQ,CAAG,EAE/C,EAAON,CACT,CAEO,CACT,C"}
1
+ {"version":3,"file":"host-bind.cjs","names":["getHost","listen","normalizeHostAttrKey","watchEffect","isReactive","setAttr","cssDeclarationName","cssDeclarationValue","resolveClassTokens","require_runtime","require_aria","require_dom","_vielzeug_ripple","bind","el","options","disposers","config","key","value","dispose","applyAttribute","toHostAttr","applyClassMap","applyStyle","_t","listenerOptions","event","listener","cleanup","applyReactiveBinding","updater","host","name","next","cssName","owned","declaration","v","getMap","cls","prev","active"],"sources":["../src/host-bind.ts"],"sourcesContent":["/**\n * Host element binding API: reactive attr, class, style, and event bindings\n * applied directly to the component's host element or any target element.\n */\n\nimport { isReactive } from '@vielzeug/ripple';\n\nimport { getHost, tryRegisterCleanup, watchEffect } from './runtime';\nimport { normalizeHostAttrKey } from './utils/aria';\nimport {\n cssDeclarationName,\n cssDeclarationValue,\n listen,\n type MaybeReactive,\n resolveClassTokens,\n setAttr,\n} from './utils/dom';\n\n/**\n * Describes a reactive or static host binding value.\n */\nexport type HostBindingValue = MaybeReactive<string | number | boolean | null | undefined>;\n\n/**\n * Configuration for host attribute bindings.\n */\nexport type AttributeBindings = Record<string, HostBindingValue>;\n\ntype HostClassBindingValue = MaybeReactive<boolean>;\n// Bivariant callback allows consumers to use narrower event types.\ntype HostEventListener = { bivarianceHack(event: Event): void }['bivarianceHack'];\n\nexport type HostBindConfig = {\n attr?: AttributeBindings;\n class?: (() => Record<string, boolean>) | Record<string, HostClassBindingValue>;\n on?: Record<string, HostEventListener | undefined>;\n style?: Record<string, HostBindingValue>;\n};\n\nexport type BindOptions = AddEventListenerOptions & {\n /**\n * Target element to bind to. Defaults to the host element when called\n * via `bind()`. Pass an explicit element to bind to any other element\n * (e.g. a slotted trigger or an internally-referenced child element).\n * When a target is provided, cleanup is always auto-registered with the\n * component scope if one is active.\n */\n target?: Element;\n};\n\n/**\n * Apply reactive or static bindings to an element's attributes, classes, styles,\n * and events. Defaults to the current component's host element; pass\n * `options.target` to bind to any other element (e.g. a slotted trigger, an\n * internally-referenced child).\n */\nexport const bind = (config: HostBindConfig, options?: BindOptions): (() => void) => {\n const el = (options?.target as HTMLElement | undefined) ?? getHost();\n const disposers: Array<() => void> = [];\n\n if (config.attr) {\n for (const [key, value] of Object.entries(config.attr)) {\n const name = toHostAttr(key);\n const dispose = applyAttribute(el, name, value);\n\n if (dispose) disposers.push(dispose);\n }\n }\n\n if (config.class) {\n disposers.push(applyClassMap(el, config.class));\n }\n\n if (config.style) {\n for (const [key, value] of Object.entries(config.style)) {\n const dispose = applyStyle(el, key, value);\n\n if (dispose) disposers.push(dispose);\n }\n }\n\n if (config.on) {\n const { target: _t, ...listenerOptions } = options ?? {};\n\n for (const event of Object.keys(config.on) as Array<keyof typeof config.on>) {\n const listener = config.on[event];\n\n if (!listener) continue;\n\n disposers.push(listen(el, event as string, listener as EventListener, listenerOptions));\n }\n }\n\n const cleanup = (): void => {\n for (const dispose of disposers) dispose();\n };\n\n tryRegisterCleanup(cleanup);\n\n return cleanup;\n};\n\nconst toHostAttr = normalizeHostAttrKey;\n\nconst applyReactiveBinding = (\n value: HostBindingValue,\n updater: (next: string | number | boolean | null | undefined) => void,\n): (() => void) | undefined => {\n if (typeof value === 'function') {\n return watchEffect(() => {\n updater(value());\n return undefined;\n });\n }\n\n if (isReactive(value)) {\n return watchEffect(() => {\n updater(value.value);\n return undefined;\n });\n }\n\n updater(value);\n};\n\nfunction applyAttribute(host: HTMLElement, name: string, value: HostBindingValue): (() => void) | undefined {\n return applyReactiveBinding(value, (next) => setAttr(host, name, next));\n}\n\nfunction applyStyle(host: HTMLElement, name: string, value: HostBindingValue): (() => void) | undefined {\n const cssName = cssDeclarationName(name);\n\n if (!cssName) return;\n\n let owned = false;\n const setStyle = (v: string | number | boolean | null | undefined): void => {\n const declaration = cssDeclarationValue(v);\n\n if (declaration) {\n owned = true;\n host.style.setProperty(cssName, declaration);\n } else if (owned) host.style.removeProperty(cssName);\n };\n\n return applyReactiveBinding(value, setStyle);\n}\n\nfunction applyClassMap(\n host: HTMLElement,\n value: (() => Record<string, boolean>) | Record<string, HostClassBindingValue>,\n): () => void {\n const getMap =\n typeof value === 'function'\n ? value\n : (): Record<string, boolean> => Object.fromEntries([...resolveClassTokens(value)].map((cls) => [cls, true]));\n\n let prev = new Set<string>();\n\n const sub = watchEffect(() => {\n const next = new Set<string>();\n\n for (const [cls, active] of Object.entries(getMap())) {\n if (!active) continue;\n\n next.add(cls);\n\n if (!prev.has(cls)) host.classList.add(cls);\n }\n for (const cls of prev) {\n if (!next.has(cls)) host.classList.remove(cls);\n }\n prev = next;\n });\n\n return sub;\n}\n"],"mappings":"A,8HAwDA,IAAaa,GAAQ,EAAwB,IAAwC,CACnF,IAAMC,EAAMC,GAAS,QAAsCf,EAAAA,QAAQ,EAC7DgB,EAA+B,CAAC,EAEtC,GAAIC,EAAO,KACT,IAAK,GAAM,CAACC,EAAKC,KAAU,OAAO,QAAQF,EAAO,IAAI,EAAG,CAEtD,IAAMG,EAAUC,EAAeP,EADlBQ,EAAWJ,CACW,EAAMC,CAAK,EAE1CC,GAASJ,EAAU,KAAKI,CAAO,CACrC,CAOF,GAJIH,EAAO,OACTD,EAAU,KAAKO,EAAcT,EAAIG,EAAO,KAAK,CAAC,EAG5CA,EAAO,MACT,IAAK,GAAM,CAACC,EAAKC,KAAU,OAAO,QAAQF,EAAO,KAAK,EAAG,CACvD,IAAMG,EAAUI,EAAWV,EAAII,EAAKC,CAAK,EAErCC,GAASJ,EAAU,KAAKI,CAAO,CACrC,CAGF,GAAIH,EAAO,GAAI,CACb,GAAM,CAAE,OAAQQ,EAAI,GAAGC,GAAoBX,GAAW,CAAC,EAEvD,IAAK,IAAMY,KAAS,OAAO,KAAKV,EAAO,EAAE,EAAoC,CAC3E,IAAMW,EAAWX,EAAO,GAAGU,GAEtBC,GAELZ,EAAU,KAAKf,EAAAA,OAAOa,EAAIa,EAAiBC,EAA2BF,CAAe,CAAC,CACxF,CACF,CAEA,IAAMG,MAAsB,CAC1B,IAAK,IAAMT,KAAWJ,EAAWI,EAAQ,CAC3C,EAIA,OAFAX,EAAA,mBAAmBoB,CAAO,EAEnBA,CACT,EAEMP,EAAapB,EAAAA,qBAEb4B,GACJ,EACA,IAC6B,CAC7B,GAAI,OAAOX,GAAU,WACnB,OAAOhB,EAAAA,gBAAkB,CACvB4B,EAAQZ,EAAM,CAAC,CAEjB,CAAC,EAGH,IAAA,EAAIf,EAAAA,WAAAA,CAAWe,CAAK,EAClB,OAAOhB,EAAAA,gBAAkB,CACvB4B,EAAQZ,EAAM,KAAK,CAErB,CAAC,EAGHY,EAAQZ,CAAK,CACf,EAEA,SAASE,EAAe,EAAmB,EAAc,EAAmD,CAC1G,OAAOS,EAAqBX,EAAQ,GAASd,EAAAA,QAAQ2B,EAAMC,EAAMC,CAAI,CAAC,CACxE,CAEA,SAASV,EAAW,EAAmB,EAAc,EAAmD,CACtG,IAAMW,EAAU7B,EAAAA,mBAAmB2B,CAAI,EAEvC,GAAI,CAACE,EAAS,OAEd,IAAIC,EAAQ,GAUZ,OAAON,EAAqBX,EATV,GAA0D,CAC1E,IAAMkB,EAAc9B,EAAAA,oBAAoB+B,CAAC,EAErCD,GACF,EAAQ,GACRL,EAAK,MAAM,YAAYG,EAASE,CAAW,GAClCD,GAAOJ,EAAK,MAAM,eAAeG,CAAO,CACrD,CAE2C,CAC7C,CAEA,SAASZ,EACP,EACA,EACY,CACZ,IAAMgB,EACJ,OAAOpB,GAAU,WACbA,MAC+B,OAAO,YAAY,CAAC,GAAGX,EAAAA,mBAAmBW,CAAK,CAAC,CAAC,CAAC,IAAK,GAAQ,CAACqB,EAAK,EAAI,CAAC,CAAC,EAE5GC,EAAO,IAAI,IAkBf,OAhBYtC,EAAAA,gBAAkB,CAC5B,IAAM+B,EAAO,IAAI,IAEjB,IAAK,GAAM,CAACM,EAAKE,KAAW,OAAO,QAAQH,EAAO,CAAC,EAC5CG,IAELR,EAAK,IAAIM,CAAG,EAEPC,EAAK,IAAID,CAAG,GAAGR,EAAK,UAAU,IAAIQ,CAAG,GAE5C,IAAK,IAAMA,KAAOC,EACXP,EAAK,IAAIM,CAAG,GAAGR,EAAK,UAAU,OAAOQ,CAAG,EAE/C,EAAON,CACT,CAEO,CACT,C"}
package/dist/host-bind.js CHANGED
@@ -1,2 +1,2 @@
1
- import{cssDeclarationName as e,cssDeclarationValue as t,listen as n,resolveClassTokens as r,setAttr as i}from"./utils/dom.js";import{getHost as a,tryRegisterCleanup as o,watchEffect as s}from"./runtime.js";import{normalizeHostAttrKey as c}from"./utils/aria.js";import{isReactive as l}from"@vielzeug/ripple";var u=(e,t)=>{let r=t?.target??a(),i=[];if(e.attr)for(let[t,n]of Object.entries(e.attr)){let e=p(r,d(t),n);e&&i.push(e)}if(e.class&&i.push(h(r,e.class)),e.style)for(let[t,n]of Object.entries(e.style)){let e=m(r,t,n);e&&i.push(e)}if(e.on){let{target:a,...o}=t??{};for(let t of Object.keys(e.on)){let a=e.on[t];a&&i.push(n(r,t,a,o))}}let s=()=>{for(let e of i)e()};return o(s),s},d=c,f=(e,t)=>{if(typeof e==`function`)return s(()=>{t(e())});if(l(e))return s(()=>{t(e.value)});t(e)};function p(e,t,n){return f(n,n=>i(e,t,n))}function m(n,r,i){let a=e(r);if(!a)return;let o=!1;return f(i,e=>{let r=t(e);r?(o=!0,n.style.setProperty(a,r)):o&&n.style.removeProperty(a)})}function h(e,t){let n=typeof t==`function`?t:()=>Object.fromEntries([...r(t)].map(e=>[e,!0])),i=/* @__PURE__ */ new Set;return s(()=>{let t=/* @__PURE__ */ new Set;for(let[r,a]of Object.entries(n()))a&&(t.add(r),i.has(r)||e.classList.add(r));for(let n of i)t.has(n)||e.classList.remove(n);i=t})}export{u as bind};
1
+ import{getHost as e,tryRegisterCleanup as t,watchEffect as n}from"./runtime.js";import{normalizeHostAttrKey as r}from"./utils/aria.js";import{cssDeclarationName as i,cssDeclarationValue as a,listen as o,resolveClassTokens as s,setAttr as c}from"./utils/dom.js";import{isReactive as l}from"@vielzeug/ripple";var u=(n,r)=>{let i=r?.target??e(),a=[];if(n.attr)for(let[e,t]of Object.entries(n.attr)){let n=p(i,d(e),t);n&&a.push(n)}if(n.class&&a.push(h(i,n.class)),n.style)for(let[e,t]of Object.entries(n.style)){let n=m(i,e,t);n&&a.push(n)}if(n.on){let{target:e,...t}=r??{};for(let e of Object.keys(n.on)){let r=n.on[e];r&&a.push(o(i,e,r,t))}}let s=()=>{for(let e of a)e()};return t(s),s},d=r,f=(e,t)=>{if(typeof e==`function`)return n(()=>{t(e())});if(l(e))return n(()=>{t(e.value)});t(e)};function p(e,t,n){return f(n,n=>c(e,t,n))}function m(e,t,n){let r=i(t);if(!r)return;let o=!1;return f(n,t=>{let n=a(t);n?(o=!0,e.style.setProperty(r,n)):o&&e.style.removeProperty(r)})}function h(e,t){let r=typeof t==`function`?t:()=>Object.fromEntries([...s(t)].map(e=>[e,!0])),i=/* @__PURE__ */ new Set;return n(()=>{let t=/* @__PURE__ */ new Set;for(let[n,a]of Object.entries(r()))a&&(t.add(n),i.has(n)||e.classList.add(n));for(let n of i)t.has(n)||e.classList.remove(n);i=t})}export{u as bind};
2
2
  //# sourceMappingURL=host-bind.js.map
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./errors.cjs"),t=require("./runtime.cjs"),n=require("./context.cjs"),r=require("./props.cjs"),i=require("./utils/css.cjs"),a=require("./define.cjs"),o=require("./directives/classMap.cjs"),s=require("./template/result.cjs"),c=require("./directives/each.cjs"),l=require("./directives/live.cjs"),u=require("./directives/model.cjs"),d=require("./directives/styleMap.cjs"),f=require("./directives/unsafe-html.cjs"),p=require("./directives/when.cjs"),m=require("./forms/field.cjs"),h=require("./host-bind.cjs"),g=require("./slots.cjs"),_=require("./template/instantiator.cjs"),v=require("./utils/emit.cjs"),y=require("./utils/id.cjs");exports.OreApiError=e.OreApiError,exports.OreError=e.OreError,exports.OreInternalError=e.OreInternalError,exports.OreLifecycleError=e.OreLifecycleError,exports.bind=h.bind,exports.classMap=o.classMap,exports.createContext=n.createContext,exports.createId=y.createId,exports.css=i.css,exports.define=a.define,exports.each=c.each,exports.getHost=t.getHost,exports.html=_.html,exports.inject=n.inject,exports.injectStrict=n.injectStrict,exports.live=l.live,exports.model=u.model,exports.onCleanup=t.onCleanup,exports.onElement=t.onElement,exports.onEvent=t.onEvent,exports.onFormReset=t.onFormReset,exports.onMounted=t.onMounted,exports.prop=r.prop,exports.provide=n.provide,exports.ref=s.ref,exports.styleMap=d.styleMap,exports.unsafeHtml=f.unsafeHtml,exports.useEmit=v.useEmit,exports.useField=m.useField,exports.useSlots=g.useSlots,exports.watchEffect=t.watchEffect,exports.when=p.when;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./context.cjs"),t=require("./define.cjs"),n=require("./directives/classMap.cjs"),r=require("./directives/each.cjs"),i=require("./directives/live.cjs"),a=require("./directives/model.cjs"),o=require("./directives/styleMap.cjs"),s=require("./directives/unsafe-html.cjs"),c=require("./directives/when.cjs"),l=require("./errors.cjs"),u=require("./forms/field.cjs"),d=require("./host-bind.cjs"),f=require("./props.cjs"),p=require("./runtime.cjs"),m=require("./slots.cjs"),h=require("./template/instantiator.cjs"),g=require("./template/result.cjs"),_=require("./utils/css.cjs"),v=require("./utils/emit.cjs"),y=require("./utils/id.cjs");exports.OreApiError=l.OreApiError,exports.OreError=l.OreError,exports.OreInternalError=l.OreInternalError,exports.OreLifecycleError=l.OreLifecycleError,exports.bind=d.bind,exports.classMap=n.classMap,exports.createContext=e.createContext,exports.createId=y.createId,exports.css=_.css,exports.define=t.define,exports.each=r.each,exports.getHost=p.getHost,exports.html=h.html,exports.inject=e.inject,exports.injectStrict=e.injectStrict,exports.live=i.live,exports.model=a.model,exports.onCleanup=p.onCleanup,exports.onElement=p.onElement,exports.onEvent=p.onEvent,exports.onFormReset=p.onFormReset,exports.onMounted=p.onMounted,exports.prop=f.prop,exports.provide=e.provide,exports.ref=g.ref,exports.styleMap=o.styleMap,exports.unsafeHtml=s.unsafeHtml,exports.useEmit=v.useEmit,exports.useField=u.useField,exports.useSlots=m.useSlots,exports.watchEffect=p.watchEffect,exports.when=c.when;
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{OreApiError as e,OreError as t,OreInternalError as n,OreLifecycleError as r}from"./errors.js";import{getHost as i,onCleanup as a,onElement as o,onEvent as s,onFormReset as c,onMounted as l,watchEffect as u}from"./runtime.js";import{createContext as d,inject as f,injectStrict as p,provide as m}from"./context.js";import{prop as h}from"./props.js";import{css as g}from"./utils/css.js";import{define as _}from"./define.js";import{classMap as v}from"./directives/classMap.js";import{ref as y}from"./template/result.js";import{each as b}from"./directives/each.js";import{live as x}from"./directives/live.js";import{model as S}from"./directives/model.js";import{styleMap as C}from"./directives/styleMap.js";import{unsafeHtml as w}from"./directives/unsafe-html.js";import{when as T}from"./directives/when.js";import{useField as E}from"./forms/field.js";import{bind as D}from"./host-bind.js";import{useSlots as O}from"./slots.js";import{html as k}from"./template/instantiator.js";import{useEmit as A}from"./utils/emit.js";import{createId as j}from"./utils/id.js";export{e as OreApiError,t as OreError,n as OreInternalError,r as OreLifecycleError,D as bind,v as classMap,d as createContext,j as createId,g as css,_ as define,b as each,i as getHost,k as html,f as inject,p as injectStrict,x as live,S as model,a as onCleanup,o as onElement,s as onEvent,c as onFormReset,l as onMounted,h as prop,m as provide,y as ref,C as styleMap,w as unsafeHtml,A as useEmit,E as useField,O as useSlots,u as watchEffect,T as when};
1
+ import{createContext as e,inject as t,injectStrict as n,provide as r}from"./context.js";import{define as i}from"./define.js";import{classMap as a}from"./directives/classMap.js";import{each as o}from"./directives/each.js";import{live as s}from"./directives/live.js";import{model as c}from"./directives/model.js";import{styleMap as l}from"./directives/styleMap.js";import{unsafeHtml as u}from"./directives/unsafe-html.js";import{when as d}from"./directives/when.js";import{OreApiError as f,OreError as p,OreInternalError as m,OreLifecycleError as h}from"./errors.js";import{useField as g}from"./forms/field.js";import{bind as _}from"./host-bind.js";import{prop as v}from"./props.js";import{getHost as y,onCleanup as b,onElement as x,onEvent as S,onFormReset as C,onMounted as w,watchEffect as T}from"./runtime.js";import{useSlots as E}from"./slots.js";import{html as D}from"./template/instantiator.js";import{ref as O}from"./template/result.js";import{css as k}from"./utils/css.js";import{useEmit as A}from"./utils/emit.js";import{createId as j}from"./utils/id.js";export{f as OreApiError,p as OreError,m as OreInternalError,h as OreLifecycleError,_ as bind,a as classMap,e as createContext,j as createId,k as css,i as define,o as each,y as getHost,D as html,t as inject,n as injectStrict,s as live,c as model,b as onCleanup,x as onElement,S as onEvent,C as onFormReset,w as onMounted,v as prop,r as provide,O as ref,l as styleMap,u as unsafeHtml,A as useEmit,g as useField,E as useSlots,T as watchEffect,d as when};
package/dist/ore.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import { batch as e, computed as t, createScope as n, effect as r, isReactive as i, signal as a, untrack as o } from "@vielzeug/ripple";
2
- //#endregion
3
- //#region src/errors.ts
2
+ // src/errors.ts
4
3
  var OreError = class extends Error {
5
4
  constructor(e, t) {
6
5
  super(e, t), this.name = new.target.name, Object.setPrototypeOf(this, new.target.prototype);
@@ -41,8 +40,7 @@ var s = {
41
40
  function invariant(e, t) {
42
41
  if (!e) throw new OreInternalError(s.invariantViolated(t));
43
42
  }
44
- //#endregion
45
- //#region src/utils/dom.ts
43
+ // src/utils/dom.ts
46
44
  var resolveMaybeReactive = (e) => typeof e == "function" ? e() : i(e) ? e.value : e, c = /[;{}]/g, sanitizeCssToken = (e) => e.replace(c, ""), runAll = (e) => {
47
45
  for (let t = e.length - 1; t >= 0; t--) e[t]?.();
48
46
  }, removeNodes = (e) => {
@@ -179,8 +177,7 @@ var injectStrict = (e) => {
179
177
  function createContext(e) {
180
178
  return Symbol(e);
181
179
  }
182
- //#endregion
183
- //#region src/props.ts
180
+ // src/props.ts
184
181
  function _jsOnlyProp(e) {
185
182
  return {
186
183
  default: e,
@@ -297,8 +294,7 @@ function createProps(e, t) {
297
294
  for (let [r, i] of Object.entries(t)) n[r] = registerProp(e, r, toKebab(r), i);
298
295
  return n;
299
296
  }
300
- //#endregion
301
- //#region src/utils/brand.ts
297
+ // src/utils/brand.ts
302
298
  var makeBrand = (e) => {
303
299
  let t = Symbol.for(e), stamp = (e) => Object.assign(e, { [t]: !0 }), is = (e) => typeof e == "object" && !!e && t in e;
304
300
  return {
@@ -457,8 +453,7 @@ var makeBrand = (e) => {
457
453
  });
458
454
  }
459
455
  };
460
- //#endregion
461
- //#region src/define.ts
456
+ // src/define.ts
462
457
  function define(e, t) {
463
458
  if (!e) throw new OreApiError(s.defineRequiresTag);
464
459
  if (customElements.get(e)) throw new OreApiError(s.defineDuplicate(e));
@@ -477,11 +472,9 @@ function define(e, t) {
477
472
  };
478
473
  return Object.defineProperty(ComponentClass, "name", { value: e }), customElements.define(e, ComponentClass), ComponentClass;
479
474
  }
480
- //#endregion
481
- //#region src/directives/classMap.ts
475
+ // src/directives/classMap.ts
482
476
  var classMap = (e) => t(() => [...resolveClassTokens(e)].join(" "));
483
- //#endregion
484
- //#region src/template/result.ts
477
+ // src/template/result.ts
485
478
  function ref() {
486
479
  return a(null);
487
480
  }
@@ -497,8 +490,7 @@ function createHtmlResult(e, t) {
497
490
  mount
498
491
  });
499
492
  }
500
- //#endregion
501
- //#region src/directives/each.ts
493
+ // src/directives/each.ts
502
494
  var createItem = (e, t, r, i, o) => {
503
495
  let s = a(e), c = a(t), l = n(), u = [], d = [];
504
496
  return l.run(() => {
@@ -599,8 +591,7 @@ function each(e, n, i, s) {
599
591
  });
600
592
  });
601
593
  }
602
- //#endregion
603
- //#region src/directives/live.ts
594
+ // src/directives/live.ts
604
595
  var k = makeBrand("ore:live"), live = (e) => k.stamp({ source: e }), A = k.is, j = makeBrand("ore:model"), M = j.is, modelDefaultGet = (e) => e instanceof HTMLInputElement && (e.type === "checkbox" || e.type === "radio") ? e.checked : e.value, modelDefaultEvent = (e) => e instanceof HTMLInputElement && (e.type === "checkbox" || e.type === "radio") || e instanceof HTMLSelectElement ? "change" : "input", model = (e, t) => j.stamp({
605
596
  event: t?.event,
606
597
  get: t?.get,
@@ -637,8 +628,7 @@ function unsafeHtml(e) {
637
628
  } else parseHtml(e, a, o), i(() => o.remove());
638
629
  });
639
630
  }
640
- //#endregion
641
- //#region src/directives/when.ts
631
+ // src/directives/when.ts
642
632
  var N = "when() anchor comment has no parent node";
643
633
  function when(e, n, a) {
644
634
  return typeof e != "function" && !i(e) ? createDirectiveResult((t, r) => {
@@ -664,8 +654,7 @@ function when(e, n, a) {
664
654
  });
665
655
  });
666
656
  }
667
- //#endregion
668
- //#region src/forms/field.ts
657
+ // src/forms/field.ts
669
658
  var P = /* @__PURE__ */ new WeakMap(), F = /* @__PURE__ */ new WeakSet(), useField = (e) => {
670
659
  let t = getHost();
671
660
  if (!t.constructor.formAssociated) throw new OreApiError(s.defineFieldRequiresFormAssociated(t.localName));
@@ -750,8 +739,7 @@ function applyClassMap(e, t) {
750
739
  r = t;
751
740
  });
752
741
  }
753
- //#endregion
754
- //#region src/slots.ts
742
+ // src/slots.ts
755
743
  var L = "default", normalizeSlotName = (e) => e || L, createSlots = (e) => {
756
744
  let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map(), ensureSlotEntry = (e) => {
757
745
  let n = t.get(e);
@@ -1181,7 +1169,6 @@ var L = "default", normalizeSlotName = (e) => e || L, createSlots = (e) => {
1181
1169
  return e.dispatchEvent(new CustomEvent(String(t), r));
1182
1170
  });
1183
1171
  }, $ = 0, ee = Math.random().toString(36).slice(2, 6), createId = (e = "id") => `${e}-${ee}${++$}`;
1184
- //#endregion
1185
1172
  export { OreApiError, OreError, OreInternalError, OreLifecycleError, bind, classMap, createContext, createId, css, define, each, getHost, html, inject, injectStrict, live, model, onCleanup, onElement, onEvent, onFormReset, onMounted, v as prop, provide, ref, styleMap, unsafeHtml, useEmit, useField, useSlots, watchEffect, when };
1186
1173
 
1187
1174
  //# sourceMappingURL=ore.js.map