@typed/template 0.14.0 → 1.0.0-beta.0

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 (453) hide show
  1. package/README.md +108 -2
  2. package/dist/EventHandler.d.ts +273 -0
  3. package/dist/EventHandler.d.ts.map +1 -0
  4. package/dist/EventHandler.js +261 -0
  5. package/dist/EventSource.d.ts +82 -0
  6. package/dist/EventSource.d.ts.map +1 -0
  7. package/dist/EventSource.js +127 -0
  8. package/dist/Html.d.ts +122 -0
  9. package/dist/Html.d.ts.map +1 -0
  10. package/dist/Html.js +250 -0
  11. package/dist/HtmlChunk.d.ts +118 -0
  12. package/dist/HtmlChunk.d.ts.map +1 -0
  13. package/dist/HtmlChunk.js +211 -0
  14. package/dist/HydrateContext.d.ts +28 -0
  15. package/dist/HydrateContext.d.ts.map +1 -0
  16. package/dist/HydrateContext.js +25 -0
  17. package/dist/Parser.d.ts +35 -0
  18. package/dist/Parser.d.ts.map +1 -0
  19. package/dist/Parser.js +437 -0
  20. package/dist/Render.d.ts +195 -0
  21. package/dist/Render.d.ts.map +1 -0
  22. package/dist/Render.js +609 -0
  23. package/dist/RenderEvent.d.ts +179 -0
  24. package/dist/RenderEvent.d.ts.map +1 -0
  25. package/dist/RenderEvent.js +102 -0
  26. package/dist/RenderQueue.d.ts +167 -0
  27. package/dist/RenderQueue.d.ts.map +1 -0
  28. package/dist/RenderQueue.js +297 -0
  29. package/dist/RenderTemplate.d.ts +90 -0
  30. package/dist/RenderTemplate.d.ts.map +1 -0
  31. package/dist/RenderTemplate.js +87 -0
  32. package/dist/Renderable.d.ts +88 -0
  33. package/dist/Renderable.d.ts.map +1 -0
  34. package/dist/Renderable.js +3 -0
  35. package/dist/{dts/Template.d.ts → Template.d.ts} +109 -74
  36. package/dist/Template.d.ts.map +1 -0
  37. package/dist/{esm/Template.js → Template.js} +96 -56
  38. package/dist/Wire.d.ts +169 -0
  39. package/dist/Wire.d.ts.map +1 -0
  40. package/dist/Wire.js +217 -0
  41. package/dist/errors.d.ts +145 -0
  42. package/dist/errors.d.ts.map +1 -0
  43. package/dist/errors.js +159 -0
  44. package/dist/index.d.ts +15 -0
  45. package/dist/index.d.ts.map +1 -0
  46. package/dist/index.js +14 -0
  47. package/dist/internal/IndexRefCounter.d.ts +11 -0
  48. package/dist/internal/IndexRefCounter.d.ts.map +1 -0
  49. package/dist/internal/IndexRefCounter.js +42 -0
  50. package/dist/internal/ParentChildNodes.d.ts +6 -0
  51. package/dist/internal/ParentChildNodes.d.ts.map +1 -0
  52. package/dist/internal/ParentChildNodes.js +1 -0
  53. package/dist/internal/PathStack.d.ts +9 -0
  54. package/dist/internal/PathStack.d.ts.map +1 -0
  55. package/dist/internal/PathStack.js +18 -0
  56. package/dist/internal/buildTemplateFragement.d.ts +3 -0
  57. package/dist/internal/buildTemplateFragement.d.ts.map +1 -0
  58. package/dist/internal/buildTemplateFragement.js +61 -0
  59. package/dist/internal/diff.d.ts +2 -0
  60. package/dist/internal/diff.d.ts.map +1 -0
  61. package/dist/internal/diff.js +119 -0
  62. package/dist/internal/dom.d.ts +45 -0
  63. package/dist/internal/dom.d.ts.map +1 -0
  64. package/dist/internal/dom.js +304 -0
  65. package/dist/internal/encoding.d.ts +7 -0
  66. package/dist/internal/encoding.d.ts.map +1 -0
  67. package/dist/internal/encoding.js +134 -0
  68. package/dist/{dts/internal/v2/hydration-template.d.ts → internal/hydration.d.ts} +10 -7
  69. package/dist/internal/hydration.d.ts.map +1 -0
  70. package/dist/{esm/internal/v2/hydration-template.js → internal/hydration.js} +80 -26
  71. package/dist/internal/keyToPartType.d.ts +2 -0
  72. package/dist/internal/keyToPartType.d.ts.map +1 -0
  73. package/dist/internal/keyToPartType.js +110 -0
  74. package/dist/internal/meta.d.ts +17 -0
  75. package/dist/internal/meta.d.ts.map +1 -0
  76. package/dist/internal/meta.js +14 -0
  77. package/dist/internal/takeOneIfNotRenderEvent.d.ts +4 -0
  78. package/dist/internal/takeOneIfNotRenderEvent.d.ts.map +1 -0
  79. package/dist/internal/takeOneIfNotRenderEvent.js +10 -0
  80. package/dist/internal/templateHash.d.ts +2 -0
  81. package/dist/internal/templateHash.d.ts.map +1 -0
  82. package/dist/internal/templateHash.js +14 -0
  83. package/dist/many.d.ts +68 -0
  84. package/dist/many.d.ts.map +1 -0
  85. package/dist/many.js +107 -0
  86. package/package.json +22 -224
  87. package/src/EventHandler.ts +318 -86
  88. package/src/EventSource.ts +202 -0
  89. package/src/Html.test.ts +490 -0
  90. package/src/Html.ts +292 -333
  91. package/src/HtmlChunk.ts +290 -332
  92. package/src/HydrateContext.ts +40 -0
  93. package/src/Hydration.test.ts +409 -0
  94. package/src/Parser.test.ts +924 -0
  95. package/src/Parser.ts +598 -10
  96. package/src/Render.test.ts +338 -0
  97. package/src/Render.ts +878 -63
  98. package/src/RenderEvent.ts +169 -40
  99. package/src/RenderQueue.ts +290 -385
  100. package/src/RenderTemplate.ts +98 -31
  101. package/src/Renderable.ts +122 -24
  102. package/src/Template.ts +246 -145
  103. package/src/Wire.ts +309 -0
  104. package/src/errors.ts +173 -0
  105. package/src/index.ts +14 -66
  106. package/src/internal/IndexRefCounter.ts +53 -0
  107. package/src/internal/ParentChildNodes.ts +7 -0
  108. package/src/internal/PathStack.ts +23 -0
  109. package/src/internal/buildTemplateFragement.ts +82 -0
  110. package/src/internal/diff.ts +127 -0
  111. package/src/internal/dom.ts +357 -0
  112. package/src/internal/encoding.ts +147 -0
  113. package/src/internal/hydration.ts +406 -0
  114. package/src/internal/keyToPartType.ts +113 -0
  115. package/src/internal/meta.ts +25 -0
  116. package/src/internal/takeOneIfNotRenderEvent.ts +19 -0
  117. package/src/internal/templateHash.ts +18 -0
  118. package/src/many.ts +148 -0
  119. package/tsconfig.json +6 -0
  120. package/Directive/package.json +0 -6
  121. package/ElementRef/package.json +0 -6
  122. package/ElementSource/package.json +0 -6
  123. package/Entry/package.json +0 -6
  124. package/EventHandler/package.json +0 -6
  125. package/Html/package.json +0 -6
  126. package/HtmlChunk/package.json +0 -6
  127. package/Hydrate/package.json +0 -6
  128. package/LICENSE +0 -21
  129. package/Many/package.json +0 -6
  130. package/Meta/package.json +0 -6
  131. package/Parser/package.json +0 -6
  132. package/Part/package.json +0 -6
  133. package/Placeholder/package.json +0 -6
  134. package/Platform/package.json +0 -6
  135. package/Render/package.json +0 -6
  136. package/RenderContext/package.json +0 -6
  137. package/RenderEvent/package.json +0 -6
  138. package/RenderQueue/package.json +0 -6
  139. package/RenderTemplate/package.json +0 -6
  140. package/Renderable/package.json +0 -6
  141. package/Template/package.json +0 -6
  142. package/Test/package.json +0 -6
  143. package/Vitest/package.json +0 -6
  144. package/compiler-tools/package.json +0 -6
  145. package/dist/cjs/Directive.js +0 -76
  146. package/dist/cjs/Directive.js.map +0 -1
  147. package/dist/cjs/ElementRef.js +0 -92
  148. package/dist/cjs/ElementRef.js.map +0 -1
  149. package/dist/cjs/ElementSource.js +0 -246
  150. package/dist/cjs/ElementSource.js.map +0 -1
  151. package/dist/cjs/Entry.js +0 -6
  152. package/dist/cjs/Entry.js.map +0 -1
  153. package/dist/cjs/EventHandler.js +0 -76
  154. package/dist/cjs/EventHandler.js.map +0 -1
  155. package/dist/cjs/Html.js +0 -224
  156. package/dist/cjs/Html.js.map +0 -1
  157. package/dist/cjs/HtmlChunk.js +0 -306
  158. package/dist/cjs/HtmlChunk.js.map +0 -1
  159. package/dist/cjs/Hydrate.js +0 -43
  160. package/dist/cjs/Hydrate.js.map +0 -1
  161. package/dist/cjs/Many.js +0 -66
  162. package/dist/cjs/Many.js.map +0 -1
  163. package/dist/cjs/Meta.js +0 -50
  164. package/dist/cjs/Meta.js.map +0 -1
  165. package/dist/cjs/Parser.js +0 -19
  166. package/dist/cjs/Parser.js.map +0 -1
  167. package/dist/cjs/Part.js +0 -6
  168. package/dist/cjs/Part.js.map +0 -1
  169. package/dist/cjs/Placeholder.js +0 -34
  170. package/dist/cjs/Placeholder.js.map +0 -1
  171. package/dist/cjs/Platform.js +0 -65
  172. package/dist/cjs/Platform.js.map +0 -1
  173. package/dist/cjs/Render.js +0 -50
  174. package/dist/cjs/Render.js.map +0 -1
  175. package/dist/cjs/RenderContext.js +0 -67
  176. package/dist/cjs/RenderContext.js.map +0 -1
  177. package/dist/cjs/RenderEvent.js +0 -52
  178. package/dist/cjs/RenderEvent.js.map +0 -1
  179. package/dist/cjs/RenderQueue.js +0 -343
  180. package/dist/cjs/RenderQueue.js.map +0 -1
  181. package/dist/cjs/RenderTemplate.js +0 -26
  182. package/dist/cjs/RenderTemplate.js.map +0 -1
  183. package/dist/cjs/Renderable.js +0 -6
  184. package/dist/cjs/Renderable.js.map +0 -1
  185. package/dist/cjs/Template.js +0 -305
  186. package/dist/cjs/Template.js.map +0 -1
  187. package/dist/cjs/Test.js +0 -184
  188. package/dist/cjs/Test.js.map +0 -1
  189. package/dist/cjs/Vitest.js +0 -52
  190. package/dist/cjs/Vitest.js.map +0 -1
  191. package/dist/cjs/compiler-tools.js +0 -100
  192. package/dist/cjs/compiler-tools.js.map +0 -1
  193. package/dist/cjs/index.js +0 -138
  194. package/dist/cjs/index.js.map +0 -1
  195. package/dist/cjs/internal/EventSource.js +0 -129
  196. package/dist/cjs/internal/EventSource.js.map +0 -1
  197. package/dist/cjs/internal/HydrateContext.js +0 -13
  198. package/dist/cjs/internal/HydrateContext.js.map +0 -1
  199. package/dist/cjs/internal/browser.js +0 -110
  200. package/dist/cjs/internal/browser.js.map +0 -1
  201. package/dist/cjs/internal/character-entities.js +0 -2141
  202. package/dist/cjs/internal/character-entities.js.map +0 -1
  203. package/dist/cjs/internal/chunks.js +0 -68
  204. package/dist/cjs/internal/chunks.js.map +0 -1
  205. package/dist/cjs/internal/errors.js +0 -52
  206. package/dist/cjs/internal/errors.js.map +0 -1
  207. package/dist/cjs/internal/indexRefCounter.js +0 -52
  208. package/dist/cjs/internal/indexRefCounter.js.map +0 -1
  209. package/dist/cjs/internal/module-augmentation.js +0 -6
  210. package/dist/cjs/internal/module-augmentation.js.map +0 -1
  211. package/dist/cjs/internal/parser.js +0 -568
  212. package/dist/cjs/internal/parser.js.map +0 -1
  213. package/dist/cjs/internal/parser2.js +0 -382
  214. package/dist/cjs/internal/parser2.js.map +0 -1
  215. package/dist/cjs/internal/server-parts.js +0 -124
  216. package/dist/cjs/internal/server-parts.js.map +0 -1
  217. package/dist/cjs/internal/server.js +0 -48
  218. package/dist/cjs/internal/server.js.map +0 -1
  219. package/dist/cjs/internal/utils.js +0 -136
  220. package/dist/cjs/internal/utils.js.map +0 -1
  221. package/dist/cjs/internal/v2/SyncPart.js +0 -6
  222. package/dist/cjs/internal/v2/SyncPart.js.map +0 -1
  223. package/dist/cjs/internal/v2/helpers.js +0 -15
  224. package/dist/cjs/internal/v2/helpers.js.map +0 -1
  225. package/dist/cjs/internal/v2/hydration-template.js +0 -269
  226. package/dist/cjs/internal/v2/hydration-template.js.map +0 -1
  227. package/dist/cjs/internal/v2/parts.js +0 -169
  228. package/dist/cjs/internal/v2/parts.js.map +0 -1
  229. package/dist/cjs/internal/v2/render-entry.js +0 -110
  230. package/dist/cjs/internal/v2/render-entry.js.map +0 -1
  231. package/dist/cjs/internal/v2/render-sync-parts.js +0 -318
  232. package/dist/cjs/internal/v2/render-sync-parts.js.map +0 -1
  233. package/dist/cjs/internal/v2/render.js +0 -592
  234. package/dist/cjs/internal/v2/render.js.map +0 -1
  235. package/dist/cjs/internal/v2/sync-parts.js +0 -115
  236. package/dist/cjs/internal/v2/sync-parts.js.map +0 -1
  237. package/dist/dts/Directive.d.ts +0 -70
  238. package/dist/dts/Directive.d.ts.map +0 -1
  239. package/dist/dts/ElementRef.d.ts +0 -42
  240. package/dist/dts/ElementRef.d.ts.map +0 -1
  241. package/dist/dts/ElementSource.d.ts +0 -79
  242. package/dist/dts/ElementSource.d.ts.map +0 -1
  243. package/dist/dts/Entry.d.ts +0 -26
  244. package/dist/dts/Entry.d.ts.map +0 -1
  245. package/dist/dts/EventHandler.d.ts +0 -73
  246. package/dist/dts/EventHandler.d.ts.map +0 -1
  247. package/dist/dts/Html.d.ts +0 -35
  248. package/dist/dts/Html.d.ts.map +0 -1
  249. package/dist/dts/HtmlChunk.d.ts +0 -56
  250. package/dist/dts/HtmlChunk.d.ts.map +0 -1
  251. package/dist/dts/Hydrate.d.ts +0 -19
  252. package/dist/dts/Hydrate.d.ts.map +0 -1
  253. package/dist/dts/Many.d.ts +0 -32
  254. package/dist/dts/Many.d.ts.map +0 -1
  255. package/dist/dts/Meta.d.ts +0 -33
  256. package/dist/dts/Meta.d.ts.map +0 -1
  257. package/dist/dts/Parser.d.ts +0 -13
  258. package/dist/dts/Parser.d.ts.map +0 -1
  259. package/dist/dts/Part.d.ts +0 -121
  260. package/dist/dts/Part.d.ts.map +0 -1
  261. package/dist/dts/Placeholder.d.ts +0 -48
  262. package/dist/dts/Placeholder.d.ts.map +0 -1
  263. package/dist/dts/Platform.d.ts +0 -21
  264. package/dist/dts/Platform.d.ts.map +0 -1
  265. package/dist/dts/Render.d.ts +0 -31
  266. package/dist/dts/Render.d.ts.map +0 -1
  267. package/dist/dts/RenderContext.d.ts +0 -70
  268. package/dist/dts/RenderContext.d.ts.map +0 -1
  269. package/dist/dts/RenderEvent.d.ts +0 -42
  270. package/dist/dts/RenderEvent.d.ts.map +0 -1
  271. package/dist/dts/RenderQueue.d.ts +0 -103
  272. package/dist/dts/RenderQueue.d.ts.map +0 -1
  273. package/dist/dts/RenderTemplate.d.ts +0 -25
  274. package/dist/dts/RenderTemplate.d.ts.map +0 -1
  275. package/dist/dts/Renderable.d.ts +0 -28
  276. package/dist/dts/Renderable.d.ts.map +0 -1
  277. package/dist/dts/Template.d.ts.map +0 -1
  278. package/dist/dts/Test.d.ts +0 -85
  279. package/dist/dts/Test.d.ts.map +0 -1
  280. package/dist/dts/Vitest.d.ts +0 -43
  281. package/dist/dts/Vitest.d.ts.map +0 -1
  282. package/dist/dts/compiler-tools.d.ts +0 -143
  283. package/dist/dts/compiler-tools.d.ts.map +0 -1
  284. package/dist/dts/index.d.ts +0 -65
  285. package/dist/dts/index.d.ts.map +0 -1
  286. package/dist/dts/internal/EventSource.d.ts +0 -13
  287. package/dist/dts/internal/EventSource.d.ts.map +0 -1
  288. package/dist/dts/internal/HydrateContext.d.ts +0 -2
  289. package/dist/dts/internal/HydrateContext.d.ts.map +0 -1
  290. package/dist/dts/internal/browser.d.ts +0 -8
  291. package/dist/dts/internal/browser.d.ts.map +0 -1
  292. package/dist/dts/internal/character-entities.d.ts +0 -2133
  293. package/dist/dts/internal/character-entities.d.ts.map +0 -1
  294. package/dist/dts/internal/chunks.d.ts +0 -23
  295. package/dist/dts/internal/chunks.d.ts.map +0 -1
  296. package/dist/dts/internal/errors.d.ts +0 -22
  297. package/dist/dts/internal/errors.d.ts.map +0 -1
  298. package/dist/dts/internal/indexRefCounter.d.ts +0 -7
  299. package/dist/dts/internal/indexRefCounter.d.ts.map +0 -1
  300. package/dist/dts/internal/module-augmentation.d.ts +0 -32
  301. package/dist/dts/internal/module-augmentation.d.ts.map +0 -1
  302. package/dist/dts/internal/parser.d.ts +0 -33
  303. package/dist/dts/internal/parser.d.ts.map +0 -1
  304. package/dist/dts/internal/parser2.d.ts +0 -12
  305. package/dist/dts/internal/parser2.d.ts.map +0 -1
  306. package/dist/dts/internal/server-parts.d.ts +0 -223
  307. package/dist/dts/internal/server-parts.d.ts.map +0 -1
  308. package/dist/dts/internal/server.d.ts +0 -5
  309. package/dist/dts/internal/server.d.ts.map +0 -1
  310. package/dist/dts/internal/utils.d.ts +0 -19
  311. package/dist/dts/internal/utils.d.ts.map +0 -1
  312. package/dist/dts/internal/v2/SyncPart.d.ts +0 -87
  313. package/dist/dts/internal/v2/SyncPart.d.ts.map +0 -1
  314. package/dist/dts/internal/v2/helpers.d.ts +0 -3
  315. package/dist/dts/internal/v2/helpers.d.ts.map +0 -1
  316. package/dist/dts/internal/v2/hydration-template.d.ts.map +0 -1
  317. package/dist/dts/internal/v2/parts.d.ts +0 -245
  318. package/dist/dts/internal/v2/parts.d.ts.map +0 -1
  319. package/dist/dts/internal/v2/render-entry.d.ts +0 -6
  320. package/dist/dts/internal/v2/render-entry.d.ts.map +0 -1
  321. package/dist/dts/internal/v2/render-sync-parts.d.ts +0 -22
  322. package/dist/dts/internal/v2/render-sync-parts.d.ts.map +0 -1
  323. package/dist/dts/internal/v2/render.d.ts +0 -83
  324. package/dist/dts/internal/v2/render.d.ts.map +0 -1
  325. package/dist/dts/internal/v2/sync-parts.d.ts +0 -129
  326. package/dist/dts/internal/v2/sync-parts.d.ts.map +0 -1
  327. package/dist/esm/Directive.js +0 -64
  328. package/dist/esm/Directive.js.map +0 -1
  329. package/dist/esm/ElementRef.js +0 -76
  330. package/dist/esm/ElementRef.js.map +0 -1
  331. package/dist/esm/ElementSource.js +0 -246
  332. package/dist/esm/ElementSource.js.map +0 -1
  333. package/dist/esm/Entry.js +0 -2
  334. package/dist/esm/Entry.js.map +0 -1
  335. package/dist/esm/EventHandler.js +0 -68
  336. package/dist/esm/EventHandler.js.map +0 -1
  337. package/dist/esm/Html.js +0 -230
  338. package/dist/esm/Html.js.map +0 -1
  339. package/dist/esm/HtmlChunk.js +0 -330
  340. package/dist/esm/HtmlChunk.js.map +0 -1
  341. package/dist/esm/Hydrate.js +0 -31
  342. package/dist/esm/Hydrate.js.map +0 -1
  343. package/dist/esm/Many.js +0 -54
  344. package/dist/esm/Many.js.map +0 -1
  345. package/dist/esm/Meta.js +0 -40
  346. package/dist/esm/Meta.js.map +0 -1
  347. package/dist/esm/Parser.js +0 -13
  348. package/dist/esm/Parser.js.map +0 -1
  349. package/dist/esm/Part.js +0 -5
  350. package/dist/esm/Part.js.map +0 -1
  351. package/dist/esm/Placeholder.js +0 -26
  352. package/dist/esm/Placeholder.js.map +0 -1
  353. package/dist/esm/Platform.js +0 -42
  354. package/dist/esm/Platform.js.map +0 -1
  355. package/dist/esm/Render.js +0 -36
  356. package/dist/esm/Render.js.map +0 -1
  357. package/dist/esm/RenderContext.js +0 -54
  358. package/dist/esm/RenderContext.js.map +0 -1
  359. package/dist/esm/RenderEvent.js +0 -43
  360. package/dist/esm/RenderEvent.js.map +0 -1
  361. package/dist/esm/RenderQueue.js +0 -338
  362. package/dist/esm/RenderQueue.js.map +0 -1
  363. package/dist/esm/RenderTemplate.js +0 -16
  364. package/dist/esm/RenderTemplate.js.map +0 -1
  365. package/dist/esm/Renderable.js +0 -2
  366. package/dist/esm/Renderable.js.map +0 -1
  367. package/dist/esm/Template.js.map +0 -1
  368. package/dist/esm/Test.js +0 -167
  369. package/dist/esm/Test.js.map +0 -1
  370. package/dist/esm/Vitest.js +0 -44
  371. package/dist/esm/Vitest.js.map +0 -1
  372. package/dist/esm/compiler-tools.js +0 -91
  373. package/dist/esm/compiler-tools.js.map +0 -1
  374. package/dist/esm/index.js +0 -65
  375. package/dist/esm/index.js.map +0 -1
  376. package/dist/esm/internal/EventSource.js +0 -126
  377. package/dist/esm/internal/EventSource.js.map +0 -1
  378. package/dist/esm/internal/HydrateContext.js +0 -7
  379. package/dist/esm/internal/HydrateContext.js.map +0 -1
  380. package/dist/esm/internal/browser.js +0 -103
  381. package/dist/esm/internal/browser.js.map +0 -1
  382. package/dist/esm/internal/character-entities.js +0 -2134
  383. package/dist/esm/internal/character-entities.js.map +0 -1
  384. package/dist/esm/internal/chunks.js +0 -60
  385. package/dist/esm/internal/chunks.js.map +0 -1
  386. package/dist/esm/internal/errors.js +0 -46
  387. package/dist/esm/internal/errors.js.map +0 -1
  388. package/dist/esm/internal/indexRefCounter.js +0 -47
  389. package/dist/esm/internal/indexRefCounter.js.map +0 -1
  390. package/dist/esm/internal/module-augmentation.js +0 -2
  391. package/dist/esm/internal/module-augmentation.js.map +0 -1
  392. package/dist/esm/internal/parser.js +0 -596
  393. package/dist/esm/internal/parser.js.map +0 -1
  394. package/dist/esm/internal/parser2.js +0 -393
  395. package/dist/esm/internal/parser2.js.map +0 -1
  396. package/dist/esm/internal/server-parts.js +0 -109
  397. package/dist/esm/internal/server-parts.js.map +0 -1
  398. package/dist/esm/internal/server.js +0 -22
  399. package/dist/esm/internal/server.js.map +0 -1
  400. package/dist/esm/internal/utils.js +0 -119
  401. package/dist/esm/internal/utils.js.map +0 -1
  402. package/dist/esm/internal/v2/SyncPart.js +0 -5
  403. package/dist/esm/internal/v2/SyncPart.js.map +0 -1
  404. package/dist/esm/internal/v2/helpers.js +0 -12
  405. package/dist/esm/internal/v2/helpers.js.map +0 -1
  406. package/dist/esm/internal/v2/hydration-template.js.map +0 -1
  407. package/dist/esm/internal/v2/parts.js +0 -150
  408. package/dist/esm/internal/v2/parts.js.map +0 -1
  409. package/dist/esm/internal/v2/render-entry.js +0 -102
  410. package/dist/esm/internal/v2/render-entry.js.map +0 -1
  411. package/dist/esm/internal/v2/render-sync-parts.js +0 -265
  412. package/dist/esm/internal/v2/render-sync-parts.js.map +0 -1
  413. package/dist/esm/internal/v2/render.js +0 -521
  414. package/dist/esm/internal/v2/render.js.map +0 -1
  415. package/dist/esm/internal/v2/sync-parts.js +0 -102
  416. package/dist/esm/internal/v2/sync-parts.js.map +0 -1
  417. package/dist/esm/package.json +0 -4
  418. package/src/Directive.ts +0 -114
  419. package/src/ElementRef.ts +0 -148
  420. package/src/ElementSource.ts +0 -510
  421. package/src/Entry.ts +0 -28
  422. package/src/Hydrate.ts +0 -51
  423. package/src/Many.ts +0 -161
  424. package/src/Meta.ts +0 -45
  425. package/src/Part.ts +0 -154
  426. package/src/Placeholder.ts +0 -78
  427. package/src/Platform.ts +0 -70
  428. package/src/RenderContext.ts +0 -121
  429. package/src/Test.ts +0 -354
  430. package/src/Vitest.ts +0 -141
  431. package/src/compiler-tools.ts +0 -250
  432. package/src/internal/EventSource.ts +0 -188
  433. package/src/internal/HydrateContext.ts +0 -22
  434. package/src/internal/browser.ts +0 -138
  435. package/src/internal/character-entities.ts +0 -2136
  436. package/src/internal/chunks.ts +0 -89
  437. package/src/internal/errors.ts +0 -49
  438. package/src/internal/external.d.ts +0 -11
  439. package/src/internal/indexRefCounter.ts +0 -54
  440. package/src/internal/module-augmentation.ts +0 -44
  441. package/src/internal/parser.ts +0 -757
  442. package/src/internal/parser2.ts +0 -468
  443. package/src/internal/server-parts.ts +0 -161
  444. package/src/internal/server.ts +0 -37
  445. package/src/internal/utils.ts +0 -153
  446. package/src/internal/v2/SyncPart.ts +0 -112
  447. package/src/internal/v2/helpers.ts +0 -13
  448. package/src/internal/v2/hydration-template.ts +0 -308
  449. package/src/internal/v2/parts.ts +0 -254
  450. package/src/internal/v2/render-entry.ts +0 -131
  451. package/src/internal/v2/render-sync-parts.ts +0 -440
  452. package/src/internal/v2/render.ts +0 -813
  453. package/src/internal/v2/sync-parts.ts +0 -133
@@ -1,142 +1,374 @@
1
- /**
2
- * @since 1.0.0
3
- */
4
- import { type EventWithTarget, isUsingKeyModifier } from "@typed/dom/EventTarget"
5
- import * as Effect from "effect/Effect"
6
- import type { Placeholder } from "./Placeholder.js"
1
+ import type * as Cause from "effect/Cause";
2
+ import * as Effect from "effect/Effect";
3
+ import { dual } from "effect/Function";
4
+ import { type Pipeable, pipeArguments } from "effect/Pipeable";
5
+ import { hasProperty } from "effect/Predicate";
6
+ import type * as ServiceMap from "effect/ServiceMap";
7
+
8
+ export const EventHandlerTypeId = Symbol.for("@typed/template/EventHandler");
9
+ export type EventHandlerTypeId = typeof EventHandlerTypeId;
7
10
 
8
11
  /**
12
+ * Represents a DOM event handler that returns an Effect.
13
+ *
14
+ * It encapsulates the event handler logic and any options (like `preventDefault`, `once`, etc.)
15
+ * that should be applied when the event is triggered.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * import { Effect } from "effect"
20
+ * import * as EventHandler from "@typed/template/EventHandler"
21
+ * import { html } from "@typed/template"
22
+ *
23
+ * // Simple event handler
24
+ * const handleClick = EventHandler.make((event: MouseEvent) => {
25
+ * console.log("Clicked!", event)
26
+ * })
27
+ *
28
+ * // Event handler with Effect
29
+ * const handleSubmit = EventHandler.make((event: SubmitEvent) =>
30
+ * Effect.gen(function* () {
31
+ * event.preventDefault()
32
+ * yield* Effect.sync(() => console.log("Form submitted"))
33
+ * })
34
+ * )
35
+ *
36
+ * // Use in template
37
+ * const template = html`<button onclick=${handleClick}>Click me</button>`
38
+ * ```
39
+ *
9
40
  * @since 1.0.0
41
+ * @category models
10
42
  */
11
- export const EventHandlerTypeId = Symbol.for("@typed/template/EventHandler")
43
+ export interface EventHandler<Ev extends Event = Event, E = never, R = never> extends Pipeable {
44
+ readonly [EventHandlerTypeId]: EventHandlerTypeId;
45
+ readonly handler: (event: Ev) => Effect.Effect<unknown, E, R>;
46
+ readonly options: (AddEventListenerOptions & EventOptions) | undefined;
47
+ }
48
+
49
+ export type Context<T> = T extends EventHandler<infer _Ev, infer _E, infer R> ? R : never;
50
+ export type Error<T> = T extends EventHandler<infer _Ev, infer E, infer _R> ? E : never;
51
+ export type EventOf<T> = T extends EventHandler<infer Ev, infer _E, infer _R> ? Ev : never;
52
+
12
53
  /**
13
- * @since 1.0.0
54
+ * Options for configuring event handling behavior.
14
55
  */
15
- export type EventHandlerTypeId = typeof EventHandlerTypeId
56
+ export type EventOptions = {
57
+ readonly preventDefault?: boolean;
58
+ readonly stopPropagation?: boolean;
59
+ readonly stopImmediatePropagation?: boolean;
60
+ };
16
61
 
17
62
  /**
63
+ * Creates a new `EventHandler`.
64
+ *
65
+ * @example
66
+ * ```ts
67
+ * import { Effect } from "effect"
68
+ * import * as EventHandler from "@typed/template/EventHandler"
69
+ * import { html } from "@typed/template"
70
+ *
71
+ * // Simple handler
72
+ * const clickHandler = EventHandler.make((event) => {
73
+ * console.log("Button clicked")
74
+ * })
75
+ *
76
+ * // Handler with Effect
77
+ * const submitHandler = EventHandler.make((event) =>
78
+ * Effect.gen(function* () {
79
+ * const form = event.target as HTMLFormElement
80
+ * const data = new FormData(form)
81
+ * yield* Effect.sync(() => console.log("Submitting:", data))
82
+ * })
83
+ * )
84
+ *
85
+ * // Handler with options
86
+ * const preventDefaultHandler = EventHandler.make(
87
+ * (event) => console.log("Prevented default"),
88
+ * { preventDefault: true }
89
+ * )
90
+ *
91
+ * const template = html`<button onclick=${clickHandler}>Click</button>`
92
+ * ```
93
+ *
94
+ * @param handler - The function to execute when the event occurs. Can return void or an Effect.
95
+ * @param options - Optional configuration for the event listener.
18
96
  * @since 1.0.0
97
+ * @category constructors
19
98
  */
20
- export interface EventHandler<Ev extends Event = Event, E = never, R = never> extends Placeholder<never, E, R> {
21
- readonly [EventHandlerTypeId]: EventHandlerTypeId
22
- readonly handler: (event: Ev) => Effect.Effect<unknown, E, R>
23
- readonly options: AddEventListenerOptions | undefined
99
+ export function make<Ev extends Event, E = never, R = never>(
100
+ handler: (event: Ev) => void | Effect.Effect<unknown, E, R>,
101
+ options?: AddEventListenerOptions & EventOptions,
102
+ ): EventHandler<Ev, E, R> {
103
+ return {
104
+ [EventHandlerTypeId]: EventHandlerTypeId,
105
+ handler: (ev: Ev) => {
106
+ if (options) handleEventOptions(options, ev);
107
+ const result = handler(ev);
108
+ if (Effect.isEffect(result)) return result;
109
+ return Effect.void;
110
+ },
111
+ options,
112
+ pipe(this: EventHandler<Ev, E, R>) {
113
+ return pipeArguments(this, arguments);
114
+ },
115
+ };
24
116
  }
25
117
 
26
118
  /**
119
+ * Provides services to the `EventHandler`.
120
+ *
121
+ * This allows you to inject dependencies into the effect returned by the event handler.
122
+ *
123
+ * @example
124
+ * ```ts
125
+ * import { Effect, Context } from "effect"
126
+ * import * as EventHandler from "@typed/template/EventHandler"
127
+ *
128
+ * interface Database {
129
+ * readonly save: (data: string) => Effect.Effect<void>
130
+ * }
131
+ * const Database = Context.GenericTag<Database>("Database")
132
+ *
133
+ * const handler = EventHandler.make((event) =>
134
+ * Effect.flatMap(Database, (db) => db.save("data"))
135
+ * )
136
+ *
137
+ * // Provide services
138
+ * const provided = EventHandler.provide(handler, Database.of({ save: (d) => Effect.sync(() => console.log(d)) }))
139
+ * ```
140
+ *
27
141
  * @since 1.0.0
142
+ * @category combinators
28
143
  */
29
- export type Context<T> = T extends EventHandler<infer _Ev, infer _E, infer R> ? R : never
144
+ export const provide: {
145
+ <R2 = never>(
146
+ services: ServiceMap.ServiceMap<R2>,
147
+ ): <Ev extends Event, E = never, R = never>(
148
+ handler: EventHandler<Ev, E, R>,
149
+ ) => EventHandler<Ev, E, Exclude<R, R2>>;
150
+
151
+ <Ev extends Event, E = never, R = never, R2 = never>(
152
+ handler: EventHandler<Ev, E, R>,
153
+ services: ServiceMap.ServiceMap<R2>,
154
+ ): EventHandler<Ev, E, Exclude<R, R2>>;
155
+ } = dual(
156
+ 2,
157
+ <Ev extends Event, E = never, R = never, R2 = never>(
158
+ handler: EventHandler<Ev, E, R>,
159
+ services: ServiceMap.ServiceMap<R2>,
160
+ ): EventHandler<Ev, E, Exclude<R, R2>> => {
161
+ return make(
162
+ (ev) => handler.handler(ev).pipe(Effect.provideServices(services)),
163
+ handler.options,
164
+ );
165
+ },
166
+ );
167
+
30
168
  /**
169
+ * Recovers from errors in the `EventHandler`.
170
+ *
171
+ * @example
172
+ * ```ts
173
+ * import { Effect } from "effect"
174
+ * import * as EventHandler from "@typed/template/EventHandler"
175
+ *
176
+ * const handler = EventHandler.make((event) =>
177
+ * Effect.fail("Something went wrong")
178
+ * )
179
+ *
180
+ * // Recover from errors
181
+ * const recovered = EventHandler.catchCause(handler, (cause) =>
182
+ * Effect.sync(() => console.error("Error:", cause))
183
+ * )
184
+ * ```
185
+ *
31
186
  * @since 1.0.0
187
+ * @category combinators
32
188
  */
33
- export type Error<T> = T extends EventHandler<infer _Ev, infer E, infer _R> ? E : never
189
+ export const catchCause: {
190
+ <E, E2 = never, R2 = never>(
191
+ f: (cause: Cause.Cause<E>) => Effect.Effect<unknown, E2, R2>,
192
+ ): <Ev extends Event, R = never>(handler: EventHandler<Ev, E, R>) => EventHandler<Ev, E2, R | R2>;
193
+
194
+ <Ev extends Event, E = never, R = never, E2 = never, R2 = never>(
195
+ handler: EventHandler<Ev, E, R>,
196
+ f: (cause: Cause.Cause<E>) => Effect.Effect<unknown, E2, R2>,
197
+ ): EventHandler<Ev, E2, R | R2>;
198
+ } = dual(
199
+ 2,
200
+ <Ev extends Event, E = never, R = never, E2 = never, R2 = never>(
201
+ handler: EventHandler<Ev, E, R>,
202
+ f: (cause: Cause.Cause<E>) => Effect.Effect<unknown, E2, R2>,
203
+ ): EventHandler<Ev, E2, R | R2> => {
204
+ return make((ev) => handler.handler(ev).pipe(Effect.catchCause(f)), handler.options);
205
+ },
206
+ );
207
+
34
208
  /**
35
- * @since 1.0.0
209
+ * Helper to ensure a value is an `EventHandler`.
210
+ *
211
+ * If the input is already an `EventHandler`, it is returned as is.
212
+ * If it is an `Effect`, it is wrapped in an `EventHandler` that ignores the event argument.
36
213
  */
37
- export type EventOf<T> = T extends EventHandler<infer Ev, infer _E, infer _R> ? Ev : never
214
+ export function fromEffectOrEventHandler<Ev extends Event, E = never, R = never>(
215
+ handler: Effect.Effect<unknown, E, R> | EventHandler<Ev, E, R>,
216
+ ): EventHandler<Ev, E, R> {
217
+ if (isEventHandler(handler)) return handler;
218
+ return make(() => handler as Effect.Effect<unknown, E, R>);
219
+ }
38
220
 
39
221
  /**
222
+ * Checks if a value is an `EventHandler`.
223
+ *
224
+ * @example
225
+ * ```ts
226
+ * import * as EventHandler from "@typed/template/EventHandler"
227
+ *
228
+ * const handler = EventHandler.make((event) => console.log("Click"))
229
+ * const isHandler = EventHandler.isEventHandler(handler)
230
+ * console.log(isHandler) // true
231
+ *
232
+ * const notHandler = (event: Event) => console.log("Click")
233
+ * const isNotHandler = EventHandler.isEventHandler(notHandler)
234
+ * console.log(isNotHandler) // false
235
+ * ```
236
+ *
40
237
  * @since 1.0.0
238
+ * @category guards
41
239
  */
42
- export function make<Ev extends Event, E = never, R = never>(
43
- handler: (event: Ev) => Effect.Effect<unknown, E, R>,
44
- options?: AddEventListenerOptions
45
- ): EventHandler<Ev, E, R> {
46
- return {
47
- [EventHandlerTypeId]: EventHandlerTypeId,
48
- handler,
49
- options
50
- } as any
240
+ export function isEventHandler<Ev extends Event, E = never, R = never>(
241
+ handler: unknown,
242
+ ): handler is EventHandler<Ev, E, R> {
243
+ return hasProperty(handler, EventHandlerTypeId);
51
244
  }
52
245
 
53
246
  /**
54
- * @since 1.0.0
247
+ * Applies event options to a native DOM event.
55
248
  */
56
- export function preventDefault<R, E, Ev extends Event>(
57
- handler: (event: Ev) => Effect.Effect<unknown, E, R>,
58
- options?: AddEventListenerOptions
59
- ): EventHandler<Ev, E, R> {
60
- return make((ev) => (ev.preventDefault(), handler(ev)), options)
249
+ export function handleEventOptions<Ev extends Event>(eventOptions: EventOptions, ev: Ev): boolean {
250
+ if (eventOptions.preventDefault) ev.preventDefault();
251
+ if (eventOptions.stopPropagation) ev.stopPropagation();
252
+ if (eventOptions.stopImmediatePropagation) ev.stopImmediatePropagation();
253
+
254
+ return true;
61
255
  }
62
256
 
63
257
  /**
258
+ * Modifies an `EventHandler` to call `preventDefault()` on the event.
259
+ *
260
+ * @example
261
+ * ```ts
262
+ * import * as EventHandler from "@typed/template/EventHandler"
263
+ * import { html } from "@typed/template"
264
+ *
265
+ * const handler = EventHandler.make((event) => {
266
+ * console.log("Form submit prevented")
267
+ * })
268
+ *
269
+ * const preventDefaultHandler = EventHandler.preventDefault(handler)
270
+ *
271
+ * const template = html`<form onsubmit=${preventDefaultHandler}>...</form>`
272
+ * ```
273
+ *
64
274
  * @since 1.0.0
275
+ * @category combinators
65
276
  */
66
- export function stopPropagation<R, E, Ev extends Event>(
67
- handler: (event: Ev) => Effect.Effect<unknown, E, R>,
68
- options?: AddEventListenerOptions
277
+ export function preventDefault<Ev extends Event, E = never, R = never>(
278
+ handler: EventHandler<Ev, E, R>,
69
279
  ): EventHandler<Ev, E, R> {
70
- return make((ev) => (ev.stopPropagation(), handler(ev)), options)
280
+ return make(handler.handler, { ...handler.options, preventDefault: true });
71
281
  }
72
282
 
73
283
  /**
284
+ * Modifies an `EventHandler` to call `stopPropagation()` on the event.
285
+ *
286
+ * @example
287
+ * ```ts
288
+ * import * as EventHandler from "@typed/template/EventHandler"
289
+ *
290
+ * const handler = EventHandler.make((event) => {
291
+ * console.log("Event stopped")
292
+ * })
293
+ *
294
+ * const stopPropHandler = EventHandler.stopPropagation(handler)
295
+ * ```
296
+ *
74
297
  * @since 1.0.0
298
+ * @category combinators
75
299
  */
76
- export function stopImmediatePropagation<R, E, Ev extends Event>(
77
- handler: (event: Ev) => Effect.Effect<unknown, E, R>,
78
- options?: AddEventListenerOptions
300
+ export function stopPropagation<Ev extends Event, E = never, R = never>(
301
+ handler: EventHandler<Ev, E, R>,
79
302
  ): EventHandler<Ev, E, R> {
80
- return make((ev) => (ev.stopImmediatePropagation(), handler(ev)), options)
303
+ return make(handler.handler, { ...handler.options, stopPropagation: true });
81
304
  }
82
305
 
83
306
  /**
307
+ * Modifies an `EventHandler` to call `stopImmediatePropagation()` on the event.
308
+ *
309
+ * @example
310
+ * ```ts
311
+ * import * as EventHandler from "@typed/template/EventHandler"
312
+ *
313
+ * const handler = EventHandler.make((event) => {
314
+ * console.log("Immediate propagation stopped")
315
+ * })
316
+ *
317
+ * const stopImmediateHandler = EventHandler.stopImmediatePropagation(handler)
318
+ * ```
319
+ *
84
320
  * @since 1.0.0
321
+ * @category combinators
85
322
  */
86
- export type EventOptions = {
87
- readonly preventDefault?: boolean
88
- readonly stopPropagation?: boolean
89
- readonly stopImmediatePropagation?: boolean
90
- }
91
-
92
- function handleEventOptions<Ev extends Event>(
93
- eventOptions: EventOptions,
94
- ev: Ev
95
- ): boolean {
96
- if (eventOptions.preventDefault) ev.preventDefault()
97
- if (eventOptions.stopPropagation) ev.stopPropagation()
98
- if (eventOptions.stopImmediatePropagation) ev.stopImmediatePropagation()
99
-
100
- return true
323
+ export function stopImmediatePropagation<Ev extends Event, E = never, R = never>(
324
+ handler: EventHandler<Ev, E, R>,
325
+ ): EventHandler<Ev, E, R> {
326
+ return make(handler.handler, { ...handler.options, stopImmediatePropagation: true });
101
327
  }
102
328
 
103
329
  /**
330
+ * Modifies an `EventHandler` to run only once.
331
+ *
332
+ * @example
333
+ * ```ts
334
+ * import * as EventHandler from "@typed/template/EventHandler"
335
+ *
336
+ * const handler = EventHandler.make((event) => {
337
+ * console.log("This will only run once")
338
+ * })
339
+ *
340
+ * const onceHandler = EventHandler.once(handler)
341
+ * ```
342
+ *
104
343
  * @since 1.0.0
344
+ * @category combinators
105
345
  */
106
- export function target<T extends HTMLElement>(eventOptions?: {
107
- preventDefault?: boolean
108
- stopPropagation?: boolean
109
- stopImmediatePropagation?: boolean
110
- }) {
111
- return <R, E, Ev extends Event>(
112
- handler: (event: EventWithTarget<T, Ev>) => Effect.Effect<unknown, E, R>,
113
- options?: AddEventListenerOptions
114
- ): EventHandler<EventWithTarget<T, Ev>, E, R> => {
115
- return make(
116
- eventOptions ?
117
- (ev) => {
118
- handleEventOptions(eventOptions, ev)
119
- return handler(ev)
120
- } :
121
- handler,
122
- options
123
- )
124
- }
346
+ export function once<Ev extends Event, E = never, R = never>(
347
+ handler: EventHandler<Ev, E, R>,
348
+ ): EventHandler<Ev, E, R> {
349
+ return make(handler.handler, { ...handler.options, once: true, passive: false });
125
350
  }
126
351
 
127
352
  /**
353
+ * Modifies an `EventHandler` to be passive (improves scrolling performance).
354
+ *
355
+ * @example
356
+ * ```ts
357
+ * import * as EventHandler from "@typed/template/EventHandler"
358
+ *
359
+ * const handler = EventHandler.make((event) => {
360
+ * // Passive handlers can't call preventDefault
361
+ * console.log("Scroll event")
362
+ * })
363
+ *
364
+ * const passiveHandler = EventHandler.passive(handler)
365
+ * ```
366
+ *
128
367
  * @since 1.0.0
368
+ * @category combinators
129
369
  */
130
- export function keys<Keys extends ReadonlyArray<string>>(...keys: Keys) {
131
- return <E, R>(
132
- handler: (event: KeyboardEvent & { key: Keys[number] }) => Effect.Effect<unknown, E, R>,
133
- options?: AddEventListenerOptions & EventOptions
134
- ): EventHandler<KeyboardEvent, E, R> =>
135
- make(
136
- (ev: KeyboardEvent) =>
137
- !isUsingKeyModifier(ev) && keys.includes(ev.key)
138
- ? (options && handleEventOptions(options, ev), handler(ev as any))
139
- : Effect.void,
140
- options
141
- )
370
+ export function passive<Ev extends Event, E = never, R = never>(
371
+ handler: EventHandler<Ev, E, R>,
372
+ ): EventHandler<Ev, E, R> {
373
+ return make(handler.handler, { ...handler.options, passive: true, once: false });
142
374
  }
@@ -0,0 +1,202 @@
1
+ import * as Effect from "effect/Effect";
2
+ import * as Fiber from "effect/Fiber";
3
+ import * as Scope from "effect/Scope";
4
+ import type { EventHandler } from "./EventHandler.js";
5
+ import { getElements, type Rendered } from "./Wire.js";
6
+
7
+ type EventName = string;
8
+
9
+ type Handler<Ev extends Event> = EventHandler<Ev>;
10
+
11
+ /**
12
+ * An interface for managing event listeners on DOM nodes.
13
+ *
14
+ * It abstracts the process of adding and removing event listeners, ensuring that they are
15
+ * properly cleaned up when the scope is closed or the element is removed.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * import { Effect } from "effect"
20
+ * import { makeEventSource } from "@typed/template/EventSource"
21
+ * import * as EventHandler from "@typed/template/EventHandler"
22
+ * import { Scope } from "effect"
23
+ *
24
+ * const program = Effect.gen(function* () {
25
+ * const eventSource = makeEventSource()
26
+ * const button = document.createElement("button")
27
+ *
28
+ * // Add event listener
29
+ * const handler = EventHandler.make((event: MouseEvent) => {
30
+ * console.log("Button clicked")
31
+ * })
32
+ *
33
+ * const disposable = eventSource.addEventListener(button, "click", handler)
34
+ *
35
+ * // Setup listeners for rendered content
36
+ * yield* eventSource.setup(button, yield* Scope.make())
37
+ *
38
+ * // Cleanup
39
+ * disposable[Symbol.dispose]()
40
+ * })
41
+ * ```
42
+ *
43
+ * @since 1.0.0
44
+ * @category models
45
+ */
46
+ export interface EventSource {
47
+ /**
48
+ * Adds an event listener to a target.
49
+ */
50
+ readonly addEventListener: <Ev extends Event>(
51
+ element: EventTarget,
52
+ event: EventName,
53
+ handler: Handler<Ev>,
54
+ ) => Disposable;
55
+
56
+ /**
57
+ * Sets up event listeners for a rendered template within a scope.
58
+ */
59
+ readonly setup: (rendered: Rendered, scope: Scope.Scope) => Effect.Effect<void>;
60
+ }
61
+
62
+ type Entry = readonly [Element, Handler<any>];
63
+ type Run = <E, A>(effect: Effect.Effect<A, E>) => Fiber.Fiber<A, E>;
64
+
65
+ const disposable = (f: () => void): Disposable => ({ [Symbol.dispose]: f });
66
+ const dispose = (d: Disposable): void => d[Symbol.dispose]();
67
+
68
+ /**
69
+ * Creates a new `EventSource`.
70
+ *
71
+ * The created `EventSource` can efficiently manage multiple event listeners,
72
+ * grouping them by event type and handling setup/teardown lifecycles.
73
+ *
74
+ * @example
75
+ * ```ts
76
+ * import { Effect } from "effect"
77
+ * import { makeEventSource } from "@typed/template/EventSource"
78
+ * import * as EventHandler from "@typed/template/EventHandler"
79
+ *
80
+ * const program = Effect.gen(function* () {
81
+ * const eventSource = makeEventSource()
82
+ * const element = document.createElement("div")
83
+ *
84
+ * // Add multiple event listeners
85
+ * eventSource.addEventListener(element, "click", EventHandler.make(() => console.log("clicked")))
86
+ * eventSource.addEventListener(element, "mouseover", EventHandler.make(() => console.log("hovered")))
87
+ *
88
+ * // Setup all listeners
89
+ * yield* eventSource.setup(element, yield* Scope.make())
90
+ * })
91
+ * ```
92
+ *
93
+ * @since 1.0.0
94
+ * @category constructors
95
+ */
96
+ export function makeEventSource(): EventSource {
97
+ const listeners = new Map<EventName, readonly [normal: Set<Entry>, once: Set<Entry>]>();
98
+
99
+ function addEventListener(
100
+ element: EventTarget,
101
+ event: EventName,
102
+ handler: Handler<any>,
103
+ ): Disposable {
104
+ const sets = listeners.get(event);
105
+ const entry: Entry = [element as Element, handler];
106
+ const isOnce = handler.options?.once === true;
107
+ const normal: Set<Entry> = sets?.[0] ?? new Set<Entry>();
108
+ const once: Set<Entry> = sets?.[1] ?? new Set<Entry>();
109
+ if (sets === undefined) {
110
+ listeners.set(event, [normal, once]);
111
+ }
112
+ if (isOnce) {
113
+ once.add(entry);
114
+ return disposable(() => once.delete(entry));
115
+ } else {
116
+ normal.add(entry);
117
+ return disposable(() => normal.delete(entry));
118
+ }
119
+ }
120
+
121
+ function setupListeners(element: Element, run: Run) {
122
+ const disposables: Array<Disposable> = [];
123
+
124
+ for (const [event, sets] of listeners) {
125
+ for (const handlers of sets) {
126
+ if (handlers.size === 0) continue;
127
+ const listener = (ev: Event) =>
128
+ run(
129
+ Effect.forEach(handlers, ([el, { handler }]) => {
130
+ const match = ev.target === el || el.contains(ev.target as Node);
131
+ return match ? handler(proxyCurrentTarget(ev, el)) : Effect.void;
132
+ }),
133
+ );
134
+ element.addEventListener(event, listener, getDerivedAddEventListenerOptions(handlers));
135
+ disposables.push(disposable(() => element.removeEventListener(event, listener)));
136
+ }
137
+ }
138
+
139
+ return disposables;
140
+ }
141
+
142
+ function setup(rendered: Rendered, scope: Scope.Scope) {
143
+ if (listeners.size === 0) return Effect.void;
144
+
145
+ const elements = getElements(rendered);
146
+ if (elements.length === 0) return Effect.void;
147
+
148
+ const disposables: Array<Disposable> = [];
149
+ const fibers = new Map<symbol, Fiber.Fiber<any, any>>();
150
+ const run: Run = <E, A>(effect: Effect.Effect<A, E>) => {
151
+ const id = Symbol();
152
+ const fiber = Effect.runFork(
153
+ Effect.onExit(effect, () => Effect.sync(() => fibers.delete(id))),
154
+ );
155
+ fibers.set(id, fiber);
156
+ return fiber;
157
+ };
158
+
159
+ if (listeners.size > 0) {
160
+ for (const element of elements) {
161
+ // eslint-disable-next-line no-restricted-syntax
162
+ disposables.push(...setupListeners(element, run));
163
+ }
164
+ }
165
+
166
+ return Scope.addFinalizer(
167
+ scope,
168
+ Effect.suspend(() => {
169
+ disposables.forEach(dispose);
170
+ if (fibers.size === 0) return Effect.void;
171
+ return Fiber.interruptAll(fibers.values());
172
+ }),
173
+ );
174
+ }
175
+
176
+ return {
177
+ addEventListener,
178
+ setup,
179
+ };
180
+ }
181
+
182
+ function proxyCurrentTarget<E extends Event>(event: E, currentTarget: Element): E {
183
+ return new Proxy(event, {
184
+ get(target: E, property: string | symbol) {
185
+ if (property === "currentTarget") return currentTarget;
186
+ const value = target[property as keyof E];
187
+ if (typeof value === "function") return value.bind(event);
188
+ return value;
189
+ },
190
+ });
191
+ }
192
+
193
+ function getDerivedAddEventListenerOptions(entries: Set<Entry>): AddEventListenerOptions {
194
+ let once = true;
195
+ let passive = true;
196
+ for (const h of entries) {
197
+ if (h[1].options?.once !== true) once = false;
198
+ if (h[1].options?.passive !== true) passive = false;
199
+ if (!once && !passive) break;
200
+ }
201
+ return { once, passive };
202
+ }