@vielzeug/craftit 2.1.0 → 3.0.3

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 (325) hide show
  1. package/README.md +58 -124
  2. package/dist/controls/a11y-control.cjs +1 -1
  3. package/dist/controls/a11y-control.cjs.map +1 -1
  4. package/dist/controls/a11y-control.d.ts +1 -1
  5. package/dist/controls/a11y-control.d.ts.map +1 -1
  6. package/dist/controls/a11y-control.js +1 -1
  7. package/dist/controls/a11y-control.js.map +1 -1
  8. package/dist/controls/checkable-control.cjs +1 -1
  9. package/dist/controls/checkable-control.cjs.map +1 -1
  10. package/dist/controls/checkable-control.d.ts +7 -7
  11. package/dist/controls/checkable-control.d.ts.map +1 -1
  12. package/dist/controls/checkable-control.js +1 -1
  13. package/dist/controls/checkable-control.js.map +1 -1
  14. package/dist/controls/choice-field-control.cjs +2 -0
  15. package/dist/controls/choice-field-control.cjs.map +1 -0
  16. package/dist/controls/choice-field-control.d.ts +3 -0
  17. package/dist/controls/choice-field-control.d.ts.map +1 -0
  18. package/dist/controls/choice-field-control.js +2 -0
  19. package/dist/controls/choice-field-control.js.map +1 -0
  20. package/dist/controls/field-control.cjs +1 -1
  21. package/dist/controls/field-control.cjs.map +1 -1
  22. package/dist/controls/field-control.d.ts +28 -73
  23. package/dist/controls/field-control.d.ts.map +1 -1
  24. package/dist/controls/field-control.js +1 -1
  25. package/dist/controls/field-control.js.map +1 -1
  26. package/dist/controls/index.d.ts +11 -9
  27. package/dist/controls/index.d.ts.map +1 -1
  28. package/dist/controls/internal/control-state.cjs +1 -1
  29. package/dist/controls/internal/control-state.cjs.map +1 -1
  30. package/dist/controls/internal/control-state.d.ts +6 -4
  31. package/dist/controls/internal/control-state.d.ts.map +1 -1
  32. package/dist/controls/internal/control-state.js +1 -1
  33. package/dist/controls/internal/control-state.js.map +1 -1
  34. package/dist/controls/internal/keyboard-utils.cjs.map +1 -1
  35. package/dist/controls/internal/keyboard-utils.js.map +1 -1
  36. package/dist/controls/internal/number-utils.cjs.map +1 -1
  37. package/dist/controls/internal/number-utils.js.map +1 -1
  38. package/dist/controls/internal/validation-utils.cjs.map +1 -1
  39. package/dist/controls/internal/validation-utils.js.map +1 -1
  40. package/dist/controls/list-control.cjs +1 -1
  41. package/dist/controls/list-control.cjs.map +1 -1
  42. package/dist/controls/list-control.d.ts +10 -8
  43. package/dist/controls/list-control.d.ts.map +1 -1
  44. package/dist/controls/list-control.js +1 -1
  45. package/dist/controls/list-control.js.map +1 -1
  46. package/dist/controls/overlay-control.cjs +1 -1
  47. package/dist/controls/overlay-control.cjs.map +1 -1
  48. package/dist/controls/overlay-control.d.ts +17 -14
  49. package/dist/controls/overlay-control.d.ts.map +1 -1
  50. package/dist/controls/overlay-control.js +1 -1
  51. package/dist/controls/overlay-control.js.map +1 -1
  52. package/dist/controls/popup-list-control.cjs +2 -0
  53. package/dist/controls/popup-list-control.cjs.map +1 -0
  54. package/dist/controls/popup-list-control.d.ts +160 -0
  55. package/dist/controls/popup-list-control.d.ts.map +1 -0
  56. package/dist/controls/popup-list-control.js +2 -0
  57. package/dist/controls/popup-list-control.js.map +1 -0
  58. package/dist/controls/press-control.cjs.map +1 -1
  59. package/dist/controls/press-control.js.map +1 -1
  60. package/dist/controls/slider-control.cjs.map +1 -1
  61. package/dist/controls/slider-control.js.map +1 -1
  62. package/dist/controls/spinner-control.cjs.map +1 -1
  63. package/dist/controls/spinner-control.js.map +1 -1
  64. package/dist/controls/swipe-control.cjs +2 -0
  65. package/dist/controls/swipe-control.cjs.map +1 -0
  66. package/dist/controls/swipe-control.d.ts +32 -0
  67. package/dist/controls/swipe-control.d.ts.map +1 -0
  68. package/dist/controls/swipe-control.js +2 -0
  69. package/dist/controls/swipe-control.js.map +1 -0
  70. package/dist/controls/text-field-control.cjs +2 -0
  71. package/dist/controls/text-field-control.cjs.map +1 -0
  72. package/dist/controls/text-field-control.d.ts +3 -0
  73. package/dist/controls/text-field-control.d.ts.map +1 -0
  74. package/dist/controls/text-field-control.js +2 -0
  75. package/dist/controls/text-field-control.js.map +1 -0
  76. package/dist/controls.cjs +1 -1
  77. package/dist/controls.js +1 -1
  78. package/dist/craftit.cjs +1 -1
  79. package/dist/craftit.cjs.map +1 -1
  80. package/dist/craftit.js +1 -1
  81. package/dist/craftit.js.map +1 -1
  82. package/dist/directives/classMap.cjs +2 -0
  83. package/dist/directives/classMap.cjs.map +1 -0
  84. package/dist/directives/classMap.d.ts +19 -0
  85. package/dist/directives/classMap.d.ts.map +1 -0
  86. package/dist/directives/classMap.js +2 -0
  87. package/dist/directives/classMap.js.map +1 -0
  88. package/dist/directives/each.cjs +1 -1
  89. package/dist/directives/each.cjs.map +1 -1
  90. package/dist/directives/each.d.ts +5 -30
  91. package/dist/directives/each.d.ts.map +1 -1
  92. package/dist/directives/each.js +1 -1
  93. package/dist/directives/each.js.map +1 -1
  94. package/dist/directives/guard.cjs +2 -0
  95. package/dist/directives/guard.cjs.map +1 -0
  96. package/dist/directives/guard.d.ts +10 -0
  97. package/dist/directives/guard.d.ts.map +1 -0
  98. package/dist/directives/guard.js +2 -0
  99. package/dist/directives/guard.js.map +1 -0
  100. package/dist/directives/live.cjs +2 -0
  101. package/dist/directives/live.cjs.map +1 -0
  102. package/dist/directives/live.d.ts +23 -0
  103. package/dist/directives/live.d.ts.map +1 -0
  104. package/dist/directives/live.js +2 -0
  105. package/dist/directives/live.js.map +1 -0
  106. package/dist/directives/raw.cjs +1 -1
  107. package/dist/directives/raw.cjs.map +1 -1
  108. package/dist/directives/raw.d.ts +3 -5
  109. package/dist/directives/raw.d.ts.map +1 -1
  110. package/dist/directives/raw.js +1 -1
  111. package/dist/directives/raw.js.map +1 -1
  112. package/dist/directives/resource.cjs +2 -0
  113. package/dist/directives/resource.cjs.map +1 -0
  114. package/dist/directives/resource.d.ts +32 -0
  115. package/dist/directives/resource.d.ts.map +1 -0
  116. package/dist/directives/resource.js +2 -0
  117. package/dist/directives/resource.js.map +1 -0
  118. package/dist/directives/styleMap.cjs +2 -0
  119. package/dist/directives/styleMap.cjs.map +1 -0
  120. package/dist/directives/styleMap.d.ts +11 -0
  121. package/dist/directives/styleMap.d.ts.map +1 -0
  122. package/dist/directives/styleMap.js +2 -0
  123. package/dist/directives/styleMap.js.map +1 -0
  124. package/dist/directives/when.cjs +1 -1
  125. package/dist/directives/when.cjs.map +1 -1
  126. package/dist/directives/when.d.ts +6 -19
  127. package/dist/directives/when.d.ts.map +1 -1
  128. package/dist/directives/when.js +1 -1
  129. package/dist/directives/when.js.map +1 -1
  130. package/dist/errors.cjs +2 -0
  131. package/dist/errors.cjs.map +1 -0
  132. package/dist/errors.d.ts +12 -0
  133. package/dist/errors.d.ts.map +1 -0
  134. package/dist/errors.js +2 -0
  135. package/dist/errors.js.map +1 -0
  136. package/dist/form.cjs +1 -1
  137. package/dist/form.cjs.map +1 -1
  138. package/dist/form.d.ts +3 -17
  139. package/dist/form.d.ts.map +1 -1
  140. package/dist/form.js +1 -1
  141. package/dist/form.js.map +1 -1
  142. package/dist/host.cjs +1 -1
  143. package/dist/host.cjs.map +1 -1
  144. package/dist/host.d.ts +40 -37
  145. package/dist/host.d.ts.map +1 -1
  146. package/dist/host.js +1 -1
  147. package/dist/host.js.map +1 -1
  148. package/dist/index.cjs +1 -1
  149. package/dist/index.d.ts +16 -8
  150. package/dist/index.d.ts.map +1 -1
  151. package/dist/index.js +1 -1
  152. package/dist/internal.cjs +1 -1
  153. package/dist/internal.cjs.map +1 -1
  154. package/dist/internal.d.ts +60 -120
  155. package/dist/internal.d.ts.map +1 -1
  156. package/dist/internal.js +1 -1
  157. package/dist/internal.js.map +1 -1
  158. package/dist/observers/index.d.ts +1 -0
  159. package/dist/observers/index.d.ts.map +1 -1
  160. package/dist/observers/intersection-observe.cjs +1 -1
  161. package/dist/observers/intersection-observe.cjs.map +1 -1
  162. package/dist/observers/intersection-observe.d.ts +1 -1
  163. package/dist/observers/intersection-observe.js +1 -1
  164. package/dist/observers/intersection-observe.js.map +1 -1
  165. package/dist/observers/media-observe.cjs +1 -1
  166. package/dist/observers/media-observe.cjs.map +1 -1
  167. package/dist/observers/media-observe.d.ts +1 -1
  168. package/dist/observers/media-observe.js +1 -1
  169. package/dist/observers/media-observe.js.map +1 -1
  170. package/dist/observers/mutation-observe.cjs +2 -0
  171. package/dist/observers/mutation-observe.cjs.map +1 -0
  172. package/dist/observers/mutation-observe.d.ts +10 -0
  173. package/dist/observers/mutation-observe.d.ts.map +1 -0
  174. package/dist/observers/mutation-observe.js +2 -0
  175. package/dist/observers/mutation-observe.js.map +1 -0
  176. package/dist/observers/resize-observe.cjs +1 -1
  177. package/dist/observers/resize-observe.cjs.map +1 -1
  178. package/dist/observers/resize-observe.d.ts +1 -1
  179. package/dist/observers/resize-observe.js +1 -1
  180. package/dist/observers/resize-observe.js.map +1 -1
  181. package/dist/observers.cjs +1 -1
  182. package/dist/observers.js +1 -1
  183. package/dist/props.cjs +1 -1
  184. package/dist/props.cjs.map +1 -1
  185. package/dist/props.d.ts +18 -31
  186. package/dist/props.d.ts.map +1 -1
  187. package/dist/props.js +1 -1
  188. package/dist/props.js.map +1 -1
  189. package/dist/registration.cjs +1 -1
  190. package/dist/registration.cjs.map +1 -1
  191. package/dist/registration.d.ts +27 -7
  192. package/dist/registration.d.ts.map +1 -1
  193. package/dist/registration.js +1 -1
  194. package/dist/registration.js.map +1 -1
  195. package/dist/runtime.cjs +1 -1
  196. package/dist/runtime.cjs.map +1 -1
  197. package/dist/runtime.d.ts +29 -17
  198. package/dist/runtime.d.ts.map +1 -1
  199. package/dist/runtime.js +1 -1
  200. package/dist/runtime.js.map +1 -1
  201. package/dist/template-bindings.cjs +1 -1
  202. package/dist/template-bindings.cjs.map +1 -1
  203. package/dist/template-bindings.d.ts +10 -47
  204. package/dist/template-bindings.d.ts.map +1 -1
  205. package/dist/template-bindings.js +1 -1
  206. package/dist/template-bindings.js.map +1 -1
  207. package/dist/template-compiler.cjs +1 -1
  208. package/dist/template-compiler.cjs.map +1 -1
  209. package/dist/template-compiler.d.ts +1 -21
  210. package/dist/template-compiler.d.ts.map +1 -1
  211. package/dist/template-compiler.js +1 -1
  212. package/dist/template-compiler.js.map +1 -1
  213. package/dist/testing/testing.cjs +1 -1
  214. package/dist/testing/testing.cjs.map +1 -1
  215. package/dist/testing/testing.d.ts +12 -5
  216. package/dist/testing/testing.d.ts.map +1 -1
  217. package/dist/testing/testing.js +1 -1
  218. package/dist/testing/testing.js.map +1 -1
  219. package/package.json +6 -12
  220. package/dist/component.cjs +0 -2
  221. package/dist/component.cjs.map +0 -1
  222. package/dist/component.d.ts +0 -39
  223. package/dist/component.d.ts.map +0 -1
  224. package/dist/component.js +0 -2
  225. package/dist/component.js.map +0 -1
  226. package/dist/controls/list-key-control.cjs +0 -2
  227. package/dist/controls/list-key-control.cjs.map +0 -1
  228. package/dist/controls/list-key-control.d.ts +0 -14
  229. package/dist/controls/list-key-control.d.ts.map +0 -1
  230. package/dist/controls/list-key-control.js +0 -2
  231. package/dist/controls/list-key-control.js.map +0 -1
  232. package/dist/directives/attr.cjs +0 -2
  233. package/dist/directives/attr.cjs.map +0 -1
  234. package/dist/directives/attr.d.ts +0 -12
  235. package/dist/directives/attr.d.ts.map +0 -1
  236. package/dist/directives/attr.js +0 -2
  237. package/dist/directives/attr.js.map +0 -1
  238. package/dist/directives/bind.cjs +0 -2
  239. package/dist/directives/bind.cjs.map +0 -1
  240. package/dist/directives/bind.d.ts +0 -38
  241. package/dist/directives/bind.d.ts.map +0 -1
  242. package/dist/directives/bind.js +0 -2
  243. package/dist/directives/bind.js.map +0 -1
  244. package/dist/directives/choose.cjs +0 -2
  245. package/dist/directives/choose.cjs.map +0 -1
  246. package/dist/directives/choose.d.ts +0 -39
  247. package/dist/directives/choose.d.ts.map +0 -1
  248. package/dist/directives/choose.js +0 -2
  249. package/dist/directives/choose.js.map +0 -1
  250. package/dist/directives/classes.cjs +0 -2
  251. package/dist/directives/classes.cjs.map +0 -1
  252. package/dist/directives/classes.d.ts +0 -20
  253. package/dist/directives/classes.d.ts.map +0 -1
  254. package/dist/directives/classes.js +0 -2
  255. package/dist/directives/classes.js.map +0 -1
  256. package/dist/directives/index.d.ts +0 -13
  257. package/dist/directives/index.d.ts.map +0 -1
  258. package/dist/directives/memo.cjs +0 -2
  259. package/dist/directives/memo.cjs.map +0 -1
  260. package/dist/directives/memo.d.ts +0 -27
  261. package/dist/directives/memo.d.ts.map +0 -1
  262. package/dist/directives/memo.js +0 -2
  263. package/dist/directives/memo.js.map +0 -1
  264. package/dist/directives/on.cjs +0 -2
  265. package/dist/directives/on.cjs.map +0 -1
  266. package/dist/directives/on.d.ts +0 -25
  267. package/dist/directives/on.d.ts.map +0 -1
  268. package/dist/directives/on.js +0 -2
  269. package/dist/directives/on.js.map +0 -1
  270. package/dist/directives/spread.cjs +0 -2
  271. package/dist/directives/spread.cjs.map +0 -1
  272. package/dist/directives/spread.d.ts +0 -14
  273. package/dist/directives/spread.d.ts.map +0 -1
  274. package/dist/directives/spread.js +0 -2
  275. package/dist/directives/spread.js.map +0 -1
  276. package/dist/directives/style.cjs +0 -2
  277. package/dist/directives/style.cjs.map +0 -1
  278. package/dist/directives/style.d.ts +0 -22
  279. package/dist/directives/style.d.ts.map +0 -1
  280. package/dist/directives/style.js +0 -2
  281. package/dist/directives/style.js.map +0 -1
  282. package/dist/directives/until.cjs +0 -2
  283. package/dist/directives/until.cjs.map +0 -1
  284. package/dist/directives/until.d.ts +0 -26
  285. package/dist/directives/until.d.ts.map +0 -1
  286. package/dist/directives/until.js +0 -2
  287. package/dist/directives/until.js.map +0 -1
  288. package/dist/directives.cjs +0 -1
  289. package/dist/directives.js +0 -1
  290. package/dist/runtime-bindings.cjs +0 -2
  291. package/dist/runtime-bindings.cjs.map +0 -1
  292. package/dist/runtime-bindings.d.ts +0 -6
  293. package/dist/runtime-bindings.d.ts.map +0 -1
  294. package/dist/runtime-bindings.js +0 -2
  295. package/dist/runtime-bindings.js.map +0 -1
  296. package/dist/runtime-core.cjs +0 -2
  297. package/dist/runtime-core.cjs.map +0 -1
  298. package/dist/runtime-core.d.ts +0 -21
  299. package/dist/runtime-core.d.ts.map +0 -1
  300. package/dist/runtime-core.js +0 -2
  301. package/dist/runtime-core.js.map +0 -1
  302. package/dist/runtime-lifecycle.cjs +0 -2
  303. package/dist/runtime-lifecycle.cjs.map +0 -1
  304. package/dist/runtime-lifecycle.d.ts +0 -24
  305. package/dist/runtime-lifecycle.d.ts.map +0 -1
  306. package/dist/runtime-lifecycle.js +0 -2
  307. package/dist/runtime-lifecycle.js.map +0 -1
  308. package/dist/template-dom.cjs +0 -2
  309. package/dist/template-dom.cjs.map +0 -1
  310. package/dist/template-dom.d.ts +0 -13
  311. package/dist/template-dom.d.ts.map +0 -1
  312. package/dist/template-dom.js +0 -2
  313. package/dist/template-dom.js.map +0 -1
  314. package/dist/template-html.cjs +0 -2
  315. package/dist/template-html.cjs.map +0 -1
  316. package/dist/template-html.d.ts +0 -23
  317. package/dist/template-html.d.ts.map +0 -1
  318. package/dist/template-html.js +0 -2
  319. package/dist/template-html.js.map +0 -1
  320. package/dist/template.cjs +0 -2
  321. package/dist/template.cjs.map +0 -1
  322. package/dist/template.d.ts +0 -10
  323. package/dist/template.d.ts.map +0 -1
  324. package/dist/template.js +0 -2
  325. package/dist/template.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"registration.js","names":[],"sources":["../src/registration.ts"],"sourcesContent":["import { type CleanupFn, untrack } from '@vielzeug/stateit';\n\nimport { formCallbackRegistry } from './form';\nimport { type CSSResult, type HTMLResult, htmlResult, loadStylesheet, runAll } from './internal';\nimport { propRegistry } from './props';\nimport { runtimeStack, type ComponentRuntime } from './runtime-core';\nimport { applyBindingsInContainer, applyHtmlBinding } from './template';\nimport { type RegisterCleanup } from './template-bindings';\nimport { parseHTML } from './template-dom';\nimport { type KeyedNode } from './template-html';\n\nexport type ComponentRegistrationOptions = {\n /** Indicates if this should be a form-associated element */\n formAssociated?: boolean;\n /** Custom options for a host element (e.g. for aria-*) */\n host?: Record<string, string | boolean | number>;\n /** @internal — list of attribute names to observe via attributeChangedCallback */\n observedAttrs?: string[];\n /** Shadow root init options (mode is always 'open') — use e.g. `{ delegatesFocus: true }` for form controls */\n shadow?: Omit<ShadowRootInit, 'mode'>;\n /** Component styles applied to the shadow root. Static — set at definition time, not per-render. */\n styles?: (string | CSSStyleSheet | CSSResult)[];\n};\n\ntype ComponentSetupResult = string | HTMLResult;\n\nclass BaseElement extends HTMLElement {\n static _options?: ComponentRegistrationOptions;\n static _setup: () => ComponentSetupResult;\n static formAssociated = false;\n static observedAttributes: string[] = [];\n\n shadow: ShadowRoot;\n private _appliedHtmlBindings = new Set<string>();\n private _keyedStates = new Map<string, Map<string | number, KeyedNode>>();\n private _mountFns: (() => CleanupFn | undefined | void)[] = [];\n private _runtime: ComponentRuntime;\n private _rendered = false;\n private _setupDone = false;\n private _template: ComponentSetupResult | null = null;\n\n constructor() {\n super();\n\n const options = (this.constructor as typeof BaseElement)._options;\n\n this.shadow = this.attachShadow({ mode: 'open', ...options?.shadow });\n this._runtime = {\n cleanups: [],\n el: this,\n errorHandlers: [],\n onMount: [],\n styles: options?.styles,\n };\n }\n\n connectedCallback(): void {\n untrack(() => {\n if (!this._setupDone) this._runSetup();\n\n this._init();\n });\n }\n\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n if (oldValue === newValue) return;\n\n const propMeta = propRegistry.get(this)?.get(name);\n\n if (!propMeta) return;\n\n const parsed = propMeta.parse(newValue);\n\n if (\n !Object.is(\n untrack(() => propMeta.signal.value),\n parsed,\n )\n ) {\n propMeta.signal.value = parsed as never;\n }\n }\n\n disconnectedCallback(): void {\n runAll(this._runtime.cleanups);\n this._runtime.cleanups = [];\n this._runtime.onMount = this._mountFns.slice();\n this._appliedHtmlBindings.clear();\n this._keyedStates.clear();\n this._rendered = false;\n }\n\n formAssociatedCallback(form: HTMLFormElement | null): void {\n formCallbackRegistry.get(this)?.onAssociated?.(form);\n }\n\n formDisabledCallback(disabled: boolean): void {\n formCallbackRegistry.get(this)?.onDisabled?.(disabled);\n }\n\n formResetCallback(): void {\n formCallbackRegistry.get(this)?.onReset?.();\n }\n\n formStateRestoreCallback(state: unknown, mode: 'autocomplete' | 'restore'): void {\n formCallbackRegistry.get(this)?.onStateRestore?.(state, mode);\n }\n\n private _handleError(err: unknown): void {\n if (this._runtime.errorHandlers.length > 0) {\n for (const fn of this._runtime.errorHandlers) fn(err);\n } else {\n console.error(`[craftit:E3] <${this.localName}>`, err);\n\n throw err instanceof Error ? err : new Error(String(err));\n }\n }\n\n private _runSetup(): void {\n this._setupDone = true;\n runtimeStack.push(this._runtime as any);\n\n try {\n const options = (this.constructor as typeof BaseElement)._options;\n const { host: hostOptions } = options ?? {};\n\n if (hostOptions) {\n for (const [name, value] of Object.entries(hostOptions)) {\n if (typeof value === 'boolean') {\n if (value) {\n this.setAttribute(name, '');\n } else {\n this.removeAttribute(name);\n }\n } else {\n this.setAttribute(name, String(value));\n }\n }\n }\n\n const result = (this.constructor as typeof BaseElement)._setup();\n\n if (typeof result === 'string' || (typeof result === 'object' && result !== null && '__html' in result)) {\n this._template = result as ComponentSetupResult;\n }\n } catch (err) {\n this._handleError(err);\n } finally {\n runtimeStack.pop();\n }\n }\n\n private _init(): void {\n const { styles } = this._runtime;\n\n if (styles?.length) this.shadow.adoptedStyleSheets = styles.map(loadStylesheet);\n\n if (this._template) {\n const result: HTMLResult = typeof this._template === 'string' ? htmlResult(this._template) : this._template;\n\n if (!this._rendered) {\n this.shadow.replaceChildren(parseHTML(result.__html));\n this._rendered = true;\n }\n\n if (result.__bindings.length) {\n const registerCleanup: RegisterCleanup = (fn) => this._runtime.cleanups.push(fn);\n\n applyBindingsInContainer(this.shadow, result.__bindings, registerCleanup, {\n onHtml: (binding) => {\n if (!this._appliedHtmlBindings.has(binding.uid)) {\n this._appliedHtmlBindings.add(binding.uid);\n applyHtmlBinding(this.shadow, binding, registerCleanup, this._keyedStates);\n }\n },\n });\n }\n }\n\n queueMicrotask(() => {\n runtimeStack.push(this._runtime as any);\n\n try {\n const mountFns = this._runtime.onMount;\n\n this._mountFns = mountFns.slice();\n\n for (const mountFn of mountFns) {\n const cleanup = mountFn();\n\n if (typeof cleanup === 'function') this._runtime.cleanups.push(cleanup);\n }\n } catch (err) {\n this._handleError(err);\n } finally {\n runtimeStack.pop();\n this._runtime.onMount = [];\n }\n });\n }\n}\n\n/** @internal — use define() instead. */\nexport function registerComponent(\n tag: string,\n setup: () => ComponentSetupResult,\n options: ComponentRegistrationOptions = {},\n): string {\n if (!tag) throw new Error('[craftit:E4] registerComponent(tag, ...) requires a tag name');\n\n if (customElements.get(tag)) {\n return tag;\n }\n\n class Element extends BaseElement {\n static override _options = options;\n static override _setup = setup;\n static override formAssociated = options.formAssociated ?? false;\n static override observedAttributes = options.observedAttrs ?? [];\n }\n\n customElements.define(tag, Element);\n\n return tag;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"registration.js","names":[],"sources":["../src/registration.ts"],"sourcesContent":["import { onCleanup as _onCleanup, scope as _scope, type Scope, untrack } from '@vielzeug/stateit';\n\nimport { CRAFTIT_ERRORS } from './errors';\nimport { createHost, createSlots, type ComponentHost, type ComponentSlots } from './host';\nimport {\n createEmitFn,\n type CSSResult,\n type EmitFn,\n extractResult,\n type HTMLResult,\n loadStylesheet,\n toKebab,\n} from './internal';\nimport {\n createProps,\n isReflecting,\n normalizePropDefinition,\n prop,\n propRegistry,\n type InferPropsFromDefs,\n type InferPropsSignals,\n type PropDef,\n type PropInputDefs,\n type PropOptions,\n type PropsDef,\n} from './props';\nimport { type OnMountedCallback, type RuntimeScope, withCurrentElement, withRuntimeScope } from './runtime';\nimport { applyBindingsInContainer, applyHtmlBinding, parseHTML } from './template-bindings';\n\nexport type ComponentRegistrationOptions = {\n /** Indicates if this should be a form-associated element */\n formAssociated?: boolean;\n /** @internal — list of attribute names to observe via attributeChangedCallback */\n observedAttrs?: string[];\n /** Shadow root init options (mode is always 'open') — use e.g. `{ delegatesFocus: true }` for form controls */\n shadow?: Omit<ShadowRootInit, 'mode'>;\n /** Component styles applied to the shadow root. Static — set at definition time, not per-render. */\n styles?: (string | CSSStyleSheet | CSSResult)[];\n};\n\nexport type ComponentTemplate = () => HTMLResult;\n\ntype ComponentState = {\n mountCallbacks: OnMountedCallback[];\n mountedCallbacksRan: boolean;\n mountToken: number;\n scope: Scope;\n setupDone: boolean;\n styles?: (string | CSSStyleSheet | CSSResult)[];\n templateMounted: boolean;\n templateResult: HTMLResult | null;\n};\n\nclass BaseElement extends HTMLElement {\n // Lifecycle: setup() runs on first connect (initializes scope + calls user setup).\n // _init() runs on every connect (applies initial attributes to reset prop state).\n // disconnectedCallback() disposes scope to run effect cleanups, then recreates it.\n // This means setup() re-runs on reconnect. Future optimization: track \"mounted\" state\n // separately to avoid re-running setup() on reconnect while still running cleanups.\n // On disconnect: cleanups run; on reconnect, styles and bindings are re-applied.\n static _options?: ComponentRegistrationOptions;\n static _setup: () => ComponentTemplate;\n static formAssociated = false;\n static observedAttributes: string[] = [];\n\n shadow: ShadowRoot;\n private _component: ComponentState;\n\n constructor() {\n super();\n\n const options = (this.constructor as typeof BaseElement)._options;\n\n this.shadow = this.attachShadow({ mode: 'open', ...options?.shadow });\n this._component = {\n mountCallbacks: [],\n mountedCallbacksRan: false,\n mountToken: 0,\n scope: _scope(),\n setupDone: false,\n styles: options?.styles,\n templateMounted: false,\n templateResult: null,\n };\n }\n\n connectedCallback(): void {\n untrack(() => {\n if (!this._component.setupDone) this._runSetup();\n\n this._init();\n });\n }\n\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n if (oldValue === newValue) return;\n\n if (isReflecting(this, name)) return;\n\n const propMeta = propRegistry.get(this)?.get(name);\n\n if (!propMeta) return;\n\n const parsed = propMeta.parse(newValue);\n\n if (\n !Object.is(\n untrack(() => propMeta.signal.value),\n parsed,\n )\n ) {\n propMeta.signal.value = parsed as never;\n }\n }\n\n disconnectedCallback(): void {\n this._component.mountToken++;\n // Dispose and recreate scope to run all effect cleanups\n this._component.scope.dispose();\n this._component.scope = _scope();\n // Reset mount state for fresh mount callbacks on reconnect\n this._component.mountCallbacks = [];\n this._component.mountedCallbacksRan = false;\n this._component.templateMounted = false;\n this._component.templateResult = null;\n // Reset setupDone to re-run setup() on reconnect, ensuring effects are re-registered\n this._component.setupDone = false;\n }\n\n private _handleError(err: unknown): void {\n console.error(CRAFTIT_ERRORS.unhandledComponentError(this.localName), err);\n\n throw err instanceof Error ? err : new Error(String(err));\n }\n\n private _runSetup(): void {\n const setupScope: RuntimeScope = {\n element: this,\n mountCallbacks: [],\n };\n\n try {\n this._component.scope.run(() => {\n const template = withRuntimeScope(setupScope, () =>\n withCurrentElement(this, () => (this.constructor as typeof BaseElement)._setup()),\n );\n\n this._component.templateResult = withRuntimeScope(setupScope, () => withCurrentElement(this, () => template()));\n });\n\n this._component.mountCallbacks.push(...setupScope.mountCallbacks);\n this._component.setupDone = true;\n } catch (err) {\n this._handleError(err);\n }\n }\n\n private _init(): void {\n const { styles } = this._component;\n\n if (styles?.length) this.shadow.adoptedStyleSheets = styles.map(loadStylesheet);\n\n if (!this._component.templateMounted && this._component.templateResult != null) {\n const { bindings, html: htmlString } = extractResult(this._component.templateResult);\n\n this.shadow.replaceChildren(parseHTML(htmlString));\n this._component.templateMounted = true;\n\n if (bindings.length) {\n this._component.scope.run(() => {\n applyBindingsInContainer(this.shadow, bindings, _onCleanup, {\n onHtml: (binding) => applyHtmlBinding(this.shadow, binding, _onCleanup),\n });\n });\n }\n }\n\n if (!this._component.mountedCallbacksRan && this._component.mountCallbacks.length > 0) {\n this._component.mountedCallbacksRan = true;\n\n const token = ++this._component.mountToken;\n\n queueMicrotask(() => {\n if (!this.isConnected || token !== this._component.mountToken) return;\n\n try {\n for (const callback of this._component.mountCallbacks) {\n this._component.scope.run(() => {\n withRuntimeScope(\n {\n element: this,\n mountCallbacks: [],\n },\n () =>\n withCurrentElement(this, () => {\n const cleanup = callback();\n\n if (typeof cleanup === 'function') _onCleanup(cleanup);\n }),\n );\n });\n }\n } catch (err) {\n this._handleError(err);\n }\n });\n }\n }\n}\n\nconst defineComponent = (\n tag: string,\n setup: () => ComponentTemplate,\n options: ComponentRegistrationOptions = {},\n): string => {\n if (!tag) throw new Error(CRAFTIT_ERRORS.defineRequiresTag);\n\n if (customElements.get(tag)) {\n throw new Error(CRAFTIT_ERRORS.defineDuplicate(tag));\n }\n\n class Element extends BaseElement {\n static override _options = options;\n static override _setup = setup;\n static override formAssociated = options.formAssociated ?? false;\n static override observedAttributes = options.observedAttrs ?? [];\n }\n\n customElements.define(tag, Element);\n\n return tag;\n};\n\n// ─────────────────────────────────────────────────────────────────────────────\n// PUBLIC COMPONENT AUTHORING API (absorbed from component.ts)\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport { prop };\nexport type { InferPropsFromDefs, InferPropsSignals, PropDef, PropInputDefs, PropOptions, PropsDef };\n\n/**\n * Setup context passed as the second argument to the component setup function.\n */\nexport type SetupContextBag<Emits extends Record<string, unknown> = Record<string, unknown>> = {\n emit: EmitFn<Emits>;\n host: ComponentHost;\n slots: ComponentSlots;\n};\n\nexport type ComponentDefinition<\n Props extends Record<string, unknown> = Record<never, never>,\n Emits extends Record<string, unknown> = Record<string, never>,\n> = {\n /** Enable form association for the custom element */\n formAssociated?: boolean;\n /** Component properties and their metadata */\n props?: PropsDef<Props>;\n /** Main setup function. Props are the first positional parameter, context bag is second. Returns a template function. */\n setup: (props: InferPropsSignals<Props>, ctx: SetupContextBag<Emits>) => ComponentTemplate;\n /** Shadow DOM configuration (mode is always 'open') */\n shadow?: Omit<ShadowRootInit, 'mode'>;\n /** Component-specific styles */\n styles?: (string | CSSStyleSheet | CSSResult)[];\n};\n\nconst createSetupProps = <Props extends Record<string, unknown>>(\n defs: PropsDef<Props> | undefined,\n): InferPropsSignals<Props> => {\n if (!defs) return {} as InferPropsSignals<Props>;\n\n return createProps(defs) as InferPropsSignals<Props>;\n};\n\nexport function define<\n Props extends Record<string, unknown> = Record<never, never>,\n Emits extends Record<string, unknown> = Record<string, never>,\n>(tag: string, definition: ComponentDefinition<Props, Emits>): string {\n const { formAssociated, props: propDefs, setup, shadow: shadowOptions, styles } = definition;\n\n // Normalize props at define-time for early error feedback\n const normalizedPropDefs: PropsDef<Props> | undefined = (() => {\n if (!propDefs) return undefined;\n\n const normalized: PropInputDefs = {};\n\n for (const [key, def] of Object.entries(propDefs)) {\n normalized[key] = normalizePropDefinition(def);\n }\n\n return normalized as PropsDef<Props>;\n })();\n\n const observedAttrs = normalizedPropDefs ? Object.keys(normalizedPropDefs).map(toKebab) : [];\n\n return defineComponent(\n tag,\n () => {\n const props = createSetupProps(normalizedPropDefs);\n const host = createHost();\n const emit = createEmitFn<Emits>();\n const slots = createSlots();\n\n return setup(props, { emit, host, slots });\n },\n { formAssociated, observedAttrs, shadow: shadowOptions, styles },\n );\n}\n"],"mappings":"qiBAqDA,IAAM,EAAN,cAA0B,WAAY,CAOpC,OAAO,SACP,OAAO,OACP,OAAO,eAAiB,GACxB,OAAO,mBAA+B,CAAC,EAEvC,OACA,WAEA,aAAc,CACZ,MAAM,EAEN,IAAM,EAAW,KAAK,YAAmC,SAEzD,KAAK,OAAS,KAAK,aAAa,CAAE,KAAM,OAAQ,GAAG,GAAS,MAAO,CAAC,EACpE,KAAK,WAAa,CAChB,eAAgB,CAAC,EACjB,oBAAqB,GACrB,WAAY,EACZ,MAAO,EAAO,EACd,UAAW,GACX,OAAQ,GAAS,OACjB,gBAAiB,GACjB,eAAgB,IAClB,CACF,CAEA,mBAA0B,CACxB,MAAc,CACP,KAAK,WAAW,WAAW,KAAK,UAAU,EAE/C,KAAK,MAAM,CACb,CAAC,CACH,CAEA,yBAAyB,EAAc,EAAyB,EAA+B,CAG7F,GAFI,IAAa,GAEb,EAAa,KAAM,CAAI,EAAG,OAE9B,IAAM,EAAW,EAAa,IAAI,IAAI,GAAG,IAAI,CAAI,EAEjD,GAAI,CAAC,EAAU,OAEf,IAAM,EAAS,EAAS,MAAM,CAAQ,EAGnC,OAAO,GACN,MAAc,EAAS,OAAO,KAAK,EACnC,CACF,IAEA,EAAS,OAAO,MAAQ,EAE5B,CAEA,sBAA6B,CAC3B,KAAK,WAAW,aAEhB,KAAK,WAAW,MAAM,QAAQ,EAC9B,KAAK,WAAW,MAAQ,EAAO,EAE/B,KAAK,WAAW,eAAiB,CAAC,EAClC,KAAK,WAAW,oBAAsB,GACtC,KAAK,WAAW,gBAAkB,GAClC,KAAK,WAAW,eAAiB,KAEjC,KAAK,WAAW,UAAY,EAC9B,CAEA,aAAqB,EAAoB,CAGvC,MAFA,QAAQ,MAAM,EAAe,wBAAwB,KAAK,SAAS,EAAG,CAAG,EAEnE,aAAe,MAAQ,EAAU,MAAM,OAAO,CAAG,CAAC,CAC1D,CAEA,WAA0B,CACxB,IAAM,EAA2B,CAC/B,QAAS,KACT,eAAgB,CAAC,CACnB,EAEA,GAAI,CACF,KAAK,WAAW,MAAM,QAAU,CAC9B,IAAM,EAAW,EAAiB,MAChC,EAAmB,SAAa,KAAK,YAAmC,OAAO,CAAC,CAClF,EAEA,KAAK,WAAW,eAAiB,EAAiB,MAAkB,EAAmB,SAAY,EAAS,CAAC,CAAC,CAChH,CAAC,EAED,KAAK,WAAW,eAAe,KAAK,GAAG,EAAW,cAAc,EAChE,KAAK,WAAW,UAAY,EAC9B,OAAS,EAAK,CACZ,KAAK,aAAa,CAAG,CACvB,CACF,CAEA,OAAsB,CACpB,GAAM,CAAE,UAAW,KAAK,WAIxB,GAFI,GAAQ,SAAQ,KAAK,OAAO,mBAAqB,EAAO,IAAI,CAAc,GAE1E,CAAC,KAAK,WAAW,iBAAmB,KAAK,WAAW,gBAAkB,KAAM,CAC9E,GAAM,CAAE,WAAU,KAAM,GAAe,EAAc,KAAK,WAAW,cAAc,EAEnF,KAAK,OAAO,gBAAgB,EAAU,CAAU,CAAC,EACjD,KAAK,WAAW,gBAAkB,GAE9B,EAAS,QACX,KAAK,WAAW,MAAM,QAAU,CAC9B,EAAyB,KAAK,OAAQ,EAAU,EAAY,CAC1D,OAAS,GAAY,EAAiB,KAAK,OAAQ,EAAS,CAAU,CACxE,CAAC,CACH,CAAC,CAEL,CAEA,GAAI,CAAC,KAAK,WAAW,qBAAuB,KAAK,WAAW,eAAe,OAAS,EAAG,CACrF,KAAK,WAAW,oBAAsB,GAEtC,IAAM,EAAQ,EAAE,KAAK,WAAW,WAEhC,mBAAqB,CACf,MAAC,KAAK,aAAe,IAAU,KAAK,WAAW,YAEnD,GAAI,CACF,IAAK,IAAM,KAAY,KAAK,WAAW,eACrC,KAAK,WAAW,MAAM,QAAU,CAC9B,EACE,CACE,QAAS,KACT,eAAgB,CAAC,CACnB,MAEE,EAAmB,SAAY,CAC7B,IAAM,EAAU,EAAS,EAErB,OAAO,GAAY,YAAY,EAAW,CAAO,CACvD,CAAC,CACL,CACF,CAAC,CAEL,OAAS,EAAK,CACZ,KAAK,aAAa,CAAG,CACvB,CACF,CAAC,CACH,CACF,CACF,EAEM,GACJ,EACA,EACA,EAAwC,CAAC,IAC9B,CACX,GAAI,CAAC,EAAK,MAAU,MAAM,EAAe,iBAAiB,EAE1D,GAAI,eAAe,IAAI,CAAG,EACxB,MAAU,MAAM,EAAe,gBAAgB,CAAG,CAAC,EAGrD,MAAM,UAAgB,CAAY,CAChC,OAAgB,SAAW,EAC3B,OAAgB,OAAS,EACzB,OAAgB,eAAiB,EAAQ,gBAAkB,GAC3D,OAAgB,mBAAqB,EAAQ,eAAiB,CAAC,CACjE,CAIA,OAFA,eAAe,OAAO,EAAK,CAAO,EAE3B,CACT,EAkCM,EACJ,GAEK,EAEE,EAAY,CAAI,EAFL,CAAC,EAKrB,SAAgB,EAGd,EAAa,EAAuD,CACpE,GAAM,CAAE,iBAAgB,MAAO,EAAU,QAAO,OAAQ,EAAe,UAAW,EAG5E,OAAyD,CAC7D,GAAI,CAAC,EAAU,OAEf,IAAM,EAA4B,CAAC,EAEnC,IAAK,GAAM,CAAC,EAAK,KAAQ,OAAO,QAAQ,CAAQ,EAC9C,EAAW,GAAO,EAAwB,CAAG,EAG/C,OAAO,CACT,GAAG,EAIH,OAAO,EACL,MACM,CACJ,IAAM,EAAQ,EAAiB,CAAkB,EAC3C,EAAO,EAAW,EAIxB,OAAO,EAAM,EAAO,CAAE,KAHT,EAGS,EAAM,OAAM,MAFpB,EAEoB,CAAM,CAAC,CAC3C,EACA,CAAE,iBAAgB,cAZE,EAAqB,OAAO,KAAK,CAAkB,EAAE,IAAI,CAAO,EAAI,CAAC,EAYxD,OAAQ,EAAe,QAAO,CACjE,CACF"}
package/dist/runtime.cjs CHANGED
@@ -1,2 +1,2 @@
1
- require(`./runtime-lifecycle.cjs`);var e={bubbles:!0,cancelable:!0,composed:!0},t={custom(t,n,r={}){return t.dispatchEvent(new CustomEvent(n,{...e,...r}))},event(e,t){return e.dispatchEvent(t)},focus(t,n,r={}){return t.dispatchEvent(new FocusEvent(n,{...e,...r}))},keyboard(t,n,r={}){return t.dispatchEvent(new KeyboardEvent(n,{...e,...r}))},mouse(t,n,r={}){return t.dispatchEvent(new MouseEvent(n,{...e,...r}))},touch(t,n,r={}){return typeof TouchEvent<`u`?t.dispatchEvent(new TouchEvent(n,{...e,...r})):t.dispatchEvent(new CustomEvent(n,{...e,...r}))}};exports.fire=t;
1
+ const e=require(`./errors.cjs`),t=require(`./internal.cjs`);let n=require(`@vielzeug/stateit`);var r=null,i=null,a=(e,t)=>{let n=r;r=e;try{return t()}finally{r=n}},o=()=>{if(r)return r;throw Error(e.CRAFTIT_ERRORS.lifecycleOutsideSetup)},s=(e,t)=>{let n=i;i=e;try{return t()}finally{i=n}},c=e=>i?((0,n.onCleanup)(e),!0):!1,l=n.onCleanup,u=t=>{if(!i)throw Error(e.CRAFTIT_ERRORS.lifecycleOutsideSetup);i.mountCallbacks.push(t)},d=e=>{let t=(0,n.effect)(()=>e());return c(t),t};function f(n,r,a,o){if(!i)throw Error(e.CRAFTIT_ERRORS.lifecycleOutsideSetup);n&&c(t.listen(n,r,a,o))}function p(e,n,r,i){return t.listen(e,n,r,i)}var m=(e,t)=>d(()=>{let n=e.value;if(n)return t(n)});exports.currentElementOrThrow=o,exports.effect=d,exports.listen=p,exports.on=f,exports.onCleanup=l,exports.onElement=m,exports.onMounted=u,exports.tryRegisterCleanup=c,exports.withCurrentElement=a,exports.withRuntimeScope=s;
2
2
  //# sourceMappingURL=runtime.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.cjs","names":[],"sources":["../src/runtime.ts"],"sourcesContent":["export {\n createCleanupSignal,\n effect,\n handle,\n onCleanup,\n onElement,\n onError,\n onMount,\n watch,\n} from './runtime-lifecycle';\nexport type { HostEventListeners, HostEventMap } from './runtime-lifecycle';\n\ntype FireDefaults = Pick<EventInit, 'bubbles' | 'cancelable' | 'composed'>;\n\nexport type FireApi = {\n custom<Detail = unknown>(target: EventTarget, type: string, options?: CustomEventInit<Detail>): boolean;\n event(target: EventTarget, event: Event): boolean;\n focus(target: EventTarget, type: string, options?: FocusEventInit): boolean;\n keyboard(target: EventTarget, type: string, options?: KeyboardEventInit): boolean;\n mouse(target: EventTarget, type: string, options?: MouseEventInit): boolean;\n touch(target: EventTarget, type: string, options?: TouchEventInit): boolean;\n};\n\nconst DEFAULT_FIRE_OPTIONS: FireDefaults = { bubbles: true, cancelable: true, composed: true };\n\n/**\n * Dispatch DOM events explicitly without guessing constructors from the event name.\n *\n * @example\n * fire.mouse(el, 'click');\n * fire.keyboard(el, 'keydown', { key: 'Enter' });\n * fire.custom(el, 'change', { detail: { value: 42 } });\n * fire.event(el, new PointerEvent('pointerdown'));\n */\nexport const fire: FireApi = {\n custom<Detail = unknown>(target: EventTarget, type: string, options: CustomEventInit<Detail> = {}) {\n return target.dispatchEvent(new CustomEvent<Detail>(type, { ...DEFAULT_FIRE_OPTIONS, ...options }));\n },\n event(target, event) {\n return target.dispatchEvent(event);\n },\n focus(target, type, options = {}) {\n return target.dispatchEvent(new FocusEvent(type, { ...DEFAULT_FIRE_OPTIONS, ...options }));\n },\n keyboard(target, type, options = {}) {\n return target.dispatchEvent(new KeyboardEvent(type, { ...DEFAULT_FIRE_OPTIONS, ...options }));\n },\n mouse(target, type, options = {}) {\n return target.dispatchEvent(new MouseEvent(type, { ...DEFAULT_FIRE_OPTIONS, ...options }));\n },\n touch(target, type, options = {}) {\n if (typeof TouchEvent !== 'undefined') {\n return target.dispatchEvent(new TouchEvent(type, { ...DEFAULT_FIRE_OPTIONS, ...options }));\n }\n\n return target.dispatchEvent(new CustomEvent(type, { ...DEFAULT_FIRE_OPTIONS, ...options }));\n },\n};\n"],"mappings":"mCAuBA,IAAM,EAAqC,CAAE,QAAS,GAAM,WAAY,GAAM,SAAU,GAAM,CAWjF,EAAgB,CAC3B,OAAyB,EAAqB,EAAc,EAAmC,EAAE,CAAE,CACjG,OAAO,EAAO,cAAc,IAAI,YAAoB,EAAM,CAAE,GAAG,EAAsB,GAAG,EAAS,CAAC,CAAC,EAErG,MAAM,EAAQ,EAAO,CACnB,OAAO,EAAO,cAAc,EAAM,EAEpC,MAAM,EAAQ,EAAM,EAAU,EAAE,CAAE,CAChC,OAAO,EAAO,cAAc,IAAI,WAAW,EAAM,CAAE,GAAG,EAAsB,GAAG,EAAS,CAAC,CAAC,EAE5F,SAAS,EAAQ,EAAM,EAAU,EAAE,CAAE,CACnC,OAAO,EAAO,cAAc,IAAI,cAAc,EAAM,CAAE,GAAG,EAAsB,GAAG,EAAS,CAAC,CAAC,EAE/F,MAAM,EAAQ,EAAM,EAAU,EAAE,CAAE,CAChC,OAAO,EAAO,cAAc,IAAI,WAAW,EAAM,CAAE,GAAG,EAAsB,GAAG,EAAS,CAAC,CAAC,EAE5F,MAAM,EAAQ,EAAM,EAAU,EAAE,CAAE,CAKhC,OAJI,OAAO,WAAe,IACjB,EAAO,cAAc,IAAI,WAAW,EAAM,CAAE,GAAG,EAAsB,GAAG,EAAS,CAAC,CAAC,CAGrF,EAAO,cAAc,IAAI,YAAY,EAAM,CAAE,GAAG,EAAsB,GAAG,EAAS,CAAC,CAAC,EAE9F"}
1
+ {"version":3,"file":"runtime.cjs","names":[],"sources":["../src/runtime.ts"],"sourcesContent":["import {\n effect as _effect,\n onCleanup as _onCleanup,\n type CleanupFn,\n type EffectCallback,\n type ReadonlySignal,\n type Subscription,\n} from '@vielzeug/stateit';\n\nimport { CRAFTIT_ERRORS } from './errors';\nimport { fire, listen as listenInternal } from './internal';\n\nexport { fire };\n\nlet currentElement: HTMLElement | null = null;\nlet currentScope: RuntimeScope | null = null;\n\nexport type OnMountedCallback = () => CleanupFn | void;\n\nexport type RuntimeScope = {\n element: HTMLElement;\n mountCallbacks: OnMountedCallback[];\n};\n\nexport const withCurrentElement = <T>(el: HTMLElement, fn: () => T): T => {\n const previous = currentElement;\n\n currentElement = el;\n\n try {\n return fn();\n } finally {\n currentElement = previous;\n }\n};\n\nexport const currentElementOrThrow = (): HTMLElement => {\n if (currentElement) return currentElement;\n\n throw new Error(CRAFTIT_ERRORS.lifecycleOutsideSetup);\n};\n\n/** @internal */\nexport const withRuntimeScope = <T>(runtimeScope: RuntimeScope, fn: () => T): T => {\n const prev = currentScope;\n\n currentScope = runtimeScope;\n\n try {\n return fn();\n } finally {\n currentScope = prev;\n }\n};\n\nexport const tryRegisterCleanup = (fn: CleanupFn): boolean => {\n if (!currentScope) return false;\n\n _onCleanup(fn);\n\n return true;\n};\n\n/**\n * Register a cleanup function to be called on component disconnect.\n * Must be called synchronously during component setup or inside scope.run().\n */\nexport const onCleanup = _onCleanup;\n\n/**\n * Register work to run after the component template mounts.\n * Multiple callbacks are supported and run in registration order.\n */\nexport const onMounted = (fn: OnMountedCallback): void => {\n if (!currentScope) throw new Error(CRAFTIT_ERRORS.lifecycleOutsideSetup);\n\n currentScope.mountCallbacks.push(fn);\n};\n\nexport const effect = (fn: EffectCallback): Subscription => {\n const dispose = _effect(() => {\n return fn();\n });\n\n tryRegisterCleanup(dispose);\n\n return dispose;\n};\n\nexport function on<K extends keyof HTMLElementEventMap>(\n target: EventTarget | null | undefined,\n event: K,\n listener: (e: HTMLElementEventMap[K]) => void,\n options?: AddEventListenerOptions,\n): void;\nexport function on(\n target: EventTarget | null | undefined,\n event: string,\n listener: EventListener,\n options?: AddEventListenerOptions,\n): void {\n if (!currentScope) throw new Error(CRAFTIT_ERRORS.lifecycleOutsideSetup);\n\n if (!target) return;\n\n const cleanup = listenInternal(target, event, listener, options);\n\n tryRegisterCleanup(cleanup);\n}\n\n/**\n * Attaches an event listener and returns a disposal function.\n * Unlike `on()`, this does not require a runtime scope and cleanup must be\n * managed manually by calling the returned function.\n */\nexport function listen<K extends keyof HTMLElementEventMap>(\n target: EventTarget | null | undefined,\n event: K,\n listener: (e: HTMLElementEventMap[K]) => void,\n options?: AddEventListenerOptions,\n): () => void;\nexport function listen(\n target: EventTarget | null | undefined,\n event: string,\n listener: EventListener,\n options?: AddEventListenerOptions,\n): () => void {\n return listenInternal(target, event, listener, options);\n}\n\nexport const onElement = <T extends HTMLElement>(\n ref: ReadonlySignal<T | null>,\n callback: (el: T) => CleanupFn | undefined | void,\n): Subscription => {\n return effect(() => {\n const el = ref.value;\n\n if (el) return callback(el);\n });\n};\n"],"mappings":"+FAcA,IAAI,EAAqC,KACrC,EAAoC,KAS3B,GAAyB,EAAiB,IAAmB,CACxE,IAAM,EAAW,EAEjB,EAAiB,EAEjB,GAAI,CACF,OAAO,EAAG,CACZ,QAAU,CACR,EAAiB,CACnB,CACF,EAEa,MAA2C,CACtD,GAAI,EAAgB,OAAO,EAE3B,MAAU,MAAM,EAAA,eAAe,qBAAqB,CACtD,EAGa,GAAuB,EAA4B,IAAmB,CACjF,IAAM,EAAO,EAEb,EAAe,EAEf,GAAI,CACF,OAAO,EAAG,CACZ,QAAU,CACR,EAAe,CACjB,CACF,EAEa,EAAsB,GAC5B,IAEL,EAAA,EAAA,WAAW,CAAE,EAEN,IAJmB,GAWf,EAAY,EAAA,UAMZ,EAAa,GAAgC,CACxD,GAAI,CAAC,EAAc,MAAU,MAAM,EAAA,eAAe,qBAAqB,EAEvE,EAAa,eAAe,KAAK,CAAE,CACrC,EAEa,EAAU,GAAqC,CAC1D,IAAM,GAAA,EAAA,EAAA,YACG,EAAG,CACX,EAID,OAFA,EAAmB,CAAO,EAEnB,CACT,EAQA,SAAgB,EACd,EACA,EACA,EACA,EACM,CACN,GAAI,CAAC,EAAc,MAAU,MAAM,EAAA,eAAe,qBAAqB,EAElE,GAIL,EAFgB,EAAA,OAAe,EAAQ,EAAO,EAAU,CAErC,CAAO,CAC5B,CAaA,SAAgB,EACd,EACA,EACA,EACA,EACY,CACZ,OAAO,EAAA,OAAe,EAAQ,EAAO,EAAU,CAAO,CACxD,CAEA,IAAa,GACX,EACA,IAEO,MAAa,CAClB,IAAM,EAAK,EAAI,MAEf,GAAI,EAAI,OAAO,EAAS,CAAE,CAC5B,CAAC"}
package/dist/runtime.d.ts CHANGED
@@ -1,21 +1,33 @@
1
- export { createCleanupSignal, effect, handle, onCleanup, onElement, onError, onMount, watch, } from './runtime-lifecycle';
2
- export type { HostEventListeners, HostEventMap } from './runtime-lifecycle';
3
- export type FireApi = {
4
- custom<Detail = unknown>(target: EventTarget, type: string, options?: CustomEventInit<Detail>): boolean;
5
- event(target: EventTarget, event: Event): boolean;
6
- focus(target: EventTarget, type: string, options?: FocusEventInit): boolean;
7
- keyboard(target: EventTarget, type: string, options?: KeyboardEventInit): boolean;
8
- mouse(target: EventTarget, type: string, options?: MouseEventInit): boolean;
9
- touch(target: EventTarget, type: string, options?: TouchEventInit): boolean;
1
+ import { type CleanupFn, type EffectCallback, type ReadonlySignal, type Subscription } from '@vielzeug/stateit';
2
+ import { fire } from './internal';
3
+ export { fire };
4
+ export type OnMountedCallback = () => CleanupFn | void;
5
+ export type RuntimeScope = {
6
+ element: HTMLElement;
7
+ mountCallbacks: OnMountedCallback[];
10
8
  };
9
+ export declare const withCurrentElement: <T>(el: HTMLElement, fn: () => T) => T;
10
+ export declare const currentElementOrThrow: () => HTMLElement;
11
+ /** @internal */
12
+ export declare const withRuntimeScope: <T>(runtimeScope: RuntimeScope, fn: () => T) => T;
13
+ export declare const tryRegisterCleanup: (fn: CleanupFn) => boolean;
11
14
  /**
12
- * Dispatch DOM events explicitly without guessing constructors from the event name.
13
- *
14
- * @example
15
- * fire.mouse(el, 'click');
16
- * fire.keyboard(el, 'keydown', { key: 'Enter' });
17
- * fire.custom(el, 'change', { detail: { value: 42 } });
18
- * fire.event(el, new PointerEvent('pointerdown'));
15
+ * Register a cleanup function to be called on component disconnect.
16
+ * Must be called synchronously during component setup or inside scope.run().
19
17
  */
20
- export declare const fire: FireApi;
18
+ export declare const onCleanup: (fn: CleanupFn) => void;
19
+ /**
20
+ * Register work to run after the component template mounts.
21
+ * Multiple callbacks are supported and run in registration order.
22
+ */
23
+ export declare const onMounted: (fn: OnMountedCallback) => void;
24
+ export declare const effect: (fn: EffectCallback) => Subscription;
25
+ export declare function on<K extends keyof HTMLElementEventMap>(target: EventTarget | null | undefined, event: K, listener: (e: HTMLElementEventMap[K]) => void, options?: AddEventListenerOptions): void;
26
+ /**
27
+ * Attaches an event listener and returns a disposal function.
28
+ * Unlike `on()`, this does not require a runtime scope and cleanup must be
29
+ * managed manually by calling the returned function.
30
+ */
31
+ export declare function listen<K extends keyof HTMLElementEventMap>(target: EventTarget | null | undefined, event: K, listener: (e: HTMLElementEventMap[K]) => void, options?: AddEventListenerOptions): () => void;
32
+ export declare const onElement: <T extends HTMLElement>(ref: ReadonlySignal<T | null>, callback: (el: T) => CleanupFn | undefined | void) => Subscription;
21
33
  //# sourceMappingURL=runtime.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,MAAM,EACN,MAAM,EACN,SAAS,EACT,SAAS,EACT,OAAO,EACP,OAAO,EACP,KAAK,GACN,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAI5E,MAAM,MAAM,OAAO,GAAG;IACpB,MAAM,CAAC,MAAM,GAAG,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC;IACxG,KAAK,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC;IAClD,KAAK,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC;IAC5E,QAAQ,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC;IAClF,KAAK,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC;IAC5E,KAAK,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC;CAC7E,CAAC;AAIF;;;;;;;;GAQG;AACH,eAAO,MAAM,IAAI,EAAE,OAuBlB,CAAC"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,YAAY,EAClB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,IAAI,EAA4B,MAAM,YAAY,CAAC;AAE5D,OAAO,EAAE,IAAI,EAAE,CAAC;AAKhB,MAAM,MAAM,iBAAiB,GAAG,MAAM,SAAS,GAAG,IAAI,CAAC;AAEvD,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,WAAW,CAAC;IACrB,cAAc,EAAE,iBAAiB,EAAE,CAAC;CACrC,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,CAAC,EAAE,IAAI,WAAW,EAAE,IAAI,MAAM,CAAC,KAAG,CAUpE,CAAC;AAEF,eAAO,MAAM,qBAAqB,QAAO,WAIxC,CAAC;AAEF,gBAAgB;AAChB,eAAO,MAAM,gBAAgB,GAAI,CAAC,EAAE,cAAc,YAAY,EAAE,IAAI,MAAM,CAAC,KAAG,CAU7E,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,IAAI,SAAS,KAAG,OAMlD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,SAAS,yBAAa,CAAC;AAEpC;;;GAGG;AACH,eAAO,MAAM,SAAS,GAAI,IAAI,iBAAiB,KAAG,IAIjD,CAAC;AAEF,eAAO,MAAM,MAAM,GAAI,IAAI,cAAc,KAAG,YAQ3C,CAAC;AAEF,wBAAgB,EAAE,CAAC,CAAC,SAAS,MAAM,mBAAmB,EACpD,MAAM,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,EACtC,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,CAAC,CAAC,EAAE,mBAAmB,CAAC,CAAC,CAAC,KAAK,IAAI,EAC7C,OAAO,CAAC,EAAE,uBAAuB,GAChC,IAAI,CAAC;AAgBR;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,CAAC,SAAS,MAAM,mBAAmB,EACxD,MAAM,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,EACtC,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,CAAC,CAAC,EAAE,mBAAmB,CAAC,CAAC,CAAC,KAAK,IAAI,EAC7C,OAAO,CAAC,EAAE,uBAAuB,GAChC,MAAM,IAAI,CAAC;AAUd,eAAO,MAAM,SAAS,GAAI,CAAC,SAAS,WAAW,EAC7C,KAAK,cAAc,CAAC,CAAC,GAAG,IAAI,CAAC,EAC7B,UAAU,CAAC,EAAE,EAAE,CAAC,KAAK,SAAS,GAAG,SAAS,GAAG,IAAI,KAChD,YAMF,CAAC"}
package/dist/runtime.js CHANGED
@@ -1,2 +1,2 @@
1
- import"./runtime-lifecycle.js";var e={bubbles:!0,cancelable:!0,composed:!0},t={custom(t,n,r={}){return t.dispatchEvent(new CustomEvent(n,{...e,...r}))},event(e,t){return e.dispatchEvent(t)},focus(t,n,r={}){return t.dispatchEvent(new FocusEvent(n,{...e,...r}))},keyboard(t,n,r={}){return t.dispatchEvent(new KeyboardEvent(n,{...e,...r}))},mouse(t,n,r={}){return t.dispatchEvent(new MouseEvent(n,{...e,...r}))},touch(t,n,r={}){return typeof TouchEvent<`u`?t.dispatchEvent(new TouchEvent(n,{...e,...r})):t.dispatchEvent(new CustomEvent(n,{...e,...r}))}};export{t as fire};
1
+ import{CRAFTIT_ERRORS as e}from"./errors.js";import{listen as t}from"./internal.js";import{effect as n,onCleanup as r}from"@vielzeug/stateit";var i=null,a=null,o=(e,t)=>{let n=i;i=e;try{return t()}finally{i=n}},s=()=>{if(i)return i;throw Error(e.lifecycleOutsideSetup)},c=(e,t)=>{let n=a;a=e;try{return t()}finally{a=n}},l=e=>a?(r(e),!0):!1,u=r,d=t=>{if(!a)throw Error(e.lifecycleOutsideSetup);a.mountCallbacks.push(t)},f=e=>{let t=n(()=>e());return l(t),t};function p(n,r,i,o){if(!a)throw Error(e.lifecycleOutsideSetup);n&&l(t(n,r,i,o))}function m(e,n,r,i){return t(e,n,r,i)}var h=(e,t)=>f(()=>{let n=e.value;if(n)return t(n)});export{s as currentElementOrThrow,f as effect,m as listen,p as on,u as onCleanup,h as onElement,d as onMounted,l as tryRegisterCleanup,o as withCurrentElement,c as withRuntimeScope};
2
2
  //# sourceMappingURL=runtime.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.js","names":[],"sources":["../src/runtime.ts"],"sourcesContent":["export {\n createCleanupSignal,\n effect,\n handle,\n onCleanup,\n onElement,\n onError,\n onMount,\n watch,\n} from './runtime-lifecycle';\nexport type { HostEventListeners, HostEventMap } from './runtime-lifecycle';\n\ntype FireDefaults = Pick<EventInit, 'bubbles' | 'cancelable' | 'composed'>;\n\nexport type FireApi = {\n custom<Detail = unknown>(target: EventTarget, type: string, options?: CustomEventInit<Detail>): boolean;\n event(target: EventTarget, event: Event): boolean;\n focus(target: EventTarget, type: string, options?: FocusEventInit): boolean;\n keyboard(target: EventTarget, type: string, options?: KeyboardEventInit): boolean;\n mouse(target: EventTarget, type: string, options?: MouseEventInit): boolean;\n touch(target: EventTarget, type: string, options?: TouchEventInit): boolean;\n};\n\nconst DEFAULT_FIRE_OPTIONS: FireDefaults = { bubbles: true, cancelable: true, composed: true };\n\n/**\n * Dispatch DOM events explicitly without guessing constructors from the event name.\n *\n * @example\n * fire.mouse(el, 'click');\n * fire.keyboard(el, 'keydown', { key: 'Enter' });\n * fire.custom(el, 'change', { detail: { value: 42 } });\n * fire.event(el, new PointerEvent('pointerdown'));\n */\nexport const fire: FireApi = {\n custom<Detail = unknown>(target: EventTarget, type: string, options: CustomEventInit<Detail> = {}) {\n return target.dispatchEvent(new CustomEvent<Detail>(type, { ...DEFAULT_FIRE_OPTIONS, ...options }));\n },\n event(target, event) {\n return target.dispatchEvent(event);\n },\n focus(target, type, options = {}) {\n return target.dispatchEvent(new FocusEvent(type, { ...DEFAULT_FIRE_OPTIONS, ...options }));\n },\n keyboard(target, type, options = {}) {\n return target.dispatchEvent(new KeyboardEvent(type, { ...DEFAULT_FIRE_OPTIONS, ...options }));\n },\n mouse(target, type, options = {}) {\n return target.dispatchEvent(new MouseEvent(type, { ...DEFAULT_FIRE_OPTIONS, ...options }));\n },\n touch(target, type, options = {}) {\n if (typeof TouchEvent !== 'undefined') {\n return target.dispatchEvent(new TouchEvent(type, { ...DEFAULT_FIRE_OPTIONS, ...options }));\n }\n\n return target.dispatchEvent(new CustomEvent(type, { ...DEFAULT_FIRE_OPTIONS, ...options }));\n },\n};\n"],"mappings":"+BAuBA,IAAM,EAAqC,CAAE,QAAS,GAAM,WAAY,GAAM,SAAU,GAAM,CAWjF,EAAgB,CAC3B,OAAyB,EAAqB,EAAc,EAAmC,EAAE,CAAE,CACjG,OAAO,EAAO,cAAc,IAAI,YAAoB,EAAM,CAAE,GAAG,EAAsB,GAAG,EAAS,CAAC,CAAC,EAErG,MAAM,EAAQ,EAAO,CACnB,OAAO,EAAO,cAAc,EAAM,EAEpC,MAAM,EAAQ,EAAM,EAAU,EAAE,CAAE,CAChC,OAAO,EAAO,cAAc,IAAI,WAAW,EAAM,CAAE,GAAG,EAAsB,GAAG,EAAS,CAAC,CAAC,EAE5F,SAAS,EAAQ,EAAM,EAAU,EAAE,CAAE,CACnC,OAAO,EAAO,cAAc,IAAI,cAAc,EAAM,CAAE,GAAG,EAAsB,GAAG,EAAS,CAAC,CAAC,EAE/F,MAAM,EAAQ,EAAM,EAAU,EAAE,CAAE,CAChC,OAAO,EAAO,cAAc,IAAI,WAAW,EAAM,CAAE,GAAG,EAAsB,GAAG,EAAS,CAAC,CAAC,EAE5F,MAAM,EAAQ,EAAM,EAAU,EAAE,CAAE,CAKhC,OAJI,OAAO,WAAe,IACjB,EAAO,cAAc,IAAI,WAAW,EAAM,CAAE,GAAG,EAAsB,GAAG,EAAS,CAAC,CAAC,CAGrF,EAAO,cAAc,IAAI,YAAY,EAAM,CAAE,GAAG,EAAsB,GAAG,EAAS,CAAC,CAAC,EAE9F"}
1
+ {"version":3,"file":"runtime.js","names":[],"sources":["../src/runtime.ts"],"sourcesContent":["import {\n effect as _effect,\n onCleanup as _onCleanup,\n type CleanupFn,\n type EffectCallback,\n type ReadonlySignal,\n type Subscription,\n} from '@vielzeug/stateit';\n\nimport { CRAFTIT_ERRORS } from './errors';\nimport { fire, listen as listenInternal } from './internal';\n\nexport { fire };\n\nlet currentElement: HTMLElement | null = null;\nlet currentScope: RuntimeScope | null = null;\n\nexport type OnMountedCallback = () => CleanupFn | void;\n\nexport type RuntimeScope = {\n element: HTMLElement;\n mountCallbacks: OnMountedCallback[];\n};\n\nexport const withCurrentElement = <T>(el: HTMLElement, fn: () => T): T => {\n const previous = currentElement;\n\n currentElement = el;\n\n try {\n return fn();\n } finally {\n currentElement = previous;\n }\n};\n\nexport const currentElementOrThrow = (): HTMLElement => {\n if (currentElement) return currentElement;\n\n throw new Error(CRAFTIT_ERRORS.lifecycleOutsideSetup);\n};\n\n/** @internal */\nexport const withRuntimeScope = <T>(runtimeScope: RuntimeScope, fn: () => T): T => {\n const prev = currentScope;\n\n currentScope = runtimeScope;\n\n try {\n return fn();\n } finally {\n currentScope = prev;\n }\n};\n\nexport const tryRegisterCleanup = (fn: CleanupFn): boolean => {\n if (!currentScope) return false;\n\n _onCleanup(fn);\n\n return true;\n};\n\n/**\n * Register a cleanup function to be called on component disconnect.\n * Must be called synchronously during component setup or inside scope.run().\n */\nexport const onCleanup = _onCleanup;\n\n/**\n * Register work to run after the component template mounts.\n * Multiple callbacks are supported and run in registration order.\n */\nexport const onMounted = (fn: OnMountedCallback): void => {\n if (!currentScope) throw new Error(CRAFTIT_ERRORS.lifecycleOutsideSetup);\n\n currentScope.mountCallbacks.push(fn);\n};\n\nexport const effect = (fn: EffectCallback): Subscription => {\n const dispose = _effect(() => {\n return fn();\n });\n\n tryRegisterCleanup(dispose);\n\n return dispose;\n};\n\nexport function on<K extends keyof HTMLElementEventMap>(\n target: EventTarget | null | undefined,\n event: K,\n listener: (e: HTMLElementEventMap[K]) => void,\n options?: AddEventListenerOptions,\n): void;\nexport function on(\n target: EventTarget | null | undefined,\n event: string,\n listener: EventListener,\n options?: AddEventListenerOptions,\n): void {\n if (!currentScope) throw new Error(CRAFTIT_ERRORS.lifecycleOutsideSetup);\n\n if (!target) return;\n\n const cleanup = listenInternal(target, event, listener, options);\n\n tryRegisterCleanup(cleanup);\n}\n\n/**\n * Attaches an event listener and returns a disposal function.\n * Unlike `on()`, this does not require a runtime scope and cleanup must be\n * managed manually by calling the returned function.\n */\nexport function listen<K extends keyof HTMLElementEventMap>(\n target: EventTarget | null | undefined,\n event: K,\n listener: (e: HTMLElementEventMap[K]) => void,\n options?: AddEventListenerOptions,\n): () => void;\nexport function listen(\n target: EventTarget | null | undefined,\n event: string,\n listener: EventListener,\n options?: AddEventListenerOptions,\n): () => void {\n return listenInternal(target, event, listener, options);\n}\n\nexport const onElement = <T extends HTMLElement>(\n ref: ReadonlySignal<T | null>,\n callback: (el: T) => CleanupFn | undefined | void,\n): Subscription => {\n return effect(() => {\n const el = ref.value;\n\n if (el) return callback(el);\n });\n};\n"],"mappings":"8IAcA,IAAI,EAAqC,KACrC,EAAoC,KAS3B,GAAyB,EAAiB,IAAmB,CACxE,IAAM,EAAW,EAEjB,EAAiB,EAEjB,GAAI,CACF,OAAO,EAAG,CACZ,QAAU,CACR,EAAiB,CACnB,CACF,EAEa,MAA2C,CACtD,GAAI,EAAgB,OAAO,EAE3B,MAAU,MAAM,EAAe,qBAAqB,CACtD,EAGa,GAAuB,EAA4B,IAAmB,CACjF,IAAM,EAAO,EAEb,EAAe,EAEf,GAAI,CACF,OAAO,EAAG,CACZ,QAAU,CACR,EAAe,CACjB,CACF,EAEa,EAAsB,GAC5B,GAEL,EAAW,CAAE,EAEN,IAJmB,GAWf,EAAY,EAMZ,EAAa,GAAgC,CACxD,GAAI,CAAC,EAAc,MAAU,MAAM,EAAe,qBAAqB,EAEvE,EAAa,eAAe,KAAK,CAAE,CACrC,EAEa,EAAU,GAAqC,CAC1D,IAAM,EAAU,MACP,EAAG,CACX,EAID,OAFA,EAAmB,CAAO,EAEnB,CACT,EAQA,SAAgB,EACd,EACA,EACA,EACA,EACM,CACN,GAAI,CAAC,EAAc,MAAU,MAAM,EAAe,qBAAqB,EAElE,GAIL,EAFgB,EAAe,EAAQ,EAAO,EAAU,CAErC,CAAO,CAC5B,CAaA,SAAgB,EACd,EACA,EACA,EACA,EACY,CACZ,OAAO,EAAe,EAAQ,EAAO,EAAU,CAAO,CACxD,CAEA,IAAa,GACX,EACA,IAEO,MAAa,CAClB,IAAM,EAAK,EAAI,MAEf,GAAI,EAAI,OAAO,EAAS,CAAE,CAC5B,CAAC"}
@@ -1,2 +1,2 @@
1
- const e=require(`./internal.cjs`),t=require(`./runtime-bindings.cjs`),n=require(`./props.cjs`),r=require(`./template-dom.cjs`);let i=require(`@vielzeug/stateit`);var a=e=>Array.isArray(e)||typeof e==`object`&&!!e,o=(e,t,n)=>{n((0,i.effect)(()=>t(e.value)))},s=(t,r,s)=>{let c=o=>{let s=n.propRegistry.get(t)?.get(r.name);if(!s&&a(o)){t[r.name]=o;return}if((!s||s.reflect)&&(r.mode===`bool`?t.toggleAttribute(r.name,!!o):e.setAttr(t,r.name,o)),!s)return;let c=a(o)?o:s.parse(r.mode===`bool`?o?``:null:o==null||o===!1?null:String(o));Object.is((0,i.untrack)(()=>s.signal.value),c)||(s.signal.value=c)};r.signal?o(r.signal,c,s):c(r.value)},c=(e,n,r)=>{let i=t=>{e[n.name]=t};n.signal?o(n.signal,i,r):i(n.value),t.bindPropertyModel(e,n.name,n.model,r)},l=(t,n,r)=>{let{modifiers:i}=n,a=i?{capture:!!i.capture,once:!!i.once,passive:!!i.passive}:void 0;r(e.listen(t,n.name,e=>{i?.self&&e.target!==e.currentTarget||(i?.stop&&e.stopPropagation(),i?.prevent&&!i?.passive&&e.preventDefault(),n.handler(e))},a))},u=(e,t,n)=>{let{ref:r}=t;if(typeof r==`function`){r(e),n(()=>r(null));return}if(Array.isArray(r)){r.push(e),n(()=>{let t=r.indexOf(e);t!==-1&&r.splice(t,1)});return}r.value=e,n(()=>{r.value=null})},d=(e,t,n,r)=>{let i=new Map;for(let a of e){let e=a.uid;if(a.type===`text`){let r=n.comments.get(e);if(r){let i=document.createTextNode(``);r.replaceWith(i),n.comments.delete(e),o(a.signal,e=>{i.textContent=String(e)},t)}}else a.type===`html`?r?.onHtml?.(a):(i.has(e)||i.set(e,[]),i.get(e).push(a))}for(let[e,r]of i){let i=n.elements.get(e);if(i){i.removeAttribute(`u`),n.elements.delete(e);for(let e of r)switch(e.type){case`attr`:s(i,e,t);break;case`callback`:e.apply(i,t);break;case`event`:l(i,e,t);break;case`prop`:c(i,e,t);break;case`ref`:u(i,e,t);break}}}},f=(e,t,n,i)=>{d(t,n,r.indexBindings(e),i)},p=(e,n,r,i)=>{let a=t.toReactiveBindingSource(i);return a?{mode:e,name:n,signal:a,type:`attr`,uid:r}:{mode:e,name:n,type:`attr`,uid:r,value:i}},m=(e,n,r)=>{let i=t.toReactiveBindingSource(r);return i?{model:t.hasWritableValueSetter(r)?r:void 0,name:e,signal:i,type:`prop`,uid:n}:{name:e,type:`prop`,uid:n,value:r}};exports.applyBindingsInContainer=f,exports.applyBindingsWithTargets=d,exports.createAttrBinding=p,exports.createPropBinding=m;
1
+ const e=require(`./internal.cjs`),t=require(`./props.cjs`),n=require(`./directives/live.cjs`);let r=require(`@vielzeug/stateit`);var i=e=>{let t=document.createElement(`template`);return t.innerHTML=e,t.content.cloneNode(!0)},a=(e,t)=>{if(e.nodeType===Node.COMMENT_NODE){let n=e.nodeValue;n&&t.comments.set(n,e);return}if(e.nodeType!==Node.ELEMENT_NODE)return;let n=e.getAttribute(`u`);n&&t.elements.set(n,e)},o=(e,t)=>{let n=document.createTreeWalker(e,NodeFilter.SHOW_COMMENT|NodeFilter.SHOW_ELEMENT);for(t(e);n.nextNode();)t(n.currentNode)},s=e=>{let t={comments:new Map,elements:new Map};for(let n of e)o(n,e=>a(e,t));return t},c=(e,t)=>{let n=document.createTreeWalker(e,NodeFilter.SHOW_COMMENT);for(;n.nextNode();){let e=n.currentNode;if(e.nodeValue===t)return e}return null},l=e=>Array.isArray(e)||typeof e==`object`&&!!e,u=e=>e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement,d=(e,t,n,r)=>{let i=t==null?``:String(t);n&&r.last!==void 0&&!Object.is(e.value,r.last)&&!Object.is(e.value,i)||(e.value=i,n&&(r.last=i))},f=(e,t,n,r)=>{let i=!!t;n&&r.last!==void 0&&e.checked!==!!r.last&&e.checked!==i||(e.checked=i,n&&(r.last=i))},p=(t,n,i,a)=>{let o=l(a)?a:n.parse(i.mode===`bool`?a?``:null:a==null||a===!1?null:String(a));if(Object.is((0,r.untrack)(()=>n.signal.value),o)||(n.signal.value=o),!n.reflect){if(l(a))return;i.mode===`bool`?t.toggleAttribute(i.name,!!a):e.setAttr(t,i.name,a)}},m=(e,t,n)=>{n((0,r.effect)(()=>t(e.value)))},h=(n,r,i)=>{let a=t.propRegistry.get(n)?.get(r.name),o={last:void 0},s=t=>{if(!a&&l(t)){n[r.name]=t;return}if(!a&&r.name===`value`&&u(n)){d(n,t,r.live,o);return}if(!a&&r.name===`checked`&&n instanceof HTMLInputElement){f(n,t,r.live,o);return}if(!a){r.mode===`bool`?n.toggleAttribute(r.name,!!t):e.setAttr(n,r.name,t);return}p(n,a,r,t)};r.signal?m(r.signal,s,i):s(r.value)},g=(t,n,r)=>{r(e.listen(t,n.name,n.handler,n.options))},_=(e,t,n)=>{let{ref:r}=t;if(typeof r==`function`){r(e),n(()=>r(null));return}if(Array.isArray(r)){r.push(e),n(()=>{let t=r.indexOf(e);t!==-1&&r.splice(t,1)});return}r.value=e,n(()=>{r.value=null})},v=(e,t,n,r)=>{let i=new Map;for(let a of e){let e=a.uid;if(a.type===`text`){let r=n.comments.get(e);if(r){let i=document.createTextNode(``);r.replaceWith(i),n.comments.delete(e),m(a.signal,e=>{i.textContent=String(e)},t)}}else if(a.type===`directive`){let r=n.comments.get(e);r&&(a.directive.mount(r,t),n.comments.delete(e))}else if(a.type===`html`)r?.onHtml?.(a);else{let t=i.get(e);t?t.push(a):i.set(e,[a])}}for(let[e,r]of i){let i=n.elements.get(e);if(i){i.removeAttribute(`u`),n.elements.delete(e);for(let e of r)e.type===`attr`?h(i,e,t):e.type===`event`?g(i,e,t):e.type===`ref`&&_(i,e,t)}}},y=(e,t,n,r)=>{v(t,n,s([e]),r)},b=(e,t,i,a)=>n.isLiveSignal(a)?{live:!0,mode:e,name:t,signal:a,type:`attr`,uid:i}:typeof a==`function`?{mode:e,name:t,signal:(0,r.computed)(a),type:`attr`,uid:i}:(0,r.isSignal)(a)?{mode:e,name:t,signal:a,type:`attr`,uid:i}:{mode:e,name:t,type:`attr`,uid:i,value:a},x=(t,n,a)=>{let o=c(t,n.uid);if(!o)return;let s=document.createComment(`html-binding`);o.replaceWith(s);let l=[],u=e=>l.push(e),d=()=>{e.runAll(l),l=[]},f=null,p=[];a((0,r.effect)(()=>{(0,r.batch)(()=>{let a;try{a=n.signal.value}catch(e){if(e instanceof Error&&e.message.includes(`[stateit] Cannot read disposed computed signal`))return;throw e}if(a.html===f)return;f=a.html,d();let{bindings:o,html:c}=a,l=s.parentElement||t;(0,r.untrack)(()=>{(0,r.batch)(()=>{e.removeNodes(p);let t=i(c);p=Array.from(t.childNodes),s.after(t)}),y(l,o,u,{onHtml:e=>x(l,e,u)})})})})),a(d)};exports.applyBindingsInContainer=y,exports.applyBindingsWithTargets=v,exports.applyHtmlBinding=x,exports.createAttrBinding=b,exports.indexBindingTargets=s,exports.parseHTML=i;
2
2
  //# sourceMappingURL=template-bindings.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"template-bindings.cjs","names":[],"sources":["../src/template-bindings.ts"],"sourcesContent":["import { effect as rawEffect, type CleanupFn, type ReadonlySignal, untrack } from '@vielzeug/stateit';\n\nimport {\n type AttrBinding,\n type EventBinding,\n type PropBinding,\n type RefBinding,\n type Binding,\n type HtmlBinding,\n CF_ID_ATTR,\n} from './internal';\nimport { listen, setAttr } from './internal';\nimport { propRegistry } from './props';\nimport { bindPropertyModel } from './runtime-bindings';\nimport { indexBindings, type BindingTargets } from './template-dom';\n\nexport type RegisterCleanup = (fn: CleanupFn) => void;\n\n// ─── Helper utilities ────────────────────────────────────────────────────────\n\n/** Check if a value is a structured type (object or array), not a primitive. */\nconst isStructuredValue = (value: unknown): value is object =>\n Array.isArray(value) || (typeof value === 'object' && value !== null);\n\n/**\n * Register a reactive effect that updates when a signal changes.\n * Common pattern: `if (signal) registerCleanup(effect(() => update(signal.value)))`\n */\nconst signalEffect = (\n signal: ReadonlySignal<unknown>,\n update: (v: unknown) => void,\n registerCleanup: RegisterCleanup,\n): void => {\n registerCleanup(rawEffect(() => update(signal.value)));\n};\n\n// ─── Individual binding application functions ─────────────────────────────────\n\n/**\n * Apply an attribute binding to an element.\n * Handles bool/attr modes, prop pre-upgrade, and reactive updates.\n */\nexport const applyAttrBinding = (el: HTMLElement, binding: AttrBinding, registerCleanup: RegisterCleanup) => {\n const update = (value: unknown) => {\n const meta = propRegistry.get(el)?.get(binding.name);\n\n // Preserve structured values as pre-upgrade properties\n if (!meta && isStructuredValue(value)) {\n (el as any)[binding.name] = value;\n\n return;\n }\n\n if (!meta || meta.reflect) {\n if (binding.mode === 'bool') {\n el.toggleAttribute(binding.name, Boolean(value));\n } else {\n setAttr(el, binding.name, value);\n }\n }\n\n if (!meta) return;\n\n const parsedValue = isStructuredValue(value)\n ? value\n : meta.parse(\n binding.mode === 'bool' ? (value ? '' : null) : value == null || value === false ? null : String(value),\n );\n\n if (\n !Object.is(\n untrack(() => meta.signal.value),\n parsedValue,\n )\n ) {\n meta.signal.value = parsedValue as never;\n }\n };\n\n if (binding.signal) {\n signalEffect(binding.signal, update, registerCleanup);\n } else {\n update(binding.value!);\n }\n};\n\n/**\n * Apply a property binding to an element.\n * Handles reactive updates and two-way binding via property models.\n */\nexport const applyPropBinding = (el: HTMLElement, binding: PropBinding, registerCleanup: RegisterCleanup) => {\n const update = (value: unknown) => {\n (el as any)[binding.name] = value;\n };\n\n if (binding.signal) {\n signalEffect(binding.signal, update, registerCleanup);\n } else {\n update(binding.value!);\n }\n\n bindPropertyModel(el, binding.name, binding.model, registerCleanup);\n};\n\n/**\n * Apply an event listener binding to an element.\n * Handles event modifiers (stop, prevent, self, capture, once, passive).\n */\nexport const applyEventBinding = (el: HTMLElement, binding: EventBinding, registerCleanup: RegisterCleanup) => {\n const { modifiers } = binding;\n const listenerOptions = modifiers\n ? { capture: !!modifiers.capture, once: !!modifiers.once, passive: !!modifiers.passive }\n : undefined;\n\n const wrappedHandler = (event: Event) => {\n if (modifiers?.self && event.target !== event.currentTarget) return;\n\n if (modifiers?.stop) event.stopPropagation();\n\n if (modifiers?.prevent && !modifiers?.passive) event.preventDefault();\n\n binding.handler(event);\n };\n\n registerCleanup(listen(el, binding.name, wrappedHandler, listenerOptions));\n};\n\n/**\n * Apply a ref binding to an element.\n * Supports function refs, ref arrays, and signal refs with cleanup.\n */\nexport const applyRefBinding = (el: HTMLElement, binding: RefBinding, registerCleanup: RegisterCleanup) => {\n const { ref } = binding;\n\n if (typeof ref === 'function') {\n ref(el as never);\n registerCleanup(() => ref(null));\n\n return;\n }\n\n if (Array.isArray(ref)) {\n ref.push(el);\n registerCleanup(() => {\n const idx = ref.indexOf(el);\n\n if (idx !== -1) ref.splice(idx, 1);\n });\n\n return;\n }\n\n ref.value = el as never;\n registerCleanup(() => {\n ref.value = null;\n });\n};\n\n// ─── Binding orchestration ────────────────────────────────────────────────────\n\n/**\n * Apply all bindings to target elements.\n *\n * - Text bindings: Create text nodes, register reactive effects\n * - HTML bindings: Notify caller for keyed reconciliation\n * - Element bindings: Group by ID, apply attr/prop/event/ref in one pass per element\n *\n * @param bindings Array of compiled bindings to apply\n * @param registerCleanup Function to register cleanup callbacks\n * @param targets Indexed comment/element targets from DOM\n * @param opts Optional callbacks (e.g., onHtml for keyed reconciliation)\n */\nexport const applyBindingsWithTargets = (\n bindings: Binding[],\n registerCleanup: RegisterCleanup,\n targets: BindingTargets,\n opts?: { onHtml?: (b: HtmlBinding) => void },\n) => {\n const bindingMap = new Map<string, Binding[]>();\n\n for (const b of bindings) {\n const id = b.uid;\n\n if (b.type === 'text') {\n const found = targets.comments.get(id);\n\n if (found) {\n const textNode = document.createTextNode('');\n\n found.replaceWith(textNode);\n targets.comments.delete(id);\n signalEffect(\n b.signal,\n (v) => {\n textNode.textContent = String(v);\n },\n registerCleanup,\n );\n }\n } else if (b.type === 'html') {\n opts?.onHtml?.(b);\n } else {\n if (!bindingMap.has(id)) bindingMap.set(id, []);\n\n bindingMap.get(id)!.push(b);\n }\n }\n\n for (const [id, elBindings] of bindingMap) {\n const el = targets.elements.get(id);\n\n if (!el) continue;\n\n el.removeAttribute(CF_ID_ATTR);\n targets.elements.delete(id);\n\n for (const b of elBindings) {\n switch (b.type) {\n case 'attr':\n applyAttrBinding(el, b, registerCleanup);\n break;\n case 'callback':\n b.apply(el, registerCleanup);\n break;\n case 'event':\n applyEventBinding(el, b, registerCleanup);\n break;\n case 'prop':\n applyPropBinding(el, b, registerCleanup);\n break;\n case 'ref':\n applyRefBinding(el, b, registerCleanup);\n break;\n }\n }\n }\n};\n\nexport const applyBindingsInContainer = (\n container: ParentNode,\n bindings: Binding[],\n registerCleanup: RegisterCleanup,\n opts?: { onHtml?: (b: HtmlBinding) => void },\n) => {\n applyBindingsWithTargets(bindings, registerCleanup, indexBindings(container), opts);\n};\n\n// ─── Binding factories ────────────────────────────────────────────────────────\n\nimport { type Signal } from '@vielzeug/stateit';\n\nimport { hasWritableValueSetter, toReactiveBindingSource } from './runtime-bindings';\n\n/**\n * Create an attribute binding descriptor.\n * Called during template compilation for each attribute interpolation.\n *\n * @param mode 'bool' for boolean attributes (presence = true), 'attr' for string values\n * @param name Attribute name (e.g., 'disabled', 'aria-label')\n * @param uid Unique binding ID\n * @param value Attribute value (signal or static)\n */\nexport const createAttrBinding = (mode: 'bool' | 'attr', name: string, uid: string, value: unknown): AttrBinding => {\n const source = toReactiveBindingSource(value);\n\n return source ? { mode, name, signal: source, type: 'attr', uid } : { mode, name, type: 'attr', uid, value };\n};\n\n/**\n * Create a property binding descriptor.\n * Called during template compilation for each `.property` interpolation.\n *\n * @param name Property name (e.g., 'value', 'checked')\n * @param uid Unique binding ID\n * @param value Property value (signal, function, or static)\n */\nexport const createPropBinding = (name: string, uid: string, value: unknown): PropBinding => {\n const source = toReactiveBindingSource(value);\n\n if (source) {\n return {\n model: hasWritableValueSetter(value) ? (value as Signal<unknown>) : undefined,\n name,\n signal: source,\n type: 'prop',\n uid,\n };\n }\n\n return { name, type: 'prop', uid, value };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"template-bindings.cjs","names":[],"sources":["../src/template-bindings.ts"],"sourcesContent":["import {\n batch,\n computed,\n effect as rawEffect,\n isSignal,\n type CleanupFn,\n type ReadonlySignal,\n untrack,\n} from '@vielzeug/stateit';\n\nimport { isLiveSignal } from './directives/live';\nimport {\n CF_ID_ATTR,\n type AttrBinding,\n type Binding,\n type EventBinding,\n type HtmlBinding,\n type RefBinding,\n listen,\n removeNodes,\n runAll,\n setAttr,\n} from './internal';\nimport { propRegistry } from './props';\n\nexport type RegisterCleanup = (fn: CleanupFn) => void;\n\nexport type BindingTargets = {\n comments: Map<string, Comment>;\n elements: Map<string, HTMLElement>;\n};\n\nexport const parseHTML = (html: string): DocumentFragment => {\n const tpl = document.createElement('template');\n\n tpl.innerHTML = html;\n\n return tpl.content.cloneNode(true) as DocumentFragment;\n};\n\nconst collectBindingTarget = (node: Node, targets: BindingTargets): void => {\n if (node.nodeType === Node.COMMENT_NODE) {\n const marker = (node as Comment).nodeValue;\n\n if (marker) targets.comments.set(marker, node as Comment);\n\n return;\n }\n\n if (node.nodeType !== Node.ELEMENT_NODE) return;\n\n const id = (node as Element).getAttribute(CF_ID_ATTR);\n\n if (id) targets.elements.set(id, node as HTMLElement);\n};\n\nconst walkBindingTargets = (root: Node, visit: (node: Node) => void): void => {\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_ELEMENT);\n\n visit(root);\n\n while (walker.nextNode()) visit(walker.currentNode);\n};\n\nexport const indexBindingTargets = (nodes: Iterable<Node>): BindingTargets => {\n const targets: BindingTargets = { comments: new Map(), elements: new Map() };\n\n for (const node of nodes) walkBindingTargets(node, (current) => collectBindingTarget(current, targets));\n\n return targets;\n};\n\nexport const findCommentMarker = (root: Node, marker: string): Comment | null => {\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_COMMENT);\n\n while (walker.nextNode()) {\n const comment = walker.currentNode as Comment;\n\n if (comment.nodeValue === marker) return comment;\n }\n\n return null;\n};\n\nconst isStructuredValue = (value: unknown): value is object =>\n Array.isArray(value) || (typeof value === 'object' && value !== null);\n\nconst isNativeFormInput = (el: HTMLElement): el is HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement =>\n el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement;\n\ntype LiveWriteState = { last: unknown };\n\nconst applyFormValue = (\n el: HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement,\n value: unknown,\n isLive: boolean | undefined,\n state: LiveWriteState,\n): void => {\n const next = value == null ? '' : String(value);\n\n if (isLive && state.last !== undefined && !Object.is(el.value, state.last) && !Object.is(el.value, next)) return;\n\n el.value = next;\n\n if (isLive) state.last = next;\n};\n\nconst applyCheckedValue = (\n el: HTMLInputElement,\n value: unknown,\n isLive: boolean | undefined,\n state: LiveWriteState,\n): void => {\n const next = Boolean(value);\n\n if (isLive && state.last !== undefined && el.checked !== Boolean(state.last) && el.checked !== next) return;\n\n el.checked = next;\n\n if (isLive) state.last = next;\n};\n\ntype PropMetaLike = { parse: (v: string | null) => unknown; reflect: boolean; signal: { value: unknown } };\n\nconst syncRegisteredProp = (el: HTMLElement, meta: PropMetaLike, binding: AttrBinding, value: unknown): void => {\n const parsed = isStructuredValue(value)\n ? value\n : meta.parse(\n binding.mode === 'bool' ? (value ? '' : null) : value == null || value === false ? null : String(value),\n );\n\n if (\n !Object.is(\n untrack(() => meta.signal.value),\n parsed,\n )\n ) {\n meta.signal.value = parsed as never;\n }\n\n // When reflect:false the prop signal has no reflect-effect; write the attribute\n // directly so the DOM stays in sync with template bindings.\n if (!meta.reflect) {\n if (isStructuredValue(value)) return;\n\n if (binding.mode === 'bool') el.toggleAttribute(binding.name, Boolean(value));\n else setAttr(el, binding.name, value);\n }\n};\n\nconst signalEffect = (\n signal: ReadonlySignal<unknown>,\n update: (v: unknown) => void,\n registerCleanup: RegisterCleanup,\n): void => {\n registerCleanup(rawEffect(() => update(signal.value)));\n};\n\nexport const applyAttrBinding = (el: HTMLElement, binding: AttrBinding, registerCleanup: RegisterCleanup): void => {\n const meta = propRegistry.get(el)?.get(binding.name) as PropMetaLike | undefined;\n const liveState: LiveWriteState = { last: undefined };\n\n const update = (value: unknown): void => {\n if (!meta && isStructuredValue(value)) {\n (el as unknown as Record<string, unknown>)[binding.name] = value;\n\n return;\n }\n\n if (!meta && binding.name === 'value' && isNativeFormInput(el)) {\n applyFormValue(el, value, binding.live, liveState);\n\n return;\n }\n\n if (!meta && binding.name === 'checked' && el instanceof HTMLInputElement) {\n applyCheckedValue(el, value, binding.live, liveState);\n\n return;\n }\n\n if (!meta) {\n if (binding.mode === 'bool') el.toggleAttribute(binding.name, Boolean(value));\n else setAttr(el, binding.name, value);\n\n return;\n }\n\n syncRegisteredProp(el, meta, binding, value);\n };\n\n if (binding.signal) {\n signalEffect(binding.signal, update, registerCleanup);\n } else {\n update(binding.value!);\n }\n};\n\nexport const applyEventBinding = (el: HTMLElement, binding: EventBinding, registerCleanup: RegisterCleanup) => {\n registerCleanup(listen(el, binding.name, binding.handler, binding.options));\n};\n\nexport const applyRefBinding = (el: HTMLElement, binding: RefBinding, registerCleanup: RegisterCleanup) => {\n const { ref } = binding;\n\n if (typeof ref === 'function') {\n ref(el as never);\n registerCleanup(() => ref(null as never));\n\n return;\n }\n\n if (Array.isArray(ref)) {\n ref.push(el);\n registerCleanup(() => {\n const i = ref.indexOf(el);\n\n if (i !== -1) ref.splice(i, 1);\n });\n\n return;\n }\n\n ref.value = el as never;\n registerCleanup(() => {\n ref.value = null as never;\n });\n};\n\ntype ElementBinding = AttrBinding | EventBinding | RefBinding;\n\nexport const applyBindingsWithTargets = (\n bindings: Binding[],\n registerCleanup: RegisterCleanup,\n targets: BindingTargets,\n opts?: { onHtml?: (b: HtmlBinding) => void },\n) => {\n const bindingMap = new Map<string, ElementBinding[]>();\n\n for (const b of bindings) {\n const id = b.uid;\n\n if (b.type === 'text') {\n const found = targets.comments.get(id);\n\n if (found) {\n const textNode = document.createTextNode('');\n\n found.replaceWith(textNode);\n targets.comments.delete(id);\n signalEffect(\n b.signal,\n (v) => {\n textNode.textContent = String(v);\n },\n registerCleanup,\n );\n }\n } else if (b.type === 'directive') {\n const found = targets.comments.get(id);\n\n if (found) {\n b.directive.mount(found, registerCleanup);\n targets.comments.delete(id);\n }\n } else if (b.type === 'html') {\n opts?.onHtml?.(b);\n } else {\n const grouped = bindingMap.get(id);\n\n if (grouped) grouped.push(b);\n else bindingMap.set(id, [b]);\n }\n }\n\n for (const [id, elBindings] of bindingMap) {\n const el = targets.elements.get(id);\n\n if (!el) continue;\n\n el.removeAttribute(CF_ID_ATTR);\n targets.elements.delete(id);\n\n // Inline element binding dispatch\n for (const b of elBindings) {\n if (b.type === 'attr') {\n applyAttrBinding(el, b, registerCleanup);\n } else if (b.type === 'event') {\n applyEventBinding(el, b, registerCleanup);\n } else if (b.type === 'ref') {\n applyRefBinding(el, b, registerCleanup);\n }\n }\n }\n};\n\nexport const applyBindingsInContainer = (\n container: ParentNode,\n bindings: Binding[],\n registerCleanup: RegisterCleanup,\n opts?: { onHtml?: (b: HtmlBinding) => void },\n) => {\n applyBindingsWithTargets(bindings, registerCleanup, indexBindingTargets([container]), opts);\n};\n\nexport const createAttrBinding = (mode: 'bool' | 'attr', name: string, uid: string, value: unknown): AttrBinding => {\n if (isLiveSignal(value)) {\n return { live: true, mode, name, signal: value as ReadonlySignal<unknown>, type: 'attr', uid };\n }\n\n if (typeof value === 'function') {\n return { mode, name, signal: computed(value as () => unknown), type: 'attr', uid };\n }\n\n if (isSignal(value)) {\n return { mode, name, signal: value as ReadonlySignal<unknown>, type: 'attr', uid };\n }\n\n return { mode, name, type: 'attr', uid, value };\n};\n\n/**\n * Sets up the reactive effect for an html-binding marker using full fragment replacement.\n */\nexport const applyHtmlBinding = (root: Node, b: HtmlBinding, registerCleanup: RegisterCleanup): void => {\n const found = findCommentMarker(root, b.uid);\n\n if (!found) return;\n\n const marker = document.createComment('html-binding');\n\n found.replaceWith(marker);\n\n let currentCleanups: CleanupFn[] = [];\n const registerInnerCleanup: RegisterCleanup = (fn) => currentCleanups.push(fn);\n const runCurrentCleanups = () => {\n runAll(currentCleanups);\n currentCleanups = [];\n };\n let lastHtml: string | null = null;\n let lastInsertedNodes: Node[] = [];\n\n const stop = rawEffect(() => {\n batch(() => {\n let data: HtmlBinding['signal']['value'];\n\n try {\n data = b.signal.value;\n } catch (error) {\n if (error instanceof Error && error.message.includes('[stateit] Cannot read disposed computed signal')) return;\n\n throw error;\n }\n\n if (data.html === lastHtml) {\n return;\n }\n\n lastHtml = data.html;\n runCurrentCleanups();\n\n const { bindings, html } = data;\n const container = (marker.parentElement || root) as ParentNode;\n\n untrack(() => {\n batch(() => {\n removeNodes(lastInsertedNodes);\n\n const parsed = parseHTML(html);\n\n lastInsertedNodes = Array.from(parsed.childNodes);\n marker.after(parsed);\n });\n\n applyBindingsInContainer(container, bindings, registerInnerCleanup, {\n onHtml: (binding) => applyHtmlBinding(container as unknown as Node, binding, registerInnerCleanup),\n });\n });\n });\n });\n\n registerCleanup(stop);\n registerCleanup(runCurrentCleanups);\n};\n"],"mappings":"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"}
@@ -1,62 +1,25 @@
1
1
  import { type CleanupFn } from '@vielzeug/stateit';
2
- import { type AttrBinding, type EventBinding, type PropBinding, type RefBinding, type Binding, type HtmlBinding } from './internal';
3
- import { type BindingTargets } from './template-dom';
2
+ import { type AttrBinding, type Binding, type EventBinding, type HtmlBinding, type RefBinding } from './internal';
4
3
  export type RegisterCleanup = (fn: CleanupFn) => void;
5
- /**
6
- * Apply an attribute binding to an element.
7
- * Handles bool/attr modes, prop pre-upgrade, and reactive updates.
8
- */
4
+ export type BindingTargets = {
5
+ comments: Map<string, Comment>;
6
+ elements: Map<string, HTMLElement>;
7
+ };
8
+ export declare const parseHTML: (html: string) => DocumentFragment;
9
+ export declare const indexBindingTargets: (nodes: Iterable<Node>) => BindingTargets;
10
+ export declare const findCommentMarker: (root: Node, marker: string) => Comment | null;
9
11
  export declare const applyAttrBinding: (el: HTMLElement, binding: AttrBinding, registerCleanup: RegisterCleanup) => void;
10
- /**
11
- * Apply a property binding to an element.
12
- * Handles reactive updates and two-way binding via property models.
13
- */
14
- export declare const applyPropBinding: (el: HTMLElement, binding: PropBinding, registerCleanup: RegisterCleanup) => void;
15
- /**
16
- * Apply an event listener binding to an element.
17
- * Handles event modifiers (stop, prevent, self, capture, once, passive).
18
- */
19
12
  export declare const applyEventBinding: (el: HTMLElement, binding: EventBinding, registerCleanup: RegisterCleanup) => void;
20
- /**
21
- * Apply a ref binding to an element.
22
- * Supports function refs, ref arrays, and signal refs with cleanup.
23
- */
24
13
  export declare const applyRefBinding: (el: HTMLElement, binding: RefBinding, registerCleanup: RegisterCleanup) => void;
25
- /**
26
- * Apply all bindings to target elements.
27
- *
28
- * - Text bindings: Create text nodes, register reactive effects
29
- * - HTML bindings: Notify caller for keyed reconciliation
30
- * - Element bindings: Group by ID, apply attr/prop/event/ref in one pass per element
31
- *
32
- * @param bindings Array of compiled bindings to apply
33
- * @param registerCleanup Function to register cleanup callbacks
34
- * @param targets Indexed comment/element targets from DOM
35
- * @param opts Optional callbacks (e.g., onHtml for keyed reconciliation)
36
- */
37
14
  export declare const applyBindingsWithTargets: (bindings: Binding[], registerCleanup: RegisterCleanup, targets: BindingTargets, opts?: {
38
15
  onHtml?: (b: HtmlBinding) => void;
39
16
  }) => void;
40
17
  export declare const applyBindingsInContainer: (container: ParentNode, bindings: Binding[], registerCleanup: RegisterCleanup, opts?: {
41
18
  onHtml?: (b: HtmlBinding) => void;
42
19
  }) => void;
43
- /**
44
- * Create an attribute binding descriptor.
45
- * Called during template compilation for each attribute interpolation.
46
- *
47
- * @param mode 'bool' for boolean attributes (presence = true), 'attr' for string values
48
- * @param name Attribute name (e.g., 'disabled', 'aria-label')
49
- * @param uid Unique binding ID
50
- * @param value Attribute value (signal or static)
51
- */
52
20
  export declare const createAttrBinding: (mode: "bool" | "attr", name: string, uid: string, value: unknown) => AttrBinding;
53
21
  /**
54
- * Create a property binding descriptor.
55
- * Called during template compilation for each `.property` interpolation.
56
- *
57
- * @param name Property name (e.g., 'value', 'checked')
58
- * @param uid Unique binding ID
59
- * @param value Property value (signal, function, or static)
22
+ * Sets up the reactive effect for an html-binding marker using full fragment replacement.
60
23
  */
61
- export declare const createPropBinding: (name: string, uid: string, value: unknown) => PropBinding;
24
+ export declare const applyHtmlBinding: (root: Node, b: HtmlBinding, registerCleanup: RegisterCleanup) => void;
62
25
  //# sourceMappingURL=template-bindings.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"template-bindings.d.ts","sourceRoot":"","sources":["../src/template-bindings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,SAAS,EAAgC,MAAM,mBAAmB,CAAC;AAEtG,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,OAAO,EACZ,KAAK,WAAW,EAEjB,MAAM,YAAY,CAAC;AAIpB,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEpE,MAAM,MAAM,eAAe,GAAG,CAAC,EAAE,EAAE,SAAS,KAAK,IAAI,CAAC;AAsBtD;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAAI,IAAI,WAAW,EAAE,SAAS,WAAW,EAAE,iBAAiB,eAAe,SA0CvG,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAAI,IAAI,WAAW,EAAE,SAAS,WAAW,EAAE,iBAAiB,eAAe,SAYvG,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAAI,IAAI,WAAW,EAAE,SAAS,YAAY,EAAE,iBAAiB,eAAe,SAiBzG,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,eAAe,GAAI,IAAI,WAAW,EAAE,SAAS,UAAU,EAAE,iBAAiB,eAAe,SAyBrG,CAAC;AAIF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,wBAAwB,GACnC,UAAU,OAAO,EAAE,EACnB,iBAAiB,eAAe,EAChC,SAAS,cAAc,EACvB,OAAO;IAAE,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,WAAW,KAAK,IAAI,CAAA;CAAE,SA4D7C,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,WAAW,UAAU,EACrB,UAAU,OAAO,EAAE,EACnB,iBAAiB,eAAe,EAChC,OAAO;IAAE,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,WAAW,KAAK,IAAI,CAAA;CAAE,SAG7C,CAAC;AAQF;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,GAAG,MAAM,EAAE,MAAM,MAAM,EAAE,KAAK,MAAM,EAAE,OAAO,OAAO,KAAG,WAIpG,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,EAAE,KAAK,MAAM,EAAE,OAAO,OAAO,KAAG,WAc7E,CAAC"}
1
+ {"version":3,"file":"template-bindings.d.ts","sourceRoot":"","sources":["../src/template-bindings.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,SAAS,EAGf,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,OAAO,EACZ,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,UAAU,EAKhB,MAAM,YAAY,CAAC;AAGpB,MAAM,MAAM,eAAe,GAAG,CAAC,EAAE,EAAE,SAAS,KAAK,IAAI,CAAC;AAEtD,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CACpC,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,KAAG,gBAMxC,CAAC;AA0BF,eAAO,MAAM,mBAAmB,GAAI,OAAO,QAAQ,CAAC,IAAI,CAAC,KAAG,cAM3D,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,MAAM,IAAI,EAAE,QAAQ,MAAM,KAAG,OAAO,GAAG,IAUxE,CAAC;AA4EF,eAAO,MAAM,gBAAgB,GAAI,IAAI,WAAW,EAAE,SAAS,WAAW,EAAE,iBAAiB,eAAe,KAAG,IAsC1G,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,IAAI,WAAW,EAAE,SAAS,YAAY,EAAE,iBAAiB,eAAe,SAEzG,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,IAAI,WAAW,EAAE,SAAS,UAAU,EAAE,iBAAiB,eAAe,SAyBrG,CAAC;AAIF,eAAO,MAAM,wBAAwB,GACnC,UAAU,OAAO,EAAE,EACnB,iBAAiB,eAAe,EAChC,SAAS,cAAc,EACvB,OAAO;IAAE,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,WAAW,KAAK,IAAI,CAAA;CAAE,SA2D7C,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,WAAW,UAAU,EACrB,UAAU,OAAO,EAAE,EACnB,iBAAiB,eAAe,EAChC,OAAO;IAAE,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,WAAW,KAAK,IAAI,CAAA;CAAE,SAG7C,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,GAAG,MAAM,EAAE,MAAM,MAAM,EAAE,KAAK,MAAM,EAAE,OAAO,OAAO,KAAG,WAcpG,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gBAAgB,GAAI,MAAM,IAAI,EAAE,GAAG,WAAW,EAAE,iBAAiB,eAAe,KAAG,IA2D/F,CAAC"}
@@ -1,2 +1,2 @@
1
- import{listen as e,setAttr as t}from"./internal.js";import{bindPropertyModel as n,hasWritableValueSetter as r,toReactiveBindingSource as i}from"./runtime-bindings.js";import{propRegistry as a}from"./props.js";import{indexBindings as o}from"./template-dom.js";import{effect as s,untrack as c}from"@vielzeug/stateit";var l=e=>Array.isArray(e)||typeof e==`object`&&!!e,u=(e,t,n)=>{n(s(()=>t(e.value)))},d=(e,n,r)=>{let i=r=>{let i=a.get(e)?.get(n.name);if(!i&&l(r)){e[n.name]=r;return}if((!i||i.reflect)&&(n.mode===`bool`?e.toggleAttribute(n.name,!!r):t(e,n.name,r)),!i)return;let o=l(r)?r:i.parse(n.mode===`bool`?r?``:null:r==null||r===!1?null:String(r));Object.is(c(()=>i.signal.value),o)||(i.signal.value=o)};n.signal?u(n.signal,i,r):i(n.value)},f=(e,t,r)=>{let i=n=>{e[t.name]=n};t.signal?u(t.signal,i,r):i(t.value),n(e,t.name,t.model,r)},p=(t,n,r)=>{let{modifiers:i}=n,a=i?{capture:!!i.capture,once:!!i.once,passive:!!i.passive}:void 0;r(e(t,n.name,e=>{i?.self&&e.target!==e.currentTarget||(i?.stop&&e.stopPropagation(),i?.prevent&&!i?.passive&&e.preventDefault(),n.handler(e))},a))},m=(e,t,n)=>{let{ref:r}=t;if(typeof r==`function`){r(e),n(()=>r(null));return}if(Array.isArray(r)){r.push(e),n(()=>{let t=r.indexOf(e);t!==-1&&r.splice(t,1)});return}r.value=e,n(()=>{r.value=null})},h=(e,t,n,r)=>{let i=new Map;for(let a of e){let e=a.uid;if(a.type===`text`){let r=n.comments.get(e);if(r){let i=document.createTextNode(``);r.replaceWith(i),n.comments.delete(e),u(a.signal,e=>{i.textContent=String(e)},t)}}else a.type===`html`?r?.onHtml?.(a):(i.has(e)||i.set(e,[]),i.get(e).push(a))}for(let[e,r]of i){let i=n.elements.get(e);if(i){i.removeAttribute(`u`),n.elements.delete(e);for(let e of r)switch(e.type){case`attr`:d(i,e,t);break;case`callback`:e.apply(i,t);break;case`event`:p(i,e,t);break;case`prop`:f(i,e,t);break;case`ref`:m(i,e,t);break}}}},g=(e,t,n,r)=>{h(t,n,o(e),r)},_=(e,t,n,r)=>{let a=i(r);return a?{mode:e,name:t,signal:a,type:`attr`,uid:n}:{mode:e,name:t,type:`attr`,uid:n,value:r}},v=(e,t,n)=>{let a=i(n);return a?{model:r(n)?n:void 0,name:e,signal:a,type:`prop`,uid:t}:{name:e,type:`prop`,uid:t,value:n}};export{g as applyBindingsInContainer,h as applyBindingsWithTargets,_ as createAttrBinding,v as createPropBinding};
1
+ import{listen as e,removeNodes as t,runAll as n,setAttr as r}from"./internal.js";import{propRegistry as i}from"./props.js";import{isLiveSignal as a}from"./directives/live.js";import{batch as o,computed as s,effect as c,isSignal as l,untrack as u}from"@vielzeug/stateit";var d=e=>{let t=document.createElement(`template`);return t.innerHTML=e,t.content.cloneNode(!0)},f=(e,t)=>{if(e.nodeType===Node.COMMENT_NODE){let n=e.nodeValue;n&&t.comments.set(n,e);return}if(e.nodeType!==Node.ELEMENT_NODE)return;let n=e.getAttribute(`u`);n&&t.elements.set(n,e)},p=(e,t)=>{let n=document.createTreeWalker(e,NodeFilter.SHOW_COMMENT|NodeFilter.SHOW_ELEMENT);for(t(e);n.nextNode();)t(n.currentNode)},m=e=>{let t={comments:new Map,elements:new Map};for(let n of e)p(n,e=>f(e,t));return t},h=(e,t)=>{let n=document.createTreeWalker(e,NodeFilter.SHOW_COMMENT);for(;n.nextNode();){let e=n.currentNode;if(e.nodeValue===t)return e}return null},g=e=>Array.isArray(e)||typeof e==`object`&&!!e,_=e=>e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement,v=(e,t,n,r)=>{let i=t==null?``:String(t);n&&r.last!==void 0&&!Object.is(e.value,r.last)&&!Object.is(e.value,i)||(e.value=i,n&&(r.last=i))},y=(e,t,n,r)=>{let i=!!t;n&&r.last!==void 0&&e.checked!==!!r.last&&e.checked!==i||(e.checked=i,n&&(r.last=i))},b=(e,t,n,i)=>{let a=g(i)?i:t.parse(n.mode===`bool`?i?``:null:i==null||i===!1?null:String(i));if(Object.is(u(()=>t.signal.value),a)||(t.signal.value=a),!t.reflect){if(g(i))return;n.mode===`bool`?e.toggleAttribute(n.name,!!i):r(e,n.name,i)}},x=(e,t,n)=>{n(c(()=>t(e.value)))},S=(e,t,n)=>{let a=i.get(e)?.get(t.name),o={last:void 0},s=n=>{if(!a&&g(n)){e[t.name]=n;return}if(!a&&t.name===`value`&&_(e)){v(e,n,t.live,o);return}if(!a&&t.name===`checked`&&e instanceof HTMLInputElement){y(e,n,t.live,o);return}if(!a){t.mode===`bool`?e.toggleAttribute(t.name,!!n):r(e,t.name,n);return}b(e,a,t,n)};t.signal?x(t.signal,s,n):s(t.value)},C=(t,n,r)=>{r(e(t,n.name,n.handler,n.options))},w=(e,t,n)=>{let{ref:r}=t;if(typeof r==`function`){r(e),n(()=>r(null));return}if(Array.isArray(r)){r.push(e),n(()=>{let t=r.indexOf(e);t!==-1&&r.splice(t,1)});return}r.value=e,n(()=>{r.value=null})},T=(e,t,n,r)=>{let i=new Map;for(let a of e){let e=a.uid;if(a.type===`text`){let r=n.comments.get(e);if(r){let i=document.createTextNode(``);r.replaceWith(i),n.comments.delete(e),x(a.signal,e=>{i.textContent=String(e)},t)}}else if(a.type===`directive`){let r=n.comments.get(e);r&&(a.directive.mount(r,t),n.comments.delete(e))}else if(a.type===`html`)r?.onHtml?.(a);else{let t=i.get(e);t?t.push(a):i.set(e,[a])}}for(let[e,r]of i){let i=n.elements.get(e);if(i){i.removeAttribute(`u`),n.elements.delete(e);for(let e of r)e.type===`attr`?S(i,e,t):e.type===`event`?C(i,e,t):e.type===`ref`&&w(i,e,t)}}},E=(e,t,n,r)=>{T(t,n,m([e]),r)},D=(e,t,n,r)=>a(r)?{live:!0,mode:e,name:t,signal:r,type:`attr`,uid:n}:typeof r==`function`?{mode:e,name:t,signal:s(r),type:`attr`,uid:n}:l(r)?{mode:e,name:t,signal:r,type:`attr`,uid:n}:{mode:e,name:t,type:`attr`,uid:n,value:r},O=(e,r,i)=>{let a=h(e,r.uid);if(!a)return;let s=document.createComment(`html-binding`);a.replaceWith(s);let l=[],f=e=>l.push(e),p=()=>{n(l),l=[]},m=null,g=[];i(c(()=>{o(()=>{let n;try{n=r.signal.value}catch(e){if(e instanceof Error&&e.message.includes(`[stateit] Cannot read disposed computed signal`))return;throw e}if(n.html===m)return;m=n.html,p();let{bindings:i,html:a}=n,c=s.parentElement||e;u(()=>{o(()=>{t(g);let e=d(a);g=Array.from(e.childNodes),s.after(e)}),E(c,i,f,{onHtml:e=>O(c,e,f)})})})})),i(p)};export{E as applyBindingsInContainer,T as applyBindingsWithTargets,O as applyHtmlBinding,D as createAttrBinding,m as indexBindingTargets,d as parseHTML};
2
2
  //# sourceMappingURL=template-bindings.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"template-bindings.js","names":[],"sources":["../src/template-bindings.ts"],"sourcesContent":["import { effect as rawEffect, type CleanupFn, type ReadonlySignal, untrack } from '@vielzeug/stateit';\n\nimport {\n type AttrBinding,\n type EventBinding,\n type PropBinding,\n type RefBinding,\n type Binding,\n type HtmlBinding,\n CF_ID_ATTR,\n} from './internal';\nimport { listen, setAttr } from './internal';\nimport { propRegistry } from './props';\nimport { bindPropertyModel } from './runtime-bindings';\nimport { indexBindings, type BindingTargets } from './template-dom';\n\nexport type RegisterCleanup = (fn: CleanupFn) => void;\n\n// ─── Helper utilities ────────────────────────────────────────────────────────\n\n/** Check if a value is a structured type (object or array), not a primitive. */\nconst isStructuredValue = (value: unknown): value is object =>\n Array.isArray(value) || (typeof value === 'object' && value !== null);\n\n/**\n * Register a reactive effect that updates when a signal changes.\n * Common pattern: `if (signal) registerCleanup(effect(() => update(signal.value)))`\n */\nconst signalEffect = (\n signal: ReadonlySignal<unknown>,\n update: (v: unknown) => void,\n registerCleanup: RegisterCleanup,\n): void => {\n registerCleanup(rawEffect(() => update(signal.value)));\n};\n\n// ─── Individual binding application functions ─────────────────────────────────\n\n/**\n * Apply an attribute binding to an element.\n * Handles bool/attr modes, prop pre-upgrade, and reactive updates.\n */\nexport const applyAttrBinding = (el: HTMLElement, binding: AttrBinding, registerCleanup: RegisterCleanup) => {\n const update = (value: unknown) => {\n const meta = propRegistry.get(el)?.get(binding.name);\n\n // Preserve structured values as pre-upgrade properties\n if (!meta && isStructuredValue(value)) {\n (el as any)[binding.name] = value;\n\n return;\n }\n\n if (!meta || meta.reflect) {\n if (binding.mode === 'bool') {\n el.toggleAttribute(binding.name, Boolean(value));\n } else {\n setAttr(el, binding.name, value);\n }\n }\n\n if (!meta) return;\n\n const parsedValue = isStructuredValue(value)\n ? value\n : meta.parse(\n binding.mode === 'bool' ? (value ? '' : null) : value == null || value === false ? null : String(value),\n );\n\n if (\n !Object.is(\n untrack(() => meta.signal.value),\n parsedValue,\n )\n ) {\n meta.signal.value = parsedValue as never;\n }\n };\n\n if (binding.signal) {\n signalEffect(binding.signal, update, registerCleanup);\n } else {\n update(binding.value!);\n }\n};\n\n/**\n * Apply a property binding to an element.\n * Handles reactive updates and two-way binding via property models.\n */\nexport const applyPropBinding = (el: HTMLElement, binding: PropBinding, registerCleanup: RegisterCleanup) => {\n const update = (value: unknown) => {\n (el as any)[binding.name] = value;\n };\n\n if (binding.signal) {\n signalEffect(binding.signal, update, registerCleanup);\n } else {\n update(binding.value!);\n }\n\n bindPropertyModel(el, binding.name, binding.model, registerCleanup);\n};\n\n/**\n * Apply an event listener binding to an element.\n * Handles event modifiers (stop, prevent, self, capture, once, passive).\n */\nexport const applyEventBinding = (el: HTMLElement, binding: EventBinding, registerCleanup: RegisterCleanup) => {\n const { modifiers } = binding;\n const listenerOptions = modifiers\n ? { capture: !!modifiers.capture, once: !!modifiers.once, passive: !!modifiers.passive }\n : undefined;\n\n const wrappedHandler = (event: Event) => {\n if (modifiers?.self && event.target !== event.currentTarget) return;\n\n if (modifiers?.stop) event.stopPropagation();\n\n if (modifiers?.prevent && !modifiers?.passive) event.preventDefault();\n\n binding.handler(event);\n };\n\n registerCleanup(listen(el, binding.name, wrappedHandler, listenerOptions));\n};\n\n/**\n * Apply a ref binding to an element.\n * Supports function refs, ref arrays, and signal refs with cleanup.\n */\nexport const applyRefBinding = (el: HTMLElement, binding: RefBinding, registerCleanup: RegisterCleanup) => {\n const { ref } = binding;\n\n if (typeof ref === 'function') {\n ref(el as never);\n registerCleanup(() => ref(null));\n\n return;\n }\n\n if (Array.isArray(ref)) {\n ref.push(el);\n registerCleanup(() => {\n const idx = ref.indexOf(el);\n\n if (idx !== -1) ref.splice(idx, 1);\n });\n\n return;\n }\n\n ref.value = el as never;\n registerCleanup(() => {\n ref.value = null;\n });\n};\n\n// ─── Binding orchestration ────────────────────────────────────────────────────\n\n/**\n * Apply all bindings to target elements.\n *\n * - Text bindings: Create text nodes, register reactive effects\n * - HTML bindings: Notify caller for keyed reconciliation\n * - Element bindings: Group by ID, apply attr/prop/event/ref in one pass per element\n *\n * @param bindings Array of compiled bindings to apply\n * @param registerCleanup Function to register cleanup callbacks\n * @param targets Indexed comment/element targets from DOM\n * @param opts Optional callbacks (e.g., onHtml for keyed reconciliation)\n */\nexport const applyBindingsWithTargets = (\n bindings: Binding[],\n registerCleanup: RegisterCleanup,\n targets: BindingTargets,\n opts?: { onHtml?: (b: HtmlBinding) => void },\n) => {\n const bindingMap = new Map<string, Binding[]>();\n\n for (const b of bindings) {\n const id = b.uid;\n\n if (b.type === 'text') {\n const found = targets.comments.get(id);\n\n if (found) {\n const textNode = document.createTextNode('');\n\n found.replaceWith(textNode);\n targets.comments.delete(id);\n signalEffect(\n b.signal,\n (v) => {\n textNode.textContent = String(v);\n },\n registerCleanup,\n );\n }\n } else if (b.type === 'html') {\n opts?.onHtml?.(b);\n } else {\n if (!bindingMap.has(id)) bindingMap.set(id, []);\n\n bindingMap.get(id)!.push(b);\n }\n }\n\n for (const [id, elBindings] of bindingMap) {\n const el = targets.elements.get(id);\n\n if (!el) continue;\n\n el.removeAttribute(CF_ID_ATTR);\n targets.elements.delete(id);\n\n for (const b of elBindings) {\n switch (b.type) {\n case 'attr':\n applyAttrBinding(el, b, registerCleanup);\n break;\n case 'callback':\n b.apply(el, registerCleanup);\n break;\n case 'event':\n applyEventBinding(el, b, registerCleanup);\n break;\n case 'prop':\n applyPropBinding(el, b, registerCleanup);\n break;\n case 'ref':\n applyRefBinding(el, b, registerCleanup);\n break;\n }\n }\n }\n};\n\nexport const applyBindingsInContainer = (\n container: ParentNode,\n bindings: Binding[],\n registerCleanup: RegisterCleanup,\n opts?: { onHtml?: (b: HtmlBinding) => void },\n) => {\n applyBindingsWithTargets(bindings, registerCleanup, indexBindings(container), opts);\n};\n\n// ─── Binding factories ────────────────────────────────────────────────────────\n\nimport { type Signal } from '@vielzeug/stateit';\n\nimport { hasWritableValueSetter, toReactiveBindingSource } from './runtime-bindings';\n\n/**\n * Create an attribute binding descriptor.\n * Called during template compilation for each attribute interpolation.\n *\n * @param mode 'bool' for boolean attributes (presence = true), 'attr' for string values\n * @param name Attribute name (e.g., 'disabled', 'aria-label')\n * @param uid Unique binding ID\n * @param value Attribute value (signal or static)\n */\nexport const createAttrBinding = (mode: 'bool' | 'attr', name: string, uid: string, value: unknown): AttrBinding => {\n const source = toReactiveBindingSource(value);\n\n return source ? { mode, name, signal: source, type: 'attr', uid } : { mode, name, type: 'attr', uid, value };\n};\n\n/**\n * Create a property binding descriptor.\n * Called during template compilation for each `.property` interpolation.\n *\n * @param name Property name (e.g., 'value', 'checked')\n * @param uid Unique binding ID\n * @param value Property value (signal, function, or static)\n */\nexport const createPropBinding = (name: string, uid: string, value: unknown): PropBinding => {\n const source = toReactiveBindingSource(value);\n\n if (source) {\n return {\n model: hasWritableValueSetter(value) ? (value as Signal<unknown>) : undefined,\n name,\n signal: source,\n type: 'prop',\n uid,\n };\n }\n\n return { name, type: 'prop', uid, value };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"template-bindings.js","names":[],"sources":["../src/template-bindings.ts"],"sourcesContent":["import {\n batch,\n computed,\n effect as rawEffect,\n isSignal,\n type CleanupFn,\n type ReadonlySignal,\n untrack,\n} from '@vielzeug/stateit';\n\nimport { isLiveSignal } from './directives/live';\nimport {\n CF_ID_ATTR,\n type AttrBinding,\n type Binding,\n type EventBinding,\n type HtmlBinding,\n type RefBinding,\n listen,\n removeNodes,\n runAll,\n setAttr,\n} from './internal';\nimport { propRegistry } from './props';\n\nexport type RegisterCleanup = (fn: CleanupFn) => void;\n\nexport type BindingTargets = {\n comments: Map<string, Comment>;\n elements: Map<string, HTMLElement>;\n};\n\nexport const parseHTML = (html: string): DocumentFragment => {\n const tpl = document.createElement('template');\n\n tpl.innerHTML = html;\n\n return tpl.content.cloneNode(true) as DocumentFragment;\n};\n\nconst collectBindingTarget = (node: Node, targets: BindingTargets): void => {\n if (node.nodeType === Node.COMMENT_NODE) {\n const marker = (node as Comment).nodeValue;\n\n if (marker) targets.comments.set(marker, node as Comment);\n\n return;\n }\n\n if (node.nodeType !== Node.ELEMENT_NODE) return;\n\n const id = (node as Element).getAttribute(CF_ID_ATTR);\n\n if (id) targets.elements.set(id, node as HTMLElement);\n};\n\nconst walkBindingTargets = (root: Node, visit: (node: Node) => void): void => {\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_ELEMENT);\n\n visit(root);\n\n while (walker.nextNode()) visit(walker.currentNode);\n};\n\nexport const indexBindingTargets = (nodes: Iterable<Node>): BindingTargets => {\n const targets: BindingTargets = { comments: new Map(), elements: new Map() };\n\n for (const node of nodes) walkBindingTargets(node, (current) => collectBindingTarget(current, targets));\n\n return targets;\n};\n\nexport const findCommentMarker = (root: Node, marker: string): Comment | null => {\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_COMMENT);\n\n while (walker.nextNode()) {\n const comment = walker.currentNode as Comment;\n\n if (comment.nodeValue === marker) return comment;\n }\n\n return null;\n};\n\nconst isStructuredValue = (value: unknown): value is object =>\n Array.isArray(value) || (typeof value === 'object' && value !== null);\n\nconst isNativeFormInput = (el: HTMLElement): el is HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement =>\n el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement;\n\ntype LiveWriteState = { last: unknown };\n\nconst applyFormValue = (\n el: HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement,\n value: unknown,\n isLive: boolean | undefined,\n state: LiveWriteState,\n): void => {\n const next = value == null ? '' : String(value);\n\n if (isLive && state.last !== undefined && !Object.is(el.value, state.last) && !Object.is(el.value, next)) return;\n\n el.value = next;\n\n if (isLive) state.last = next;\n};\n\nconst applyCheckedValue = (\n el: HTMLInputElement,\n value: unknown,\n isLive: boolean | undefined,\n state: LiveWriteState,\n): void => {\n const next = Boolean(value);\n\n if (isLive && state.last !== undefined && el.checked !== Boolean(state.last) && el.checked !== next) return;\n\n el.checked = next;\n\n if (isLive) state.last = next;\n};\n\ntype PropMetaLike = { parse: (v: string | null) => unknown; reflect: boolean; signal: { value: unknown } };\n\nconst syncRegisteredProp = (el: HTMLElement, meta: PropMetaLike, binding: AttrBinding, value: unknown): void => {\n const parsed = isStructuredValue(value)\n ? value\n : meta.parse(\n binding.mode === 'bool' ? (value ? '' : null) : value == null || value === false ? null : String(value),\n );\n\n if (\n !Object.is(\n untrack(() => meta.signal.value),\n parsed,\n )\n ) {\n meta.signal.value = parsed as never;\n }\n\n // When reflect:false the prop signal has no reflect-effect; write the attribute\n // directly so the DOM stays in sync with template bindings.\n if (!meta.reflect) {\n if (isStructuredValue(value)) return;\n\n if (binding.mode === 'bool') el.toggleAttribute(binding.name, Boolean(value));\n else setAttr(el, binding.name, value);\n }\n};\n\nconst signalEffect = (\n signal: ReadonlySignal<unknown>,\n update: (v: unknown) => void,\n registerCleanup: RegisterCleanup,\n): void => {\n registerCleanup(rawEffect(() => update(signal.value)));\n};\n\nexport const applyAttrBinding = (el: HTMLElement, binding: AttrBinding, registerCleanup: RegisterCleanup): void => {\n const meta = propRegistry.get(el)?.get(binding.name) as PropMetaLike | undefined;\n const liveState: LiveWriteState = { last: undefined };\n\n const update = (value: unknown): void => {\n if (!meta && isStructuredValue(value)) {\n (el as unknown as Record<string, unknown>)[binding.name] = value;\n\n return;\n }\n\n if (!meta && binding.name === 'value' && isNativeFormInput(el)) {\n applyFormValue(el, value, binding.live, liveState);\n\n return;\n }\n\n if (!meta && binding.name === 'checked' && el instanceof HTMLInputElement) {\n applyCheckedValue(el, value, binding.live, liveState);\n\n return;\n }\n\n if (!meta) {\n if (binding.mode === 'bool') el.toggleAttribute(binding.name, Boolean(value));\n else setAttr(el, binding.name, value);\n\n return;\n }\n\n syncRegisteredProp(el, meta, binding, value);\n };\n\n if (binding.signal) {\n signalEffect(binding.signal, update, registerCleanup);\n } else {\n update(binding.value!);\n }\n};\n\nexport const applyEventBinding = (el: HTMLElement, binding: EventBinding, registerCleanup: RegisterCleanup) => {\n registerCleanup(listen(el, binding.name, binding.handler, binding.options));\n};\n\nexport const applyRefBinding = (el: HTMLElement, binding: RefBinding, registerCleanup: RegisterCleanup) => {\n const { ref } = binding;\n\n if (typeof ref === 'function') {\n ref(el as never);\n registerCleanup(() => ref(null as never));\n\n return;\n }\n\n if (Array.isArray(ref)) {\n ref.push(el);\n registerCleanup(() => {\n const i = ref.indexOf(el);\n\n if (i !== -1) ref.splice(i, 1);\n });\n\n return;\n }\n\n ref.value = el as never;\n registerCleanup(() => {\n ref.value = null as never;\n });\n};\n\ntype ElementBinding = AttrBinding | EventBinding | RefBinding;\n\nexport const applyBindingsWithTargets = (\n bindings: Binding[],\n registerCleanup: RegisterCleanup,\n targets: BindingTargets,\n opts?: { onHtml?: (b: HtmlBinding) => void },\n) => {\n const bindingMap = new Map<string, ElementBinding[]>();\n\n for (const b of bindings) {\n const id = b.uid;\n\n if (b.type === 'text') {\n const found = targets.comments.get(id);\n\n if (found) {\n const textNode = document.createTextNode('');\n\n found.replaceWith(textNode);\n targets.comments.delete(id);\n signalEffect(\n b.signal,\n (v) => {\n textNode.textContent = String(v);\n },\n registerCleanup,\n );\n }\n } else if (b.type === 'directive') {\n const found = targets.comments.get(id);\n\n if (found) {\n b.directive.mount(found, registerCleanup);\n targets.comments.delete(id);\n }\n } else if (b.type === 'html') {\n opts?.onHtml?.(b);\n } else {\n const grouped = bindingMap.get(id);\n\n if (grouped) grouped.push(b);\n else bindingMap.set(id, [b]);\n }\n }\n\n for (const [id, elBindings] of bindingMap) {\n const el = targets.elements.get(id);\n\n if (!el) continue;\n\n el.removeAttribute(CF_ID_ATTR);\n targets.elements.delete(id);\n\n // Inline element binding dispatch\n for (const b of elBindings) {\n if (b.type === 'attr') {\n applyAttrBinding(el, b, registerCleanup);\n } else if (b.type === 'event') {\n applyEventBinding(el, b, registerCleanup);\n } else if (b.type === 'ref') {\n applyRefBinding(el, b, registerCleanup);\n }\n }\n }\n};\n\nexport const applyBindingsInContainer = (\n container: ParentNode,\n bindings: Binding[],\n registerCleanup: RegisterCleanup,\n opts?: { onHtml?: (b: HtmlBinding) => void },\n) => {\n applyBindingsWithTargets(bindings, registerCleanup, indexBindingTargets([container]), opts);\n};\n\nexport const createAttrBinding = (mode: 'bool' | 'attr', name: string, uid: string, value: unknown): AttrBinding => {\n if (isLiveSignal(value)) {\n return { live: true, mode, name, signal: value as ReadonlySignal<unknown>, type: 'attr', uid };\n }\n\n if (typeof value === 'function') {\n return { mode, name, signal: computed(value as () => unknown), type: 'attr', uid };\n }\n\n if (isSignal(value)) {\n return { mode, name, signal: value as ReadonlySignal<unknown>, type: 'attr', uid };\n }\n\n return { mode, name, type: 'attr', uid, value };\n};\n\n/**\n * Sets up the reactive effect for an html-binding marker using full fragment replacement.\n */\nexport const applyHtmlBinding = (root: Node, b: HtmlBinding, registerCleanup: RegisterCleanup): void => {\n const found = findCommentMarker(root, b.uid);\n\n if (!found) return;\n\n const marker = document.createComment('html-binding');\n\n found.replaceWith(marker);\n\n let currentCleanups: CleanupFn[] = [];\n const registerInnerCleanup: RegisterCleanup = (fn) => currentCleanups.push(fn);\n const runCurrentCleanups = () => {\n runAll(currentCleanups);\n currentCleanups = [];\n };\n let lastHtml: string | null = null;\n let lastInsertedNodes: Node[] = [];\n\n const stop = rawEffect(() => {\n batch(() => {\n let data: HtmlBinding['signal']['value'];\n\n try {\n data = b.signal.value;\n } catch (error) {\n if (error instanceof Error && error.message.includes('[stateit] Cannot read disposed computed signal')) return;\n\n throw error;\n }\n\n if (data.html === lastHtml) {\n return;\n }\n\n lastHtml = data.html;\n runCurrentCleanups();\n\n const { bindings, html } = data;\n const container = (marker.parentElement || root) as ParentNode;\n\n untrack(() => {\n batch(() => {\n removeNodes(lastInsertedNodes);\n\n const parsed = parseHTML(html);\n\n lastInsertedNodes = Array.from(parsed.childNodes);\n marker.after(parsed);\n });\n\n applyBindingsInContainer(container, bindings, registerInnerCleanup, {\n onHtml: (binding) => applyHtmlBinding(container as unknown as Node, binding, registerInnerCleanup),\n });\n });\n });\n });\n\n registerCleanup(stop);\n registerCleanup(runCurrentCleanups);\n};\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- const e=require(`./internal.cjs`),t=require(`./template-bindings.cjs`);let n=require(`@vielzeug/stateit`);var r=RegExp(`u="([^"]+)"`,`g`),i=e=>e.replace(/>\s+</g,`><`).trim(),a=[{kind:`event`,regex:/\s+@([a-zA-Z_][-a-zA-Z0-9_.]*)\s*=\s*["']?$/},{kind:`ref`,regex:/\s+ref\s*=\s*["']?$/},{kind:`specialAttr`,regex:/\s+([:?])([a-zA-Z_][-a-zA-Z0-9_]*)\s*=\s*["']?$/},{kind:`prop`,regex:/\.([a-zA-Z_][-a-zA-Z0-9_]*)\s*=\s*["']?$/},{kind:`plainAttr`,regex:/\s+([a-zA-Z_][-a-zA-Z0-9_]*)\s*=\s*["']?$/}],o=new WeakMap,s=e=>{let[t,...n]=e.split(`.`),r={};for(let e of n)e===`capture`?r.capture=!0:e===`once`?r.once=!0:e===`passive`?r.passive=!0:e===`prevent`?r.prevent=!0:e===`self`?r.self=!0:e===`stop`&&(r.stop=!0);return{modifiers:Object.keys(r).length?r:void 0,name:t}},c=e=>{let t=[];for(let n=0;n<e.length-1;n++){let r=e[n],i=!1;for(let e of a){let n=e.regex.exec(r);if(!n)continue;let a=r.slice(0,-n[0].length);if(i=!0,e.kind===`event`){let e=s(n[1]);t.push({kind:`event`,modifiers:e.modifiers,name:e.name,prefix:a,raw:r})}else e.kind===`ref`?t.push({kind:`ref`,prefix:a,raw:r}):e.kind===`specialAttr`?t.push({kind:`specialAttr`,mode:n[1]===`?`?`bool`:`attr`,name:n[2],prefix:a,raw:r}):e.kind===`prop`?t.push({kind:`prop`,name:n[1],prefix:a,raw:r}):e.kind===`plainAttr`&&t.push({kind:`plainAttr`,name:n[1],prefix:a,raw:r});break}i||t.push({kind:`node`,prefix:r,raw:r})}return{slots:t,tail:e[e.length-1]??``}},l=e=>{let t=o.get(e);return t||(t=c(e),o.set(e,t)),t},u=()=>{let e=0;return()=>String(e++)},d=(e,t)=>{let n=new Map,i=e=>{let r=n.get(e);if(r)return r;let i=t();return n.set(e,i),i};return{bindings:e.__bindings.map(e=>({...e,uid:i(e.uid)})),html:e.__html.replace(r,(e,t)=>`u="${i(t)}"`).replace(/<!--(\d+)-->/g,(e,t)=>`<!--${i(t)}-->`)}},f=t=>typeof t!=`object`||!t||!(e.EACH_SIGNAL in t)?null:t[e.EACH_SIGNAL],p=t=>typeof t==`string`?e.escapeHtml(t):t==null?``:e.isHtmlResult(t)?t.__html:e.escapeHtml(String(t)),m=t=>{let r={bindings:[],html:``};return{bindings:[],signal:(0,n.computed)(()=>{let n=t(),i=Array.isArray(n)?n:[n],a=u(),o=``,s=[];for(let t of i)if(e.isHtmlResult(t)){let e=d(t,a);o+=e.html,s.push(...e.bindings)}else o+=p(t);let c=s.length!==r.bindings.length||s.some((e,t)=>e!==r.bindings[t]);return(o!==r.html||c)&&(r={bindings:s,html:o}),r})}},h=t=>{let r=f(t);if(r)return{keyed:!0,signal:r};if(typeof t==`function`&&!(0,n.isSignal)(t)){let{signal:e}=m(t);return{keyed:!1,signal:e}}return(0,n.isSignal)(t)&&e.isHtmlResult(t.value)?{keyed:!1,signal:(0,n.computed)(()=>{let n=t.value;if(!e.isHtmlResult(n))return{bindings:[],html:p(n)};let r=d(n,u());return{bindings:r.bindings,html:r.html}})}:null},g=(r,a)=>{let o=l(r),s=``,c=[],f=null,m=u(),g=e=>e.lastIndexOf(`<`)>e.lastIndexOf(`>`),_=e=>((!f||g(e))&&(f=m()),f),v=()=>{f=null};for(let r=0;r<o.slots.length;r++){let i=o.slots[r],l=a[r];if(i.kind===`event`){if(typeof l==`function`){let e=_(i.prefix);s+=`${i.prefix} u="${e}"`,c.push({handler:l,modifiers:i.modifiers,name:i.name,type:`event`,uid:e})}else s+=i.raw;continue}if(i.kind===`ref`){if(l){let e=_(i.prefix);s+=`${i.prefix} u="${e}"`,c.push({ref:l,type:`ref`,uid:e})}else s+=i.raw;continue}if(i.kind===`specialAttr`){let e=_(i.prefix);s+=`${i.prefix} u="${e}"`,c.push(t.createAttrBinding(i.mode,i.name,e,l));continue}if(i.kind===`prop`){let e=_(i.prefix);s+=`${i.prefix} u="${e}"`,c.push(t.createPropBinding(i.name,e,l));continue}if(i.kind===`plainAttr`){let e=_(i.prefix);s+=`${i.prefix} u="${e}"`,c.push(t.createAttrBinding(`attr`,i.name,e,l));continue}if(typeof l==`object`&&l&&(`mount`in l||`render`in l)){let t=`render`in l,r=t?m():_(i.raw);t?s+=`${i.raw}<!--${r}-->`:s+=`${i.raw} u="${r}"`;let a=l.mount?.bind(l);if(a&&c.push({apply:(e,t)=>{a(e,{registerCleanup:t})},type:`callback`,uid:r}),t){let t=l.render.bind(l),i={bindings:[],html:``},a=(0,n.computed)(()=>{let n=t(),r=Array.isArray(n)?n:[n],a=u(),o=``,s=[];for(let t of r)if(e.isHtmlResult(t)){let e=d(t,a);o+=e.html,s.push(...e.bindings)}else o+=p(t);let c=s.length!==i.bindings.length||s.some((e,t)=>e!==i.bindings[t]);return(o!==i.html||c)&&(i={bindings:s,html:o}),i});c.push({keyed:!1,signal:a,type:`html`,uid:r})}continue}v();let f=h(l);if(f){let e=m();s+=`${i.raw}<!--${e}-->`,c.push({keyed:f.keyed,signal:f.signal,type:`html`,uid:e});continue}if(Array.isArray(l)){let t=``;for(let n of l)if(e.isHtmlResult(n)){let e=d(n,m);t+=e.html,c.push(...e.bindings)}else t+=p(n);s+=i.raw+t;continue}if((0,n.isSignal)(l)){let e=m();s+=`${i.raw}<!--${e}-->`,c.push({signal:l,type:`text`,uid:e})}else if(e.isHtmlResult(l)){let e=d(l,m);s+=i.raw+e.html,c.push(...e.bindings)}else s+=i.raw+p(l)}return s+=o.tail,e.htmlResult(i(s),c)};exports.compileTemplate=g;
1
+ const e=require(`./internal.cjs`),t=require(`./template-bindings.cjs`);let n=require(`@vielzeug/stateit`);var r=[{kind:`event`,regex:/\s+@([a-zA-Z_][-a-zA-Z0-9_.-]*)\s*=\s*["']?$/},{kind:`ref`,regex:/\s+ref\s*=\s*["']?$/},{kind:`boolAttr`,regex:/\s+\?([a-zA-Z_][-a-zA-Z0-9_]*)\s*=\s*["']?$/},{kind:`attr`,regex:/\s+:?([a-zA-Z_][-a-zA-Z0-9_]*)\s*=\s*["']?$/}],i=new WeakMap,a=new WeakMap,o=new WeakMap,s={prevent:e=>t=>{t.preventDefault(),e(t)},self:e=>t=>{t.target===t.currentTarget&&e(t)},stop:e=>t=>{t.stopPropagation(),e(t)}},c=(e,t)=>{let n=t.reduce((e,t)=>s[t]?.(e)??e,e),r={};return t.includes(`capture`)&&(r.capture=!0),t.includes(`once`)&&(r.once=!0),t.includes(`passive`)&&(r.passive=!0),{handler:n,...Object.keys(r).length?{options:r}:{}}},l=t=>typeof t==`string`?e.escapeHtml(t):t==null?``:e.isHtmlResult(t)?t.__html:e.escapeHtml(String(t)),u=t=>{let r={bindings:[],html:``};return{bindings:[],signal:(0,n.computed)(()=>{let n=t(),i=Array.isArray(n)?n:[n],a=e.createMarkerIdFactory(),o=``,s=[];for(let t of i)if(e.isHtmlResult(t)){let n=e.rekeyHtmlResult(t,a);o+=n.html,s.push(...n.bindings)}else o+=l(t);let c=s.length!==r.bindings.length||s.some((e,t)=>e!==r.bindings[t]);return(o!==r.html||c)&&(r={bindings:s,html:o}),r})}},d=t=>{if(typeof t==`function`){let e=t,n=a.get(e);if(n)return{signal:n};let{signal:r}=u(e);return a.set(e,r),{signal:r}}if((0,n.isSignal)(t)&&e.isHtmlResult(t.value)){let r=t,i=o.get(r);if(i)return{signal:i};let a=(0,n.computed)(()=>{let t=r.value;if(!e.isHtmlResult(t))return{bindings:[],html:l(t)};let n=e.rekeyHtmlResult(t,e.createMarkerIdFactory());return{bindings:n.bindings,html:n.html}});return o.set(r,a),{signal:a}}return null},f=e=>{let t=[];for(let n=0;n<e.length-1;n++){let i=e[n],a=!1;for(let e of r){let n=e.regex.exec(i);if(!n)continue;let r=i.slice(0,-n[0].length);if(a=!0,e.kind===`event`){let e=n[1].split(`.`),a=e[0],o=e.slice(1);t.push({kind:`event`,modifiers:o,name:a,prefix:r,raw:i})}else e.kind===`ref`?t.push({kind:`ref`,prefix:r,raw:i}):e.kind===`boolAttr`?t.push({kind:`boolAttr`,mode:`bool`,name:n[1],prefix:r,raw:i}):e.kind===`attr`&&t.push({kind:`attr`,mode:`attr`,name:n[1],prefix:r,raw:i});break}a||t.push({kind:`node`,prefix:i,raw:i})}return{slots:t,tail:e[e.length-1]??``}},p=e=>{let t=i.get(e);return t||(t=f(e),i.set(e,t)),t},m=(r,i)=>{let a=p(r),o=``,s=[],u=null,f=e.createMarkerIdFactory(),m=e=>e.lastIndexOf(`<`)>e.lastIndexOf(`>`),h=e=>((!u||m(e))&&(u=f()),u),g=()=>{u=null};for(let r=0;r<a.slots.length;r++){let u=a.slots[r],p=i[r];if(u.kind===`event`){if(typeof p==`function`){let e=h(u.prefix),{handler:t,options:n}=c(p,u.modifiers??[]);o+=`${u.prefix} u="${e}"`,s.push({handler:t,name:u.name,options:n,type:`event`,uid:e})}else if((0,n.isSignal)(p)){let e=h(u.prefix),{handler:t,options:n}=c(e=>{let t=p.value;typeof t==`function`&&t(e)},u.modifiers??[]);o+=`${u.prefix} u="${e}"`,s.push({handler:t,name:u.name,options:n,type:`event`,uid:e})}else o+=u.raw;continue}if(u.kind===`ref`){if(p){let e=h(u.prefix);o+=`${u.prefix} u="${e}"`,s.push({ref:p,type:`ref`,uid:e})}else o+=u.raw;continue}if(u.kind===`boolAttr`||u.kind===`attr`){let e=h(u.prefix);o+=`${u.prefix} u="${e}"`,s.push(t.createAttrBinding(u.mode,u.name,e,p));continue}if(u.kind===`node`){if(g(),e.isDirectiveResult(p)){let e=f();o+=`${u.raw}<!--${e}-->`,s.push({directive:p,type:`directive`,uid:e});continue}let t=d(p);if(t){let e=f();o+=`${u.raw}<!--${e}-->`,s.push({signal:t.signal,type:`html`,uid:e});continue}if(Array.isArray(p)){let t=``;for(let n of p)if(e.isHtmlResult(n)){let r=e.rekeyHtmlResult(n,f);t+=r.html,s.push(...r.bindings)}else t+=l(n);o+=u.raw+t;continue}if((0,n.isSignal)(p)){let e=f();o+=`${u.raw}<!--${e}-->`,s.push({signal:p,type:`text`,uid:e})}else if(e.isHtmlResult(p)){let t=e.rekeyHtmlResult(p,f);o+=u.raw+t.html,s.push(...t.bindings)}else o+=u.raw+l(p);continue}}return o+=a.tail,e.htmlResult(o,s)},h=(e,...t)=>m(e,t);exports.html=h;
2
2
  //# sourceMappingURL=template-compiler.cjs.map