@vielzeug/craftit 2.0.1 → 3.0.1

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 (432) hide show
  1. package/README.md +60 -108
  2. package/dist/controls/a11y-control.cjs +2 -0
  3. package/dist/controls/a11y-control.cjs.map +1 -0
  4. package/dist/controls/a11y-control.d.ts +16 -0
  5. package/dist/controls/a11y-control.d.ts.map +1 -0
  6. package/dist/controls/a11y-control.js +2 -0
  7. package/dist/controls/a11y-control.js.map +1 -0
  8. package/dist/controls/checkable-control.cjs +2 -0
  9. package/dist/controls/checkable-control.cjs.map +1 -0
  10. package/dist/controls/checkable-control.d.ts +15 -0
  11. package/dist/controls/checkable-control.d.ts.map +1 -0
  12. package/dist/controls/checkable-control.js +2 -0
  13. package/dist/controls/checkable-control.js.map +1 -0
  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 +2 -0
  21. package/dist/controls/field-control.cjs.map +1 -0
  22. package/dist/controls/field-control.d.ts +111 -0
  23. package/dist/controls/field-control.d.ts.map +1 -0
  24. package/dist/controls/field-control.js +2 -0
  25. package/dist/controls/field-control.js.map +1 -0
  26. package/dist/controls/index.d.ts +12 -0
  27. package/dist/controls/index.d.ts.map +1 -0
  28. package/dist/controls/internal/control-state.cjs +2 -0
  29. package/dist/controls/internal/control-state.cjs.map +1 -0
  30. package/dist/controls/internal/control-state.d.ts +21 -0
  31. package/dist/controls/internal/control-state.d.ts.map +1 -0
  32. package/dist/controls/internal/control-state.js +2 -0
  33. package/dist/controls/internal/control-state.js.map +1 -0
  34. package/dist/controls/internal/keyboard-utils.cjs +2 -0
  35. package/dist/controls/internal/keyboard-utils.cjs.map +1 -0
  36. package/dist/controls/internal/keyboard-utils.d.ts +7 -0
  37. package/dist/controls/internal/keyboard-utils.d.ts.map +1 -0
  38. package/dist/controls/internal/keyboard-utils.js +2 -0
  39. package/dist/controls/internal/keyboard-utils.js.map +1 -0
  40. package/dist/controls/internal/number-utils.cjs +2 -0
  41. package/dist/controls/internal/number-utils.cjs.map +1 -0
  42. package/dist/controls/internal/number-utils.d.ts +6 -0
  43. package/dist/controls/internal/number-utils.d.ts.map +1 -0
  44. package/dist/controls/internal/number-utils.js +2 -0
  45. package/dist/controls/internal/number-utils.js.map +1 -0
  46. package/dist/controls/internal/validation-utils.cjs +2 -0
  47. package/dist/controls/internal/validation-utils.cjs.map +1 -0
  48. package/dist/controls/internal/validation-utils.d.ts +13 -0
  49. package/dist/controls/internal/validation-utils.d.ts.map +1 -0
  50. package/dist/controls/internal/validation-utils.js +2 -0
  51. package/dist/controls/internal/validation-utils.js.map +1 -0
  52. package/dist/controls/list-control.cjs +2 -0
  53. package/dist/controls/list-control.cjs.map +1 -0
  54. package/dist/controls/list-control.d.ts +23 -0
  55. package/dist/controls/list-control.d.ts.map +1 -0
  56. package/dist/controls/list-control.js +2 -0
  57. package/dist/controls/list-control.js.map +1 -0
  58. package/dist/controls/overlay-control.cjs +2 -0
  59. package/dist/controls/overlay-control.cjs.map +1 -0
  60. package/dist/{labs/overlay.d.ts → controls/overlay-control.d.ts} +19 -14
  61. package/dist/controls/overlay-control.d.ts.map +1 -0
  62. package/dist/controls/overlay-control.js +2 -0
  63. package/dist/controls/overlay-control.js.map +1 -0
  64. package/dist/controls/popup-list-control.cjs +2 -0
  65. package/dist/controls/popup-list-control.cjs.map +1 -0
  66. package/dist/controls/popup-list-control.d.ts +160 -0
  67. package/dist/controls/popup-list-control.d.ts.map +1 -0
  68. package/dist/controls/popup-list-control.js +2 -0
  69. package/dist/controls/popup-list-control.js.map +1 -0
  70. package/dist/controls/press-control.cjs +2 -0
  71. package/dist/controls/press-control.cjs.map +1 -0
  72. package/dist/controls/press-control.d.ts +12 -0
  73. package/dist/controls/press-control.d.ts.map +1 -0
  74. package/dist/controls/press-control.js +2 -0
  75. package/dist/controls/press-control.js.map +1 -0
  76. package/dist/controls/slider-control.cjs +2 -0
  77. package/dist/controls/slider-control.cjs.map +1 -0
  78. package/dist/controls/slider-control.d.ts +19 -0
  79. package/dist/controls/slider-control.d.ts.map +1 -0
  80. package/dist/controls/slider-control.js +2 -0
  81. package/dist/controls/slider-control.js.map +1 -0
  82. package/dist/controls/spinner-control.cjs +2 -0
  83. package/dist/controls/spinner-control.cjs.map +1 -0
  84. package/dist/controls/spinner-control.d.ts +18 -0
  85. package/dist/controls/spinner-control.d.ts.map +1 -0
  86. package/dist/controls/spinner-control.js +2 -0
  87. package/dist/controls/spinner-control.js.map +1 -0
  88. package/dist/controls/swipe-control.cjs +2 -0
  89. package/dist/controls/swipe-control.cjs.map +1 -0
  90. package/dist/controls/swipe-control.d.ts +32 -0
  91. package/dist/controls/swipe-control.d.ts.map +1 -0
  92. package/dist/controls/swipe-control.js +2 -0
  93. package/dist/controls/swipe-control.js.map +1 -0
  94. package/dist/controls/text-field-control.cjs +2 -0
  95. package/dist/controls/text-field-control.cjs.map +1 -0
  96. package/dist/controls/text-field-control.d.ts +3 -0
  97. package/dist/controls/text-field-control.d.ts.map +1 -0
  98. package/dist/controls/text-field-control.js +2 -0
  99. package/dist/controls/text-field-control.js.map +1 -0
  100. package/dist/controls.cjs +1 -0
  101. package/dist/controls.js +1 -0
  102. package/dist/craftit.cjs +1 -1
  103. package/dist/craftit.cjs.map +1 -1
  104. package/dist/craftit.js +1 -1
  105. package/dist/craftit.js.map +1 -1
  106. package/dist/directives/classMap.cjs +2 -0
  107. package/dist/directives/classMap.cjs.map +1 -0
  108. package/dist/directives/classMap.d.ts +19 -0
  109. package/dist/directives/classMap.d.ts.map +1 -0
  110. package/dist/directives/classMap.js +2 -0
  111. package/dist/directives/classMap.js.map +1 -0
  112. package/dist/directives/each.cjs +1 -1
  113. package/dist/directives/each.cjs.map +1 -1
  114. package/dist/directives/each.d.ts +12 -49
  115. package/dist/directives/each.d.ts.map +1 -1
  116. package/dist/directives/each.js +1 -1
  117. package/dist/directives/each.js.map +1 -1
  118. package/dist/directives/guard.cjs +2 -0
  119. package/dist/directives/guard.cjs.map +1 -0
  120. package/dist/directives/guard.d.ts +10 -0
  121. package/dist/directives/guard.d.ts.map +1 -0
  122. package/dist/directives/guard.js +2 -0
  123. package/dist/directives/guard.js.map +1 -0
  124. package/dist/directives/live.cjs +2 -0
  125. package/dist/directives/live.cjs.map +1 -0
  126. package/dist/directives/live.d.ts +23 -0
  127. package/dist/directives/live.d.ts.map +1 -0
  128. package/dist/directives/live.js +2 -0
  129. package/dist/directives/live.js.map +1 -0
  130. package/dist/directives/raw.cjs +1 -1
  131. package/dist/directives/raw.cjs.map +1 -1
  132. package/dist/directives/raw.d.ts +4 -6
  133. package/dist/directives/raw.d.ts.map +1 -1
  134. package/dist/directives/raw.js +1 -1
  135. package/dist/directives/raw.js.map +1 -1
  136. package/dist/directives/resource.cjs +2 -0
  137. package/dist/directives/resource.cjs.map +1 -0
  138. package/dist/directives/resource.d.ts +32 -0
  139. package/dist/directives/resource.d.ts.map +1 -0
  140. package/dist/directives/resource.js +2 -0
  141. package/dist/directives/resource.js.map +1 -0
  142. package/dist/directives/styleMap.cjs +2 -0
  143. package/dist/directives/styleMap.cjs.map +1 -0
  144. package/dist/directives/styleMap.d.ts +11 -0
  145. package/dist/directives/styleMap.d.ts.map +1 -0
  146. package/dist/directives/styleMap.js +2 -0
  147. package/dist/directives/styleMap.js.map +1 -0
  148. package/dist/directives/when.cjs +1 -1
  149. package/dist/directives/when.cjs.map +1 -1
  150. package/dist/directives/when.d.ts +7 -14
  151. package/dist/directives/when.d.ts.map +1 -1
  152. package/dist/directives/when.js +1 -1
  153. package/dist/directives/when.js.map +1 -1
  154. package/dist/errors.cjs +2 -0
  155. package/dist/errors.cjs.map +1 -0
  156. package/dist/errors.d.ts +12 -0
  157. package/dist/errors.d.ts.map +1 -0
  158. package/dist/errors.js +2 -0
  159. package/dist/errors.js.map +1 -0
  160. package/dist/form.cjs +2 -0
  161. package/dist/form.cjs.map +1 -0
  162. package/dist/form.d.ts +15 -0
  163. package/dist/form.d.ts.map +1 -0
  164. package/dist/form.js +2 -0
  165. package/dist/form.js.map +1 -0
  166. package/dist/host.cjs +2 -0
  167. package/dist/host.cjs.map +1 -0
  168. package/dist/host.d.ts +78 -0
  169. package/dist/host.d.ts.map +1 -0
  170. package/dist/host.js +2 -0
  171. package/dist/host.js.map +1 -0
  172. package/dist/index.cjs +1 -1
  173. package/dist/index.d.ts +16 -9
  174. package/dist/index.d.ts.map +1 -1
  175. package/dist/index.js +1 -1
  176. package/dist/internal.cjs +2 -0
  177. package/dist/internal.cjs.map +1 -0
  178. package/dist/internal.d.ts +111 -0
  179. package/dist/internal.d.ts.map +1 -0
  180. package/dist/internal.js +2 -0
  181. package/dist/internal.js.map +1 -0
  182. package/dist/observers/index.d.ts +5 -0
  183. package/dist/observers/index.d.ts.map +1 -0
  184. package/dist/observers/intersection-observe.cjs +2 -0
  185. package/dist/observers/intersection-observe.cjs.map +1 -0
  186. package/dist/observers/intersection-observe.d.ts +9 -0
  187. package/dist/observers/intersection-observe.d.ts.map +1 -0
  188. package/dist/observers/intersection-observe.js +2 -0
  189. package/dist/observers/intersection-observe.js.map +1 -0
  190. package/dist/observers/media-observe.cjs +2 -0
  191. package/dist/observers/media-observe.cjs.map +1 -0
  192. package/dist/observers/media-observe.d.ts +8 -0
  193. package/dist/observers/media-observe.d.ts.map +1 -0
  194. package/dist/observers/media-observe.js +2 -0
  195. package/dist/observers/media-observe.js.map +1 -0
  196. package/dist/observers/mutation-observe.cjs +2 -0
  197. package/dist/observers/mutation-observe.cjs.map +1 -0
  198. package/dist/observers/mutation-observe.d.ts +10 -0
  199. package/dist/observers/mutation-observe.d.ts.map +1 -0
  200. package/dist/observers/mutation-observe.js +2 -0
  201. package/dist/observers/mutation-observe.js.map +1 -0
  202. package/dist/observers/resize-observe.cjs +2 -0
  203. package/dist/observers/resize-observe.cjs.map +1 -0
  204. package/dist/observers/resize-observe.d.ts +11 -0
  205. package/dist/observers/resize-observe.d.ts.map +1 -0
  206. package/dist/observers/resize-observe.js +2 -0
  207. package/dist/observers/resize-observe.js.map +1 -0
  208. package/dist/observers.cjs +1 -0
  209. package/dist/observers.js +1 -0
  210. package/dist/props.cjs +2 -0
  211. package/dist/props.cjs.map +1 -0
  212. package/dist/props.d.ts +39 -0
  213. package/dist/props.d.ts.map +1 -0
  214. package/dist/props.js +2 -0
  215. package/dist/props.js.map +1 -0
  216. package/dist/registration.cjs +2 -0
  217. package/dist/registration.cjs.map +1 -0
  218. package/dist/registration.d.ts +38 -0
  219. package/dist/registration.d.ts.map +1 -0
  220. package/dist/registration.js +2 -0
  221. package/dist/registration.js.map +1 -0
  222. package/dist/runtime.cjs +2 -0
  223. package/dist/runtime.cjs.map +1 -0
  224. package/dist/runtime.d.ts +33 -0
  225. package/dist/runtime.d.ts.map +1 -0
  226. package/dist/runtime.js +2 -0
  227. package/dist/runtime.js.map +1 -0
  228. package/dist/template-bindings.cjs +2 -0
  229. package/dist/template-bindings.cjs.map +1 -0
  230. package/dist/template-bindings.d.ts +25 -0
  231. package/dist/template-bindings.d.ts.map +1 -0
  232. package/dist/template-bindings.js +2 -0
  233. package/dist/template-bindings.js.map +1 -0
  234. package/dist/template-compiler.cjs +2 -0
  235. package/dist/template-compiler.cjs.map +1 -0
  236. package/dist/template-compiler.d.ts +4 -0
  237. package/dist/template-compiler.d.ts.map +1 -0
  238. package/dist/template-compiler.js +2 -0
  239. package/dist/template-compiler.js.map +1 -0
  240. package/dist/testing/index.d.ts +2 -0
  241. package/dist/testing/index.d.ts.map +1 -0
  242. package/dist/testing/testing.cjs +2 -0
  243. package/dist/testing/testing.cjs.map +1 -0
  244. package/dist/{test/test.d.ts → testing/testing.d.ts} +18 -11
  245. package/dist/testing/testing.d.ts.map +1 -0
  246. package/dist/testing/testing.js +2 -0
  247. package/dist/testing/testing.js.map +1 -0
  248. package/dist/testing.cjs +1 -0
  249. package/dist/testing.js +1 -0
  250. package/package.json +21 -22
  251. package/dist/core/component.cjs +0 -2
  252. package/dist/core/component.cjs.map +0 -1
  253. package/dist/core/component.d.ts +0 -172
  254. package/dist/core/component.d.ts.map +0 -1
  255. package/dist/core/component.js +0 -2
  256. package/dist/core/component.js.map +0 -1
  257. package/dist/core/host.cjs +0 -2
  258. package/dist/core/host.cjs.map +0 -1
  259. package/dist/core/host.d.ts +0 -77
  260. package/dist/core/host.d.ts.map +0 -1
  261. package/dist/core/host.js +0 -2
  262. package/dist/core/host.js.map +0 -1
  263. package/dist/core/internal.cjs +0 -2
  264. package/dist/core/internal.cjs.map +0 -1
  265. package/dist/core/internal.d.ts +0 -107
  266. package/dist/core/internal.d.ts.map +0 -1
  267. package/dist/core/internal.js +0 -2
  268. package/dist/core/internal.js.map +0 -1
  269. package/dist/core/runtime-bindings.cjs +0 -2
  270. package/dist/core/runtime-bindings.cjs.map +0 -1
  271. package/dist/core/runtime-bindings.d.ts +0 -6
  272. package/dist/core/runtime-bindings.d.ts.map +0 -1
  273. package/dist/core/runtime-bindings.js +0 -2
  274. package/dist/core/runtime-bindings.js.map +0 -1
  275. package/dist/core/runtime-lifecycle.cjs +0 -2
  276. package/dist/core/runtime-lifecycle.cjs.map +0 -1
  277. package/dist/core/runtime-lifecycle.d.ts +0 -116
  278. package/dist/core/runtime-lifecycle.d.ts.map +0 -1
  279. package/dist/core/runtime-lifecycle.js +0 -2
  280. package/dist/core/runtime-lifecycle.js.map +0 -1
  281. package/dist/core/runtime.cjs +0 -1
  282. package/dist/core/runtime.d.ts +0 -3
  283. package/dist/core/runtime.d.ts.map +0 -1
  284. package/dist/core/runtime.js +0 -1
  285. package/dist/core/template-bindings.cjs +0 -2
  286. package/dist/core/template-bindings.cjs.map +0 -1
  287. package/dist/core/template-bindings.d.ts +0 -59
  288. package/dist/core/template-bindings.d.ts.map +0 -1
  289. package/dist/core/template-bindings.js +0 -2
  290. package/dist/core/template-bindings.js.map +0 -1
  291. package/dist/core/template-compiler.cjs +0 -2
  292. package/dist/core/template-compiler.cjs.map +0 -1
  293. package/dist/core/template-compiler.d.ts +0 -25
  294. package/dist/core/template-compiler.d.ts.map +0 -1
  295. package/dist/core/template-compiler.js +0 -2
  296. package/dist/core/template-compiler.js.map +0 -1
  297. package/dist/core/template-dom.cjs +0 -2
  298. package/dist/core/template-dom.cjs.map +0 -1
  299. package/dist/core/template-dom.d.ts +0 -13
  300. package/dist/core/template-dom.d.ts.map +0 -1
  301. package/dist/core/template-dom.js +0 -2
  302. package/dist/core/template-dom.js.map +0 -1
  303. package/dist/core/template-html.cjs +0 -2
  304. package/dist/core/template-html.cjs.map +0 -1
  305. package/dist/core/template-html.d.ts +0 -26
  306. package/dist/core/template-html.d.ts.map +0 -1
  307. package/dist/core/template-html.js +0 -2
  308. package/dist/core/template-html.js.map +0 -1
  309. package/dist/core/template.cjs +0 -2
  310. package/dist/core/template.cjs.map +0 -1
  311. package/dist/core/template.d.ts +0 -11
  312. package/dist/core/template.d.ts.map +0 -1
  313. package/dist/core/template.js +0 -2
  314. package/dist/core/template.js.map +0 -1
  315. package/dist/core/utilities.cjs +0 -2
  316. package/dist/core/utilities.cjs.map +0 -1
  317. package/dist/core/utilities.d.ts +0 -68
  318. package/dist/core/utilities.d.ts.map +0 -1
  319. package/dist/core/utilities.js +0 -2
  320. package/dist/core/utilities.js.map +0 -1
  321. package/dist/directives/attr.cjs +0 -2
  322. package/dist/directives/attr.cjs.map +0 -1
  323. package/dist/directives/attr.d.ts +0 -14
  324. package/dist/directives/attr.d.ts.map +0 -1
  325. package/dist/directives/attr.js +0 -2
  326. package/dist/directives/attr.js.map +0 -1
  327. package/dist/directives/bind.cjs +0 -2
  328. package/dist/directives/bind.cjs.map +0 -1
  329. package/dist/directives/bind.d.ts +0 -30
  330. package/dist/directives/bind.d.ts.map +0 -1
  331. package/dist/directives/bind.js +0 -2
  332. package/dist/directives/bind.js.map +0 -1
  333. package/dist/directives/choose.cjs +0 -2
  334. package/dist/directives/choose.cjs.map +0 -1
  335. package/dist/directives/choose.d.ts +0 -34
  336. package/dist/directives/choose.d.ts.map +0 -1
  337. package/dist/directives/choose.js +0 -2
  338. package/dist/directives/choose.js.map +0 -1
  339. package/dist/directives/classes.cjs +0 -2
  340. package/dist/directives/classes.cjs.map +0 -1
  341. package/dist/directives/classes.d.ts +0 -20
  342. package/dist/directives/classes.d.ts.map +0 -1
  343. package/dist/directives/classes.js +0 -2
  344. package/dist/directives/classes.js.map +0 -1
  345. package/dist/directives/index.cjs +0 -1
  346. package/dist/directives/index.d.ts +0 -14
  347. package/dist/directives/index.d.ts.map +0 -1
  348. package/dist/directives/index.js +0 -1
  349. package/dist/directives/match.cjs +0 -2
  350. package/dist/directives/match.cjs.map +0 -1
  351. package/dist/directives/match.d.ts +0 -31
  352. package/dist/directives/match.d.ts.map +0 -1
  353. package/dist/directives/match.js +0 -2
  354. package/dist/directives/match.js.map +0 -1
  355. package/dist/directives/memo.cjs +0 -2
  356. package/dist/directives/memo.cjs.map +0 -1
  357. package/dist/directives/memo.d.ts +0 -23
  358. package/dist/directives/memo.d.ts.map +0 -1
  359. package/dist/directives/memo.js +0 -2
  360. package/dist/directives/memo.js.map +0 -1
  361. package/dist/directives/on.cjs +0 -2
  362. package/dist/directives/on.cjs.map +0 -1
  363. package/dist/directives/on.d.ts +0 -25
  364. package/dist/directives/on.d.ts.map +0 -1
  365. package/dist/directives/on.js +0 -2
  366. package/dist/directives/on.js.map +0 -1
  367. package/dist/directives/spread.cjs +0 -2
  368. package/dist/directives/spread.cjs.map +0 -1
  369. package/dist/directives/spread.d.ts +0 -14
  370. package/dist/directives/spread.d.ts.map +0 -1
  371. package/dist/directives/spread.js +0 -2
  372. package/dist/directives/spread.js.map +0 -1
  373. package/dist/directives/style.cjs +0 -2
  374. package/dist/directives/style.cjs.map +0 -1
  375. package/dist/directives/style.d.ts +0 -22
  376. package/dist/directives/style.d.ts.map +0 -1
  377. package/dist/directives/style.js +0 -2
  378. package/dist/directives/style.js.map +0 -1
  379. package/dist/directives/until.cjs +0 -2
  380. package/dist/directives/until.cjs.map +0 -1
  381. package/dist/directives/until.d.ts +0 -26
  382. package/dist/directives/until.d.ts.map +0 -1
  383. package/dist/directives/until.js +0 -2
  384. package/dist/directives/until.js.map +0 -1
  385. package/dist/labs/a11y.cjs +0 -2
  386. package/dist/labs/a11y.cjs.map +0 -1
  387. package/dist/labs/a11y.d.ts +0 -61
  388. package/dist/labs/a11y.d.ts.map +0 -1
  389. package/dist/labs/a11y.js +0 -2
  390. package/dist/labs/a11y.js.map +0 -1
  391. package/dist/labs/index.d.ts +0 -8
  392. package/dist/labs/index.d.ts.map +0 -1
  393. package/dist/labs/list.cjs +0 -2
  394. package/dist/labs/list.cjs.map +0 -1
  395. package/dist/labs/list.d.ts +0 -26
  396. package/dist/labs/list.d.ts.map +0 -1
  397. package/dist/labs/list.js +0 -2
  398. package/dist/labs/list.js.map +0 -1
  399. package/dist/labs/observers.cjs +0 -2
  400. package/dist/labs/observers.cjs.map +0 -1
  401. package/dist/labs/observers.d.ts +0 -42
  402. package/dist/labs/observers.d.ts.map +0 -1
  403. package/dist/labs/observers.js +0 -2
  404. package/dist/labs/observers.js.map +0 -1
  405. package/dist/labs/overlay.cjs +0 -2
  406. package/dist/labs/overlay.cjs.map +0 -1
  407. package/dist/labs/overlay.d.ts.map +0 -1
  408. package/dist/labs/overlay.js +0 -2
  409. package/dist/labs/overlay.js.map +0 -1
  410. package/dist/labs/selectable.cjs +0 -2
  411. package/dist/labs/selectable.cjs.map +0 -1
  412. package/dist/labs/selectable.d.ts +0 -70
  413. package/dist/labs/selectable.d.ts.map +0 -1
  414. package/dist/labs/selectable.js +0 -2
  415. package/dist/labs/selectable.js.map +0 -1
  416. package/dist/labs/selection.cjs +0 -2
  417. package/dist/labs/selection.cjs.map +0 -1
  418. package/dist/labs/selection.d.ts +0 -68
  419. package/dist/labs/selection.d.ts.map +0 -1
  420. package/dist/labs/selection.js +0 -2
  421. package/dist/labs/selection.js.map +0 -1
  422. package/dist/labs.cjs +0 -1
  423. package/dist/labs.js +0 -1
  424. package/dist/test/index.d.ts +0 -2
  425. package/dist/test/index.d.ts.map +0 -1
  426. package/dist/test/test.cjs +0 -2
  427. package/dist/test/test.cjs.map +0 -1
  428. package/dist/test/test.d.ts.map +0 -1
  429. package/dist/test/test.js +0 -2
  430. package/dist/test/test.js.map +0 -1
  431. package/dist/test.cjs +0 -1
  432. package/dist/test.js +0 -1
@@ -0,0 +1,2 @@
1
+ let e=require(`@vielzeug/stateit`);var t=t=>(0,e.computed)(()=>Object.entries(t).filter(([,t])=>typeof t==`function`?t():(0,e.isSignal)(t)?t.value:t).map(([e])=>e).join(` `));exports.classMap=t;
2
+ //# sourceMappingURL=classMap.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classMap.cjs","names":[],"sources":["../../src/directives/classMap.ts"],"sourcesContent":["import { computed, isSignal, type ReadonlySignal } from '@vielzeug/stateit';\n\n/**\n * Produces a reactive string of class names from an object map.\n *\n * Each key is a class name. Its value may be:\n * - a static `boolean`\n * - a `Signal<boolean>`\n * - a getter `() => boolean`\n *\n * Returns a `ReadonlySignal<string>` that can be used directly in a template\n * class attribute:\n *\n * @example\n * ```ts\n * html`<div class=\"${classMap({ active: isActive, hidden: () => !isVisible.value })}\"></div>`\n * ```\n */\nexport const classMap = (\n map: Record<string, (() => boolean) | ReadonlySignal<boolean> | boolean>,\n): ReadonlySignal<string> => {\n return computed(() =>\n Object.entries(map)\n .filter(([, v]) => (typeof v === 'function' ? v() : isSignal(v) ? v.value : v))\n .map(([k]) => k)\n .join(' '),\n );\n};\n"],"mappings":"mCAkBA,IAAa,EACX,IAEA,EAAA,EAAA,cACE,OAAO,QAAQ,CAAG,EACf,QAAQ,EAAG,KAAQ,OAAO,GAAM,WAAa,EAAE,GAAA,EAAA,EAAA,UAAa,CAAC,EAAI,EAAE,MAAQ,CAAE,EAC7E,KAAK,CAAC,KAAO,CAAC,EACd,KAAK,GAAG,CACb"}
@@ -0,0 +1,19 @@
1
+ import { type ReadonlySignal } from '@vielzeug/stateit';
2
+ /**
3
+ * Produces a reactive string of class names from an object map.
4
+ *
5
+ * Each key is a class name. Its value may be:
6
+ * - a static `boolean`
7
+ * - a `Signal<boolean>`
8
+ * - a getter `() => boolean`
9
+ *
10
+ * Returns a `ReadonlySignal<string>` that can be used directly in a template
11
+ * class attribute:
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * html`<div class="${classMap({ active: isActive, hidden: () => !isVisible.value })}"></div>`
16
+ * ```
17
+ */
18
+ export declare const classMap: (map: Record<string, (() => boolean) | ReadonlySignal<boolean> | boolean>) => ReadonlySignal<string>;
19
+ //# sourceMappingURL=classMap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classMap.d.ts","sourceRoot":"","sources":["../../src/directives/classMap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAE5E;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,QAAQ,GACnB,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC,MAAM,OAAO,CAAC,GAAG,cAAc,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,KACvE,cAAc,CAAC,MAAM,CAOvB,CAAC"}
@@ -0,0 +1,2 @@
1
+ import{computed as e,isSignal as t}from"@vielzeug/stateit";var n=n=>e(()=>Object.entries(n).filter(([,e])=>typeof e==`function`?e():t(e)?e.value:e).map(([e])=>e).join(` `));export{n as classMap};
2
+ //# sourceMappingURL=classMap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classMap.js","names":[],"sources":["../../src/directives/classMap.ts"],"sourcesContent":["import { computed, isSignal, type ReadonlySignal } from '@vielzeug/stateit';\n\n/**\n * Produces a reactive string of class names from an object map.\n *\n * Each key is a class name. Its value may be:\n * - a static `boolean`\n * - a `Signal<boolean>`\n * - a getter `() => boolean`\n *\n * Returns a `ReadonlySignal<string>` that can be used directly in a template\n * class attribute:\n *\n * @example\n * ```ts\n * html`<div class=\"${classMap({ active: isActive, hidden: () => !isVisible.value })}\"></div>`\n * ```\n */\nexport const classMap = (\n map: Record<string, (() => boolean) | ReadonlySignal<boolean> | boolean>,\n): ReadonlySignal<string> => {\n return computed(() =>\n Object.entries(map)\n .filter(([, v]) => (typeof v === 'function' ? v() : isSignal(v) ? v.value : v))\n .map(([k]) => k)\n .join(' '),\n );\n};\n"],"mappings":"2DAkBA,IAAa,EACX,GAEO,MACL,OAAO,QAAQ,CAAG,EACf,QAAQ,EAAG,KAAQ,OAAO,GAAM,WAAa,EAAE,EAAI,EAAS,CAAC,EAAI,EAAE,MAAQ,CAAE,EAC7E,KAAK,CAAC,KAAO,CAAC,EACd,KAAK,GAAG,CACb"}
@@ -1,2 +1,2 @@
1
- const e=require(`../core/internal.cjs`),t=require(`../core/utilities.cjs`);let n=require(`@vielzeug/stateit`);var r=RegExp(`u="(\\d+)"`,`g`),i=e.htmlResult(``),a=[],o=(n,r)=>e.isHtmlResult(n)?c(n,r):{bindings:a,html:t.escapeHtml(n)},s=n=>e.isHtmlResult(n)?n:e.htmlResult(t.escapeHtml(n));function c(e,t){let n=new Map,i=[];for(let r of e.__bindings){let e=r.uid,a=n.get(e)??String(t.n++);n.has(e)||n.set(e,a),i.push({...r,uid:a})}return{bindings:i,html:e.__html.replace(r,(e,t)=>`u="${n.get(t)??t}"`).replace(/<!--(\d+)-->/g,(e,t)=>`<!--${n.get(t)??t}-->`)}}function l(e,t,n){let r=``,i=[],a=[],s=[],c={n:0};for(let l=0;l<e.length;l++){a.push(n(e[l],l));let u=o(t(e[l],l),c);r+=u.html,i.push(...u.bindings),s.push(u)}return{bindings:i,html:r,keys:a,rendered:s}}function u(e,t){let n=``,r=[],i={n:0};for(let a=0;a<e.length;a++){let s=o(t(e[a],a),i);n+=s.html,r.push(...s.bindings)}return{bindings:r,html:n}}function d(t,r,a,o){let c=typeof a==`function`,d=c?a:void 0,f=(c?o:o??a)??{},p=f.select;if(Array.isArray(t)){let n=p?t.filter(p):t;if(!n.length){if(d){let t=e.extractResult(s(d()));return e.htmlResult(t.html,t.bindings)}return i}let{bindings:a,html:o}=u(n,r);return e.htmlResult(o,a)}let m=f.key;if(!m)throw Error(`[craftit:each] Reactive each() requires options.key for stable reconciliation.`);let h=(0,n.isSignal)(t)?()=>t.value:t;return{[e.EACH_SIGNAL]:(0,n.computed)(()=>{let t=h(),n=p?t.filter(p):t;if(!n.length){let t=d?s(d()):void 0;return t?{...e.extractResult(t),items:[],keys:[]}:{bindings:[],html:``,items:[],keys:[]}}let{bindings:i,html:a,keys:o,rendered:c}=l(n,r,m);return{bindings:i,html:a,items:c,keys:o}})}}exports.each=d;
1
+ const e=require(`../errors.cjs`),t=require(`../internal.cjs`),n=require(`../template-bindings.cjs`);let r=require(`@vielzeug/stateit`);var i=(e,n)=>t.isHtmlResult(e)?t.rekeyHtmlResult(e,n):{bindings:[],html:t.escapeHtml(e)},a=e=>t.isHtmlResult(e)?e:t.htmlResult(t.escapeHtml(e));function o(n,r,a){let o=``,s=[],c=[],l=new Set,u=[],d=t.createMarkerIdFactory();for(let t=0;t<n.length;t++){let f=a(n[t],t);if(l.has(f))throw Error(e.CRAFTIT_ERRORS.eachDuplicateKey(String(f),t));l.add(f),c.push(f);let p=i(r(n[t],t),d);o+=p.html,s.push(...p.bindings),u.push(p)}return{bindings:s,html:o,keys:c,rendered:u}}function s(e,i){let{fallback:s,key:c,render:l}=i;return{__craftitDirective:!0,mount:(i,u)=>{let d=new Map,f=[],p=[],m=()=>{t.removeNodes(f),f=[],t.runAll(p),p=[]},h=()=>{for(let[,e]of d)t.removeNodes(e.nodes),t.runAll(e.cleanups);d.clear()};u((0,r.effect)(()=>{let u=i.parentNode;u&&(0,r.batch)(()=>{let g=e.value;if(!g.length){if(h(),m(),!s)return;let e=t.extractResult(a(s())),r=n.parseHTML(e.html);f=Array.from(r.childNodes),i.after(r);let o=e=>p.push(e);n.applyBindingsWithTargets(e.bindings,o,n.indexBindingTargets(f),{onHtml:e=>n.applyHtmlBinding(u,e,o)});return}m();let{keys:_,rendered:v}=o(g,l,c),y=new Map,b=[];for(let e=0;e<_.length;e++){let r=_[e],i=v[e],a=d.get(r),o,s=[];if(a&&a.html===i.html)o=a.nodes,t.runAll(a.cleanups);else{a&&(t.removeNodes(a.nodes),t.runAll(a.cleanups));let e=n.parseHTML(i.html);o=Array.from(e.childNodes)}b.push({item:i,key:r,nodes:o}),y.set(r,{cleanups:s,html:i.html,nodes:o})}for(let[e,n]of d)y.has(e)||(t.removeNodes(n.nodes),t.runAll(n.cleanups));let x=i;for(let e of b){for(let t of e.nodes)u.insertBefore(t,x.nextSibling),x=t;let t=y.get(e.key);if(!t)continue;let i=e=>t.cleanups.push(e);(0,r.untrack)(()=>{n.applyBindingsWithTargets(e.item.bindings,i,n.indexBindingTargets(e.nodes),{onHtml:e=>n.applyHtmlBinding(u,e,i)})})}d=y})})),u(()=>{m(),h()})}}}exports.each=s;
2
2
  //# sourceMappingURL=each.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"each.cjs","names":[],"sources":["../../src/directives/each.ts"],"sourcesContent":["import { computed, isSignal, type ReadonlySignal } from '@vielzeug/stateit';\n\nimport {\n CF_ID_ATTR,\n EACH_SIGNAL,\n extractResult,\n htmlResult,\n isHtmlResult,\n type Binding,\n type Directive,\n type HTMLResult,\n} from '../core/internal';\nimport { escapeHtml } from '../core/utilities';\n\nconst ATTR_ID_RE = new RegExp(`${CF_ID_ATTR}=\"(\\\\d+)\"`, 'g');\n\n/* immutable — shared singleton for empty static lists */\nconst EMPTY = htmlResult('');\nconst NO_BINDINGS: Binding[] = [];\n\nconst toResultEntry = (value: string | HTMLResult, c: { n: number }): { bindings: Binding[]; html: string } =>\n isHtmlResult(value) ? renumber(value, c) : { bindings: NO_BINDINGS, html: escapeHtml(value) };\n\nconst toHtmlResult = (value: string | HTMLResult): HTMLResult =>\n isHtmlResult(value) ? value : htmlResult(escapeHtml(value));\n\nfunction renumber(res: HTMLResult, c: { n: number }): { bindings: Binding[]; html: string } {\n const map = new Map<string, string>();\n const nb: Binding[] = [];\n\n for (const b of res.__bindings) {\n const oldId = b.uid;\n const newId = map.get(oldId) ?? String(c.n++);\n\n if (!map.has(oldId)) map.set(oldId, newId);\n\n nb.push({ ...b, uid: newId });\n }\n\n return {\n bindings: nb,\n html: res.__html\n // Re-map element binding ids.\n .replace(ATTR_ID_RE, (_, id) => `${CF_ID_ATTR}=\"${map.get(id) ?? id}\"`)\n // Re-map numeric comment markers used by text/html placeholders.\n .replace(/<!--(\\d+)-->/g, (_, id) => `<!--${map.get(id) ?? id}-->`),\n };\n}\n\n/** Render loop used by the reactive path (keys + rendered metadata required for reconciliation). */\nfunction renderKeyed<T>(\n items: T[],\n template: (item: T, index: number) => string | HTMLResult,\n keyFn: (item: T, index: number) => string | number,\n): {\n bindings: Binding[];\n html: string;\n keys: (string | number)[];\n rendered: Array<{ bindings: Binding[]; html: string }>;\n} {\n let html = '';\n const allBindings: Binding[] = [];\n const keys: (string | number)[] = [];\n const rendered: Array<{ bindings: Binding[]; html: string }> = [];\n const c = { n: 0 };\n\n for (let i = 0; i < items.length; i++) {\n keys.push(keyFn(items[i], i));\n\n const entry = toResultEntry(template(items[i], i), c);\n\n html += entry.html;\n allBindings.push(...entry.bindings);\n rendered.push(entry);\n }\n\n return { bindings: allBindings, html, keys, rendered };\n}\n\n/** Render loop used by the static path — no key/reconciliation metadata needed. */\nfunction renderStatic<T>(\n items: T[],\n template: (item: T, index: number) => string | HTMLResult,\n): { bindings: Binding[]; html: string } {\n let html = '';\n const allBindings: Binding[] = [];\n const c = { n: 0 };\n\n for (let i = 0; i < items.length; i++) {\n const entry = toResultEntry(template(items[i], i), c);\n\n html += entry.html;\n allBindings.push(...entry.bindings);\n }\n\n return { bindings: allBindings, html };\n}\n\n/**\n * Options accepted by `each()`.\n */\nexport interface EachOptions<T> {\n /**\n * Key extractor for stable DOM reconciliation.\n * Receives the item and its **filtered** array index (after `select` is applied).\n *\n * Required when `source` is reactive (Signal/getter).\n * Optional for static arrays (render-once path).\n */\n key?: (item: T, index: number) => string | number;\n /**\n * Filter predicate. Receives the item and its **original** array index.\n * Only items for which `select` returns `true` are rendered.\n *\n * @example\n * each(items, item => html`<li>${item.name}</li>`, undefined, { select: item => item.active })\n */\n select?: (item: T, index: number) => boolean;\n}\n\ntype ReactiveSource<T> = ReadonlySignal<T[]> | (() => T[]);\ntype EachSignalResult = Directive & {\n [EACH_SIGNAL]: ReadonlySignal<{\n bindings: Binding[];\n html: string;\n items?: Array<{ bindings: Binding[]; html: string }>;\n keys?: (string | number)[];\n }>;\n};\n\n/**\n * Renders a reactive list with keyed DOM reconciliation for efficient updates.\n * Use inside `html` tagged templates.\n *\n * For reactive sources (Signal/getter), you must provide a stable `key` function.\n *\n * For dynamic lists with click handlers, prefer event delegation on a parent node\n * (`@click` + `closest(...)`) over per-item handlers inside `each()`.\n *\n * @example\n * import { each } from '@vielzeug/craftit/directives';\n *\n * // Static array (key optional):\n * html`${each([1, 2, 3], item => html`<li>${item}</li>`)}`\n *\n * // Reactive source (key required):\n * html`${each(items, item => html`<li>${item.name}</li>`, undefined, { key: item => item.id })}`\n *\n * // Full example:\n * html`${each(items, item => html`<li>${item.name}</li>`, () => html`<p>No items</p>`, {\n * key: item => item.id,\n * select: item => item.active,\n * })}`\n */\nexport function each<T>(\n source: T[],\n template: (item: T, index: number) => string | HTMLResult,\n empty?: () => string | HTMLResult,\n options?: EachOptions<T>,\n): HTMLResult;\nexport function each<T>(\n source: ReactiveSource<T>,\n template: (item: T, index: number) => string | HTMLResult,\n options: EachOptions<T> & { key: (item: T, index: number) => string | number },\n): EachSignalResult;\nexport function each<T>(\n source: ReactiveSource<T>,\n template: (item: T, index: number) => string | HTMLResult,\n empty: (() => string | HTMLResult) | undefined,\n options: EachOptions<T> & { key: (item: T, index: number) => string | number },\n): EachSignalResult;\nexport function each<T>(\n source: T[] | ReactiveSource<T>,\n template: (item: T, index: number) => string | HTMLResult,\n emptyOrOptions?: (() => string | HTMLResult) | EachOptions<T>,\n options?: EachOptions<T>,\n): HTMLResult | EachSignalResult {\n const hasEmptyFn = typeof emptyOrOptions === 'function';\n const empty = hasEmptyFn ? emptyOrOptions : undefined;\n const resolvedOptions = (hasEmptyFn ? options : (options ?? emptyOrOptions)) ?? {};\n const select = resolvedOptions.select;\n\n if (Array.isArray(source)) {\n const filtered = select ? source.filter(select) : source;\n\n if (!filtered.length) {\n if (empty) {\n const er = extractResult(toHtmlResult(empty()));\n\n return htmlResult(er.html, er.bindings);\n }\n\n return EMPTY;\n }\n\n const { bindings, html } = renderStatic(filtered, template);\n\n return htmlResult(html, bindings);\n }\n\n const keyFn = resolvedOptions.key;\n\n if (!keyFn) {\n throw new Error('[craftit:each] Reactive each() requires options.key for stable reconciliation.');\n }\n\n const getItems = isSignal(source) ? () => (source as ReadonlySignal<T[]>).value : (source as () => T[]);\n\n return {\n [EACH_SIGNAL]: computed(() => {\n const raw = getItems();\n const filtered = select ? raw.filter(select) : raw;\n\n if (!filtered.length) {\n const er = empty ? toHtmlResult(empty()) : undefined;\n\n return er ? { ...extractResult(er), items: [], keys: [] } : { bindings: [], html: '', items: [], keys: [] };\n }\n\n const { bindings, html, keys, rendered } = renderKeyed(filtered, template, keyFn);\n\n return { bindings, html, items: rendered, keys };\n }),\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"each.cjs","names":[],"sources":["../../src/directives/each.ts"],"sourcesContent":["import { batch, effect as _effect, untrack, type CleanupFn, type ReadonlySignal } from '@vielzeug/stateit';\n\nimport { CRAFTIT_ERRORS } from '../errors';\nimport {\n createMarkerIdFactory,\n escapeHtml,\n extractResult,\n htmlResult,\n isHtmlResult,\n removeNodes,\n rekeyHtmlResult,\n runAll,\n type Binding,\n type DirectiveResult,\n type HTMLResult,\n} from '../internal';\nimport { applyBindingsWithTargets, indexBindingTargets, parseHTML, type RegisterCleanup } from '../template-bindings';\nimport { applyHtmlBinding } from '../template-bindings';\n\nconst toResultEntry = (value: string | HTMLResult, getNextId: () => string): { bindings: Binding[]; html: string } =>\n isHtmlResult(value) ? rekeyHtmlResult(value, getNextId) : { bindings: [], html: escapeHtml(value) };\n\nconst toHtmlResult = (value: string | HTMLResult): HTMLResult =>\n isHtmlResult(value) ? value : htmlResult(escapeHtml(value));\n\n/** Render loop used by the reactive path (keys + rendered metadata required for reconciliation). */\nfunction renderKeyed<T>(\n items: T[],\n template: (item: T, index: number) => string | HTMLResult,\n keyFn: (item: T, index: number) => string | number,\n): {\n bindings: Binding[];\n html: string;\n keys: (string | number)[];\n rendered: Array<{ bindings: Binding[]; html: string }>;\n} {\n let html = '';\n const allBindings: Binding[] = [];\n const keys: (string | number)[] = [];\n const seenKeys = new Set<string | number>();\n const rendered: Array<{ bindings: Binding[]; html: string }> = [];\n const getNextId = createMarkerIdFactory();\n\n for (let i = 0; i < items.length; i++) {\n const nextKey = keyFn(items[i], i);\n\n if (seenKeys.has(nextKey)) {\n throw new Error(CRAFTIT_ERRORS.eachDuplicateKey(String(nextKey), i));\n }\n\n seenKeys.add(nextKey);\n keys.push(nextKey);\n\n const entry = toResultEntry(template(items[i], i), getNextId);\n\n html += entry.html;\n allBindings.push(...entry.bindings);\n rendered.push(entry);\n }\n\n return { bindings: allBindings, html, keys, rendered };\n}\n\nexport interface EachOptions<T> {\n fallback?: () => string | HTMLResult;\n key: (item: T, index: number) => string | number;\n render: (item: T, index: number) => string | HTMLResult;\n}\n\n/**\n * Renders a list with keyed DOM reconciliation for reactive sources.\n * Use inside `html` tagged templates.\n *\n * `each()` expects a reactive signal source and a stable `key` function.\n *\n * For dynamic lists with click handlers, prefer event delegation on a parent node\n * (`@click` + `closest(...)`) over per-item handlers inside `each()`.\n *\n * @example\n * import { each } from '@vielzeug/craftit';\n *\n * // Reactive source (key required):\n * html`${each(items, { key: item => item.id, render: (item) => html`<li>${item.name}</li>` })}`\n *\n * // Full example:\n * html`${each(items, {\n * fallback: () => html`<p>No items</p>`,\n * key: item => item.id,\n * render: (item) => html`<li>${item.name}</li>`,\n * })}`\n */\nexport function each<T>(source: ReadonlySignal<T[]>, options: EachOptions<T>): DirectiveResult;\nexport function each<T>(source: ReadonlySignal<T[]>, options: EachOptions<T>): DirectiveResult {\n const { fallback, key, render: renderItem } = options;\n\n const mount = (anchor: Comment, registerCleanup: RegisterCleanup): void => {\n type KeyedNode = {\n cleanups: CleanupFn[];\n html: string;\n nodes: Node[];\n };\n\n let keyedNodes = new Map<string | number, KeyedNode>();\n let fallbackNodes: Node[] = [];\n let fallbackCleanups: CleanupFn[] = [];\n\n const clearFallback = (): void => {\n removeNodes(fallbackNodes);\n fallbackNodes = [];\n runAll(fallbackCleanups);\n fallbackCleanups = [];\n };\n\n const clearKeyed = (): void => {\n for (const [, node] of keyedNodes) {\n removeNodes(node.nodes);\n runAll(node.cleanups);\n }\n\n keyedNodes.clear();\n };\n\n const stop = _effect(() => {\n const parent = anchor.parentNode;\n\n if (!parent) return;\n\n batch(() => {\n const raw = source.value;\n\n if (!raw.length) {\n clearKeyed();\n clearFallback();\n\n if (!fallback) return;\n\n const fallbackResult = extractResult(toHtmlResult(fallback()));\n const parsed = parseHTML(fallbackResult.html);\n\n fallbackNodes = Array.from(parsed.childNodes);\n anchor.after(parsed);\n\n const addFallbackCleanup: RegisterCleanup = (fn) => fallbackCleanups.push(fn);\n\n applyBindingsWithTargets(fallbackResult.bindings, addFallbackCleanup, indexBindingTargets(fallbackNodes), {\n onHtml: (binding) => applyHtmlBinding(parent as unknown as Node, binding, addFallbackCleanup),\n });\n\n return;\n }\n\n clearFallback();\n\n const { keys, rendered } = renderKeyed(raw, renderItem, key);\n const nextKeyed = new Map<string | number, KeyedNode>();\n const ordered: Array<{ item: { bindings: Binding[]; html: string }; key: string | number; nodes: Node[] }> = [];\n\n for (let i = 0; i < keys.length; i++) {\n const nextKey = keys[i];\n const item = rendered[i];\n const existing = keyedNodes.get(nextKey);\n let nodes: Node[];\n const cleanups: CleanupFn[] = [];\n\n if (existing && existing.html === item.html) {\n nodes = existing.nodes;\n runAll(existing.cleanups);\n } else {\n if (existing) {\n removeNodes(existing.nodes);\n runAll(existing.cleanups);\n }\n\n const parsed = parseHTML(item.html);\n\n nodes = Array.from(parsed.childNodes);\n }\n\n ordered.push({ item, key: nextKey, nodes });\n nextKeyed.set(nextKey, { cleanups, html: item.html, nodes });\n }\n\n for (const [oldKey, oldNode] of keyedNodes) {\n if (!nextKeyed.has(oldKey)) {\n removeNodes(oldNode.nodes);\n runAll(oldNode.cleanups);\n }\n }\n\n let cursor: Node = anchor;\n\n for (const entry of ordered) {\n for (const node of entry.nodes) {\n parent.insertBefore(node, cursor.nextSibling);\n cursor = node;\n }\n\n const targetNode = nextKeyed.get(entry.key);\n\n if (!targetNode) continue;\n\n const addItemCleanup: RegisterCleanup = (fn) => targetNode.cleanups.push(fn);\n\n untrack(() => {\n applyBindingsWithTargets(entry.item.bindings, addItemCleanup, indexBindingTargets(entry.nodes), {\n onHtml: (binding) => applyHtmlBinding(parent as unknown as Node, binding, addItemCleanup),\n });\n });\n }\n\n keyedNodes = nextKeyed;\n });\n });\n\n registerCleanup(stop);\n registerCleanup(() => {\n clearFallback();\n clearKeyed();\n });\n };\n\n return { __craftitDirective: true, mount };\n}\n"],"mappings":"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"}
@@ -1,68 +1,31 @@
1
1
  import { type ReadonlySignal } from '@vielzeug/stateit';
2
- import { EACH_SIGNAL, type Binding, type Directive, type HTMLResult } from '../core/internal';
3
- /**
4
- * Options accepted by `each()`.
5
- */
2
+ import { type DirectiveResult, type HTMLResult } from '../internal';
6
3
  export interface EachOptions<T> {
7
- /**
8
- * Key extractor for stable DOM reconciliation.
9
- * Receives the item and its **filtered** array index (after `select` is applied).
10
- *
11
- * Required when `source` is reactive (Signal/getter).
12
- * Optional for static arrays (render-once path).
13
- */
14
- key?: (item: T, index: number) => string | number;
15
- /**
16
- * Filter predicate. Receives the item and its **original** array index.
17
- * Only items for which `select` returns `true` are rendered.
18
- *
19
- * @example
20
- * each(items, item => html`<li>${item.name}</li>`, undefined, { select: item => item.active })
21
- */
22
- select?: (item: T, index: number) => boolean;
4
+ fallback?: () => string | HTMLResult;
5
+ key: (item: T, index: number) => string | number;
6
+ render: (item: T, index: number) => string | HTMLResult;
23
7
  }
24
- type ReactiveSource<T> = ReadonlySignal<T[]> | (() => T[]);
25
- type EachSignalResult = Directive & {
26
- [EACH_SIGNAL]: ReadonlySignal<{
27
- bindings: Binding[];
28
- html: string;
29
- items?: Array<{
30
- bindings: Binding[];
31
- html: string;
32
- }>;
33
- keys?: (string | number)[];
34
- }>;
35
- };
36
8
  /**
37
- * Renders a reactive list with keyed DOM reconciliation for efficient updates.
9
+ * Renders a list with keyed DOM reconciliation for reactive sources.
38
10
  * Use inside `html` tagged templates.
39
11
  *
40
- * For reactive sources (Signal/getter), you must provide a stable `key` function.
12
+ * `each()` expects a reactive signal source and a stable `key` function.
41
13
  *
42
14
  * For dynamic lists with click handlers, prefer event delegation on a parent node
43
15
  * (`@click` + `closest(...)`) over per-item handlers inside `each()`.
44
16
  *
45
17
  * @example
46
- * import { each } from '@vielzeug/craftit/directives';
47
- *
48
- * // Static array (key optional):
49
- * html`${each([1, 2, 3], item => html`<li>${item}</li>`)}`
18
+ * import { each } from '@vielzeug/craftit';
50
19
  *
51
20
  * // Reactive source (key required):
52
- * html`${each(items, item => html`<li>${item.name}</li>`, undefined, { key: item => item.id })}`
21
+ * html`${each(items, { key: item => item.id, render: (item) => html`<li>${item.name}</li>` })}`
53
22
  *
54
23
  * // Full example:
55
- * html`${each(items, item => html`<li>${item.name}</li>`, () => html`<p>No items</p>`, {
24
+ * html`${each(items, {
25
+ * fallback: () => html`<p>No items</p>`,
56
26
  * key: item => item.id,
57
- * select: item => item.active,
27
+ * render: (item) => html`<li>${item.name}</li>`,
58
28
  * })}`
59
29
  */
60
- export declare function each<T>(source: T[], template: (item: T, index: number) => string | HTMLResult, empty?: () => string | HTMLResult, options?: EachOptions<T>): HTMLResult;
61
- export declare function each<T>(source: ReactiveSource<T>, template: (item: T, index: number) => string | HTMLResult, options: EachOptions<T> & {
62
- key: (item: T, index: number) => string | number;
63
- }): EachSignalResult;
64
- export declare function each<T>(source: ReactiveSource<T>, template: (item: T, index: number) => string | HTMLResult, empty: (() => string | HTMLResult) | undefined, options: EachOptions<T> & {
65
- key: (item: T, index: number) => string | number;
66
- }): EachSignalResult;
67
- export {};
30
+ export declare function each<T>(source: ReadonlySignal<T[]>, options: EachOptions<T>): DirectiveResult;
68
31
  //# sourceMappingURL=each.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"each.d.ts","sourceRoot":"","sources":["../../src/directives/each.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAE5E,OAAO,EAEL,WAAW,EAIX,KAAK,OAAO,EACZ,KAAK,SAAS,EACd,KAAK,UAAU,EAChB,MAAM,kBAAkB,CAAC;AAuF1B;;GAEG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,MAAM,CAAC;IAClD;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;CAC9C;AAED,KAAK,cAAc,CAAC,CAAC,IAAI,cAAc,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAC3D,KAAK,gBAAgB,GAAG,SAAS,GAAG;IAClC,CAAC,WAAW,CAAC,EAAE,cAAc,CAAC;QAC5B,QAAQ,EAAE,OAAO,EAAE,CAAC;QACpB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,KAAK,CAAC;YAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QACrD,IAAI,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;KAC5B,CAAC,CAAC;CACJ,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,IAAI,CAAC,CAAC,EACpB,MAAM,EAAE,CAAC,EAAE,EACX,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,UAAU,EACzD,KAAK,CAAC,EAAE,MAAM,MAAM,GAAG,UAAU,EACjC,OAAO,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,GACvB,UAAU,CAAC;AACd,wBAAgB,IAAI,CAAC,CAAC,EACpB,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,EACzB,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,UAAU,EACzD,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG;IAAE,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,MAAM,CAAA;CAAE,GAC7E,gBAAgB,CAAC;AACpB,wBAAgB,IAAI,CAAC,CAAC,EACpB,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,EACzB,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,UAAU,EACzD,KAAK,EAAE,CAAC,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,SAAS,EAC9C,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG;IAAE,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,MAAM,CAAA;CAAE,GAC7E,gBAAgB,CAAC"}
1
+ {"version":3,"file":"each.d.ts","sourceRoot":"","sources":["../../src/directives/each.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqD,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAG3G,OAAO,EAUL,KAAK,eAAe,EACpB,KAAK,UAAU,EAChB,MAAM,aAAa,CAAC;AAgDrB,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,MAAM,GAAG,UAAU,CAAC;IACrC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,MAAM,CAAC;IACjD,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,UAAU,CAAC;CACzD;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC"}
@@ -1,2 +1,2 @@
1
- import{EACH_SIGNAL as e,extractResult as t,htmlResult as n,isHtmlResult as r}from"../core/internal.js";import{escapeHtml as i}from"../core/utilities.js";import{computed as a,isSignal as o}from"@vielzeug/stateit";var s=RegExp(`u="(\\d+)"`,`g`),c=n(``),l=[],u=(e,t)=>r(e)?f(e,t):{bindings:l,html:i(e)},d=e=>r(e)?e:n(i(e));function f(e,t){let n=new Map,r=[];for(let i of e.__bindings){let e=i.uid,a=n.get(e)??String(t.n++);n.has(e)||n.set(e,a),r.push({...i,uid:a})}return{bindings:r,html:e.__html.replace(s,(e,t)=>`u="${n.get(t)??t}"`).replace(/<!--(\d+)-->/g,(e,t)=>`<!--${n.get(t)??t}-->`)}}function p(e,t,n){let r=``,i=[],a=[],o=[],s={n:0};for(let c=0;c<e.length;c++){a.push(n(e[c],c));let l=u(t(e[c],c),s);r+=l.html,i.push(...l.bindings),o.push(l)}return{bindings:i,html:r,keys:a,rendered:o}}function m(e,t){let n=``,r=[],i={n:0};for(let a=0;a<e.length;a++){let o=u(t(e[a],a),i);n+=o.html,r.push(...o.bindings)}return{bindings:r,html:n}}function h(r,i,s,l){let u=typeof s==`function`,f=u?s:void 0,h=(u?l:l??s)??{},g=h.select;if(Array.isArray(r)){let e=g?r.filter(g):r;if(!e.length){if(f){let e=t(d(f()));return n(e.html,e.bindings)}return c}let{bindings:a,html:o}=m(e,i);return n(o,a)}let _=h.key;if(!_)throw Error(`[craftit:each] Reactive each() requires options.key for stable reconciliation.`);let v=o(r)?()=>r.value:r;return{[e]:a(()=>{let e=v(),n=g?e.filter(g):e;if(!n.length){let e=f?d(f()):void 0;return e?{...t(e),items:[],keys:[]}:{bindings:[],html:``,items:[],keys:[]}}let{bindings:r,html:a,keys:o,rendered:s}=p(n,i,_);return{bindings:r,html:a,items:s,keys:o}})}}export{h as each};
1
+ import{CRAFTIT_ERRORS as e}from"../errors.js";import{createMarkerIdFactory as t,escapeHtml as n,extractResult as r,htmlResult as i,isHtmlResult as a,rekeyHtmlResult as o,removeNodes as s,runAll as c}from"../internal.js";import{applyBindingsWithTargets as l,applyHtmlBinding as u,indexBindingTargets as d,parseHTML as f}from"../template-bindings.js";import{batch as p,effect as m,untrack as h}from"@vielzeug/stateit";var g=(e,t)=>a(e)?o(e,t):{bindings:[],html:n(e)},_=e=>a(e)?e:i(n(e));function v(n,r,i){let a=``,o=[],s=[],c=new Set,l=[],u=t();for(let t=0;t<n.length;t++){let d=i(n[t],t);if(c.has(d))throw Error(e.eachDuplicateKey(String(d),t));c.add(d),s.push(d);let f=g(r(n[t],t),u);a+=f.html,o.push(...f.bindings),l.push(f)}return{bindings:o,html:a,keys:s,rendered:l}}function y(e,t){let{fallback:n,key:i,render:a}=t;return{__craftitDirective:!0,mount:(t,o)=>{let g=new Map,y=[],b=[],x=()=>{s(y),y=[],c(b),b=[]},S=()=>{for(let[,e]of g)s(e.nodes),c(e.cleanups);g.clear()};o(m(()=>{let o=t.parentNode;o&&p(()=>{let p=e.value;if(!p.length){if(S(),x(),!n)return;let e=r(_(n())),i=f(e.html);y=Array.from(i.childNodes),t.after(i);let a=e=>b.push(e);l(e.bindings,a,d(y),{onHtml:e=>u(o,e,a)});return}x();let{keys:m,rendered:C}=v(p,a,i),w=new Map,T=[];for(let e=0;e<m.length;e++){let t=m[e],n=C[e],r=g.get(t),i,a=[];if(r&&r.html===n.html)i=r.nodes,c(r.cleanups);else{r&&(s(r.nodes),c(r.cleanups));let e=f(n.html);i=Array.from(e.childNodes)}T.push({item:n,key:t,nodes:i}),w.set(t,{cleanups:a,html:n.html,nodes:i})}for(let[e,t]of g)w.has(e)||(s(t.nodes),c(t.cleanups));let E=t;for(let e of T){for(let t of e.nodes)o.insertBefore(t,E.nextSibling),E=t;let t=w.get(e.key);if(!t)continue;let n=e=>t.cleanups.push(e);h(()=>{l(e.item.bindings,n,d(e.nodes),{onHtml:e=>u(o,e,n)})})}g=w})})),o(()=>{x(),S()})}}}export{y as each};
2
2
  //# sourceMappingURL=each.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"each.js","names":[],"sources":["../../src/directives/each.ts"],"sourcesContent":["import { computed, isSignal, type ReadonlySignal } from '@vielzeug/stateit';\n\nimport {\n CF_ID_ATTR,\n EACH_SIGNAL,\n extractResult,\n htmlResult,\n isHtmlResult,\n type Binding,\n type Directive,\n type HTMLResult,\n} from '../core/internal';\nimport { escapeHtml } from '../core/utilities';\n\nconst ATTR_ID_RE = new RegExp(`${CF_ID_ATTR}=\"(\\\\d+)\"`, 'g');\n\n/* immutable — shared singleton for empty static lists */\nconst EMPTY = htmlResult('');\nconst NO_BINDINGS: Binding[] = [];\n\nconst toResultEntry = (value: string | HTMLResult, c: { n: number }): { bindings: Binding[]; html: string } =>\n isHtmlResult(value) ? renumber(value, c) : { bindings: NO_BINDINGS, html: escapeHtml(value) };\n\nconst toHtmlResult = (value: string | HTMLResult): HTMLResult =>\n isHtmlResult(value) ? value : htmlResult(escapeHtml(value));\n\nfunction renumber(res: HTMLResult, c: { n: number }): { bindings: Binding[]; html: string } {\n const map = new Map<string, string>();\n const nb: Binding[] = [];\n\n for (const b of res.__bindings) {\n const oldId = b.uid;\n const newId = map.get(oldId) ?? String(c.n++);\n\n if (!map.has(oldId)) map.set(oldId, newId);\n\n nb.push({ ...b, uid: newId });\n }\n\n return {\n bindings: nb,\n html: res.__html\n // Re-map element binding ids.\n .replace(ATTR_ID_RE, (_, id) => `${CF_ID_ATTR}=\"${map.get(id) ?? id}\"`)\n // Re-map numeric comment markers used by text/html placeholders.\n .replace(/<!--(\\d+)-->/g, (_, id) => `<!--${map.get(id) ?? id}-->`),\n };\n}\n\n/** Render loop used by the reactive path (keys + rendered metadata required for reconciliation). */\nfunction renderKeyed<T>(\n items: T[],\n template: (item: T, index: number) => string | HTMLResult,\n keyFn: (item: T, index: number) => string | number,\n): {\n bindings: Binding[];\n html: string;\n keys: (string | number)[];\n rendered: Array<{ bindings: Binding[]; html: string }>;\n} {\n let html = '';\n const allBindings: Binding[] = [];\n const keys: (string | number)[] = [];\n const rendered: Array<{ bindings: Binding[]; html: string }> = [];\n const c = { n: 0 };\n\n for (let i = 0; i < items.length; i++) {\n keys.push(keyFn(items[i], i));\n\n const entry = toResultEntry(template(items[i], i), c);\n\n html += entry.html;\n allBindings.push(...entry.bindings);\n rendered.push(entry);\n }\n\n return { bindings: allBindings, html, keys, rendered };\n}\n\n/** Render loop used by the static path — no key/reconciliation metadata needed. */\nfunction renderStatic<T>(\n items: T[],\n template: (item: T, index: number) => string | HTMLResult,\n): { bindings: Binding[]; html: string } {\n let html = '';\n const allBindings: Binding[] = [];\n const c = { n: 0 };\n\n for (let i = 0; i < items.length; i++) {\n const entry = toResultEntry(template(items[i], i), c);\n\n html += entry.html;\n allBindings.push(...entry.bindings);\n }\n\n return { bindings: allBindings, html };\n}\n\n/**\n * Options accepted by `each()`.\n */\nexport interface EachOptions<T> {\n /**\n * Key extractor for stable DOM reconciliation.\n * Receives the item and its **filtered** array index (after `select` is applied).\n *\n * Required when `source` is reactive (Signal/getter).\n * Optional for static arrays (render-once path).\n */\n key?: (item: T, index: number) => string | number;\n /**\n * Filter predicate. Receives the item and its **original** array index.\n * Only items for which `select` returns `true` are rendered.\n *\n * @example\n * each(items, item => html`<li>${item.name}</li>`, undefined, { select: item => item.active })\n */\n select?: (item: T, index: number) => boolean;\n}\n\ntype ReactiveSource<T> = ReadonlySignal<T[]> | (() => T[]);\ntype EachSignalResult = Directive & {\n [EACH_SIGNAL]: ReadonlySignal<{\n bindings: Binding[];\n html: string;\n items?: Array<{ bindings: Binding[]; html: string }>;\n keys?: (string | number)[];\n }>;\n};\n\n/**\n * Renders a reactive list with keyed DOM reconciliation for efficient updates.\n * Use inside `html` tagged templates.\n *\n * For reactive sources (Signal/getter), you must provide a stable `key` function.\n *\n * For dynamic lists with click handlers, prefer event delegation on a parent node\n * (`@click` + `closest(...)`) over per-item handlers inside `each()`.\n *\n * @example\n * import { each } from '@vielzeug/craftit/directives';\n *\n * // Static array (key optional):\n * html`${each([1, 2, 3], item => html`<li>${item}</li>`)}`\n *\n * // Reactive source (key required):\n * html`${each(items, item => html`<li>${item.name}</li>`, undefined, { key: item => item.id })}`\n *\n * // Full example:\n * html`${each(items, item => html`<li>${item.name}</li>`, () => html`<p>No items</p>`, {\n * key: item => item.id,\n * select: item => item.active,\n * })}`\n */\nexport function each<T>(\n source: T[],\n template: (item: T, index: number) => string | HTMLResult,\n empty?: () => string | HTMLResult,\n options?: EachOptions<T>,\n): HTMLResult;\nexport function each<T>(\n source: ReactiveSource<T>,\n template: (item: T, index: number) => string | HTMLResult,\n options: EachOptions<T> & { key: (item: T, index: number) => string | number },\n): EachSignalResult;\nexport function each<T>(\n source: ReactiveSource<T>,\n template: (item: T, index: number) => string | HTMLResult,\n empty: (() => string | HTMLResult) | undefined,\n options: EachOptions<T> & { key: (item: T, index: number) => string | number },\n): EachSignalResult;\nexport function each<T>(\n source: T[] | ReactiveSource<T>,\n template: (item: T, index: number) => string | HTMLResult,\n emptyOrOptions?: (() => string | HTMLResult) | EachOptions<T>,\n options?: EachOptions<T>,\n): HTMLResult | EachSignalResult {\n const hasEmptyFn = typeof emptyOrOptions === 'function';\n const empty = hasEmptyFn ? emptyOrOptions : undefined;\n const resolvedOptions = (hasEmptyFn ? options : (options ?? emptyOrOptions)) ?? {};\n const select = resolvedOptions.select;\n\n if (Array.isArray(source)) {\n const filtered = select ? source.filter(select) : source;\n\n if (!filtered.length) {\n if (empty) {\n const er = extractResult(toHtmlResult(empty()));\n\n return htmlResult(er.html, er.bindings);\n }\n\n return EMPTY;\n }\n\n const { bindings, html } = renderStatic(filtered, template);\n\n return htmlResult(html, bindings);\n }\n\n const keyFn = resolvedOptions.key;\n\n if (!keyFn) {\n throw new Error('[craftit:each] Reactive each() requires options.key for stable reconciliation.');\n }\n\n const getItems = isSignal(source) ? () => (source as ReadonlySignal<T[]>).value : (source as () => T[]);\n\n return {\n [EACH_SIGNAL]: computed(() => {\n const raw = getItems();\n const filtered = select ? raw.filter(select) : raw;\n\n if (!filtered.length) {\n const er = empty ? toHtmlResult(empty()) : undefined;\n\n return er ? { ...extractResult(er), items: [], keys: [] } : { bindings: [], html: '', items: [], keys: [] };\n }\n\n const { bindings, html, keys, rendered } = renderKeyed(filtered, template, keyFn);\n\n return { bindings, html, items: rendered, keys };\n }),\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"each.js","names":[],"sources":["../../src/directives/each.ts"],"sourcesContent":["import { batch, effect as _effect, untrack, type CleanupFn, type ReadonlySignal } from '@vielzeug/stateit';\n\nimport { CRAFTIT_ERRORS } from '../errors';\nimport {\n createMarkerIdFactory,\n escapeHtml,\n extractResult,\n htmlResult,\n isHtmlResult,\n removeNodes,\n rekeyHtmlResult,\n runAll,\n type Binding,\n type DirectiveResult,\n type HTMLResult,\n} from '../internal';\nimport { applyBindingsWithTargets, indexBindingTargets, parseHTML, type RegisterCleanup } from '../template-bindings';\nimport { applyHtmlBinding } from '../template-bindings';\n\nconst toResultEntry = (value: string | HTMLResult, getNextId: () => string): { bindings: Binding[]; html: string } =>\n isHtmlResult(value) ? rekeyHtmlResult(value, getNextId) : { bindings: [], html: escapeHtml(value) };\n\nconst toHtmlResult = (value: string | HTMLResult): HTMLResult =>\n isHtmlResult(value) ? value : htmlResult(escapeHtml(value));\n\n/** Render loop used by the reactive path (keys + rendered metadata required for reconciliation). */\nfunction renderKeyed<T>(\n items: T[],\n template: (item: T, index: number) => string | HTMLResult,\n keyFn: (item: T, index: number) => string | number,\n): {\n bindings: Binding[];\n html: string;\n keys: (string | number)[];\n rendered: Array<{ bindings: Binding[]; html: string }>;\n} {\n let html = '';\n const allBindings: Binding[] = [];\n const keys: (string | number)[] = [];\n const seenKeys = new Set<string | number>();\n const rendered: Array<{ bindings: Binding[]; html: string }> = [];\n const getNextId = createMarkerIdFactory();\n\n for (let i = 0; i < items.length; i++) {\n const nextKey = keyFn(items[i], i);\n\n if (seenKeys.has(nextKey)) {\n throw new Error(CRAFTIT_ERRORS.eachDuplicateKey(String(nextKey), i));\n }\n\n seenKeys.add(nextKey);\n keys.push(nextKey);\n\n const entry = toResultEntry(template(items[i], i), getNextId);\n\n html += entry.html;\n allBindings.push(...entry.bindings);\n rendered.push(entry);\n }\n\n return { bindings: allBindings, html, keys, rendered };\n}\n\nexport interface EachOptions<T> {\n fallback?: () => string | HTMLResult;\n key: (item: T, index: number) => string | number;\n render: (item: T, index: number) => string | HTMLResult;\n}\n\n/**\n * Renders a list with keyed DOM reconciliation for reactive sources.\n * Use inside `html` tagged templates.\n *\n * `each()` expects a reactive signal source and a stable `key` function.\n *\n * For dynamic lists with click handlers, prefer event delegation on a parent node\n * (`@click` + `closest(...)`) over per-item handlers inside `each()`.\n *\n * @example\n * import { each } from '@vielzeug/craftit';\n *\n * // Reactive source (key required):\n * html`${each(items, { key: item => item.id, render: (item) => html`<li>${item.name}</li>` })}`\n *\n * // Full example:\n * html`${each(items, {\n * fallback: () => html`<p>No items</p>`,\n * key: item => item.id,\n * render: (item) => html`<li>${item.name}</li>`,\n * })}`\n */\nexport function each<T>(source: ReadonlySignal<T[]>, options: EachOptions<T>): DirectiveResult;\nexport function each<T>(source: ReadonlySignal<T[]>, options: EachOptions<T>): DirectiveResult {\n const { fallback, key, render: renderItem } = options;\n\n const mount = (anchor: Comment, registerCleanup: RegisterCleanup): void => {\n type KeyedNode = {\n cleanups: CleanupFn[];\n html: string;\n nodes: Node[];\n };\n\n let keyedNodes = new Map<string | number, KeyedNode>();\n let fallbackNodes: Node[] = [];\n let fallbackCleanups: CleanupFn[] = [];\n\n const clearFallback = (): void => {\n removeNodes(fallbackNodes);\n fallbackNodes = [];\n runAll(fallbackCleanups);\n fallbackCleanups = [];\n };\n\n const clearKeyed = (): void => {\n for (const [, node] of keyedNodes) {\n removeNodes(node.nodes);\n runAll(node.cleanups);\n }\n\n keyedNodes.clear();\n };\n\n const stop = _effect(() => {\n const parent = anchor.parentNode;\n\n if (!parent) return;\n\n batch(() => {\n const raw = source.value;\n\n if (!raw.length) {\n clearKeyed();\n clearFallback();\n\n if (!fallback) return;\n\n const fallbackResult = extractResult(toHtmlResult(fallback()));\n const parsed = parseHTML(fallbackResult.html);\n\n fallbackNodes = Array.from(parsed.childNodes);\n anchor.after(parsed);\n\n const addFallbackCleanup: RegisterCleanup = (fn) => fallbackCleanups.push(fn);\n\n applyBindingsWithTargets(fallbackResult.bindings, addFallbackCleanup, indexBindingTargets(fallbackNodes), {\n onHtml: (binding) => applyHtmlBinding(parent as unknown as Node, binding, addFallbackCleanup),\n });\n\n return;\n }\n\n clearFallback();\n\n const { keys, rendered } = renderKeyed(raw, renderItem, key);\n const nextKeyed = new Map<string | number, KeyedNode>();\n const ordered: Array<{ item: { bindings: Binding[]; html: string }; key: string | number; nodes: Node[] }> = [];\n\n for (let i = 0; i < keys.length; i++) {\n const nextKey = keys[i];\n const item = rendered[i];\n const existing = keyedNodes.get(nextKey);\n let nodes: Node[];\n const cleanups: CleanupFn[] = [];\n\n if (existing && existing.html === item.html) {\n nodes = existing.nodes;\n runAll(existing.cleanups);\n } else {\n if (existing) {\n removeNodes(existing.nodes);\n runAll(existing.cleanups);\n }\n\n const parsed = parseHTML(item.html);\n\n nodes = Array.from(parsed.childNodes);\n }\n\n ordered.push({ item, key: nextKey, nodes });\n nextKeyed.set(nextKey, { cleanups, html: item.html, nodes });\n }\n\n for (const [oldKey, oldNode] of keyedNodes) {\n if (!nextKeyed.has(oldKey)) {\n removeNodes(oldNode.nodes);\n runAll(oldNode.cleanups);\n }\n }\n\n let cursor: Node = anchor;\n\n for (const entry of ordered) {\n for (const node of entry.nodes) {\n parent.insertBefore(node, cursor.nextSibling);\n cursor = node;\n }\n\n const targetNode = nextKeyed.get(entry.key);\n\n if (!targetNode) continue;\n\n const addItemCleanup: RegisterCleanup = (fn) => targetNode.cleanups.push(fn);\n\n untrack(() => {\n applyBindingsWithTargets(entry.item.bindings, addItemCleanup, indexBindingTargets(entry.nodes), {\n onHtml: (binding) => applyHtmlBinding(parent as unknown as Node, binding, addItemCleanup),\n });\n });\n }\n\n keyedNodes = nextKeyed;\n });\n });\n\n registerCleanup(stop);\n registerCleanup(() => {\n clearFallback();\n clearKeyed();\n });\n };\n\n return { __craftitDirective: true, mount };\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ let e=require(`@vielzeug/stateit`);var t=t=>typeof t==`function`?t():(0,e.isSignal)(t)?t.value:t,n=(e,t)=>{if(e.length!==t.length)return!1;for(let n=0;n<e.length;n++)if(!Object.is(e[n],t[n]))return!1;return!0};function r(r,i){let a=!1,o=[],s=``;return(0,e.computed)(()=>{let c=(Array.isArray(r)?r:[r]).map(e=>t(e));return(!a||!n(o,c))&&(s=(0,e.untrack)(i),o=c,a=!0),s})}exports.guard=r;
2
+ //# sourceMappingURL=guard.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guard.cjs","names":[],"sources":["../../src/directives/guard.ts"],"sourcesContent":["import { computed, isSignal, type ReadonlySignal, untrack } from '@vielzeug/stateit';\n\nimport type { HTMLResult } from '../internal';\n\ntype GuardDep = unknown | (() => unknown) | ReadonlySignal<unknown>;\n\ntype GuardRenderable = string | HTMLResult;\n\nconst resolve = (value: GuardDep): unknown => {\n if (typeof value === 'function') return (value as () => unknown)();\n\n if (isSignal(value)) return value.value;\n\n return value;\n};\n\nconst depsEqual = (prev: unknown[], next: unknown[]): boolean => {\n if (prev.length !== next.length) return false;\n\n for (let index = 0; index < prev.length; index++) {\n if (!Object.is(prev[index], next[index])) return false;\n }\n\n return true;\n};\n\n/**\n * Memoizes rendering until the provided dependency tuple changes.\n */\nexport function guard(deps: GuardDep | GuardDep[], render: () => GuardRenderable): ReadonlySignal<GuardRenderable> {\n let initialized = false;\n let previousDeps: unknown[] = [];\n let cached: GuardRenderable = '';\n\n return computed(() => {\n const resolvedDeps = (Array.isArray(deps) ? deps : [deps]).map((dep) => resolve(dep));\n\n if (!initialized || !depsEqual(previousDeps, resolvedDeps)) {\n // untrack() prevents signals read inside render() from invalidating this\n // computed — only changes to the explicit dep array trigger re-renders.\n cached = untrack(render);\n previousDeps = resolvedDeps;\n initialized = true;\n }\n\n return cached;\n });\n}\n"],"mappings":"mCAQA,IAAM,EAAW,GACX,OAAO,GAAU,WAAoB,EAAwB,GAEjE,EAAA,EAAA,UAAa,CAAK,EAAU,EAAM,MAE3B,EAGH,GAAa,EAAiB,IAA6B,CAC/D,GAAI,EAAK,SAAW,EAAK,OAAQ,MAAO,GAExC,IAAK,IAAI,EAAQ,EAAG,EAAQ,EAAK,OAAQ,IACvC,GAAI,CAAC,OAAO,GAAG,EAAK,GAAQ,EAAK,EAAM,EAAG,MAAO,GAGnD,MAAO,EACT,EAKA,SAAgB,EAAM,EAA6B,EAAgE,CACjH,IAAI,EAAc,GACd,EAA0B,CAAC,EAC3B,EAA0B,GAE9B,OAAA,EAAA,EAAA,cAAsB,CACpB,IAAM,GAAgB,MAAM,QAAQ,CAAI,EAAI,EAAO,CAAC,CAAI,GAAG,IAAK,GAAQ,EAAQ,CAAG,CAAC,EAUpF,OARI,CAAC,GAAe,CAAC,EAAU,EAAc,CAAY,KAGvD,GAAA,EAAA,EAAA,SAAiB,CAAM,EACvB,EAAe,EACf,EAAc,IAGT,CACT,CAAC,CACH"}
@@ -0,0 +1,10 @@
1
+ import { type ReadonlySignal } from '@vielzeug/stateit';
2
+ import type { HTMLResult } from '../internal';
3
+ type GuardDep = unknown | (() => unknown) | ReadonlySignal<unknown>;
4
+ type GuardRenderable = string | HTMLResult;
5
+ /**
6
+ * Memoizes rendering until the provided dependency tuple changes.
7
+ */
8
+ export declare function guard(deps: GuardDep | GuardDep[], render: () => GuardRenderable): ReadonlySignal<GuardRenderable>;
9
+ export {};
10
+ //# sourceMappingURL=guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../../src/directives/guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,cAAc,EAAW,MAAM,mBAAmB,CAAC;AAErF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,KAAK,QAAQ,GAAG,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;AAEpE,KAAK,eAAe,GAAG,MAAM,GAAG,UAAU,CAAC;AAoB3C;;GAEG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,eAAe,GAAG,cAAc,CAAC,eAAe,CAAC,CAkBjH"}
@@ -0,0 +1,2 @@
1
+ import{computed as e,isSignal as t,untrack as n}from"@vielzeug/stateit";var r=e=>typeof e==`function`?e():t(e)?e.value:e,i=(e,t)=>{if(e.length!==t.length)return!1;for(let n=0;n<e.length;n++)if(!Object.is(e[n],t[n]))return!1;return!0};function a(t,a){let o=!1,s=[],c=``;return e(()=>{let e=(Array.isArray(t)?t:[t]).map(e=>r(e));return(!o||!i(s,e))&&(c=n(a),s=e,o=!0),c})}export{a as guard};
2
+ //# sourceMappingURL=guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guard.js","names":[],"sources":["../../src/directives/guard.ts"],"sourcesContent":["import { computed, isSignal, type ReadonlySignal, untrack } from '@vielzeug/stateit';\n\nimport type { HTMLResult } from '../internal';\n\ntype GuardDep = unknown | (() => unknown) | ReadonlySignal<unknown>;\n\ntype GuardRenderable = string | HTMLResult;\n\nconst resolve = (value: GuardDep): unknown => {\n if (typeof value === 'function') return (value as () => unknown)();\n\n if (isSignal(value)) return value.value;\n\n return value;\n};\n\nconst depsEqual = (prev: unknown[], next: unknown[]): boolean => {\n if (prev.length !== next.length) return false;\n\n for (let index = 0; index < prev.length; index++) {\n if (!Object.is(prev[index], next[index])) return false;\n }\n\n return true;\n};\n\n/**\n * Memoizes rendering until the provided dependency tuple changes.\n */\nexport function guard(deps: GuardDep | GuardDep[], render: () => GuardRenderable): ReadonlySignal<GuardRenderable> {\n let initialized = false;\n let previousDeps: unknown[] = [];\n let cached: GuardRenderable = '';\n\n return computed(() => {\n const resolvedDeps = (Array.isArray(deps) ? deps : [deps]).map((dep) => resolve(dep));\n\n if (!initialized || !depsEqual(previousDeps, resolvedDeps)) {\n // untrack() prevents signals read inside render() from invalidating this\n // computed — only changes to the explicit dep array trigger re-renders.\n cached = untrack(render);\n previousDeps = resolvedDeps;\n initialized = true;\n }\n\n return cached;\n });\n}\n"],"mappings":"wEAQA,IAAM,EAAW,GACX,OAAO,GAAU,WAAoB,EAAwB,EAE7D,EAAS,CAAK,EAAU,EAAM,MAE3B,EAGH,GAAa,EAAiB,IAA6B,CAC/D,GAAI,EAAK,SAAW,EAAK,OAAQ,MAAO,GAExC,IAAK,IAAI,EAAQ,EAAG,EAAQ,EAAK,OAAQ,IACvC,GAAI,CAAC,OAAO,GAAG,EAAK,GAAQ,EAAK,EAAM,EAAG,MAAO,GAGnD,MAAO,EACT,EAKA,SAAgB,EAAM,EAA6B,EAAgE,CACjH,IAAI,EAAc,GACd,EAA0B,CAAC,EAC3B,EAA0B,GAE9B,OAAO,MAAe,CACpB,IAAM,GAAgB,MAAM,QAAQ,CAAI,EAAI,EAAO,CAAC,CAAI,GAAG,IAAK,GAAQ,EAAQ,CAAG,CAAC,EAUpF,OARI,CAAC,GAAe,CAAC,EAAU,EAAc,CAAY,KAGvD,EAAS,EAAQ,CAAM,EACvB,EAAe,EACf,EAAc,IAGT,CACT,CAAC,CACH"}
@@ -0,0 +1,2 @@
1
+ var e=e=>({__live:!0,get value(){return e.value}}),t=e=>typeof e==`object`&&!!e&&e.__live===!0;exports.isLiveSignal=t,exports.live=e;
2
+ //# sourceMappingURL=live.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live.cjs","names":[],"sources":["../../src/directives/live.ts"],"sourcesContent":["import type { ReadonlySignal } from '@vielzeug/stateit';\n\n/**\n * A branded signal that tells the attribute binding engine to skip writing when\n * the DOM value has diverged from the last programmatically-written value.\n * Created via live(signal) — pass a signal directly rather than wrapping a value.\n *\n * @example\n * html`<input :value=\"${live(model)}\" />`\n */\nexport type LiveSignal<T> = ReadonlySignal<T> & { readonly __live: true };\n\n/**\n * Marks a signal binding as \"live\" so stale app-state writes never clobber\n * in-progress user input.\n *\n * For form controls: if the current DOM value diverges from the last write made\n * by this binding, subsequent app-state writes are silently dropped until the\n * DOM value matches the incoming value or no prior write has been recorded.\n */\nexport const live = <T>(source: ReadonlySignal<T>): LiveSignal<T> =>\n ({\n __live: true as const,\n get value(): T {\n return source.value;\n },\n }) as LiveSignal<T>;\n\nexport const isLiveSignal = (value: unknown): value is LiveSignal<unknown> =>\n typeof value === 'object' && value !== null && (value as Record<string, unknown>).__live === true;\n"],"mappings":"AAoBA,IAAa,EAAW,IACrB,CACC,OAAQ,GACR,IAAI,OAAW,CACb,OAAO,EAAO,KAChB,CACF,GAEW,EAAgB,GAC3B,OAAO,GAAU,YAAY,GAAmB,EAAkC,SAAW"}
@@ -0,0 +1,23 @@
1
+ import type { ReadonlySignal } from '@vielzeug/stateit';
2
+ /**
3
+ * A branded signal that tells the attribute binding engine to skip writing when
4
+ * the DOM value has diverged from the last programmatically-written value.
5
+ * Created via live(signal) — pass a signal directly rather than wrapping a value.
6
+ *
7
+ * @example
8
+ * html`<input :value="${live(model)}" />`
9
+ */
10
+ export type LiveSignal<T> = ReadonlySignal<T> & {
11
+ readonly __live: true;
12
+ };
13
+ /**
14
+ * Marks a signal binding as "live" so stale app-state writes never clobber
15
+ * in-progress user input.
16
+ *
17
+ * For form controls: if the current DOM value diverges from the last write made
18
+ * by this binding, subsequent app-state writes are silently dropped until the
19
+ * DOM value matches the incoming value or no prior write has been recorded.
20
+ */
21
+ export declare const live: <T>(source: ReadonlySignal<T>) => LiveSignal<T>;
22
+ export declare const isLiveSignal: (value: unknown) => value is LiveSignal<unknown>;
23
+ //# sourceMappingURL=live.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../src/directives/live.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD;;;;;;;GAOG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,cAAc,CAAC,CAAC,CAAC,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAA;CAAE,CAAC;AAE1E;;;;;;;GAOG;AACH,eAAO,MAAM,IAAI,GAAI,CAAC,EAAE,QAAQ,cAAc,CAAC,CAAC,CAAC,KAAG,UAAU,CAAC,CAAC,CAM3C,CAAC;AAEtB,eAAO,MAAM,YAAY,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,UAAU,CAAC,OAAO,CAC0B,CAAC"}
@@ -0,0 +1,2 @@
1
+ var e=e=>({__live:!0,get value(){return e.value}}),t=e=>typeof e==`object`&&!!e&&e.__live===!0;export{t as isLiveSignal,e as live};
2
+ //# sourceMappingURL=live.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live.js","names":[],"sources":["../../src/directives/live.ts"],"sourcesContent":["import type { ReadonlySignal } from '@vielzeug/stateit';\n\n/**\n * A branded signal that tells the attribute binding engine to skip writing when\n * the DOM value has diverged from the last programmatically-written value.\n * Created via live(signal) — pass a signal directly rather than wrapping a value.\n *\n * @example\n * html`<input :value=\"${live(model)}\" />`\n */\nexport type LiveSignal<T> = ReadonlySignal<T> & { readonly __live: true };\n\n/**\n * Marks a signal binding as \"live\" so stale app-state writes never clobber\n * in-progress user input.\n *\n * For form controls: if the current DOM value diverges from the last write made\n * by this binding, subsequent app-state writes are silently dropped until the\n * DOM value matches the incoming value or no prior write has been recorded.\n */\nexport const live = <T>(source: ReadonlySignal<T>): LiveSignal<T> =>\n ({\n __live: true as const,\n get value(): T {\n return source.value;\n },\n }) as LiveSignal<T>;\n\nexport const isLiveSignal = (value: unknown): value is LiveSignal<unknown> =>\n typeof value === 'object' && value !== null && (value as Record<string, unknown>).__live === true;\n"],"mappings":"AAoBA,IAAa,EAAW,IACrB,CACC,OAAQ,GACR,IAAI,OAAW,CACb,OAAO,EAAO,KAChB,CACF,GAEW,EAAgB,GAC3B,OAAO,GAAU,YAAY,GAAmB,EAAkC,SAAW"}
@@ -1,2 +1,2 @@
1
- const e=require(`../core/internal.cjs`);let t=require(`@vielzeug/stateit`);function n(n){return(0,t.isSignal)(n)?(0,t.computed)(()=>e.htmlResult(n.value)):typeof n==`function`?(0,t.computed)(()=>e.htmlResult(n())):e.htmlResult(n)}exports.raw=n;
1
+ const e=require(`../internal.cjs`);let t=require(`@vielzeug/stateit`);function n(n){return(0,t.isSignal)(n)?(0,t.computed)(()=>e.htmlResult(n.value)):e.htmlResult(n)}exports.raw=n;
2
2
  //# sourceMappingURL=raw.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"raw.cjs","names":[],"sources":["../../src/directives/raw.ts"],"sourcesContent":["import { computed, isSignal, type ReadonlySignal, type Signal } from '@vielzeug/stateit';\n\nimport { htmlResult, type HTMLResult } from '../core/internal';\n\n/**\n * Renders a trusted HTML string without escaping.\n * **Only use with content you control** — passing user-supplied strings\n * directly is an XSS risk.\n *\n * Supports static strings, writable Signals, and getter functions.\n * When reactive, the DOM is updated in-place whenever the value changes.\n *\n * @example\n * import { raw } from '@vielzeug/craftit/directives';\n *\n * // Static\n * html`<div>${raw('<strong>bold</strong>')}</div>`\n *\n * // Reactive signal\n * const content = signal('<em>hello</em>');\n * html`<div>${raw(content)}</div>`\n *\n * // Getter\n * html`<div>${raw(() => sanitize(props.body.value))}</div>`\n */\nexport function raw(\n value: string | Signal<string> | ReadonlySignal<string> | (() => string),\n): HTMLResult | ReadonlySignal<HTMLResult> {\n if (isSignal(value)) {\n return computed(() => htmlResult((value as ReadonlySignal<string>).value));\n }\n\n if (typeof value === 'function') {\n return computed(() => htmlResult((value as () => string)()));\n }\n\n return htmlResult(value);\n}\n"],"mappings":"2EAyBA,SAAgB,EACd,EACyC,CASzC,OARA,EAAA,EAAA,UAAa,EAAM,EACjB,EAAA,EAAA,cAAsB,EAAA,WAAY,EAAiC,MAAM,CAAC,CAGxE,OAAO,GAAU,YACnB,EAAA,EAAA,cAAsB,EAAA,WAAY,GAAwB,CAAC,CAAC,CAGvD,EAAA,WAAW,EAAM"}
1
+ {"version":3,"file":"raw.cjs","names":[],"sources":["../../src/directives/raw.ts"],"sourcesContent":["import { computed, isSignal, type ReadonlySignal, type Signal } from '@vielzeug/stateit';\n\nimport { htmlResult, type HTMLResult } from '../internal';\n\n/**\n * Renders a trusted HTML string without escaping.\n * **Only use with content you control** — passing user-supplied strings\n * directly is an XSS risk.\n *\n * Supports static strings and signals.\n * When reactive, the DOM is updated in-place whenever the value changes.\n *\n * @example\n * import { raw } from '@vielzeug/craftit';\n *\n * // Static\n * html`<div>${raw('<strong>bold</strong>')}</div>`\n *\n * // Reactive signal\n * const content = signal('<em>hello</em>');\n * html`<div>${raw(content)}</div>`\n *\n */\nexport function raw(value: string | Signal<string> | ReadonlySignal<string>): HTMLResult | ReadonlySignal<HTMLResult> {\n if (isSignal(value)) {\n return computed(() => htmlResult((value as ReadonlySignal<string>).value));\n }\n\n return htmlResult(value);\n}\n"],"mappings":"sEAuBA,SAAgB,EAAI,EAAkG,CAKpH,OAJA,EAAA,EAAA,UAAa,CAAK,GAChB,EAAA,EAAA,cAAsB,EAAA,WAAY,EAAiC,KAAK,CAAC,EAGpE,EAAA,WAAW,CAAK,CACzB"}
@@ -1,15 +1,15 @@
1
1
  import { type ReadonlySignal, type Signal } from '@vielzeug/stateit';
2
- import { type HTMLResult } from '../core/internal';
2
+ import { type HTMLResult } from '../internal';
3
3
  /**
4
4
  * Renders a trusted HTML string without escaping.
5
5
  * **Only use with content you control** — passing user-supplied strings
6
6
  * directly is an XSS risk.
7
7
  *
8
- * Supports static strings, writable Signals, and getter functions.
8
+ * Supports static strings and signals.
9
9
  * When reactive, the DOM is updated in-place whenever the value changes.
10
10
  *
11
11
  * @example
12
- * import { raw } from '@vielzeug/craftit/directives';
12
+ * import { raw } from '@vielzeug/craftit';
13
13
  *
14
14
  * // Static
15
15
  * html`<div>${raw('<strong>bold</strong>')}</div>`
@@ -18,8 +18,6 @@ import { type HTMLResult } from '../core/internal';
18
18
  * const content = signal('<em>hello</em>');
19
19
  * html`<div>${raw(content)}</div>`
20
20
  *
21
- * // Getter
22
- * html`<div>${raw(() => sanitize(props.body.value))}</div>`
23
21
  */
24
- export declare function raw(value: string | Signal<string> | ReadonlySignal<string> | (() => string)): HTMLResult | ReadonlySignal<HTMLResult>;
22
+ export declare function raw(value: string | Signal<string> | ReadonlySignal<string>): HTMLResult | ReadonlySignal<HTMLResult>;
25
23
  //# sourceMappingURL=raw.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"raw.d.ts","sourceRoot":"","sources":["../../src/directives/raw.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,cAAc,EAAE,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEzF,OAAO,EAAc,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,GAAG,CACjB,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,MAAM,CAAC,GACvE,UAAU,GAAG,cAAc,CAAC,UAAU,CAAC,CAUzC"}
1
+ {"version":3,"file":"raw.d.ts","sourceRoot":"","sources":["../../src/directives/raw.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,cAAc,EAAE,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEzF,OAAO,EAAc,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAE1D;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,GAAG,UAAU,GAAG,cAAc,CAAC,UAAU,CAAC,CAMpH"}
@@ -1,2 +1,2 @@
1
- import{htmlResult as e}from"../core/internal.js";import{computed as t,isSignal as n}from"@vielzeug/stateit";function r(r){return n(r)?t(()=>e(r.value)):typeof r==`function`?t(()=>e(r())):e(r)}export{r as raw};
1
+ import{htmlResult as e}from"../internal.js";import{computed as t,isSignal as n}from"@vielzeug/stateit";function r(r){return n(r)?t(()=>e(r.value)):e(r)}export{r as raw};
2
2
  //# sourceMappingURL=raw.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"raw.js","names":[],"sources":["../../src/directives/raw.ts"],"sourcesContent":["import { computed, isSignal, type ReadonlySignal, type Signal } from '@vielzeug/stateit';\n\nimport { htmlResult, type HTMLResult } from '../core/internal';\n\n/**\n * Renders a trusted HTML string without escaping.\n * **Only use with content you control** — passing user-supplied strings\n * directly is an XSS risk.\n *\n * Supports static strings, writable Signals, and getter functions.\n * When reactive, the DOM is updated in-place whenever the value changes.\n *\n * @example\n * import { raw } from '@vielzeug/craftit/directives';\n *\n * // Static\n * html`<div>${raw('<strong>bold</strong>')}</div>`\n *\n * // Reactive signal\n * const content = signal('<em>hello</em>');\n * html`<div>${raw(content)}</div>`\n *\n * // Getter\n * html`<div>${raw(() => sanitize(props.body.value))}</div>`\n */\nexport function raw(\n value: string | Signal<string> | ReadonlySignal<string> | (() => string),\n): HTMLResult | ReadonlySignal<HTMLResult> {\n if (isSignal(value)) {\n return computed(() => htmlResult((value as ReadonlySignal<string>).value));\n }\n\n if (typeof value === 'function') {\n return computed(() => htmlResult((value as () => string)()));\n }\n\n return htmlResult(value);\n}\n"],"mappings":"4GAyBA,SAAgB,EACd,EACyC,CASzC,OARI,EAAS,EAAM,CACV,MAAe,EAAY,EAAiC,MAAM,CAAC,CAGxE,OAAO,GAAU,WACZ,MAAe,EAAY,GAAwB,CAAC,CAAC,CAGvD,EAAW,EAAM"}
1
+ {"version":3,"file":"raw.js","names":[],"sources":["../../src/directives/raw.ts"],"sourcesContent":["import { computed, isSignal, type ReadonlySignal, type Signal } from '@vielzeug/stateit';\n\nimport { htmlResult, type HTMLResult } from '../internal';\n\n/**\n * Renders a trusted HTML string without escaping.\n * **Only use with content you control** — passing user-supplied strings\n * directly is an XSS risk.\n *\n * Supports static strings and signals.\n * When reactive, the DOM is updated in-place whenever the value changes.\n *\n * @example\n * import { raw } from '@vielzeug/craftit';\n *\n * // Static\n * html`<div>${raw('<strong>bold</strong>')}</div>`\n *\n * // Reactive signal\n * const content = signal('<em>hello</em>');\n * html`<div>${raw(content)}</div>`\n *\n */\nexport function raw(value: string | Signal<string> | ReadonlySignal<string>): HTMLResult | ReadonlySignal<HTMLResult> {\n if (isSignal(value)) {\n return computed(() => htmlResult((value as ReadonlySignal<string>).value));\n }\n\n return htmlResult(value);\n}\n"],"mappings":"uGAuBA,SAAgB,EAAI,EAAkG,CAKpH,OAJI,EAAS,CAAK,EACT,MAAe,EAAY,EAAiC,KAAK,CAAC,EAGpE,EAAW,CAAK,CACzB"}
@@ -0,0 +1,2 @@
1
+ const e=require(`../errors.cjs`),t=require(`../runtime.cjs`);let n=require(`@vielzeug/stateit`);function r(r,i){let a=(0,n.signal)({data:void 0,error:void 0,pending:!0}),o;if(!t.tryRegisterCleanup((0,n.effect)(()=>{let e=r(),t=new AbortController;return a.value={data:o,error:void 0,pending:!0},i(e,t.signal).then(e=>{t.signal.aborted||(o=e,a.value={data:e,error:void 0,pending:!1})}).catch(e=>{t.signal.aborted||(a.value={data:o,error:e,pending:!1})}),()=>t.abort()})))throw Error(e.CRAFTIT_ERRORS.lifecycleOutsideSetup);return a}exports.resource=r;
2
+ //# sourceMappingURL=resource.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource.cjs","names":[],"sources":["../../src/directives/resource.ts"],"sourcesContent":["import { effect as signalEffect, type Signal, signal } from '@vielzeug/stateit';\n\nimport { CRAFTIT_ERRORS } from '../errors';\nimport { tryRegisterCleanup } from '../runtime';\n\nexport type ResourceState<T> = {\n /** Previous successful data, available while a reload is pending. */\n data: T | undefined;\n /** Rejection reason from the most recent failed fetch, or `undefined`. */\n error: unknown;\n /** `true` while the fetcher promise is in flight. */\n pending: boolean;\n};\n\n/**\n * Reactive async resource. Re-fetches whenever the `deps` getter returns a new value.\n * Previous data is preserved during reloads so the UI can show stale-while-revalidate UX.\n * In-flight requests are cancelled via `AbortController` when deps change.\n *\n * Must be called inside component `setup()` or another Craftit runtime scope.\n *\n * @example\n * ```ts\n * const user = resource(\n * () => props.userId.value,\n * (id, signal) => fetch(`/api/users/${id}`, { signal }).then(r => r.json()),\n * );\n *\n * return () => html`\n * ${when(() => user.value.pending, () => html`<p>Loading…</p>`)}\n * ${when(() => !!user.value.error, () => html`<p>Error</p>`)}\n * ${when(() => !!user.value.data, () => html`<p>${user.value.data?.name}</p>`)}\n * `;\n * ```\n */\nexport function resource<Deps, T>(deps: () => Deps, fetcher: (deps: Deps, signal: AbortSignal) => Promise<T>) {\n const state: Signal<ResourceState<T>> = signal({ data: undefined, error: undefined, pending: true });\n let previousData: T | undefined;\n\n // Use raw stateit effect and register cleanup explicitly.\n const dispose = signalEffect(() => {\n const currentDeps = deps();\n const controller = new AbortController();\n\n state.value = { data: previousData, error: undefined, pending: true };\n\n fetcher(currentDeps, controller.signal)\n .then((data) => {\n if (!controller.signal.aborted) {\n previousData = data;\n state.value = { data, error: undefined, pending: false };\n }\n })\n .catch((error: unknown) => {\n if (!controller.signal.aborted) {\n state.value = { data: previousData, error, pending: false };\n }\n });\n\n return () => controller.abort();\n });\n\n if (!tryRegisterCleanup(dispose)) throw new Error(CRAFTIT_ERRORS.lifecycleOutsideSetup);\n\n return state;\n}\n"],"mappings":"gGAmCA,SAAgB,EAAkB,EAAkB,EAA0D,CAC5G,IAAM,GAAA,EAAA,EAAA,QAAyC,CAAE,KAAM,IAAA,GAAW,MAAO,IAAA,GAAW,QAAS,EAAK,CAAC,EAC/F,EAyBJ,GAAI,CAAC,EAAA,oBAAA,EAAA,EAAA,YAtB8B,CACjC,IAAM,EAAc,EAAK,EACnB,EAAa,IAAI,gBAiBvB,MAfA,GAAM,MAAQ,CAAE,KAAM,EAAc,MAAO,IAAA,GAAW,QAAS,EAAK,EAEpE,EAAQ,EAAa,EAAW,MAAM,EACnC,KAAM,GAAS,CACT,EAAW,OAAO,UACrB,EAAe,EACf,EAAM,MAAQ,CAAE,OAAM,MAAO,IAAA,GAAW,QAAS,EAAM,EAE3D,CAAC,EACA,MAAO,GAAmB,CACpB,EAAW,OAAO,UACrB,EAAM,MAAQ,CAAE,KAAM,EAAc,QAAO,QAAS,EAAM,EAE9D,CAAC,MAEU,EAAW,MAAM,CAChC,CAEwB,CAAO,EAAG,MAAU,MAAM,EAAA,eAAe,qBAAqB,EAEtF,OAAO,CACT"}
@@ -0,0 +1,32 @@
1
+ import { type Signal } from '@vielzeug/stateit';
2
+ export type ResourceState<T> = {
3
+ /** Previous successful data, available while a reload is pending. */
4
+ data: T | undefined;
5
+ /** Rejection reason from the most recent failed fetch, or `undefined`. */
6
+ error: unknown;
7
+ /** `true` while the fetcher promise is in flight. */
8
+ pending: boolean;
9
+ };
10
+ /**
11
+ * Reactive async resource. Re-fetches whenever the `deps` getter returns a new value.
12
+ * Previous data is preserved during reloads so the UI can show stale-while-revalidate UX.
13
+ * In-flight requests are cancelled via `AbortController` when deps change.
14
+ *
15
+ * Must be called inside component `setup()` or another Craftit runtime scope.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * const user = resource(
20
+ * () => props.userId.value,
21
+ * (id, signal) => fetch(`/api/users/${id}`, { signal }).then(r => r.json()),
22
+ * );
23
+ *
24
+ * return () => html`
25
+ * ${when(() => user.value.pending, () => html`<p>Loading…</p>`)}
26
+ * ${when(() => !!user.value.error, () => html`<p>Error</p>`)}
27
+ * ${when(() => !!user.value.data, () => html`<p>${user.value.data?.name}</p>`)}
28
+ * `;
29
+ * ```
30
+ */
31
+ export declare function resource<Deps, T>(deps: () => Deps, fetcher: (deps: Deps, signal: AbortSignal) => Promise<T>): Signal<ResourceState<T>>;
32
+ //# sourceMappingURL=resource.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../../src/directives/resource.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,MAAM,EAAU,MAAM,mBAAmB,CAAC;AAKhF,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI;IAC7B,qEAAqE;IACrE,IAAI,EAAE,CAAC,GAAG,SAAS,CAAC;IACpB,0EAA0E;IAC1E,KAAK,EAAE,OAAO,CAAC;IACf,qDAAqD;IACrD,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,IAAI,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,4BA8B3G"}
@@ -0,0 +1,2 @@
1
+ import{CRAFTIT_ERRORS as e}from"../errors.js";import{tryRegisterCleanup as t}from"../runtime.js";import{effect as n,signal as r}from"@vielzeug/stateit";function i(i,a){let o=r({data:void 0,error:void 0,pending:!0}),s;if(!t(n(()=>{let e=i(),t=new AbortController;return o.value={data:s,error:void 0,pending:!0},a(e,t.signal).then(e=>{t.signal.aborted||(s=e,o.value={data:e,error:void 0,pending:!1})}).catch(e=>{t.signal.aborted||(o.value={data:s,error:e,pending:!1})}),()=>t.abort()})))throw Error(e.lifecycleOutsideSetup);return o}export{i as resource};
2
+ //# sourceMappingURL=resource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource.js","names":[],"sources":["../../src/directives/resource.ts"],"sourcesContent":["import { effect as signalEffect, type Signal, signal } from '@vielzeug/stateit';\n\nimport { CRAFTIT_ERRORS } from '../errors';\nimport { tryRegisterCleanup } from '../runtime';\n\nexport type ResourceState<T> = {\n /** Previous successful data, available while a reload is pending. */\n data: T | undefined;\n /** Rejection reason from the most recent failed fetch, or `undefined`. */\n error: unknown;\n /** `true` while the fetcher promise is in flight. */\n pending: boolean;\n};\n\n/**\n * Reactive async resource. Re-fetches whenever the `deps` getter returns a new value.\n * Previous data is preserved during reloads so the UI can show stale-while-revalidate UX.\n * In-flight requests are cancelled via `AbortController` when deps change.\n *\n * Must be called inside component `setup()` or another Craftit runtime scope.\n *\n * @example\n * ```ts\n * const user = resource(\n * () => props.userId.value,\n * (id, signal) => fetch(`/api/users/${id}`, { signal }).then(r => r.json()),\n * );\n *\n * return () => html`\n * ${when(() => user.value.pending, () => html`<p>Loading…</p>`)}\n * ${when(() => !!user.value.error, () => html`<p>Error</p>`)}\n * ${when(() => !!user.value.data, () => html`<p>${user.value.data?.name}</p>`)}\n * `;\n * ```\n */\nexport function resource<Deps, T>(deps: () => Deps, fetcher: (deps: Deps, signal: AbortSignal) => Promise<T>) {\n const state: Signal<ResourceState<T>> = signal({ data: undefined, error: undefined, pending: true });\n let previousData: T | undefined;\n\n // Use raw stateit effect and register cleanup explicitly.\n const dispose = signalEffect(() => {\n const currentDeps = deps();\n const controller = new AbortController();\n\n state.value = { data: previousData, error: undefined, pending: true };\n\n fetcher(currentDeps, controller.signal)\n .then((data) => {\n if (!controller.signal.aborted) {\n previousData = data;\n state.value = { data, error: undefined, pending: false };\n }\n })\n .catch((error: unknown) => {\n if (!controller.signal.aborted) {\n state.value = { data: previousData, error, pending: false };\n }\n });\n\n return () => controller.abort();\n });\n\n if (!tryRegisterCleanup(dispose)) throw new Error(CRAFTIT_ERRORS.lifecycleOutsideSetup);\n\n return state;\n}\n"],"mappings":"wJAmCA,SAAgB,EAAkB,EAAkB,EAA0D,CAC5G,IAAM,EAAkC,EAAO,CAAE,KAAM,IAAA,GAAW,MAAO,IAAA,GAAW,QAAS,EAAK,CAAC,EAC/F,EAyBJ,GAAI,CAAC,EAtBW,MAAmB,CACjC,IAAM,EAAc,EAAK,EACnB,EAAa,IAAI,gBAiBvB,MAfA,GAAM,MAAQ,CAAE,KAAM,EAAc,MAAO,IAAA,GAAW,QAAS,EAAK,EAEpE,EAAQ,EAAa,EAAW,MAAM,EACnC,KAAM,GAAS,CACT,EAAW,OAAO,UACrB,EAAe,EACf,EAAM,MAAQ,CAAE,OAAM,MAAO,IAAA,GAAW,QAAS,EAAM,EAE3D,CAAC,EACA,MAAO,GAAmB,CACpB,EAAW,OAAO,UACrB,EAAM,MAAQ,CAAE,KAAM,EAAc,QAAO,QAAS,EAAM,EAE9D,CAAC,MAEU,EAAW,MAAM,CAChC,CAEwB,CAAO,EAAG,MAAU,MAAM,EAAe,qBAAqB,EAEtF,OAAO,CACT"}
@@ -0,0 +1,2 @@
1
+ let e=require(`@vielzeug/stateit`);var t=t=>{let n=typeof t==`function`?t():(0,e.isSignal)(t)?t.value:t;return n==null||n===!1?``:String(n)},n=e=>e.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`),r=r=>(0,e.computed)(()=>{let e=[];for(let[i,a]of Object.entries(r)){let r=t(a);r&&e.push(`${n(i)}:${r}`)}return e.join(`;`)});exports.styleMap=r;
2
+ //# sourceMappingURL=styleMap.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styleMap.cjs","names":[],"sources":["../../src/directives/styleMap.ts"],"sourcesContent":["import { computed, isSignal, type ReadonlySignal } from '@vielzeug/stateit';\n\ntype StyleInput =\n | string\n | number\n | null\n | undefined\n | false\n | (() => string | number | null | undefined | false)\n | ReadonlySignal<string | number | null | undefined | false>;\n\nconst toStyleValue = (value: StyleInput): string => {\n const resolved = typeof value === 'function' ? value() : isSignal(value) ? value.value : value;\n\n if (resolved == null || resolved === false) return '';\n\n return String(resolved);\n};\n\nconst toKebabCase = (name: string): string => name.replace(/[A-Z]/g, (char) => `-${char.toLowerCase()}`);\n\n/**\n * Builds a reactive inline style string from a style object.\n *\n * @example\n * html`<div :style=${styleMap({ backgroundColor: color, width: () => `${size.value}px` })}></div>`\n */\nexport const styleMap = (record: Record<string, StyleInput>): ReadonlySignal<string> => {\n return computed(() => {\n const declarations: string[] = [];\n\n for (const [name, input] of Object.entries(record)) {\n const value = toStyleValue(input);\n\n if (!value) continue;\n\n declarations.push(`${toKebabCase(name)}:${value}`);\n }\n\n return declarations.join(';');\n });\n};\n"],"mappings":"mCAWA,IAAM,EAAgB,GAA8B,CAClD,IAAM,EAAW,OAAO,GAAU,WAAa,EAAM,GAAA,EAAA,EAAA,UAAa,CAAK,EAAI,EAAM,MAAQ,EAIzF,OAFI,GAAY,MAAQ,IAAa,GAAc,GAE5C,OAAO,CAAQ,CACxB,EAEM,EAAe,GAAyB,EAAK,QAAQ,SAAW,GAAS,IAAI,EAAK,YAAY,GAAG,EAQ1F,EAAY,IACvB,EAAA,EAAA,cAAsB,CACpB,IAAM,EAAyB,CAAC,EAEhC,IAAK,GAAM,CAAC,EAAM,KAAU,OAAO,QAAQ,CAAM,EAAG,CAClD,IAAM,EAAQ,EAAa,CAAK,EAE3B,GAEL,EAAa,KAAK,GAAG,EAAY,CAAI,EAAE,GAAG,GAAO,CACnD,CAEA,OAAO,EAAa,KAAK,GAAG,CAC9B,CAAC"}