@vielzeug/ore 26.10.0 → 26.10.5

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 (93) hide show
  1. package/README.md +1 -1
  2. package/dist/base-element.cjs.map +1 -1
  3. package/dist/base-element.d.ts +2 -2
  4. package/dist/base-element.js.map +1 -1
  5. package/dist/component-types.d.ts +2 -2
  6. package/dist/context.cjs.map +1 -1
  7. package/dist/context.d.ts +2 -2
  8. package/dist/context.d.ts.map +1 -1
  9. package/dist/context.js.map +1 -1
  10. package/dist/define.cjs.map +1 -1
  11. package/dist/define.d.ts +3 -3
  12. package/dist/define.js.map +1 -1
  13. package/dist/directives/classMap.cjs.map +1 -1
  14. package/dist/directives/classMap.js.map +1 -1
  15. package/dist/directives/each.cjs.map +1 -1
  16. package/dist/directives/each.d.ts +3 -3
  17. package/dist/directives/each.js.map +1 -1
  18. package/dist/directives/live.cjs.map +1 -1
  19. package/dist/directives/live.d.ts +1 -1
  20. package/dist/directives/live.js.map +1 -1
  21. package/dist/errors.cjs +1 -1
  22. package/dist/errors.cjs.map +1 -1
  23. package/dist/errors.d.ts +10 -10
  24. package/dist/errors.js +1 -1
  25. package/dist/errors.js.map +1 -1
  26. package/dist/forms/field.cjs.map +1 -1
  27. package/dist/forms/field.d.ts +4 -4
  28. package/dist/forms/field.js.map +1 -1
  29. package/dist/host-bind.cjs.map +1 -1
  30. package/dist/host-bind.d.ts +1 -1
  31. package/dist/host-bind.js.map +1 -1
  32. package/dist/ore.cjs +1 -1
  33. package/dist/ore.cjs.map +1 -1
  34. package/dist/ore.iife.js +1 -1
  35. package/dist/ore.iife.js.map +1 -1
  36. package/dist/ore.js +1 -1
  37. package/dist/ore.js.map +1 -1
  38. package/dist/props.cjs.map +1 -1
  39. package/dist/props.d.ts +3 -3
  40. package/dist/props.js.map +1 -1
  41. package/dist/runtime.cjs.map +1 -1
  42. package/dist/runtime.d.ts +5 -5
  43. package/dist/runtime.js.map +1 -1
  44. package/dist/slots.cjs.map +1 -1
  45. package/dist/slots.d.ts +3 -3
  46. package/dist/slots.js.map +1 -1
  47. package/dist/template/binding-types.d.ts +2 -2
  48. package/dist/template/bindings.cjs.map +1 -1
  49. package/dist/template/bindings.d.ts +2 -2
  50. package/dist/template/bindings.js.map +1 -1
  51. package/dist/template/compiler.cjs.map +1 -1
  52. package/dist/template/compiler.d.ts +1 -1
  53. package/dist/template/compiler.js.map +1 -1
  54. package/dist/template/instantiator.cjs.map +1 -1
  55. package/dist/template/instantiator.d.ts +1 -1
  56. package/dist/template/instantiator.js.map +1 -1
  57. package/dist/template/result.cjs.map +1 -1
  58. package/dist/template/result.d.ts +4 -4
  59. package/dist/template/result.js.map +1 -1
  60. package/dist/testing/dom.cjs.map +1 -1
  61. package/dist/testing/dom.d.ts +3 -3
  62. package/dist/testing/dom.js.map +1 -1
  63. package/dist/testing/flush.cjs +1 -1
  64. package/dist/testing/flush.cjs.map +1 -1
  65. package/dist/testing/flush.d.ts +4 -4
  66. package/dist/testing/flush.js +1 -1
  67. package/dist/testing/flush.js.map +1 -1
  68. package/dist/testing/form-internals-polyfill.cjs.map +1 -1
  69. package/dist/testing/form-internals-polyfill.d.ts +2 -2
  70. package/dist/testing/form-internals-polyfill.js.map +1 -1
  71. package/dist/testing/mount.cjs.map +1 -1
  72. package/dist/testing/mount.d.ts +3 -3
  73. package/dist/testing/mount.d.ts.map +1 -1
  74. package/dist/testing/mount.js.map +1 -1
  75. package/dist/testing/render-hook.cjs.map +1 -1
  76. package/dist/testing/render-hook.d.ts +1 -1
  77. package/dist/testing/render-hook.js.map +1 -1
  78. package/dist/testing/reset.cjs.map +1 -1
  79. package/dist/testing/reset.d.ts +2 -2
  80. package/dist/testing/reset.js.map +1 -1
  81. package/dist/testing.cjs.map +1 -1
  82. package/dist/testing.js.map +1 -1
  83. package/dist/utils/brand.cjs.map +1 -1
  84. package/dist/utils/brand.d.ts +2 -2
  85. package/dist/utils/brand.js.map +1 -1
  86. package/dist/utils/dom.cjs.map +1 -1
  87. package/dist/utils/dom.d.ts +5 -5
  88. package/dist/utils/dom.d.ts.map +1 -1
  89. package/dist/utils/dom.js.map +1 -1
  90. package/dist/utils/emit.cjs.map +1 -1
  91. package/dist/utils/emit.d.ts +4 -4
  92. package/dist/utils/emit.js.map +1 -1
  93. package/package.json +5 -5
package/dist/errors.d.ts CHANGED
@@ -6,7 +6,7 @@ export declare class OreError extends Error {
6
6
  export declare class OreApiError extends OreError {
7
7
  }
8
8
  /**
9
- * Thrown when an internal invariant fails — e.g. compiled template metadata no
9
+ * Thrown when an internal invariant fails: e.g. compiled template metadata no
10
10
  * longer matching the DOM it was cloned from. Distinct from `OreApiError`: this
11
11
  * is never the caller's fault, it signals a bug in ore itself. See `invariant()`.
12
12
  */
@@ -14,10 +14,10 @@ export declare class OreInternalError extends OreError {
14
14
  }
15
15
  /**
16
16
  * The phase in which a component error occurred.
17
- * - `'setup'` — synchronous setup() threw
18
- * - `'mounted'` — an onMounted callback threw
19
- * - `'form-reset'` — an onFormReset callback threw
20
- * - `'each-reconcile'` — `each()` failed to reconcile a list update (e.g. duplicate keys)
17
+ * - `'setup'`: synchronous setup() threw
18
+ * - `'mounted'`: an onMounted callback threw
19
+ * - `'form-reset'`: an onFormReset callback threw
20
+ * - `'each-reconcile'`: `each()` failed to reconcile a list update (e.g. duplicate keys)
21
21
  */
22
22
  export type OreErrorPhase = 'each-reconcile' | 'form-reset' | 'mounted' | 'setup';
23
23
  /**
@@ -36,7 +36,7 @@ export declare class OreLifecycleError extends OreError {
36
36
  /**
37
37
  * Report a runtime error via the ore:error event and console.
38
38
  *
39
- * `target` only needs to be an `EventTarget` (not specifically an `HTMLElement`) — component
39
+ * `target` only needs to be an `EventTarget` (not specifically an `HTMLElement`): component
40
40
  * lifecycle errors dispatch on the host element, but non-lifecycle failures (e.g. `each()`
41
41
  * reconciliation, which has no single "component" to attribute the error to) dispatch on
42
42
  * whatever live DOM node is available, such as the directive's own anchor `Comment`. Either way
@@ -44,7 +44,7 @@ export declare class OreLifecycleError extends OreError {
44
44
  * `document`/`window` observes every report regardless of where it originated.
45
45
  *
46
46
  * The console log (via `_dev.ts`'s `error()`) is still dev-gated like the rest of the package's
47
- * console diagnostics, but the `ore:error` DOM event dispatch below is **not** — it fires in
47
+ * console diagnostics, but the `ore:error` DOM event dispatch below is **not**: it fires in
48
48
  * every build, so consumers always have a way to observe runtime failures programmatically even
49
49
  * when console output is stripped in production.
50
50
  */
@@ -60,19 +60,19 @@ export declare const ORE_ERRORS: {
60
60
  readonly invariantViolated: (message: string) => string;
61
61
  readonly lifecycleOutsideSetup: "Lifecycle hooks must be called during component setup";
62
62
  readonly listenNullTarget: (eventName: string) => string;
63
- readonly propInvalidReflect: "Structured props cannot use reflect:true — use prop.json() with reflect:false";
63
+ readonly propInvalidReflect: "Structured props cannot use reflect:true: use prop.json() with reflect:false";
64
64
  readonly templateInterpolationInTag: "html`...`: interpolations inside a tag must be named attributes, boolean attributes, events, or refs";
65
65
  readonly useFieldAlreadyCalled: (tag: string) => string;
66
66
  readonly validationFailed: (tag: string, errors: string[]) => string;
67
67
  };
68
68
  /**
69
- * Assert an internal invariant that must always hold — e.g. compiled template
69
+ * Assert an internal invariant that must always hold: e.g. compiled template
70
70
  * metadata staying in sync with the DOM it was cloned from. A failed invariant
71
71
  * means a bug in ore itself, never user input, so it throws `OreInternalError`
72
72
  * unconditionally (every build, never gated like `_dev.ts`'s `warn()`).
73
73
  *
74
74
  * Narrowing caveat: `asserts condition` only narrows the exact expression
75
- * passed in. Assign to a local `const` first — `invariant(el.parentNode, msg)`
75
+ * passed in. Assign to a local `const` first: `invariant(el.parentNode, msg)`
76
76
  * does not narrow later reads of `el.parentNode`.
77
77
  */
78
78
  export declare function invariant(condition: unknown, message: string): asserts condition;
package/dist/errors.js CHANGED
@@ -1,3 +1,3 @@
1
- import"./_dev.js";var e=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},t=class extends e{},n=class extends e{},r=class extends e{component;phase;constructor(e,t){super(e,{cause:t.cause}),this.component=t.component,this.phase=t.phase}};function i(e,t){`${e.component}${e.phase}`,e.cause,t.dispatchEvent(new CustomEvent(`ore:error`,{bubbles:!0,composed:!0,detail:e}))}var a={asyncSetupUnsupported:`setup() must return an HTMLResult or null; use reactive state for asynchronous work`,defineDuplicate:e=>`define('${e}') called twice — custom element already registered`,defineFieldRequiresFormAssociated:e=>`useField() requires define('${e}', { formAssociated: true })`,defineRequiresTag:`define() requires a tag name`,eachDuplicateKey:(e,t)=>`each() received duplicate key "${e}" at index ${t}`,eventModifiersUnsupported:e=>`@${e}: event modifiers are unsupported; call native event methods in the handler instead`,injectStrictFailed:(e,t)=>`injectStrict() could not resolve key "${e}" in <${t}>`,invariantViolated:e=>`invariant violated: ${e}`,lifecycleOutsideSetup:`Lifecycle hooks must be called during component setup`,listenNullTarget:e=>`listen() called with a null/undefined target for event "${e}" — listener not attached`,propInvalidReflect:`Structured props cannot use reflect:true — use prop.json() with reflect:false`,templateInterpolationInTag:"html`...`: interpolations inside a tag must be named attributes, boolean attributes, events, or refs",useFieldAlreadyCalled:e=>`useField() was already called on <${e}>. Call it only once per component.`,validationFailed:(e,t)=>`Validation failed for <${e}>:\n${t.join(`
1
+ import"./_dev.js";var e=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},t=class extends e{},n=class extends e{},r=class extends e{component;phase;constructor(e,t){super(e,{cause:t.cause}),this.component=t.component,this.phase=t.phase}};function i(e,t){`${e.component}${e.phase}`,e.cause,t.dispatchEvent(new CustomEvent(`ore:error`,{bubbles:!0,composed:!0,detail:e}))}var a={asyncSetupUnsupported:`setup() must return an HTMLResult or null; use reactive state for asynchronous work`,defineDuplicate:e=>`define('${e}') called twice: custom element already registered`,defineFieldRequiresFormAssociated:e=>`useField() requires define('${e}', { formAssociated: true })`,defineRequiresTag:`define() requires a tag name`,eachDuplicateKey:(e,t)=>`each() received duplicate key "${e}" at index ${t}`,eventModifiersUnsupported:e=>`@${e}: event modifiers are unsupported; call native event methods in the handler instead`,injectStrictFailed:(e,t)=>`injectStrict() could not resolve key "${e}" in <${t}>`,invariantViolated:e=>`invariant violated: ${e}`,lifecycleOutsideSetup:`Lifecycle hooks must be called during component setup`,listenNullTarget:e=>`listen() called with a null/undefined target for event "${e}": listener not attached`,propInvalidReflect:`Structured props cannot use reflect:true: use prop.json() with reflect:false`,templateInterpolationInTag:"html`...`: interpolations inside a tag must be named attributes, boolean attributes, events, or refs",useFieldAlreadyCalled:e=>`useField() was already called on <${e}>. Call it only once per component.`,validationFailed:(e,t)=>`Validation failed for <${e}>:\n${t.join(`
2
2
  `)}`};function o(e,t){if(!e)throw new n(a.invariantViolated(t))}export{a as ORE_ERRORS,t as OreApiError,e as OreError,n as OreInternalError,r as OreLifecycleError,o as invariant,i as reportRuntimeError};
3
3
  //# sourceMappingURL=errors.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","names":[],"sources":["../src/errors.ts"],"sourcesContent":["import { error as logError } from './_dev';\n\n// ─── Error policy ─────────────────────────────────────────────────────────────\n// One rule for the whole package — decide by whose code failed and whether it\n// can continue, never ad hoc per call site:\n//\n// API misuse (wrong arguments, hook outside setup, duplicate define)\n// → throw `OreApiError`, immediately, every build.\n// User-authored code failing inside ore's execution (setup, onMounted,\n// onFormReset, each() reconciliation)\n// → wrap in `OreLifecycleError` and report via `reportRuntimeError()`\n// (`ore:error` DOM event + dev console) so other callbacks keep running.\n// Recoverable oddity (overwrite warnings, blocked attribute writes)\n// → dev `warn()`/`error()` and continue. Never swallow silently.\n// Internal impossibility (compiled template metadata out of sync)\n// → `invariant()` throws `OreInternalError`, every build.\n\n// ─── Structured error types ───────────────────────────────────────────────────\n\n/** Base class for all Ore errors. Use `instanceof OreError` to catch any Ore-originated error. */\nexport class OreError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when Ore API is called incorrectly (e.g. outside setup, duplicate define, invalid prop). */\nexport class OreApiError extends OreError {}\n\n/**\n * Thrown when an internal invariant fails — e.g. compiled template metadata no\n * longer matching the DOM it was cloned from. Distinct from `OreApiError`: this\n * is never the caller's fault, it signals a bug in ore itself. See `invariant()`.\n */\nexport class OreInternalError extends OreError {}\n\n/**\n * The phase in which a component error occurred.\n * - `'setup'` — synchronous setup() threw\n * - `'mounted'` — an onMounted callback threw\n * - `'form-reset'` — an onFormReset callback threw\n * - `'each-reconcile'` — `each()` failed to reconcile a list update (e.g. duplicate keys)\n */\nexport type OreErrorPhase = 'each-reconcile' | 'form-reset' | 'mounted' | 'setup';\n\n/**\n * Structured error thrown by the Ore runtime when component setup fails.\n * Provides component name and original cause for debugging.\n */\nexport class OreLifecycleError extends OreError {\n readonly component: string;\n readonly phase: OreErrorPhase;\n\n constructor(message: string, options: { cause: Error; component: string; phase: OreErrorPhase }) {\n super(message, { cause: options.cause });\n this.component = options.component;\n this.phase = options.phase;\n }\n}\n\n/**\n * Report a runtime error via the ore:error event and console.\n *\n * `target` only needs to be an `EventTarget` (not specifically an `HTMLElement`) — component\n * lifecycle errors dispatch on the host element, but non-lifecycle failures (e.g. `each()`\n * reconciliation, which has no single \"component\" to attribute the error to) dispatch on\n * whatever live DOM node is available, such as the directive's own anchor `Comment`. Either way\n * the event still bubbles and crosses shadow boundaries (`composed: true`), so a listener on\n * `document`/`window` observes every report regardless of where it originated.\n *\n * The console log (via `_dev.ts`'s `error()`) is still dev-gated like the rest of the package's\n * console diagnostics, but the `ore:error` DOM event dispatch below is **not** — it fires in\n * every build, so consumers always have a way to observe runtime failures programmatically even\n * when console output is stripped in production.\n */\nexport function reportRuntimeError(error: OreLifecycleError, target: EventTarget): void {\n logError(`<${error.component}> lifecycle error (phase: ${error.phase}):`, error.cause);\n\n target.dispatchEvent(\n new CustomEvent('ore:error', {\n bubbles: true,\n composed: true,\n detail: error,\n }),\n );\n}\n\n// ─── Error message constants ─────────────────────────────────────────────────\n\nexport const ORE_ERRORS = {\n asyncSetupUnsupported: 'setup() must return an HTMLResult or null; use reactive state for asynchronous work',\n defineDuplicate: (tag: string): string => `define('${tag}') called twice — custom element already registered`,\n defineFieldRequiresFormAssociated: (tag: string): string =>\n `useField() requires define('${tag}', { formAssociated: true })`,\n defineRequiresTag: 'define() requires a tag name',\n eachDuplicateKey: (key: string, index: number): string => `each() received duplicate key \"${key}\" at index ${index}`,\n eventModifiersUnsupported: (eventName: string): string =>\n `@${eventName}: event modifiers are unsupported; call native event methods in the handler instead`,\n injectStrictFailed: (key: string, tag: string): string => `injectStrict() could not resolve key \"${key}\" in <${tag}>`,\n invariantViolated: (message: string): string => `invariant violated: ${message}`,\n lifecycleOutsideSetup: 'Lifecycle hooks must be called during component setup',\n listenNullTarget: (eventName: string): string =>\n `listen() called with a null/undefined target for event \"${eventName}\" — listener not attached`,\n propInvalidReflect: 'Structured props cannot use reflect:true — use prop.json() with reflect:false',\n templateInterpolationInTag:\n 'html`...`: interpolations inside a tag must be named attributes, boolean attributes, events, or refs',\n useFieldAlreadyCalled: (tag: string): string =>\n `useField() was already called on <${tag}>. Call it only once per component.`,\n validationFailed: (tag: string, errors: string[]): string => `Validation failed for <${tag}>:\\n${errors.join('\\n')}`,\n} as const;\n\n/**\n * Assert an internal invariant that must always hold — e.g. compiled template\n * metadata staying in sync with the DOM it was cloned from. A failed invariant\n * means a bug in ore itself, never user input, so it throws `OreInternalError`\n * unconditionally (every build, never gated like `_dev.ts`'s `warn()`).\n *\n * Narrowing caveat: `asserts condition` only narrows the exact expression\n * passed in. Assign to a local `const` first — `invariant(el.parentNode, msg)`\n * does not narrow later reads of `el.parentNode`.\n */\nexport function invariant(condition: unknown, message: string): asserts condition {\n if (!condition) throw new OreInternalError(ORE_ERRORS.invariantViolated(message));\n}\n"],"mappings":"kBAoBA,IAAa,EAAb,cAA8B,KAAM,CAClC,YAAY,EAAiB,EAAqB,CAChD,MAAM,EAAS,CAAI,EACnB,KAAK,KAAO,WAAW,KACvB,OAAO,eAAe,KAAM,WAAW,SAAS,CAClD,CACF,EAGa,EAAb,cAAiC,CAAS,CAAC,EAO9B,EAAb,cAAsC,CAAS,CAAC,EAenC,EAAb,cAAuC,CAAS,CAC9C,UACA,MAEA,YAAY,EAAiB,EAAoE,CAC/F,MAAM,EAAS,CAAE,MAAO,EAAQ,KAAM,CAAC,EACvC,KAAK,UAAY,EAAQ,UACzB,KAAK,MAAQ,EAAQ,KACvB,CACF,EAiBA,SAAgB,EAAmB,EAA0B,EAA2B,CAC7E,GAAI,EAAM,UAAV,EAAgD,EAAM,MAAtD,EAAiE,EAAM,MAEhF,EAAO,cACL,IAAI,YAAY,YAAa,CAC3B,QAAS,GACT,SAAU,GACV,OAAQ,CACV,CAAC,CACH,CACF,CAIA,IAAa,EAAa,CACxB,sBAAuB,sFACvB,gBAAkB,GAAwB,WAAW,EAAI,qDACzD,kCAAoC,GAClC,+BAA+B,EAAI,8BACrC,kBAAmB,+BACnB,kBAAmB,EAAa,IAA0B,kCAAkC,EAAI,aAAa,IAC7G,0BAA4B,GAC1B,IAAI,EAAU,qFAChB,oBAAqB,EAAa,IAAwB,yCAAyC,EAAI,QAAQ,EAAI,GACnH,kBAAoB,GAA4B,uBAAuB,IACvE,sBAAuB,wDACvB,iBAAmB,GACjB,2DAA2D,EAAU,2BACvE,mBAAoB,gFACpB,2BACE,uGACF,sBAAwB,GACtB,qCAAqC,EAAI,qCAC3C,kBAAmB,EAAa,IAA6B,0BAA0B,EAAI,MAAM,EAAO,KAAK;CAAI,GACnH,EAYA,SAAgB,EAAU,EAAoB,EAAoC,CAChF,GAAI,CAAC,EAAW,MAAM,IAAI,EAAiB,EAAW,kBAAkB,CAAO,CAAC,CAClF"}
1
+ {"version":3,"file":"errors.js","names":[],"sources":["../src/errors.ts"],"sourcesContent":["import { error as logError } from './_dev';\n\n// ─── Error policy ─────────────────────────────────────────────────────────────\n// One rule for the whole package: decide by whose code failed and whether it\n// can continue, never ad hoc per call site:\n//\n// API misuse (wrong arguments, hook outside setup, duplicate define)\n// → throw `OreApiError`, immediately, every build.\n// User-authored code failing inside ore's execution (setup, onMounted,\n// onFormReset, each() reconciliation)\n// → wrap in `OreLifecycleError` and report via `reportRuntimeError()`\n// (`ore:error` DOM event + dev console) so other callbacks keep running.\n// Recoverable oddity (overwrite warnings, blocked attribute writes)\n// → dev `warn()`/`error()` and continue. Never swallow silently.\n// Internal impossibility (compiled template metadata out of sync)\n// → `invariant()` throws `OreInternalError`, every build.\n\n// ─── Structured error types ───────────────────────────────────────────────────\n\n/** Base class for all Ore errors. Use `instanceof OreError` to catch any Ore-originated error. */\nexport class OreError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when Ore API is called incorrectly (e.g. outside setup, duplicate define, invalid prop). */\nexport class OreApiError extends OreError {}\n\n/**\n * Thrown when an internal invariant fails: e.g. compiled template metadata no\n * longer matching the DOM it was cloned from. Distinct from `OreApiError`: this\n * is never the caller's fault, it signals a bug in ore itself. See `invariant()`.\n */\nexport class OreInternalError extends OreError {}\n\n/**\n * The phase in which a component error occurred.\n * - `'setup'`: synchronous setup() threw\n * - `'mounted'`: an onMounted callback threw\n * - `'form-reset'`: an onFormReset callback threw\n * - `'each-reconcile'`: `each()` failed to reconcile a list update (e.g. duplicate keys)\n */\nexport type OreErrorPhase = 'each-reconcile' | 'form-reset' | 'mounted' | 'setup';\n\n/**\n * Structured error thrown by the Ore runtime when component setup fails.\n * Provides component name and original cause for debugging.\n */\nexport class OreLifecycleError extends OreError {\n readonly component: string;\n readonly phase: OreErrorPhase;\n\n constructor(message: string, options: { cause: Error; component: string; phase: OreErrorPhase }) {\n super(message, { cause: options.cause });\n this.component = options.component;\n this.phase = options.phase;\n }\n}\n\n/**\n * Report a runtime error via the ore:error event and console.\n *\n * `target` only needs to be an `EventTarget` (not specifically an `HTMLElement`): component\n * lifecycle errors dispatch on the host element, but non-lifecycle failures (e.g. `each()`\n * reconciliation, which has no single \"component\" to attribute the error to) dispatch on\n * whatever live DOM node is available, such as the directive's own anchor `Comment`. Either way\n * the event still bubbles and crosses shadow boundaries (`composed: true`), so a listener on\n * `document`/`window` observes every report regardless of where it originated.\n *\n * The console log (via `_dev.ts`'s `error()`) is still dev-gated like the rest of the package's\n * console diagnostics, but the `ore:error` DOM event dispatch below is **not**: it fires in\n * every build, so consumers always have a way to observe runtime failures programmatically even\n * when console output is stripped in production.\n */\nexport function reportRuntimeError(error: OreLifecycleError, target: EventTarget): void {\n logError(`<${error.component}> lifecycle error (phase: ${error.phase}):`, error.cause);\n\n target.dispatchEvent(\n new CustomEvent('ore:error', {\n bubbles: true,\n composed: true,\n detail: error,\n }),\n );\n}\n\n// ─── Error message constants ─────────────────────────────────────────────────\n\nexport const ORE_ERRORS = {\n asyncSetupUnsupported: 'setup() must return an HTMLResult or null; use reactive state for asynchronous work',\n defineDuplicate: (tag: string): string => `define('${tag}') called twice: custom element already registered`,\n defineFieldRequiresFormAssociated: (tag: string): string =>\n `useField() requires define('${tag}', { formAssociated: true })`,\n defineRequiresTag: 'define() requires a tag name',\n eachDuplicateKey: (key: string, index: number): string => `each() received duplicate key \"${key}\" at index ${index}`,\n eventModifiersUnsupported: (eventName: string): string =>\n `@${eventName}: event modifiers are unsupported; call native event methods in the handler instead`,\n injectStrictFailed: (key: string, tag: string): string => `injectStrict() could not resolve key \"${key}\" in <${tag}>`,\n invariantViolated: (message: string): string => `invariant violated: ${message}`,\n lifecycleOutsideSetup: 'Lifecycle hooks must be called during component setup',\n listenNullTarget: (eventName: string): string =>\n `listen() called with a null/undefined target for event \"${eventName}\": listener not attached`,\n propInvalidReflect: 'Structured props cannot use reflect:true: use prop.json() with reflect:false',\n templateInterpolationInTag:\n 'html`...`: interpolations inside a tag must be named attributes, boolean attributes, events, or refs',\n useFieldAlreadyCalled: (tag: string): string =>\n `useField() was already called on <${tag}>. Call it only once per component.`,\n validationFailed: (tag: string, errors: string[]): string => `Validation failed for <${tag}>:\\n${errors.join('\\n')}`,\n} as const;\n\n/**\n * Assert an internal invariant that must always hold: e.g. compiled template\n * metadata staying in sync with the DOM it was cloned from. A failed invariant\n * means a bug in ore itself, never user input, so it throws `OreInternalError`\n * unconditionally (every build, never gated like `_dev.ts`'s `warn()`).\n *\n * Narrowing caveat: `asserts condition` only narrows the exact expression\n * passed in. Assign to a local `const` first: `invariant(el.parentNode, msg)`\n * does not narrow later reads of `el.parentNode`.\n */\nexport function invariant(condition: unknown, message: string): asserts condition {\n if (!condition) throw new OreInternalError(ORE_ERRORS.invariantViolated(message));\n}\n"],"mappings":"kBAoBA,IAAa,EAAb,cAA8B,KAAM,CAClC,YAAY,EAAiB,EAAqB,CAChD,MAAM,EAAS,CAAI,EACnB,KAAK,KAAO,WAAW,KACvB,OAAO,eAAe,KAAM,WAAW,SAAS,CAClD,CACF,EAGa,EAAb,cAAiC,CAAS,CAAC,EAO9B,EAAb,cAAsC,CAAS,CAAC,EAenC,EAAb,cAAuC,CAAS,CAC9C,UACA,MAEA,YAAY,EAAiB,EAAoE,CAC/F,MAAM,EAAS,CAAE,MAAO,EAAQ,KAAM,CAAC,EACvC,KAAK,UAAY,EAAQ,UACzB,KAAK,MAAQ,EAAQ,KACvB,CACF,EAiBA,SAAgB,EAAmB,EAA0B,EAA2B,CAC7E,GAAI,EAAM,UAAV,EAAgD,EAAM,MAAtD,EAAiE,EAAM,MAEhF,EAAO,cACL,IAAI,YAAY,YAAa,CAC3B,QAAS,GACT,SAAU,GACV,OAAQ,CACV,CAAC,CACH,CACF,CAIA,IAAa,EAAa,CACxB,sBAAuB,sFACvB,gBAAkB,GAAwB,WAAW,EAAI,oDACzD,kCAAoC,GAClC,+BAA+B,EAAI,8BACrC,kBAAmB,+BACnB,kBAAmB,EAAa,IAA0B,kCAAkC,EAAI,aAAa,IAC7G,0BAA4B,GAC1B,IAAI,EAAU,qFAChB,oBAAqB,EAAa,IAAwB,yCAAyC,EAAI,QAAQ,EAAI,GACnH,kBAAoB,GAA4B,uBAAuB,IACvE,sBAAuB,wDACvB,iBAAmB,GACjB,2DAA2D,EAAU,0BACvE,mBAAoB,+EACpB,2BACE,uGACF,sBAAwB,GACtB,qCAAqC,EAAI,qCAC3C,kBAAmB,EAAa,IAA6B,0BAA0B,EAAI,MAAM,EAAO,KAAK;CAAI,GACnH,EAYA,SAAgB,EAAU,EAAoB,EAAoC,CAChF,GAAI,CAAC,EAAW,MAAM,IAAI,EAAiB,EAAW,kBAAkB,CAAO,CAAC,CAClF"}
@@ -1 +1 @@
1
- {"version":3,"file":"field.cjs","names":[],"sources":["../../src/forms/field.ts"],"sourcesContent":["import type { Readable, Signal } from '@vielzeug/ripple';\n\nimport { warn } from '../_dev';\nimport { ORE_ERRORS, OreApiError } from '../errors';\nimport { getHost, onCleanup, onFormReset, watchEffect } from '../runtime';\n\n/** @internal */\nconst internalsRegistry = new WeakMap<HTMLElement, ElementInternals>();\n/** @internal */\nconst activeFieldRegistry = new WeakSet<HTMLElement>();\n\nexport type FormFieldOptions<T = unknown> = {\n disabled?: Readable<boolean>;\n /**\n * When `true`, a `null` or `undefined` value is submitted as an empty string\n * (`''`) instead of `null`. This keeps the field's key present in `FormData`\n * even when the value is absent — useful when the server expects the field to\n * always be included.\n *\n * @default false\n */\n emptyStringForNull?: boolean;\n /**\n * Called when the ancestor `<form>` is reset (see `onFormReset`). Use to restore\n * whatever local state backs `value` — `useField` itself owns no field state to reset.\n */\n onReset?: () => void;\n toFormValue?: (value: T) => File | FormData | string | null;\n /**\n * Recomputed reactively and passed straight to `internals.setValidity()` — `null`\n * (or omitting `validity` entirely) means always valid. Pair with `validationMessage`.\n *\n * @example\n * ```ts\n * validity: computed(() => (required.value && isBlank(value.value)) ? { valueMissing: true } : null),\n * validationMessage: computed(() => (required.value && isBlank(value.value)) ? 'Required.' : ''),\n * ```\n */\n validationMessage?: Readable<string>;\n validity?: Readable<ValidityStateFlags | null>;\n value: Signal<T> | Readable<T>;\n};\n\nexport type FormFieldHandle = {\n checkValidity: () => boolean;\n readonly internals: ElementInternals;\n reportValidity: () => boolean;\n /**\n * Set (non-empty message) or clear (empty string) a custom validity error.\n * Guards the platform's throw-on-empty-message contract — prefer this over\n * calling `internals.setValidity` directly.\n */\n setCustomValidity: (message: string) => void;\n};\n\nexport const useField = <T = unknown>(options: FormFieldOptions<T>): FormFieldHandle => {\n const host = getHost();\n const ctor = host.constructor as typeof HTMLElement & { formAssociated?: boolean };\n\n if (!ctor.formAssociated) {\n throw new OreApiError(ORE_ERRORS.defineFieldRequiresFormAssociated(host.localName));\n }\n\n if (activeFieldRegistry.has(host)) {\n throw new OreApiError(ORE_ERRORS.useFieldAlreadyCalled(host.localName));\n }\n\n // ElementInternals may only be attached once for an element's lifetime, while setup\n // legitimately runs again when a custom element is reconnected.\n const internals = internalsRegistry.get(host) ?? host.attachInternals();\n\n internalsRegistry.set(host, internals);\n activeFieldRegistry.add(host);\n onCleanup(() => activeFieldRegistry.delete(host));\n\n const toFormValue =\n options.toFormValue ??\n ((v: T): File | FormData | string | null => {\n if (v == null) return options.emptyStringForNull ? '' : null;\n\n if (v instanceof File || v instanceof FormData) return v;\n\n return String(v);\n });\n\n watchEffect(() => {\n internals.setFormValue(toFormValue(options.value.value));\n });\n\n const disabled = options.disabled;\n\n if (disabled) {\n if (!('states' in internals)) {\n warn(\n 'useField(): ElementInternals.states (CustomStateSet) is not available in this environment — disabled state tracking skipped.',\n );\n } else {\n const states = internals.states as CustomStateSet;\n\n watchEffect(() => {\n if (disabled.value) states.add('disabled');\n else states.delete('disabled');\n });\n }\n }\n\n if (options.validity) {\n watchEffect(() => {\n const flags = options.validity?.value ?? {};\n // Per spec, ElementInternals.setValidity() throws if any flag is true and message is\n // empty — a caller-supplied `validity` with no matching `validationMessage` would crash\n // this effect in a real browser. Fail safe with a generic message instead of propagating\n // that crash, and say so loudly in dev so the real fix (pass validationMessage) gets made.\n const hasFlag = Object.values(flags).some(Boolean);\n const message = options.validationMessage?.value ?? '';\n\n if (hasFlag && !message) {\n warn(\n 'useField(): `validity` has a truthy flag but `validationMessage` is empty — internals.setValidity() ' +\n 'requires a non-empty message whenever any flag is true. Falling back to a generic message; pass ' +\n '`validationMessage` to customize it.',\n );\n internals.setValidity(flags, 'Invalid value.');\n\n return;\n }\n\n internals.setValidity(flags, message);\n });\n }\n\n if (options.onReset) onFormReset(options.onReset);\n\n const checkValidity = () => internals.checkValidity();\n const reportValidity = () => internals.reportValidity();\n const setCustomValidity = (message: string) =>\n message ? internals.setValidity({ customError: true }, message) : internals.setValidity({});\n\n return {\n checkValidity,\n internals,\n reportValidity,\n setCustomValidity,\n };\n};\n"],"mappings":"oFAOA,IAAM,EAAoB,IAAI,QAExB,EAAsB,IAAI,QA8CnB,EAAyB,GAAkD,CACtF,IAAM,EAAO,EAAA,QAAQ,EAGrB,GAAI,CAFS,EAAK,YAER,eACR,MAAM,IAAI,EAAA,YAAY,EAAA,WAAW,kCAAkC,EAAK,SAAS,CAAC,EAGpF,GAAI,EAAoB,IAAI,CAAI,EAC9B,MAAM,IAAI,EAAA,YAAY,EAAA,WAAW,sBAAsB,EAAK,SAAS,CAAC,EAKxE,IAAM,EAAY,EAAkB,IAAI,CAAI,GAAK,EAAK,gBAAgB,EAEtE,EAAkB,IAAI,EAAM,CAAS,EACrC,EAAoB,IAAI,CAAI,EAC5B,EAAA,cAAgB,EAAoB,OAAO,CAAI,CAAC,EAEhD,IAAM,EACJ,EAAQ,cACN,GACI,GAAK,KAAa,EAAQ,mBAAqB,GAAK,KAEpD,aAAa,MAAQ,aAAa,SAAiB,EAEhD,OAAO,CAAC,GAGnB,EAAA,gBAAkB,CAChB,EAAU,aAAa,EAAY,EAAQ,MAAM,KAAK,CAAC,CACzD,CAAC,EAED,IAAM,EAAW,EAAQ,SAEzB,GAAI,GACI,WAAY,EAIX,CACL,IAAM,EAAS,EAAU,OAEzB,EAAA,gBAAkB,CACZ,EAAS,MAAO,EAAO,IAAI,UAAU,EACpC,EAAO,OAAO,UAAU,CAC/B,CAAC,CACH,CAmCF,OAhCI,EAAQ,UACV,EAAA,gBAAkB,CAChB,IAAM,EAAQ,EAAQ,UAAU,OAAS,CAAC,EAKpC,EAAU,OAAO,OAAO,CAAK,CAAC,CAAC,KAAK,OAAO,EAC3C,EAAU,EAAQ,mBAAmB,OAAS,GAEpD,GAAI,GAAW,CAAC,EAAS,CAMvB,EAAU,YAAY,EAAO,gBAAgB,EAE7C,MACF,CAEA,EAAU,YAAY,EAAO,CAAO,CACtC,CAAC,EAGC,EAAQ,SAAS,EAAA,YAAY,EAAQ,OAAO,EAOzC,CACL,kBAN0B,EAAU,cAAc,EAOlD,YACA,mBAP2B,EAAU,eAAe,EAQpD,kBAPyB,GACzB,EAAU,EAAU,YAAY,CAAE,YAAa,EAAK,EAAG,CAAO,EAAI,EAAU,YAAY,CAAC,CAAC,CAO5F,CACF"}
1
+ {"version":3,"file":"field.cjs","names":[],"sources":["../../src/forms/field.ts"],"sourcesContent":["import type { Readable, Signal } from '@vielzeug/ripple';\n\nimport { warn } from '../_dev';\nimport { ORE_ERRORS, OreApiError } from '../errors';\nimport { getHost, onCleanup, onFormReset, watchEffect } from '../runtime';\n\n/** @internal */\nconst internalsRegistry = new WeakMap<HTMLElement, ElementInternals>();\n/** @internal */\nconst activeFieldRegistry = new WeakSet<HTMLElement>();\n\nexport type FormFieldOptions<T = unknown> = {\n disabled?: Readable<boolean>;\n /**\n * When `true`, a `null` or `undefined` value is submitted as an empty string\n * (`''`) instead of `null`. This keeps the field's key present in `FormData`\n * even when the value is absent: useful when the server expects the field to\n * always be included.\n *\n * @default false\n */\n emptyStringForNull?: boolean;\n /**\n * Called when the ancestor `<form>` is reset (see `onFormReset`). Use to restore\n * whatever local state backs `value`: `useField` itself owns no field state to reset.\n */\n onReset?: () => void;\n toFormValue?: (value: T) => File | FormData | string | null;\n /**\n * Recomputed reactively and passed straight to `internals.setValidity()`: `null`\n * (or omitting `validity` entirely) means always valid. Pair with `validationMessage`.\n *\n * @example\n * ```ts\n * validity: computed(() => (required.value && isBlank(value.value)) ? { valueMissing: true } : null),\n * validationMessage: computed(() => (required.value && isBlank(value.value)) ? 'Required.' : ''),\n * ```\n */\n validationMessage?: Readable<string>;\n validity?: Readable<ValidityStateFlags | null>;\n value: Signal<T> | Readable<T>;\n};\n\nexport type FormFieldHandle = {\n checkValidity: () => boolean;\n readonly internals: ElementInternals;\n reportValidity: () => boolean;\n /**\n * Set (non-empty message) or clear (empty string) a custom validity error.\n * Guards the platform's throw-on-empty-message contract: prefer this over\n * calling `internals.setValidity` directly.\n */\n setCustomValidity: (message: string) => void;\n};\n\nexport const useField = <T = unknown>(options: FormFieldOptions<T>): FormFieldHandle => {\n const host = getHost();\n const ctor = host.constructor as typeof HTMLElement & { formAssociated?: boolean };\n\n if (!ctor.formAssociated) {\n throw new OreApiError(ORE_ERRORS.defineFieldRequiresFormAssociated(host.localName));\n }\n\n if (activeFieldRegistry.has(host)) {\n throw new OreApiError(ORE_ERRORS.useFieldAlreadyCalled(host.localName));\n }\n\n // ElementInternals may only be attached once for an element's lifetime, while setup\n // legitimately runs again when a custom element is reconnected.\n const internals = internalsRegistry.get(host) ?? host.attachInternals();\n\n internalsRegistry.set(host, internals);\n activeFieldRegistry.add(host);\n onCleanup(() => activeFieldRegistry.delete(host));\n\n const toFormValue =\n options.toFormValue ??\n ((v: T): File | FormData | string | null => {\n if (v == null) return options.emptyStringForNull ? '' : null;\n\n if (v instanceof File || v instanceof FormData) return v;\n\n return String(v);\n });\n\n watchEffect(() => {\n internals.setFormValue(toFormValue(options.value.value));\n });\n\n const disabled = options.disabled;\n\n if (disabled) {\n if (!('states' in internals)) {\n warn(\n 'useField(): ElementInternals.states (CustomStateSet) is not available in this environment: disabled state tracking skipped.',\n );\n } else {\n const states = internals.states as CustomStateSet;\n\n watchEffect(() => {\n if (disabled.value) states.add('disabled');\n else states.delete('disabled');\n });\n }\n }\n\n if (options.validity) {\n watchEffect(() => {\n const flags = options.validity?.value ?? {};\n // Per spec, ElementInternals.setValidity() throws if any flag is true and message is\n // empty: a caller-supplied `validity` with no matching `validationMessage` would crash\n // this effect in a real browser. Fail safe with a generic message instead of propagating\n // that crash, and say so loudly in dev so the real fix (pass validationMessage) gets made.\n const hasFlag = Object.values(flags).some(Boolean);\n const message = options.validationMessage?.value ?? '';\n\n if (hasFlag && !message) {\n warn(\n 'useField(): `validity` has a truthy flag but `validationMessage` is empty: internals.setValidity() ' +\n 'requires a non-empty message whenever any flag is true. Falling back to a generic message; pass ' +\n '`validationMessage` to customize it.',\n );\n internals.setValidity(flags, 'Invalid value.');\n\n return;\n }\n\n internals.setValidity(flags, message);\n });\n }\n\n if (options.onReset) onFormReset(options.onReset);\n\n const checkValidity = () => internals.checkValidity();\n const reportValidity = () => internals.reportValidity();\n const setCustomValidity = (message: string) =>\n message ? internals.setValidity({ customError: true }, message) : internals.setValidity({});\n\n return {\n checkValidity,\n internals,\n reportValidity,\n setCustomValidity,\n };\n};\n"],"mappings":"oFAOA,IAAM,EAAoB,IAAI,QAExB,EAAsB,IAAI,QA8CnB,EAAyB,GAAkD,CACtF,IAAM,EAAO,EAAA,QAAQ,EAGrB,GAAI,CAFS,EAAK,YAER,eACR,MAAM,IAAI,EAAA,YAAY,EAAA,WAAW,kCAAkC,EAAK,SAAS,CAAC,EAGpF,GAAI,EAAoB,IAAI,CAAI,EAC9B,MAAM,IAAI,EAAA,YAAY,EAAA,WAAW,sBAAsB,EAAK,SAAS,CAAC,EAKxE,IAAM,EAAY,EAAkB,IAAI,CAAI,GAAK,EAAK,gBAAgB,EAEtE,EAAkB,IAAI,EAAM,CAAS,EACrC,EAAoB,IAAI,CAAI,EAC5B,EAAA,cAAgB,EAAoB,OAAO,CAAI,CAAC,EAEhD,IAAM,EACJ,EAAQ,cACN,GACI,GAAK,KAAa,EAAQ,mBAAqB,GAAK,KAEpD,aAAa,MAAQ,aAAa,SAAiB,EAEhD,OAAO,CAAC,GAGnB,EAAA,gBAAkB,CAChB,EAAU,aAAa,EAAY,EAAQ,MAAM,KAAK,CAAC,CACzD,CAAC,EAED,IAAM,EAAW,EAAQ,SAEzB,GAAI,GACI,WAAY,EAIX,CACL,IAAM,EAAS,EAAU,OAEzB,EAAA,gBAAkB,CACZ,EAAS,MAAO,EAAO,IAAI,UAAU,EACpC,EAAO,OAAO,UAAU,CAC/B,CAAC,CACH,CAmCF,OAhCI,EAAQ,UACV,EAAA,gBAAkB,CAChB,IAAM,EAAQ,EAAQ,UAAU,OAAS,CAAC,EAKpC,EAAU,OAAO,OAAO,CAAK,CAAC,CAAC,KAAK,OAAO,EAC3C,EAAU,EAAQ,mBAAmB,OAAS,GAEpD,GAAI,GAAW,CAAC,EAAS,CAMvB,EAAU,YAAY,EAAO,gBAAgB,EAE7C,MACF,CAEA,EAAU,YAAY,EAAO,CAAO,CACtC,CAAC,EAGC,EAAQ,SAAS,EAAA,YAAY,EAAQ,OAAO,EAOzC,CACL,kBAN0B,EAAU,cAAc,EAOlD,YACA,mBAP2B,EAAU,eAAe,EAQpD,kBAPyB,GACzB,EAAU,EAAU,YAAY,CAAE,YAAa,EAAK,EAAG,CAAO,EAAI,EAAU,YAAY,CAAC,CAAC,CAO5F,CACF"}
@@ -4,7 +4,7 @@ export type FormFieldOptions<T = unknown> = {
4
4
  /**
5
5
  * When `true`, a `null` or `undefined` value is submitted as an empty string
6
6
  * (`''`) instead of `null`. This keeps the field's key present in `FormData`
7
- * even when the value is absent — useful when the server expects the field to
7
+ * even when the value is absent: useful when the server expects the field to
8
8
  * always be included.
9
9
  *
10
10
  * @default false
@@ -12,12 +12,12 @@ export type FormFieldOptions<T = unknown> = {
12
12
  emptyStringForNull?: boolean;
13
13
  /**
14
14
  * Called when the ancestor `<form>` is reset (see `onFormReset`). Use to restore
15
- * whatever local state backs `value` — `useField` itself owns no field state to reset.
15
+ * whatever local state backs `value`: `useField` itself owns no field state to reset.
16
16
  */
17
17
  onReset?: () => void;
18
18
  toFormValue?: (value: T) => File | FormData | string | null;
19
19
  /**
20
- * Recomputed reactively and passed straight to `internals.setValidity()` — `null`
20
+ * Recomputed reactively and passed straight to `internals.setValidity()`: `null`
21
21
  * (or omitting `validity` entirely) means always valid. Pair with `validationMessage`.
22
22
  *
23
23
  * @example
@@ -36,7 +36,7 @@ export type FormFieldHandle = {
36
36
  reportValidity: () => boolean;
37
37
  /**
38
38
  * Set (non-empty message) or clear (empty string) a custom validity error.
39
- * Guards the platform's throw-on-empty-message contract — prefer this over
39
+ * Guards the platform's throw-on-empty-message contract: prefer this over
40
40
  * calling `internals.setValidity` directly.
41
41
  */
42
42
  setCustomValidity: (message: string) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"field.js","names":[],"sources":["../../src/forms/field.ts"],"sourcesContent":["import type { Readable, Signal } from '@vielzeug/ripple';\n\nimport { warn } from '../_dev';\nimport { ORE_ERRORS, OreApiError } from '../errors';\nimport { getHost, onCleanup, onFormReset, watchEffect } from '../runtime';\n\n/** @internal */\nconst internalsRegistry = new WeakMap<HTMLElement, ElementInternals>();\n/** @internal */\nconst activeFieldRegistry = new WeakSet<HTMLElement>();\n\nexport type FormFieldOptions<T = unknown> = {\n disabled?: Readable<boolean>;\n /**\n * When `true`, a `null` or `undefined` value is submitted as an empty string\n * (`''`) instead of `null`. This keeps the field's key present in `FormData`\n * even when the value is absent — useful when the server expects the field to\n * always be included.\n *\n * @default false\n */\n emptyStringForNull?: boolean;\n /**\n * Called when the ancestor `<form>` is reset (see `onFormReset`). Use to restore\n * whatever local state backs `value` — `useField` itself owns no field state to reset.\n */\n onReset?: () => void;\n toFormValue?: (value: T) => File | FormData | string | null;\n /**\n * Recomputed reactively and passed straight to `internals.setValidity()` — `null`\n * (or omitting `validity` entirely) means always valid. Pair with `validationMessage`.\n *\n * @example\n * ```ts\n * validity: computed(() => (required.value && isBlank(value.value)) ? { valueMissing: true } : null),\n * validationMessage: computed(() => (required.value && isBlank(value.value)) ? 'Required.' : ''),\n * ```\n */\n validationMessage?: Readable<string>;\n validity?: Readable<ValidityStateFlags | null>;\n value: Signal<T> | Readable<T>;\n};\n\nexport type FormFieldHandle = {\n checkValidity: () => boolean;\n readonly internals: ElementInternals;\n reportValidity: () => boolean;\n /**\n * Set (non-empty message) or clear (empty string) a custom validity error.\n * Guards the platform's throw-on-empty-message contract — prefer this over\n * calling `internals.setValidity` directly.\n */\n setCustomValidity: (message: string) => void;\n};\n\nexport const useField = <T = unknown>(options: FormFieldOptions<T>): FormFieldHandle => {\n const host = getHost();\n const ctor = host.constructor as typeof HTMLElement & { formAssociated?: boolean };\n\n if (!ctor.formAssociated) {\n throw new OreApiError(ORE_ERRORS.defineFieldRequiresFormAssociated(host.localName));\n }\n\n if (activeFieldRegistry.has(host)) {\n throw new OreApiError(ORE_ERRORS.useFieldAlreadyCalled(host.localName));\n }\n\n // ElementInternals may only be attached once for an element's lifetime, while setup\n // legitimately runs again when a custom element is reconnected.\n const internals = internalsRegistry.get(host) ?? host.attachInternals();\n\n internalsRegistry.set(host, internals);\n activeFieldRegistry.add(host);\n onCleanup(() => activeFieldRegistry.delete(host));\n\n const toFormValue =\n options.toFormValue ??\n ((v: T): File | FormData | string | null => {\n if (v == null) return options.emptyStringForNull ? '' : null;\n\n if (v instanceof File || v instanceof FormData) return v;\n\n return String(v);\n });\n\n watchEffect(() => {\n internals.setFormValue(toFormValue(options.value.value));\n });\n\n const disabled = options.disabled;\n\n if (disabled) {\n if (!('states' in internals)) {\n warn(\n 'useField(): ElementInternals.states (CustomStateSet) is not available in this environment — disabled state tracking skipped.',\n );\n } else {\n const states = internals.states as CustomStateSet;\n\n watchEffect(() => {\n if (disabled.value) states.add('disabled');\n else states.delete('disabled');\n });\n }\n }\n\n if (options.validity) {\n watchEffect(() => {\n const flags = options.validity?.value ?? {};\n // Per spec, ElementInternals.setValidity() throws if any flag is true and message is\n // empty — a caller-supplied `validity` with no matching `validationMessage` would crash\n // this effect in a real browser. Fail safe with a generic message instead of propagating\n // that crash, and say so loudly in dev so the real fix (pass validationMessage) gets made.\n const hasFlag = Object.values(flags).some(Boolean);\n const message = options.validationMessage?.value ?? '';\n\n if (hasFlag && !message) {\n warn(\n 'useField(): `validity` has a truthy flag but `validationMessage` is empty — internals.setValidity() ' +\n 'requires a non-empty message whenever any flag is true. Falling back to a generic message; pass ' +\n '`validationMessage` to customize it.',\n );\n internals.setValidity(flags, 'Invalid value.');\n\n return;\n }\n\n internals.setValidity(flags, message);\n });\n }\n\n if (options.onReset) onFormReset(options.onReset);\n\n const checkValidity = () => internals.checkValidity();\n const reportValidity = () => internals.reportValidity();\n const setCustomValidity = (message: string) =>\n message ? internals.setValidity({ customError: true }, message) : internals.setValidity({});\n\n return {\n checkValidity,\n internals,\n reportValidity,\n setCustomValidity,\n };\n};\n"],"mappings":"uKAOA,IAAM,EAAoB,IAAI,QAExB,EAAsB,IAAI,QA8CnB,EAAyB,GAAkD,CACtF,IAAM,EAAO,EAAQ,EAGrB,GAAI,CAFS,EAAK,YAER,eACR,MAAM,IAAI,EAAY,EAAW,kCAAkC,EAAK,SAAS,CAAC,EAGpF,GAAI,EAAoB,IAAI,CAAI,EAC9B,MAAM,IAAI,EAAY,EAAW,sBAAsB,EAAK,SAAS,CAAC,EAKxE,IAAM,EAAY,EAAkB,IAAI,CAAI,GAAK,EAAK,gBAAgB,EAEtE,EAAkB,IAAI,EAAM,CAAS,EACrC,EAAoB,IAAI,CAAI,EAC5B,MAAgB,EAAoB,OAAO,CAAI,CAAC,EAEhD,IAAM,EACJ,EAAQ,cACN,GACI,GAAK,KAAa,EAAQ,mBAAqB,GAAK,KAEpD,aAAa,MAAQ,aAAa,SAAiB,EAEhD,OAAO,CAAC,GAGnB,MAAkB,CAChB,EAAU,aAAa,EAAY,EAAQ,MAAM,KAAK,CAAC,CACzD,CAAC,EAED,IAAM,EAAW,EAAQ,SAEzB,GAAI,GACI,WAAY,EAIX,CACL,IAAM,EAAS,EAAU,OAEzB,MAAkB,CACZ,EAAS,MAAO,EAAO,IAAI,UAAU,EACpC,EAAO,OAAO,UAAU,CAC/B,CAAC,CACH,CAmCF,OAhCI,EAAQ,UACV,MAAkB,CAChB,IAAM,EAAQ,EAAQ,UAAU,OAAS,CAAC,EAKpC,EAAU,OAAO,OAAO,CAAK,CAAC,CAAC,KAAK,OAAO,EAC3C,EAAU,EAAQ,mBAAmB,OAAS,GAEpD,GAAI,GAAW,CAAC,EAAS,CAMvB,EAAU,YAAY,EAAO,gBAAgB,EAE7C,MACF,CAEA,EAAU,YAAY,EAAO,CAAO,CACtC,CAAC,EAGC,EAAQ,SAAS,EAAY,EAAQ,OAAO,EAOzC,CACL,kBAN0B,EAAU,cAAc,EAOlD,YACA,mBAP2B,EAAU,eAAe,EAQpD,kBAPyB,GACzB,EAAU,EAAU,YAAY,CAAE,YAAa,EAAK,EAAG,CAAO,EAAI,EAAU,YAAY,CAAC,CAAC,CAO5F,CACF"}
1
+ {"version":3,"file":"field.js","names":[],"sources":["../../src/forms/field.ts"],"sourcesContent":["import type { Readable, Signal } from '@vielzeug/ripple';\n\nimport { warn } from '../_dev';\nimport { ORE_ERRORS, OreApiError } from '../errors';\nimport { getHost, onCleanup, onFormReset, watchEffect } from '../runtime';\n\n/** @internal */\nconst internalsRegistry = new WeakMap<HTMLElement, ElementInternals>();\n/** @internal */\nconst activeFieldRegistry = new WeakSet<HTMLElement>();\n\nexport type FormFieldOptions<T = unknown> = {\n disabled?: Readable<boolean>;\n /**\n * When `true`, a `null` or `undefined` value is submitted as an empty string\n * (`''`) instead of `null`. This keeps the field's key present in `FormData`\n * even when the value is absent: useful when the server expects the field to\n * always be included.\n *\n * @default false\n */\n emptyStringForNull?: boolean;\n /**\n * Called when the ancestor `<form>` is reset (see `onFormReset`). Use to restore\n * whatever local state backs `value`: `useField` itself owns no field state to reset.\n */\n onReset?: () => void;\n toFormValue?: (value: T) => File | FormData | string | null;\n /**\n * Recomputed reactively and passed straight to `internals.setValidity()`: `null`\n * (or omitting `validity` entirely) means always valid. Pair with `validationMessage`.\n *\n * @example\n * ```ts\n * validity: computed(() => (required.value && isBlank(value.value)) ? { valueMissing: true } : null),\n * validationMessage: computed(() => (required.value && isBlank(value.value)) ? 'Required.' : ''),\n * ```\n */\n validationMessage?: Readable<string>;\n validity?: Readable<ValidityStateFlags | null>;\n value: Signal<T> | Readable<T>;\n};\n\nexport type FormFieldHandle = {\n checkValidity: () => boolean;\n readonly internals: ElementInternals;\n reportValidity: () => boolean;\n /**\n * Set (non-empty message) or clear (empty string) a custom validity error.\n * Guards the platform's throw-on-empty-message contract: prefer this over\n * calling `internals.setValidity` directly.\n */\n setCustomValidity: (message: string) => void;\n};\n\nexport const useField = <T = unknown>(options: FormFieldOptions<T>): FormFieldHandle => {\n const host = getHost();\n const ctor = host.constructor as typeof HTMLElement & { formAssociated?: boolean };\n\n if (!ctor.formAssociated) {\n throw new OreApiError(ORE_ERRORS.defineFieldRequiresFormAssociated(host.localName));\n }\n\n if (activeFieldRegistry.has(host)) {\n throw new OreApiError(ORE_ERRORS.useFieldAlreadyCalled(host.localName));\n }\n\n // ElementInternals may only be attached once for an element's lifetime, while setup\n // legitimately runs again when a custom element is reconnected.\n const internals = internalsRegistry.get(host) ?? host.attachInternals();\n\n internalsRegistry.set(host, internals);\n activeFieldRegistry.add(host);\n onCleanup(() => activeFieldRegistry.delete(host));\n\n const toFormValue =\n options.toFormValue ??\n ((v: T): File | FormData | string | null => {\n if (v == null) return options.emptyStringForNull ? '' : null;\n\n if (v instanceof File || v instanceof FormData) return v;\n\n return String(v);\n });\n\n watchEffect(() => {\n internals.setFormValue(toFormValue(options.value.value));\n });\n\n const disabled = options.disabled;\n\n if (disabled) {\n if (!('states' in internals)) {\n warn(\n 'useField(): ElementInternals.states (CustomStateSet) is not available in this environment: disabled state tracking skipped.',\n );\n } else {\n const states = internals.states as CustomStateSet;\n\n watchEffect(() => {\n if (disabled.value) states.add('disabled');\n else states.delete('disabled');\n });\n }\n }\n\n if (options.validity) {\n watchEffect(() => {\n const flags = options.validity?.value ?? {};\n // Per spec, ElementInternals.setValidity() throws if any flag is true and message is\n // empty: a caller-supplied `validity` with no matching `validationMessage` would crash\n // this effect in a real browser. Fail safe with a generic message instead of propagating\n // that crash, and say so loudly in dev so the real fix (pass validationMessage) gets made.\n const hasFlag = Object.values(flags).some(Boolean);\n const message = options.validationMessage?.value ?? '';\n\n if (hasFlag && !message) {\n warn(\n 'useField(): `validity` has a truthy flag but `validationMessage` is empty: internals.setValidity() ' +\n 'requires a non-empty message whenever any flag is true. Falling back to a generic message; pass ' +\n '`validationMessage` to customize it.',\n );\n internals.setValidity(flags, 'Invalid value.');\n\n return;\n }\n\n internals.setValidity(flags, message);\n });\n }\n\n if (options.onReset) onFormReset(options.onReset);\n\n const checkValidity = () => internals.checkValidity();\n const reportValidity = () => internals.reportValidity();\n const setCustomValidity = (message: string) =>\n message ? internals.setValidity({ customError: true }, message) : internals.setValidity({});\n\n return {\n checkValidity,\n internals,\n reportValidity,\n setCustomValidity,\n };\n};\n"],"mappings":"uKAOA,IAAM,EAAoB,IAAI,QAExB,EAAsB,IAAI,QA8CnB,EAAyB,GAAkD,CACtF,IAAM,EAAO,EAAQ,EAGrB,GAAI,CAFS,EAAK,YAER,eACR,MAAM,IAAI,EAAY,EAAW,kCAAkC,EAAK,SAAS,CAAC,EAGpF,GAAI,EAAoB,IAAI,CAAI,EAC9B,MAAM,IAAI,EAAY,EAAW,sBAAsB,EAAK,SAAS,CAAC,EAKxE,IAAM,EAAY,EAAkB,IAAI,CAAI,GAAK,EAAK,gBAAgB,EAEtE,EAAkB,IAAI,EAAM,CAAS,EACrC,EAAoB,IAAI,CAAI,EAC5B,MAAgB,EAAoB,OAAO,CAAI,CAAC,EAEhD,IAAM,EACJ,EAAQ,cACN,GACI,GAAK,KAAa,EAAQ,mBAAqB,GAAK,KAEpD,aAAa,MAAQ,aAAa,SAAiB,EAEhD,OAAO,CAAC,GAGnB,MAAkB,CAChB,EAAU,aAAa,EAAY,EAAQ,MAAM,KAAK,CAAC,CACzD,CAAC,EAED,IAAM,EAAW,EAAQ,SAEzB,GAAI,GACI,WAAY,EAIX,CACL,IAAM,EAAS,EAAU,OAEzB,MAAkB,CACZ,EAAS,MAAO,EAAO,IAAI,UAAU,EACpC,EAAO,OAAO,UAAU,CAC/B,CAAC,CACH,CAmCF,OAhCI,EAAQ,UACV,MAAkB,CAChB,IAAM,EAAQ,EAAQ,UAAU,OAAS,CAAC,EAKpC,EAAU,OAAO,OAAO,CAAK,CAAC,CAAC,KAAK,OAAO,EAC3C,EAAU,EAAQ,mBAAmB,OAAS,GAEpD,GAAI,GAAW,CAAC,EAAS,CAMvB,EAAU,YAAY,EAAO,gBAAgB,EAE7C,MACF,CAEA,EAAU,YAAY,EAAO,CAAO,CACtC,CAAC,EAGC,EAAQ,SAAS,EAAY,EAAQ,OAAO,EAOzC,CACL,kBAN0B,EAAU,cAAc,EAOlD,YACA,mBAP2B,EAAU,eAAe,EAQpD,kBAPyB,GACzB,EAAU,EAAU,YAAY,CAAE,YAAa,EAAK,EAAG,CAAO,EAAI,EAAU,YAAY,CAAC,CAAC,CAO5F,CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"host-bind.cjs","names":[],"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 { listen, type MaybeReactive, resolveMaybeReactive, sanitizeCssToken, setAttr, toKebab } 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 = sanitizeCssToken(name.startsWith('--') ? name : toKebab(name));\n\n if (!cssName) return;\n\n let owned = false;\n const setStyle = (v: string | number | boolean | null | undefined): void => {\n if (v != null && v !== '') {\n owned = true;\n host.style.setProperty(cssName, sanitizeCssToken(String(v)));\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> => {\n const result: Record<string, boolean> = {};\n\n for (const [cls, entry] of Object.entries(value)) {\n result[cls] = resolveMaybeReactive(entry);\n }\n\n return result;\n };\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":"8HAiDA,IAAa,GAAQ,EAAwB,IAAwC,CACnF,IAAM,EAAM,GAAS,QAAsC,EAAA,QAAQ,EAC7D,EAA+B,CAAC,EAEtC,GAAI,EAAO,KACT,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,EAAO,IAAI,EAAG,CAEtD,IAAM,EAAU,EAAe,EADlB,EAAW,CACW,EAAM,CAAK,EAE1C,GAAS,EAAU,KAAK,CAAO,CACrC,CAOF,GAJI,EAAO,OACT,EAAU,KAAK,EAAc,EAAI,EAAO,KAAK,CAAC,EAG5C,EAAO,MACT,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,EAAO,KAAK,EAAG,CACvD,IAAM,EAAU,EAAW,EAAI,EAAK,CAAK,EAErC,GAAS,EAAU,KAAK,CAAO,CACrC,CAGF,GAAI,EAAO,GAAI,CACb,GAAM,CAAE,OAAQ,EAAI,GAAG,GAAoB,GAAW,CAAC,EAEvD,IAAK,IAAM,KAAS,OAAO,KAAK,EAAO,EAAE,EAAoC,CAC3E,IAAM,EAAW,EAAO,GAAG,GAEtB,GAEL,EAAU,KAAK,EAAA,OAAO,EAAI,EAAiB,EAA2B,CAAe,CAAC,CACxF,CACF,CAEA,IAAM,MAAsB,CAC1B,IAAK,IAAM,KAAW,EAAW,EAAQ,CAC3C,EAIA,OAFA,EAAA,mBAAmB,CAAO,EAEnB,CACT,EAEM,EAAa,EAAA,qBAEb,GACJ,EACA,IAC6B,CAC7B,GAAI,OAAO,GAAU,WACnB,OAAO,EAAA,gBAAkB,CACvB,EAAQ,EAAM,CAAC,CAEjB,CAAC,EAGH,IAAA,EAAI,EAAA,WAAA,CAAW,CAAK,EAClB,OAAO,EAAA,gBAAkB,CACvB,EAAQ,EAAM,KAAK,CAErB,CAAC,EAGH,EAAQ,CAAK,CACf,EAEA,SAAS,EAAe,EAAmB,EAAc,EAAmD,CAC1G,OAAO,EAAqB,EAAQ,GAAS,EAAA,QAAQ,EAAM,EAAM,CAAI,CAAC,CACxE,CAEA,SAAS,EAAW,EAAmB,EAAc,EAAmD,CACtG,IAAM,EAAU,EAAA,iBAAiB,EAAK,WAAW,IAAI,EAAI,EAAO,EAAA,QAAQ,CAAI,CAAC,EAE7E,GAAI,CAAC,EAAS,OAEd,IAAI,EAAQ,GAQZ,OAAO,EAAqB,EAPV,GAA0D,CACtE,GAAK,MAAQ,IAAM,IACrB,EAAQ,GACR,EAAK,MAAM,YAAY,EAAS,EAAA,iBAAiB,OAAO,CAAC,CAAC,CAAC,GAClD,GAAO,EAAK,MAAM,eAAe,CAAO,CACrD,CAE2C,CAC7C,CAEA,SAAS,EACP,EACA,EACY,CACZ,IAAM,EACJ,OAAO,GAAU,WACb,MAC+B,CAC7B,IAAM,EAAkC,CAAC,EAEzC,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,CAAK,EAC7C,EAAO,GAAO,EAAA,qBAAqB,CAAK,EAG1C,OAAO,CACT,EAEF,EAAO,IAAI,IAkBf,OAhBY,EAAA,gBAAkB,CAC5B,IAAM,EAAO,IAAI,IAEjB,IAAK,GAAM,CAAC,EAAK,KAAW,OAAO,QAAQ,EAAO,CAAC,EAC5C,IAEL,EAAK,IAAI,CAAG,EAEP,EAAK,IAAI,CAAG,GAAG,EAAK,UAAU,IAAI,CAAG,GAE5C,IAAK,IAAM,KAAO,EACX,EAAK,IAAI,CAAG,GAAG,EAAK,UAAU,OAAO,CAAG,EAE/C,EAAO,CACT,CAEO,CACT"}
1
+ {"version":3,"file":"host-bind.cjs","names":[],"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 { listen, type MaybeReactive, resolveMaybeReactive, sanitizeCssToken, setAttr, toKebab } 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 = sanitizeCssToken(name.startsWith('--') ? name : toKebab(name));\n\n if (!cssName) return;\n\n let owned = false;\n const setStyle = (v: string | number | boolean | null | undefined): void => {\n if (v != null && v !== '') {\n owned = true;\n host.style.setProperty(cssName, sanitizeCssToken(String(v)));\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> => {\n const result: Record<string, boolean> = {};\n\n for (const [cls, entry] of Object.entries(value)) {\n result[cls] = resolveMaybeReactive(entry);\n }\n\n return result;\n };\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":"8HAiDA,IAAa,GAAQ,EAAwB,IAAwC,CACnF,IAAM,EAAM,GAAS,QAAsC,EAAA,QAAQ,EAC7D,EAA+B,CAAC,EAEtC,GAAI,EAAO,KACT,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,EAAO,IAAI,EAAG,CAEtD,IAAM,EAAU,EAAe,EADlB,EAAW,CACW,EAAM,CAAK,EAE1C,GAAS,EAAU,KAAK,CAAO,CACrC,CAOF,GAJI,EAAO,OACT,EAAU,KAAK,EAAc,EAAI,EAAO,KAAK,CAAC,EAG5C,EAAO,MACT,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,EAAO,KAAK,EAAG,CACvD,IAAM,EAAU,EAAW,EAAI,EAAK,CAAK,EAErC,GAAS,EAAU,KAAK,CAAO,CACrC,CAGF,GAAI,EAAO,GAAI,CACb,GAAM,CAAE,OAAQ,EAAI,GAAG,GAAoB,GAAW,CAAC,EAEvD,IAAK,IAAM,KAAS,OAAO,KAAK,EAAO,EAAE,EAAoC,CAC3E,IAAM,EAAW,EAAO,GAAG,GAEtB,GAEL,EAAU,KAAK,EAAA,OAAO,EAAI,EAAiB,EAA2B,CAAe,CAAC,CACxF,CACF,CAEA,IAAM,MAAsB,CAC1B,IAAK,IAAM,KAAW,EAAW,EAAQ,CAC3C,EAIA,OAFA,EAAA,mBAAmB,CAAO,EAEnB,CACT,EAEM,EAAa,EAAA,qBAEb,GACJ,EACA,IAC6B,CAC7B,GAAI,OAAO,GAAU,WACnB,OAAO,EAAA,gBAAkB,CACvB,EAAQ,EAAM,CAAC,CAEjB,CAAC,EAGH,IAAA,EAAI,EAAA,WAAA,CAAW,CAAK,EAClB,OAAO,EAAA,gBAAkB,CACvB,EAAQ,EAAM,KAAK,CAErB,CAAC,EAGH,EAAQ,CAAK,CACf,EAEA,SAAS,EAAe,EAAmB,EAAc,EAAmD,CAC1G,OAAO,EAAqB,EAAQ,GAAS,EAAA,QAAQ,EAAM,EAAM,CAAI,CAAC,CACxE,CAEA,SAAS,EAAW,EAAmB,EAAc,EAAmD,CACtG,IAAM,EAAU,EAAA,iBAAiB,EAAK,WAAW,IAAI,EAAI,EAAO,EAAA,QAAQ,CAAI,CAAC,EAE7E,GAAI,CAAC,EAAS,OAEd,IAAI,EAAQ,GAQZ,OAAO,EAAqB,EAPV,GAA0D,CACtE,GAAK,MAAQ,IAAM,IACrB,EAAQ,GACR,EAAK,MAAM,YAAY,EAAS,EAAA,iBAAiB,OAAO,CAAC,CAAC,CAAC,GAClD,GAAO,EAAK,MAAM,eAAe,CAAO,CACrD,CAE2C,CAC7C,CAEA,SAAS,EACP,EACA,EACY,CACZ,IAAM,EACJ,OAAO,GAAU,WACb,MAC+B,CAC7B,IAAM,EAAkC,CAAC,EAEzC,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,CAAK,EAC7C,EAAO,GAAO,EAAA,qBAAqB,CAAK,EAG1C,OAAO,CACT,EAEF,EAAO,IAAI,IAkBf,OAhBY,EAAA,gBAAkB,CAC5B,IAAM,EAAO,IAAI,IAEjB,IAAK,GAAM,CAAC,EAAK,KAAW,OAAO,QAAQ,EAAO,CAAC,EAC5C,IAEL,EAAK,IAAI,CAAG,EAEP,EAAK,IAAI,CAAG,GAAG,EAAK,UAAU,IAAI,CAAG,GAE5C,IAAK,IAAM,KAAO,EACX,EAAK,IAAI,CAAG,GAAG,EAAK,UAAU,OAAO,CAAG,EAE/C,EAAO,CACT,CAEO,CACT"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Host element binding API — reactive attr, class, style, and event bindings
2
+ * Host element binding API: reactive attr, class, style, and event bindings
3
3
  * applied directly to the component's host element or any target element.
4
4
  */
5
5
  import { type MaybeReactive } from './utils/dom';
@@ -1 +1 @@
1
- {"version":3,"file":"host-bind.js","names":[],"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 { listen, type MaybeReactive, resolveMaybeReactive, sanitizeCssToken, setAttr, toKebab } 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 = sanitizeCssToken(name.startsWith('--') ? name : toKebab(name));\n\n if (!cssName) return;\n\n let owned = false;\n const setStyle = (v: string | number | boolean | null | undefined): void => {\n if (v != null && v !== '') {\n owned = true;\n host.style.setProperty(cssName, sanitizeCssToken(String(v)));\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> => {\n const result: Record<string, boolean> = {};\n\n for (const [cls, entry] of Object.entries(value)) {\n result[cls] = resolveMaybeReactive(entry);\n }\n\n return result;\n };\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":"uSAiDA,IAAa,GAAQ,EAAwB,IAAwC,CACnF,IAAM,EAAM,GAAS,QAAsC,EAAQ,EAC7D,EAA+B,CAAC,EAEtC,GAAI,EAAO,KACT,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,EAAO,IAAI,EAAG,CAEtD,IAAM,EAAU,EAAe,EADlB,EAAW,CACW,EAAM,CAAK,EAE1C,GAAS,EAAU,KAAK,CAAO,CACrC,CAOF,GAJI,EAAO,OACT,EAAU,KAAK,EAAc,EAAI,EAAO,KAAK,CAAC,EAG5C,EAAO,MACT,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,EAAO,KAAK,EAAG,CACvD,IAAM,EAAU,EAAW,EAAI,EAAK,CAAK,EAErC,GAAS,EAAU,KAAK,CAAO,CACrC,CAGF,GAAI,EAAO,GAAI,CACb,GAAM,CAAE,OAAQ,EAAI,GAAG,GAAoB,GAAW,CAAC,EAEvD,IAAK,IAAM,KAAS,OAAO,KAAK,EAAO,EAAE,EAAoC,CAC3E,IAAM,EAAW,EAAO,GAAG,GAEtB,GAEL,EAAU,KAAK,EAAO,EAAI,EAAiB,EAA2B,CAAe,CAAC,CACxF,CACF,CAEA,IAAM,MAAsB,CAC1B,IAAK,IAAM,KAAW,EAAW,EAAQ,CAC3C,EAIA,OAFA,EAAmB,CAAO,EAEnB,CACT,EAEM,EAAa,EAEb,GACJ,EACA,IAC6B,CAC7B,GAAI,OAAO,GAAU,WACnB,OAAO,MAAkB,CACvB,EAAQ,EAAM,CAAC,CAEjB,CAAC,EAGH,GAAI,EAAW,CAAK,EAClB,OAAO,MAAkB,CACvB,EAAQ,EAAM,KAAK,CAErB,CAAC,EAGH,EAAQ,CAAK,CACf,EAEA,SAAS,EAAe,EAAmB,EAAc,EAAmD,CAC1G,OAAO,EAAqB,EAAQ,GAAS,EAAQ,EAAM,EAAM,CAAI,CAAC,CACxE,CAEA,SAAS,EAAW,EAAmB,EAAc,EAAmD,CACtG,IAAM,EAAU,EAAiB,EAAK,WAAW,IAAI,EAAI,EAAO,EAAQ,CAAI,CAAC,EAE7E,GAAI,CAAC,EAAS,OAEd,IAAI,EAAQ,GAQZ,OAAO,EAAqB,EAPV,GAA0D,CACtE,GAAK,MAAQ,IAAM,IACrB,EAAQ,GACR,EAAK,MAAM,YAAY,EAAS,EAAiB,OAAO,CAAC,CAAC,CAAC,GAClD,GAAO,EAAK,MAAM,eAAe,CAAO,CACrD,CAE2C,CAC7C,CAEA,SAAS,EACP,EACA,EACY,CACZ,IAAM,EACJ,OAAO,GAAU,WACb,MAC+B,CAC7B,IAAM,EAAkC,CAAC,EAEzC,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,CAAK,EAC7C,EAAO,GAAO,EAAqB,CAAK,EAG1C,OAAO,CACT,EAEF,EAAO,IAAI,IAkBf,OAhBY,MAAkB,CAC5B,IAAM,EAAO,IAAI,IAEjB,IAAK,GAAM,CAAC,EAAK,KAAW,OAAO,QAAQ,EAAO,CAAC,EAC5C,IAEL,EAAK,IAAI,CAAG,EAEP,EAAK,IAAI,CAAG,GAAG,EAAK,UAAU,IAAI,CAAG,GAE5C,IAAK,IAAM,KAAO,EACX,EAAK,IAAI,CAAG,GAAG,EAAK,UAAU,OAAO,CAAG,EAE/C,EAAO,CACT,CAEO,CACT"}
1
+ {"version":3,"file":"host-bind.js","names":[],"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 { listen, type MaybeReactive, resolveMaybeReactive, sanitizeCssToken, setAttr, toKebab } 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 = sanitizeCssToken(name.startsWith('--') ? name : toKebab(name));\n\n if (!cssName) return;\n\n let owned = false;\n const setStyle = (v: string | number | boolean | null | undefined): void => {\n if (v != null && v !== '') {\n owned = true;\n host.style.setProperty(cssName, sanitizeCssToken(String(v)));\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> => {\n const result: Record<string, boolean> = {};\n\n for (const [cls, entry] of Object.entries(value)) {\n result[cls] = resolveMaybeReactive(entry);\n }\n\n return result;\n };\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":"uSAiDA,IAAa,GAAQ,EAAwB,IAAwC,CACnF,IAAM,EAAM,GAAS,QAAsC,EAAQ,EAC7D,EAA+B,CAAC,EAEtC,GAAI,EAAO,KACT,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,EAAO,IAAI,EAAG,CAEtD,IAAM,EAAU,EAAe,EADlB,EAAW,CACW,EAAM,CAAK,EAE1C,GAAS,EAAU,KAAK,CAAO,CACrC,CAOF,GAJI,EAAO,OACT,EAAU,KAAK,EAAc,EAAI,EAAO,KAAK,CAAC,EAG5C,EAAO,MACT,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,EAAO,KAAK,EAAG,CACvD,IAAM,EAAU,EAAW,EAAI,EAAK,CAAK,EAErC,GAAS,EAAU,KAAK,CAAO,CACrC,CAGF,GAAI,EAAO,GAAI,CACb,GAAM,CAAE,OAAQ,EAAI,GAAG,GAAoB,GAAW,CAAC,EAEvD,IAAK,IAAM,KAAS,OAAO,KAAK,EAAO,EAAE,EAAoC,CAC3E,IAAM,EAAW,EAAO,GAAG,GAEtB,GAEL,EAAU,KAAK,EAAO,EAAI,EAAiB,EAA2B,CAAe,CAAC,CACxF,CACF,CAEA,IAAM,MAAsB,CAC1B,IAAK,IAAM,KAAW,EAAW,EAAQ,CAC3C,EAIA,OAFA,EAAmB,CAAO,EAEnB,CACT,EAEM,EAAa,EAEb,GACJ,EACA,IAC6B,CAC7B,GAAI,OAAO,GAAU,WACnB,OAAO,MAAkB,CACvB,EAAQ,EAAM,CAAC,CAEjB,CAAC,EAGH,GAAI,EAAW,CAAK,EAClB,OAAO,MAAkB,CACvB,EAAQ,EAAM,KAAK,CAErB,CAAC,EAGH,EAAQ,CAAK,CACf,EAEA,SAAS,EAAe,EAAmB,EAAc,EAAmD,CAC1G,OAAO,EAAqB,EAAQ,GAAS,EAAQ,EAAM,EAAM,CAAI,CAAC,CACxE,CAEA,SAAS,EAAW,EAAmB,EAAc,EAAmD,CACtG,IAAM,EAAU,EAAiB,EAAK,WAAW,IAAI,EAAI,EAAO,EAAQ,CAAI,CAAC,EAE7E,GAAI,CAAC,EAAS,OAEd,IAAI,EAAQ,GAQZ,OAAO,EAAqB,EAPV,GAA0D,CACtE,GAAK,MAAQ,IAAM,IACrB,EAAQ,GACR,EAAK,MAAM,YAAY,EAAS,EAAiB,OAAO,CAAC,CAAC,CAAC,GAClD,GAAO,EAAK,MAAM,eAAe,CAAO,CACrD,CAE2C,CAC7C,CAEA,SAAS,EACP,EACA,EACY,CACZ,IAAM,EACJ,OAAO,GAAU,WACb,MAC+B,CAC7B,IAAM,EAAkC,CAAC,EAEzC,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,CAAK,EAC7C,EAAO,GAAO,EAAqB,CAAK,EAG1C,OAAO,CACT,EAEF,EAAO,IAAI,IAkBf,OAhBY,MAAkB,CAC5B,IAAM,EAAO,IAAI,IAEjB,IAAK,GAAM,CAAC,EAAK,KAAW,OAAO,QAAQ,EAAO,CAAC,EAC5C,IAEL,EAAK,IAAI,CAAG,EAEP,EAAK,IAAI,CAAG,GAAG,EAAK,UAAU,IAAI,CAAG,GAE5C,IAAK,IAAM,KAAO,EACX,EAAK,IAAI,CAAG,GAAG,EAAK,UAAU,OAAO,CAAG,EAE/C,EAAO,CACT,CAEO,CACT"}
package/dist/ore.cjs CHANGED
@@ -1,3 +1,3 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@vielzeug/ripple");var OreError=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},OreApiError=class extends OreError{},OreInternalError=class extends OreError{},OreLifecycleError=class extends OreError{component;phase;constructor(e,t){super(e,{cause:t.cause}),this.component=t.component,this.phase=t.phase}};function reportRuntimeError(e,t){`${e.component}${e.phase}`,e.cause,t.dispatchEvent(new CustomEvent(`ore:error`,{bubbles:!0,composed:!0,detail:e}))}var t={asyncSetupUnsupported:`setup() must return an HTMLResult or null; use reactive state for asynchronous work`,defineDuplicate:e=>`define('${e}') called twice — custom element already registered`,defineFieldRequiresFormAssociated:e=>`useField() requires define('${e}', { formAssociated: true })`,defineRequiresTag:`define() requires a tag name`,eachDuplicateKey:(e,t)=>`each() received duplicate key "${e}" at index ${t}`,eventModifiersUnsupported:e=>`@${e}: event modifiers are unsupported; call native event methods in the handler instead`,injectStrictFailed:(e,t)=>`injectStrict() could not resolve key "${e}" in <${t}>`,invariantViolated:e=>`invariant violated: ${e}`,lifecycleOutsideSetup:`Lifecycle hooks must be called during component setup`,listenNullTarget:e=>`listen() called with a null/undefined target for event "${e}" — listener not attached`,propInvalidReflect:`Structured props cannot use reflect:true — use prop.json() with reflect:false`,templateInterpolationInTag:"html`...`: interpolations inside a tag must be named attributes, boolean attributes, events, or refs",useFieldAlreadyCalled:e=>`useField() was already called on <${e}>. Call it only once per component.`,validationFailed:(e,t)=>`Validation failed for <${e}>:\n${t.join(`
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@vielzeug/ripple");var OreError=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},OreApiError=class extends OreError{},OreInternalError=class extends OreError{},OreLifecycleError=class extends OreError{component;phase;constructor(e,t){super(e,{cause:t.cause}),this.component=t.component,this.phase=t.phase}};function reportRuntimeError(e,t){`${e.component}${e.phase}`,e.cause,t.dispatchEvent(new CustomEvent(`ore:error`,{bubbles:!0,composed:!0,detail:e}))}var t={asyncSetupUnsupported:`setup() must return an HTMLResult or null; use reactive state for asynchronous work`,defineDuplicate:e=>`define('${e}') called twice: custom element already registered`,defineFieldRequiresFormAssociated:e=>`useField() requires define('${e}', { formAssociated: true })`,defineRequiresTag:`define() requires a tag name`,eachDuplicateKey:(e,t)=>`each() received duplicate key "${e}" at index ${t}`,eventModifiersUnsupported:e=>`@${e}: event modifiers are unsupported; call native event methods in the handler instead`,injectStrictFailed:(e,t)=>`injectStrict() could not resolve key "${e}" in <${t}>`,invariantViolated:e=>`invariant violated: ${e}`,lifecycleOutsideSetup:`Lifecycle hooks must be called during component setup`,listenNullTarget:e=>`listen() called with a null/undefined target for event "${e}": listener not attached`,propInvalidReflect:`Structured props cannot use reflect:true: use prop.json() with reflect:false`,templateInterpolationInTag:"html`...`: interpolations inside a tag must be named attributes, boolean attributes, events, or refs",useFieldAlreadyCalled:e=>`useField() was already called on <${e}>. Call it only once per component.`,validationFailed:(e,t)=>`Validation failed for <${e}>:\n${t.join(`
2
2
  `)}`};function invariant(e,n){if(!e)throw new OreInternalError(t.invariantViolated(n))}var resolveMaybeReactive=t=>typeof t==`function`?t():(0,e.isReactive)(t)?t.value:t,n=/[;{}]/g,sanitizeCssToken=e=>e.replace(n,``),runAll=e=>{for(let t=e.length-1;t>=0;t--)e[t]?.()},removeNodes=e=>{for(let t of e)t.remove()},createReplaceableSlot=()=>{let e=[],t=[];return{clear(){runAll(t),removeNodes(e),t=[],e=[]},get nodes(){return e},registerCleanup(e){t.push(e)},setNodes(t){e=t}}},r=new Set([`action`,`cite`,`codebase`,`data`,`formaction`,`href`,`manifest`,`ping`,`poster`,`src`,`xlink:href`]),i=/^\s*(?:(?:javascript|vbscript|blob):|data:(?:[^,]*\/(?:html|svg\+xml)|application\/(?:xhtml|xml)))/i,setAttr=(e,t,n)=>{let a=t.toLowerCase();if(/^on[a-z]/i.test(t)){`${t}${t.slice(2)}`,e.removeAttribute(t);return}if(a===`srcdoc`){e.removeAttribute(t);return}if(n==null||n===!1){e.removeAttribute(t);return}let o=n===!0?`true`:String(n);if(r.has(a)&&i.test(o)){`${t}`,e.removeAttribute(t);return}e.setAttribute(t,o)},listen=(e,n,r,i)=>{if(!e)return t.listenNullTarget(n),()=>{};let a=r;return e.addEventListener(n,a,i),()=>e.removeEventListener(n,a,i)},toKebab=e=>e.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`),isStructuredValue=e=>Array.isArray(e)||typeof e==`object`&&!!e,a=null,createRuntimeContext=e=>({element:e,formResetCallbacks:[],mountCallbacks:[]}),o=0,beginPendingWork=()=>{o++;let e=!1;return()=>{e||(e=!0,o--)}},runWithContext=(e,t)=>{let n=a;a=e;try{return t()}finally{a=n}},requireSetupContext=e=>{if(a)return a;throw new OreApiError(`${e}: ${t.lifecycleOutsideSetup}`)},getHost=()=>requireSetupContext(`getHost`).element,tryRegisterCleanup=t=>a?((0,e.effect)(()=>t),!0):!1,onCleanup=e=>{if(!tryRegisterCleanup(e))throw new OreApiError(`onCleanup: ${t.lifecycleOutsideSetup}`)},onMounted=e=>{requireSetupContext(`onMounted`).mountCallbacks.push(e)},onFormReset=e=>{requireSetupContext(`onFormReset`).formResetCallbacks.push(e)},watchEffect=t=>{let n=(0,e.effect)(t),stop=()=>n.dispose();return tryRegisterCleanup(stop),stop};function onEvent(e,t,n,r){if(requireSetupContext(`onEvent`),!e)return;let i=listen(e,t,n,r);tryRegisterCleanup(i)||i()}var onElement=(e,t)=>watchEffect(()=>{let n=e.value;if(n)return t(n)}),s=new WeakMap,buildAncestorChain=e=>{let t=[],n=e;for(;n;)n instanceof HTMLElement&&t.push(n),n=n.parentNode??(n instanceof ShadowRoot?n.host:null);return t},provideOnElement=(e,t,n)=>{let r=s.get(e)??new Map;r.has(t)&&`${e.localName}`,r.set(t,n),s.set(e,r)},provide=(e,t)=>{let n=requireSetupContext(`provide`).element;provideOnElement(n,e,t),onCleanup(()=>{let t=s.get(n);t&&(t.delete(e),t.size===0&&s.delete(n))})},c=Symbol(`inject.not_found`),l=new WeakMap,walkAndFind=(e,t)=>{let n=buildAncestorChain(e);for(let e of n){let n=s.get(e);if(n?.has(t))return n.get(t)}return c},lookup=(e,t)=>{let n=l.get(e);n||(n=new Map,l.set(e,n));let r=t;return n.has(r)||n.set(r,walkAndFind(e.element,t)),n.get(r)};function inject(e,...t){let n=lookup(requireSetupContext(`inject`),e);return n===c?t.length>0?t[0]:void 0:n}var injectStrict=e=>{let n=requireSetupContext(`injectStrict`),r=lookup(n,e);if(r!==c)return r;throw new OreApiError(t.injectStrictFailed(String(e),n.element.localName))};function createContext(e){return Symbol(e)}function _jsOnlyProp(e){return{default:e,parse:()=>e,reflect:!1}}var u={bool(e){return{default:e??!1,parse:e=>e!==null&&e!==`false`,reflect:!0}},data(e){return _jsOnlyProp(e)},json(e){return{default:e,parse:t=>{if(t==null||t===``)return e;try{return JSON.parse(t)}catch{return e}},reflect:!1}},number(e){let t=e===void 0?void 0:e;return{default:t,parse:e=>{if(e==null)return t;let n=Number(e);return Number.isNaN(n)?(`${e}${String(t)}`,t):n},reflect:!0}},oneOf(e,t){return{default:t,parse:n=>n!=null&&e.includes(n)?n:t,reflect:!0}},string(e){let t=e===void 0?void 0:e;return{default:t,parse:e=>e??t,reflect:!0}}},isPropDef=e=>typeof e==`object`&&!!e&&`default`in e&&`parse`in e;function normalizePropDefinition(e,n){if(!isPropDef(e))throw new OreApiError(`Prop "${n}" must use a prop.* helper (string/number/bool/json/oneOf). Received: ${typeof e}`);let r=e;if(!r.parse)throw new OreApiError(`Prop "${n}" must have a parse function. Use prop.* helpers.`);let i=r.reflect??!1;if(i&&isStructuredValue(r.default))throw new OreApiError(`Prop "${n}": ${t.propInvalidReflect}`);return{...r,reflect:i}}function validatePropDefs(e){let t=[];for(let[n,r]of Object.entries(e))try{normalizePropDefinition(r,n)}catch(e){t.push(e instanceof Error?e.message:String(e))}return t}var d=new WeakMap,getPropMeta=(e,t)=>d.get(e)?.get(t),coerceIncoming=(e,t)=>typeof e==`string`?t(e):e,registerProp=(t,n,r,i)=>{let a=d.get(t);a||(a=new Map,d.set(t,a));let{default:o,parse:s,reflect:c=!1}=i,l=(0,e.signal)(o),u=a.get(r),f=Object.hasOwn(t,n),p=f?t[n]:void 0,m={parse:s,reflect:c,signal:l};return u?l.value=u.signal.peek():f?(delete t[n],l.value=coerceIncoming(p,s)):t.hasAttribute(r)&&(l.value=s(t.getAttribute(r))),a.set(r,m),Object.defineProperty(t,n,{configurable:!0,enumerable:!0,get:()=>l.value,set:e=>{l.value=coerceIncoming(e,s)}}),c&&watchEffect(()=>{let e=l.value;e==null?t.removeAttribute(r):typeof e==`boolean`?t.toggleAttribute(r,e):setAttr(t,r,e)}),l};function createProps(e,t){let n={};for(let[r,i]of Object.entries(t))n[r]=registerProp(e,r,toKebab(r),i);return n}var makeBrand=e=>{let t=Symbol.for(e),stamp=e=>Object.assign(e,{[t]:!0}),is=e=>typeof e==`object`&&!!e&&t in e;return{is,stamp}},f=makeBrand(`ore:css-result`),p=f.is,cssResultToString=function(){return this.content},css=(e,...t)=>{let n=``;for(let r=0;r<e.length;r++)if(n+=e[r],r<t.length){let e=t[r];n+=p(e)?e.content:String(e)}return f.stamp({content:n.trim(),toString:cssResultToString})},m=new Map,h=256,loadStylesheet=e=>{if(e instanceof CSSStyleSheet)return e;let t=typeof e==`string`?e:e.content,n=m.get(t);if(n)return m.delete(t),m.set(t,n),n;let r=new CSSStyleSheet;try{r.replaceSync(t)}catch{return r}if(m.set(t,r),m.size>h){let e=m.keys().next().value;e!==void 0&&m.delete(e)}return r},g={SETUP_DONE:`setup_done`,SETUP_RUNNING:`setup_running`,UNINITIALIZED:`uninitialized`,UNMOUNTED:`unmounted`},createComponentState=()=>({formResetCallbacks:[],generation:0,mountCallbacks:[],phase:g.UNINITIALIZED,scope:(0,e.createScope)(),templateResult:null}),isPromiseLike=e=>(typeof e==`object`||typeof e==`function`)&&e!==null&&`then`in e&&typeof e.then==`function`,BaseElement=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=createComponentState()}connectedCallback(){(0,e.untrack)(()=>{this._component.phase===g.UNINITIALIZED&&this._runSetup(),this._init()})}attributeChangedCallback(t,n,r){if(n===r)return;let i=getPropMeta(this,t);if(!i)return;let a=i.parse(r);Object.is((0,e.untrack)(()=>i.signal.value),a)||(i.signal.value=a)}disconnectedCallback(){this._component.generation++,this._component.phase=g.UNMOUNTED,this._resetSetupState()}_resetSetupState(){this._component.scope.dispose(),this._component.formResetCallbacks=[],this._component.mountCallbacks=[],this._component.phase=g.UNINITIALIZED,this._component.scope=(0,e.createScope)(),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 n=e instanceof Error?e:Error(String(e));reportRuntimeError(new OreLifecycleError(`<${this.localName}> failed during ${this._component.phase} (${t})`,{cause:n,component:this.localName,phase:t}),this)}_runSetup(){this._component.phase=g.SETUP_RUNNING;let e=this.constructor._definition,n=this.constructor._normalizedPropDefs,r=createRuntimeContext(this);try{let i;if(this._component.scope.run(()=>{i=runWithContext(r,()=>{let t=n?createProps(this,n):{};return e.setup(t)})}),this._component.mountCallbacks.push(...r.mountCallbacks),this._component.formResetCallbacks.push(...r.formResetCallbacks),isPromiseLike(i))throw new OreApiError(t.asyncSetupUnsupported);this._component.templateResult=i??null,this._component.phase=g.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=createRuntimeContext(this);t.replaceChildren(),this._component.scope.run(()=>{runWithContext(n,()=>{e.mount(t,null,onCleanup)})})}_init(){this._applyStyles(),this._mountTemplate(),this._component.phase===g.SETUP_DONE&&this._scheduleMountCallbacks()}_applyStyles(){let e=this.constructor._definition;this.shadowRoot&&e?.styles?.length&&(this.shadowRoot.adoptedStyleSheets=e.styles.map(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=beginPendingWork();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=createRuntimeContext(this);this._component.scope.run(()=>{runWithContext(e,()=>{let e=n();typeof e==`function`&&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()}})}};function createComponentClass(e,n){let{props:r}=n,i=(()=>{if(!r)return;let n=validatePropDefs(r);if(n.length>0)throw new OreApiError(t.validationFailed(e,n));let i={};for(let[e,t]of Object.entries(r))i[e]=normalizePropDefinition(t,e);return i})(),a=i?Object.keys(i).map(toKebab):[],ComponentClass=class extends BaseElement{static _definition=n;static _normalizedPropDefs=i;static formAssociated=n.formAssociated??!1;static observedAttributes=a};return ComponentClass}function define(e,n){if(!e)throw new OreApiError(t.defineRequiresTag);if(customElements.get(e))throw new OreApiError(t.defineDuplicate(e));let r=createComponentClass(e,n);return Object.defineProperty(r,"name",{value:e}),customElements.define(e,r),r}var classMap=t=>(0,e.computed)(()=>Object.entries(t).filter(([,e])=>resolveMaybeReactive(e)).map(([e])=>e.replace(/\s+/g,``)).filter(Boolean).join(` `));function ref(){return(0,e.signal)(null)}var _=makeBrand(`ore:directive`),createDirectiveResult=e=>_.stamp({mount:e}),v=_.is,y=makeBrand(`ore:html-result`),b=y.is;function createHtmlResult(e,t){let mount=(n,r,i)=>{let a=Array.from(e.childNodes);return n.insertBefore(e,r),t(i),a};return y.stamp({apply:t,fragment:e,mount})}var createItem=(t,n,r,i,a)=>{let o=(0,e.signal)(t),s=(0,e.signal)(n),c=(0,e.createScope)(),l=[],u=[];return c.run(()=>{u=r(o,s).mount(i,a,e=>l.push(e))}),{cleanups:l,data:o,index:s,nodes:u,scope:c}},removeItem=e=>{e.scope.dispose(),runAll(e.cleanups),removeNodes(e.nodes)},reconcileItems=(t,n,r,i,a,o)=>{let s=new Set(r);for(let[e,n]of t)s.has(e)||(removeItem(n),t.delete(e));let c=[];for(let s=0;s<n.length;s++){let l=r[s],u=t.get(l);if(u)(0,e.batch)(()=>{u.data.value=n[s],u.index.value=s}),c.push(u);else{let r=(0,e.untrack)(()=>createItem(n[s],s,i,a,o));t.set(l,r),c.push(r)}}let l=o;for(let e=c.length-1;e>=0;e--){let t=c[e],n=t.nodes[0],r=t.nodes[t.nodes.length-1];if(n&&r!==l.previousSibling)for(let e of t.nodes)a.insertBefore(e,l);l=n??l}return c},collectKeys=(e,n)=>{let r=[],i=new Set;for(let a=0;a<e.length;a++){let o=n(e[a],a);if(i.has(o))throw new OreApiError(t.eachDuplicateKey(String(o),a));i.add(o),r.push(o)}return r},reportEachError=(e,t)=>{let n=e instanceof Error?e:Error(String(e));reportRuntimeError(new OreLifecycleError(`each() failed to reconcile a list update: ${n.message}`,{cause:n,component:`each()`,phase:`each-reconcile`}),t)};function each(t,n,r,i){let a=Array.isArray(t)?(0,e.signal)(t):typeof t==`function`?(0,e.computed)(t):t;return createDirectiveResult((t,o)=>{let s=t.parentNode;invariant(s,`each() anchor comment has no parent node`);let c=document.createComment(`each/end`);s.insertBefore(c,t.nextSibling);let l=new Map,u=[],d=null,f=[],mountFallback=()=>{i&&(d=i().mount(s,c,e=>f.push(e)))},clearFallback=()=>{d&&(runAll(f),removeNodes(d),d=null,f=[])},p=(0,e.effect)(()=>{let i=a.value??[];if(i.length===0){for(let t of(0,e.untrack)(()=>u))removeItem(t);l=new Map,u=[],d||(0,e.untrack)(mountFallback);return}let o;try{o=(0,e.untrack)(()=>collectKeys(i,n))}catch(e){reportEachError(e,t);return}clearFallback();try{u=(0,e.untrack)(()=>reconcileItems(l,i,o,r,s,c))}catch(e){reportEachError(e,t);for(let e of l.values())removeItem(e);l=new Map,u=[]}});o(()=>p.dispose()),o(()=>{clearFallback();for(let e of u)removeItem(e);c.remove()})})}var x=makeBrand(`ore:live`),live=e=>x.stamp({source:e}),S=x.is,toStyleValue=e=>{let t=resolveMaybeReactive(e);return t==null||t===!1?``:sanitizeCssToken(String(t))},styleMap=t=>(0,e.computed)(()=>{let e=[];for(let[n,r]of Object.entries(t)){let t=toStyleValue(r);if(!t)continue;let i=sanitizeCssToken(toKebab(n));i&&e.push(`${i}:${t}`)}return e.join(`;`)}),parseHtml=(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 unsafeHtml(t){let n=typeof t==`function`?(0,e.computed)(t):(0,e.isReactive)(t)?t:null;return createDirectiveResult((r,i)=>{let a=r.parentNode;invariant(a,`unsafeHtml() anchor comment has no parent node`);let o=document.createComment(`unsafe-html/end`);if(a.insertBefore(o,r.nextSibling),n){let t=createReplaceableSlot(),r=(0,e.effect)(()=>{t.clear(),t.setNodes(parseHtml(n.value,a,o))});i(()=>r.dispose()),i(()=>{t.clear(),o.remove()})}else parseHtml(t,a,o),i(()=>o.remove())})}var C=`when() anchor comment has no parent node`;function when(t,n,r){return typeof t!=`function`&&!(0,e.isReactive)(t)?createDirectiveResult((e,i)=>{let a=t?n():r?r():null;if(!a||!b(a))return;let o=e.parentNode;invariant(o,C);let s=a.mount(o,e,i);i(()=>removeNodes(s))}):createDirectiveResult((i,a)=>{let o=(typeof t==`function`?(0,e.computed)(t):null)??t,s=i.parentNode;invariant(s,C);let c=document.createComment(`when/end`);s.insertBefore(c,i.nextSibling);let l=createReplaceableSlot(),u=(0,e.effect)(()=>{let t=o.value;l.clear();let i=t?n():r?r():null;i&&b(i)&&l.setNodes((0,e.untrack)(()=>i.mount(s,c,l.registerCleanup)))});a(()=>u.dispose()),a(()=>{l.clear(),c.remove()})})}var w=new WeakMap,T=new WeakSet,useField=e=>{let n=getHost();if(!n.constructor.formAssociated)throw new OreApiError(t.defineFieldRequiresFormAssociated(n.localName));if(T.has(n))throw new OreApiError(t.useFieldAlreadyCalled(n.localName));let r=w.get(n)??n.attachInternals();w.set(n,r),T.add(n),onCleanup(()=>T.delete(n));let i=e.toFormValue??(t=>t==null?e.emptyStringForNull?``:null:t instanceof File||t instanceof FormData?t:String(t));watchEffect(()=>{r.setFormValue(i(e.value.value))});let a=e.disabled;if(a&&`states`in r){let e=r.states;watchEffect(()=>{a.value?e.add(`disabled`):e.delete(`disabled`)})}e.validity&&watchEffect(()=>{let t=e.validity?.value??{},n=Object.values(t).some(Boolean),i=e.validationMessage?.value??``;if(n&&!i){r.setValidity(t,`Invalid value.`);return}r.setValidity(t,i)}),e.onReset&&onFormReset(e.onReset);let checkValidity=()=>r.checkValidity(),reportValidity=()=>r.reportValidity(),setCustomValidity=e=>e?r.setValidity({customError:!0},e):r.setValidity({});return{checkValidity,internals:r,reportValidity,setCustomValidity}},normalizeHostAttrKey=e=>e===`role`||e.startsWith(`aria-`)?e:e.startsWith(`aria`)?`aria-${e.slice(4).toLowerCase()}`:e,bind=(e,t)=>{let n=t?.target??getHost(),r=[];if(e.attr)for(let[t,i]of Object.entries(e.attr)){let e=applyAttribute(n,E(t),i);e&&r.push(e)}if(e.class&&r.push(applyClassMap(n,e.class)),e.style)for(let[t,i]of Object.entries(e.style)){let e=applyStyle(n,t,i);e&&r.push(e)}if(e.on){let{target:i,...a}=t??{};for(let t of Object.keys(e.on)){let i=e.on[t];i&&r.push(listen(n,t,i,a))}}let cleanup=()=>{for(let e of r)e()};return tryRegisterCleanup(cleanup),cleanup},E=normalizeHostAttrKey,applyReactiveBinding=(t,n)=>{if(typeof t==`function`)return watchEffect(()=>{n(t())});if((0,e.isReactive)(t))return watchEffect(()=>{n(t.value)});n(t)};function applyAttribute(e,t,n){return applyReactiveBinding(n,n=>setAttr(e,t,n))}function applyStyle(e,t,n){let r=sanitizeCssToken(t.startsWith(`--`)?t:toKebab(t));if(!r)return;let i=!1,setStyle=t=>{t!=null&&t!==``?(i=!0,e.style.setProperty(r,sanitizeCssToken(String(t)))):i&&e.style.removeProperty(r)};return applyReactiveBinding(n,setStyle)}function applyClassMap(e,t){let n=typeof t==`function`?t:()=>{let e={};for(let[n,r]of Object.entries(t))e[n]=resolveMaybeReactive(r);return e},r=new Set;return watchEffect(()=>{let t=new Set;for(let[i,a]of Object.entries(n()))a&&(t.add(i),r.has(i)||e.classList.add(i));for(let n of r)t.has(n)||e.classList.remove(n);r=t})}var D=`default`,normalizeSlotName=e=>e||D,createSlots=t=>{let n=new Map,r=new Map,i=new Map,ensureSlotEntry=t=>{let r=n.get(t);return r||(r={elements:(0,e.signal)([]),presence:(0,e.signal)(!1)},n.set(t,r)),r},areElementsEqual=(e,t)=>{if(e.length!==t.length)return!1;for(let n=0;n<e.length;n++)if(e[n]!==t[n])return!1;return!0},recomputeSlot=e=>{let t=normalizeSlotName(e),n=r.get(t),i=[];if(n)for(let e of n)i.push(...e.assignedElements({flatten:!0}));let a=ensureSlotEntry(t);areElementsEqual(a.elements.value,i)||(a.elements.value=i);let o=i.length>0;a.presence.value!==o&&(a.presence.value=o)},bindSlot=e=>{if(i.has(e))return;let t=normalizeSlotName(e.getAttribute(`name`)),n=r.get(t)??new Set;n.add(e),r.set(t,n);let onChange=()=>recomputeSlot(t);e.addEventListener(`slotchange`,onChange),i.set(e,()=>{e.removeEventListener(`slotchange`,onChange)}),recomputeSlot(t)},unbindSlot=e=>{let t=i.get(e);if(!t)return;t(),i.delete(e);let n=normalizeSlotName(e.getAttribute(`name`)),a=r.get(n);a&&(a.delete(e),a.size===0&&r.delete(n)),recomputeSlot(n)},bindAllSlots=()=>{t.shadowRoot?.querySelectorAll(`slot`).forEach(e=>{bindSlot(e)})},recomputeAllSlots=()=>{for(let e of r.keys())recomputeSlot(e)},a=null,initSlots=()=>{bindAllSlots(),recomputeAllSlots(),!a&&t.shadowRoot&&(a=new MutationObserver(e=>{for(let t of e)for(let e of t.removedNodes)e instanceof HTMLSlotElement&&unbindSlot(e);bindAllSlots(),i.size>0&&recomputeAllSlots()}),a.observe(t.shadowRoot,{childList:!0,subtree:!0}))};return onMounted(initSlots),onCleanup(()=>{a?.disconnect(),a=null;for(let e of i.values())e();i.clear(),r.clear(),n.clear(),O.delete(t)}),{elements:e=>ensureSlotEntry(normalizeSlotName(e)).elements,has:e=>ensureSlotEntry(normalizeSlotName(e)).presence}},O=new WeakMap,useSlots=()=>{let e=requireSetupContext(`useSlots`),t=O.get(e.element);return t||(t=createSlots(e.element),O.set(e.element,t)),t},signalEffect=(t,n,r)=>{let i=(0,e.effect)(()=>{n(t.value)});r(()=>i.dispose())},isNativeFormInput=e=>e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement,isCheckableInput=e=>e instanceof HTMLInputElement&&(e.type===`checkbox`||e.type===`radio`),syncFormControl=(e,t,n,r={last:void 0})=>{let i=isCheckableInput(e),a=i?!!t:t==null?``:String(t),o=i?e.checked:e.value;(!n||r.last===void 0||Object.is(o,r.last)||Object.is(o,a))&&(i?e.checked=a:e.value=a,n&&(r.last=a))},syncRegisteredProp=(t,n,r,i)=>{let a=isStructuredValue(i)?i:n.parse(r.mode===`bool`?i?``:null:i==null||i===!1?null:String(i));if(Object.is((0,e.untrack)(()=>n.signal.value),a)||(n.signal.value=a),!n.reflect){if(isStructuredValue(i))return;r.mode===`bool`?t.toggleAttribute(r.name,!!i):setAttr(t,r.name,i)}},applyAttrBinding=(t,n)=>{let{el:r,mode:i,name:a,propMeta:o}=t,s={last:void 0},update=n=>{if(o){syncRegisteredProp(r,o,t,n);return}if(!(0,e.isReactive)(n)&&isStructuredValue(n)){a!==`__proto__`&&a!==`constructor`&&a!==`prototype`&&(r[a]=n);return}if(a===`value`&&isNativeFormInput(r)||a===`checked`&&r instanceof HTMLInputElement){syncFormControl(r,n,t.live,s);return}i===`bool`?r.toggleAttribute(a,!!n):setAttr(r,a,n)};`signal`in t?signalEffect(t.signal,update,n):update(t.value)},applyEventBinding=(e,t)=>{t(listen(e.el,e.name,e.handler))},applyRefBinding=(e,t)=>{let{el:n,ref:r}=e;if(typeof r==`function`){r(n),t(()=>r(null));return}r.value=n,t(()=>{r.value=null})},insertHtmlValues=(e,t,n)=>{let r=[],i=t.parentNode;invariant(i,`html binding anchor has no parent node`);for(let a of e)if(b(a)){let e=Array.from(a.fragment.childNodes);i.insertBefore(a.fragment,t),a.apply(n),r.push(...e)}else if(a!=null&&a!==!1){let e=document.createTextNode(String(a));i.insertBefore(e,t),r.push(e)}return r},applyHtmlBinding=(t,n)=>{let{anchor:r,signal:i}=t,a=createReplaceableSlot(),o=(0,e.effect)(()=>{let t=i.value;a.clear(),t!=null&&t.length!==0&&(0,e.untrack)(()=>{a.setNodes(insertHtmlValues(t,r,a.registerCleanup))})});n(()=>{o.dispose(),a.clear()})},applyDirectiveBinding=(e,t)=>{e.directive.mount(e.anchor,t)},applyBinding=(e,t)=>{switch(e.type){case`attr`:applyAttrBinding(e,t);break;case`directive`:applyDirectiveBinding(e,t);break;case`event`:applyEventBinding(e,t);break;case`html`:applyHtmlBinding(e,t);break;case`ref`:applyRefBinding(e,t)}},createAttrBindingFromValue=(t,n,r,i)=>{let a=getPropMeta(t,r);return S(i)?{el:t,live:!0,mode:n,name:r,propMeta:a,signal:i.source,type:`attr`}:typeof i==`function`?{el:t,mode:n,name:r,propMeta:a,signal:(0,e.computed)(i),type:`attr`}:(0,e.isReactive)(i)?{el:t,mode:n,name:r,propMeta:a,signal:i,type:`attr`}:{el:t,mode:n,name:r,propMeta:a,type:`attr`,value:i}},resolveStaticText=e=>e==null?``:String(e),k={ATTR:`attr`,BOOL_ATTR:`boolAttr`,EVENT:`event`,NODE:`node`,REF:`ref`},A=/\s+@([a-zA-Z_][-a-zA-Z0-9_.-]*)\s*=\s*["']?$/,j=/\s+ref\s*=\s*["']?$/,M=/\s+\?([a-zA-Z_][-a-zA-Z0-9_]*)\s*=\s*["']?$/,N=/\s+([a-zA-Z_][-a-zA-Z0-9_]*)\s*=\s*["']?$/,detectSlot=e=>{let n;if(n=A.exec(e)){let r=e.slice(0,-n[0].length),[i,...a]=n[1].split(`.`);if(a.length>0)throw new OreApiError(t.eventModifiersUnsupported(n[1]));return{kind:k.EVENT,name:i,prefix:r}}if(n=j.exec(e))return{kind:k.REF,prefix:e.slice(0,-n[0].length)};if(n=M.exec(e))return{kind:k.BOOL_ATTR,name:n[1],prefix:e.slice(0,-n[0].length)};if(n=N.exec(e))return{kind:k.ATTR,name:n[1],prefix:e.slice(0,-n[0].length)};let r=e.lastIndexOf(`<`);if(r>e.lastIndexOf(`>`)&&e[r+1]!==`/`)throw new OreApiError(t.templateInterpolationInTag);return{kind:k.NODE,prefix:e}},P=new WeakMap,F=/[@?]?[a-zA-Z_][-a-zA-Z0-9_.]*\s*=\s*$/,normalizeTemplateStrings=e=>{let t=Array.from(e),n=!1;for(let e=0;e<t.length-1;e++){let r=t[e],i=r[r.length-1];for(let e of r)e===`<`?n=!0:e===`>`&&(n=!1);if((i===`"`||i===`'`)&&n&&F.test(r.slice(0,-1))){t[e]=r.slice(0,-1);let n=t[e+1];n.startsWith(i)&&(t[e+1]=n.slice(1))}}return t},I=`data-ore-b`,L=/^ore:(\d+)$/,walkNode=(e,t,n,r)=>{if(e.nodeType===Node.ELEMENT_NODE){let r=e,i=r.getAttribute(I);i!==null&&(n.set(Number(i),[...t]),r.removeAttribute(I))}else if(e.nodeType===Node.COMMENT_NODE){let n=e.nodeValue,i=n===null?null:L.exec(n);i&&r.set(Number(i[1]),[...t])}let i=e.childNodes;for(let e=0;e<i.length;e++)walkNode(i[e],[...t,e],n,r)},buildStaticTemplate=e=>{let t=normalizeTemplateStrings(e),n=``,r,i=0,a=0,o=[];for(let e=0;e<t.length-1;e++){let s=t[e],c=detectSlot(s);if(c.kind===k.NODE)n+=`${c.prefix}<!--ore:${a}-->`,o.push({commentId:a,kind:k.NODE}),a++,r=void 0;else{r===void 0||c.prefix.lastIndexOf(`<`)>c.prefix.lastIndexOf(`>`)?(r=i++,n+=`${c.prefix} ${I}="${r}"`):n+=c.prefix;let e=c.kind===k.BOOL_ATTR?`bool`:c.kind===k.ATTR?`attr`:void 0;o.push({elementId:r,kind:c.kind,mode:e,name:c.name})}}n+=t[t.length-1]??``;let s=document.createElement(`template`);s.innerHTML=n;let c=new Map,l=new Map,u=s.content.childNodes;for(let e=0;e<u.length;e++)walkNode(u[e],[e],c,l);return{commentPaths:l,element:s,elementPaths:c,slots:o}},getStaticTemplate=e=>{let t=P.get(e);return t||(t=buildStaticTemplate(e),P.set(e,t)),t},followPath=(e,t)=>{let n=e;for(let e of t)n=n.childNodes[e];return n},R="html`...`: node-slot comment anchor has no parent node",toHtmlValues=e=>Array.isArray(e)?e:[e],embedStaticResult=(e,t,n)=>{let r=t.parentNode;for(invariant(r,R);e.fragment.firstChild;)r.insertBefore(e.fragment.firstChild,t);n.push(e.apply.bind(e))},compileTemplate=(t,n)=>{let r=getStaticTemplate(t),i=r.element.content.cloneNode(!0),a=[],o=[],s=r.slots.map((e,t)=>{let a=n[t];if(e.kind===k.NODE){let t=e.commentId===void 0?void 0:r.commentPaths.get(e.commentId);return invariant(t,`compiled template is missing a comment path for node slot ${e.commentId}`),{comment:followPath(i,t),slot:e,value:a}}let o=e.elementId===void 0?void 0:r.elementPaths.get(e.elementId);return invariant(o,`compiled template is missing an element path for slot ${e.elementId}`),{el:followPath(i,o),slot:e,value:a}});for(let{comment:t,el:n,slot:r,value:i}of s){if(r.kind===k.NODE){let n=t;if(invariant(n,`compiled template produced a node slot without a comment anchor`),v(i)){a.push({anchor:n,directive:i,type:`directive`});continue}if(b(i)){embedStaticResult(i,n,o),n.remove();continue}if(typeof i==`function`||(0,e.isReactive)(i)){let t=typeof i==`function`?(0,e.computed)(()=>toHtmlValues(i())):(0,e.computed)(()=>toHtmlValues(i.value));a.push({anchor:n,signal:t,type:`html`});continue}if(Array.isArray(i)){for(let e of i)if(b(e))embedStaticResult(e,n,o);else{let t=n.parentNode;invariant(t,R),t.insertBefore(document.createTextNode(resolveStaticText(e)),n)}n.remove();continue}n.replaceWith(document.createTextNode(resolveStaticText(i)));continue}if(invariant(n,`compiled template produced an element slot without an element`),r.kind===k.EVENT){let t=r.name;if(invariant(t,`compiled template produced an event slot without an event name`),typeof i==`function`)a.push({el:n,handler:i,name:t,type:`event`});else if((0,e.isReactive)(i)){let e=i,handler=t=>{let n=e.value;typeof n==`function`&&n(t)};a.push({el:n,handler,name:t,type:`event`})}continue}if(r.kind===k.REF){i&&a.push({el:n,ref:i,type:`ref`});continue}invariant(r.name,`compiled template produced an attr slot without an attribute name`),a.push(createAttrBindingFromValue(n,r.mode??`attr`,r.name,i))}return createHtmlResult(i,e=>{for(let t of a)applyBinding(t,e);for(let t of o)t(e)})},html=(e,...t)=>compileTemplate(e,t),z={bubbles:!0,cancelable:!0,composed:!0},useEmit=()=>{let e=getHost();return((t,...n)=>{let r=n.length>0?{...z,detail:n[0]}:z;return e.dispatchEvent(new CustomEvent(String(t),r))})},B=0,V=Math.random().toString(36).slice(2,6),createId=(e=`id`)=>`${e}-${V}${++B}`;exports.OreApiError=OreApiError,exports.OreError=OreError,exports.OreInternalError=OreInternalError,exports.OreLifecycleError=OreLifecycleError,exports.bind=bind,exports.classMap=classMap,exports.createContext=createContext,exports.createId=createId,exports.css=css,exports.define=define,exports.each=each,exports.getHost=getHost,exports.html=html,exports.inject=inject,exports.injectStrict=injectStrict,exports.live=live,exports.onCleanup=onCleanup,exports.onElement=onElement,exports.onEvent=onEvent,exports.onFormReset=onFormReset,exports.onMounted=onMounted,exports.prop=u,exports.provide=provide,exports.ref=ref,exports.styleMap=styleMap,exports.unsafeHtml=unsafeHtml,exports.useEmit=useEmit,exports.useField=useField,exports.useSlots=useSlots,exports.watchEffect=watchEffect,exports.when=when;
3
3
  //# sourceMappingURL=ore.cjs.map