sygnal 5.3.7 → 6.0.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 (438) hide show
  1. package/CHANGELOG.md +646 -0
  2. package/README.md +77 -47
  3. package/dist/astro/client.cjs.js +33 -8114
  4. package/dist/astro/client.cjs.js.map +1 -0
  5. package/dist/astro/client.mjs +33 -8114
  6. package/dist/astro/client.mjs.map +1 -0
  7. package/dist/astro/index.cjs.js +1039 -9
  8. package/dist/astro/index.cjs.js.map +1 -0
  9. package/dist/astro/index.mjs +1038 -9
  10. package/dist/astro/index.mjs.map +1 -0
  11. package/dist/astro/server.cjs.js +3400 -166
  12. package/dist/astro/server.cjs.js.map +1 -0
  13. package/dist/astro/server.mjs +3400 -166
  14. package/dist/astro/server.mjs.map +1 -0
  15. package/dist/devtools.cjs.js +1431 -0
  16. package/dist/devtools.cjs.js.map +1 -0
  17. package/dist/devtools.esm.js +1419 -0
  18. package/dist/devtools.esm.js.map +1 -0
  19. package/dist/diagnostics.cjs.js +4033 -0
  20. package/dist/diagnostics.cjs.js.map +1 -0
  21. package/dist/diagnostics.esm.js +4003 -0
  22. package/dist/diagnostics.esm.js.map +1 -0
  23. package/dist/element.cjs.js +230 -0
  24. package/dist/element.cjs.js.map +1 -0
  25. package/dist/element.esm.js +228 -0
  26. package/dist/element.esm.js.map +1 -0
  27. package/dist/guide/accessibility.md +257 -0
  28. package/dist/guide/adapters.md +221 -0
  29. package/dist/guide/behaviors.md +312 -0
  30. package/dist/guide/browser-sources.md +203 -0
  31. package/dist/guide/drag-and-drop.md +342 -0
  32. package/dist/guide/element-commands.md +306 -0
  33. package/dist/guide/error-boundaries.md +169 -0
  34. package/dist/guide/forms-reference.md +381 -0
  35. package/dist/guide/forms.md +250 -0
  36. package/dist/guide/http.md +299 -0
  37. package/dist/guide/inputs.md +173 -0
  38. package/dist/guide/persistence.md +245 -0
  39. package/dist/guide/recipes/carousel.md +155 -0
  40. package/dist/guide/recipes/charts.md +177 -0
  41. package/dist/guide/recipes/code-editor.md +135 -0
  42. package/dist/guide/recipes/data-grid.md +155 -0
  43. package/dist/guide/recipes/data-table.md +196 -0
  44. package/dist/guide/recipes/i18n.md +222 -0
  45. package/dist/guide/recipes/icons.md +115 -0
  46. package/dist/guide/recipes/overview.md +33 -0
  47. package/dist/guide/recipes/rich-text.md +154 -0
  48. package/dist/guide/resources.md +471 -0
  49. package/dist/guide/ssr.md +255 -0
  50. package/dist/guide/timers.md +178 -0
  51. package/dist/guide/ui/accordion.md +93 -0
  52. package/dist/guide/ui/combobox.md +144 -0
  53. package/dist/guide/ui/dialog.md +124 -0
  54. package/dist/guide/ui/disclosure.md +60 -0
  55. package/dist/guide/ui/menu.md +125 -0
  56. package/dist/guide/ui/overview.md +166 -0
  57. package/dist/guide/ui/popover.md +101 -0
  58. package/dist/guide/ui/select.md +114 -0
  59. package/dist/guide/ui/tabs.md +161 -0
  60. package/dist/guide/ui/toaster.md +152 -0
  61. package/dist/guide/ui/tooltip.md +103 -0
  62. package/dist/guide/undo.md +178 -0
  63. package/dist/guide/virtual-collections.md +183 -0
  64. package/dist/guide/web-components.md +179 -0
  65. package/dist/guide/widgets.md +217 -0
  66. package/dist/index.cjs.js +15283 -6279
  67. package/dist/index.cjs.js.map +1 -0
  68. package/dist/index.d.ts +3739 -370
  69. package/dist/index.esm.js +15230 -6274
  70. package/dist/index.esm.js.map +1 -0
  71. package/dist/jsx-dev-runtime.cjs.js +27 -329
  72. package/dist/jsx-dev-runtime.cjs.js.map +1 -0
  73. package/dist/jsx-dev-runtime.esm.js +20 -322
  74. package/dist/jsx-dev-runtime.esm.js.map +1 -0
  75. package/dist/jsx-runtime.cjs.js +27 -329
  76. package/dist/jsx-runtime.cjs.js.map +1 -0
  77. package/dist/jsx-runtime.esm.js +20 -322
  78. package/dist/jsx-runtime.esm.js.map +1 -0
  79. package/dist/jsx.cjs.js +11 -309
  80. package/dist/jsx.cjs.js.map +1 -0
  81. package/dist/jsx.esm.js +9 -310
  82. package/dist/jsx.esm.js.map +1 -0
  83. package/dist/react.cjs.js +117 -0
  84. package/dist/react.cjs.js.map +1 -0
  85. package/dist/react.esm.js +115 -0
  86. package/dist/react.esm.js.map +1 -0
  87. package/dist/shims/globalthis.cjs +20 -0
  88. package/dist/sygnal.min.js +2 -1
  89. package/dist/sygnal.min.js.map +1 -0
  90. package/dist/ui-combobox.cjs.js +169 -0
  91. package/dist/ui-combobox.cjs.js.map +1 -0
  92. package/dist/ui-combobox.esm.js +148 -0
  93. package/dist/ui-combobox.esm.js.map +1 -0
  94. package/dist/ui-menu.cjs.js +87 -0
  95. package/dist/ui-menu.cjs.js.map +1 -0
  96. package/dist/ui-menu.esm.js +66 -0
  97. package/dist/ui-menu.esm.js.map +1 -0
  98. package/dist/ui-select.cjs.js +104 -0
  99. package/dist/ui-select.cjs.js.map +1 -0
  100. package/dist/ui-select.esm.js +83 -0
  101. package/dist/ui-select.esm.js.map +1 -0
  102. package/dist/ui.cjs.js +738 -0
  103. package/dist/ui.cjs.js.map +1 -0
  104. package/dist/ui.esm.js +727 -0
  105. package/dist/ui.esm.js.map +1 -0
  106. package/dist/vike/ClientOnly.cjs.js +5 -14
  107. package/dist/vike/ClientOnly.cjs.js.map +1 -0
  108. package/dist/vike/ClientOnly.mjs +5 -14
  109. package/dist/vike/ClientOnly.mjs.map +1 -0
  110. package/dist/vike/{+config.js → config/+config.js} +10 -1
  111. package/dist/vike/config/+config.js.map +1 -0
  112. package/dist/vike/config/package.json +6 -0
  113. package/dist/vike/onRenderClient.cjs.js +166 -95
  114. package/dist/vike/onRenderClient.cjs.js.map +1 -0
  115. package/dist/vike/onRenderClient.mjs +166 -95
  116. package/dist/vike/onRenderClient.mjs.map +1 -0
  117. package/dist/vike/onRenderHtml.cjs.js +60 -24
  118. package/dist/vike/onRenderHtml.cjs.js.map +1 -0
  119. package/dist/vike/onRenderHtml.mjs +61 -25
  120. package/dist/vike/onRenderHtml.mjs.map +1 -0
  121. package/dist/vite/plugin.cjs.js +926 -65
  122. package/dist/vite/plugin.cjs.js.map +1 -0
  123. package/dist/vite/plugin.mjs +925 -65
  124. package/dist/vite/plugin.mjs.map +1 -0
  125. package/dist/zag.cjs.js +408 -0
  126. package/dist/zag.cjs.js.map +1 -0
  127. package/dist/zag.esm.js +405 -0
  128. package/dist/zag.esm.js.map +1 -0
  129. package/llms.txt +313 -0
  130. package/package.json +109 -16
  131. package/src/astro/client.ts +40 -18
  132. package/src/astro/index.d.ts +48 -1
  133. package/src/astro/index.ts +106 -9
  134. package/src/astro/server.ts +11 -3
  135. package/src/collection.ts +6 -90
  136. package/src/core/actions.ts +134 -0
  137. package/src/core/cell.ts +202 -0
  138. package/src/core/debug.ts +23 -0
  139. package/src/core/define.ts +242 -0
  140. package/src/core/hooks.ts +314 -0
  141. package/src/core/hosts/collection.ts +325 -0
  142. package/src/core/hosts/switchable.ts +146 -0
  143. package/src/core/instance.ts +592 -0
  144. package/src/core/markers/clientonly.ts +13 -0
  145. package/src/core/markers/lazy.ts +40 -0
  146. package/src/core/markers/portal.ts +96 -0
  147. package/src/core/markers/suspense.ts +41 -0
  148. package/src/core/markers/transition.ts +70 -0
  149. package/src/core/registry.ts +25 -0
  150. package/src/core/runtime.ts +573 -0
  151. package/src/core/statics.ts +104 -0
  152. package/src/core/teardown.ts +60 -0
  153. package/src/core/view.ts +37 -0
  154. package/src/cycle/dom/DocumentDOMSource.ts +13 -8
  155. package/src/cycle/dom/ElementFinder.ts +7 -9
  156. package/src/cycle/dom/EventDelegator.ts +174 -223
  157. package/src/cycle/dom/IsolateModule.ts +65 -35
  158. package/src/cycle/dom/MainDOMSource.ts +13 -2
  159. package/src/cycle/dom/PriorityQueue.ts +4 -2
  160. package/src/cycle/dom/SymbolTree.ts +18 -47
  161. package/src/cycle/dom/classNameModule.ts +76 -0
  162. package/src/cycle/dom/controlledInputModule.ts +50 -0
  163. package/src/cycle/dom/enrichEventStream.ts +29 -45
  164. package/src/cycle/dom/fragment.ts +7 -0
  165. package/src/cycle/dom/isolate.ts +30 -27
  166. package/src/cycle/dom/makeDOMDriver.ts +115 -57
  167. package/src/cycle/dom/mockDOMSource.ts +83 -9
  168. package/src/cycle/dom/modules.ts +21 -4
  169. package/src/cycle/dom/propsModule.ts +65 -0
  170. package/src/cycle/dom/selectModule.ts +22 -17
  171. package/src/cycle/dom/snabbdom.ts +1 -6
  172. package/src/cycle/dom/thunk.ts +3 -0
  173. package/src/cycle/dom/utils.ts +98 -0
  174. package/src/cycle/dom/viewTransition.ts +43 -0
  175. package/src/cycle/state/StateSource.ts +20 -4
  176. package/src/cycle/state/objIsEqual.ts +50 -0
  177. package/src/cycle/state/types.ts +0 -10
  178. package/src/defineComponent.ts +34 -0
  179. package/src/devtools.d.ts +151 -0
  180. package/src/devtools.ts +34 -0
  181. package/src/element.d.ts +59 -0
  182. package/src/element.ts +235 -0
  183. package/src/extra/backoff.ts +9 -0
  184. package/src/extra/behaviors.ts +169 -0
  185. package/src/extra/browserSignals.ts +23 -0
  186. package/src/extra/browserSources.ts +326 -0
  187. package/src/extra/command.ts +3 -3
  188. package/src/extra/controls.ts +47 -0
  189. package/src/extra/copyAsTest.ts +286 -0
  190. package/src/extra/devtools.ts +109 -31
  191. package/src/extra/devtoolsActions.ts +379 -0
  192. package/src/extra/devtoolsHook.ts +9 -0
  193. package/src/extra/devtoolsNext.ts +83 -0
  194. package/src/extra/diagnostics/checks/actionLog.ts +108 -0
  195. package/src/extra/diagnostics/checks/behaviors.ts +49 -0
  196. package/src/extra/diagnostics/checks/browserSources.ts +96 -0
  197. package/src/extra/diagnostics/checks/collections.ts +67 -0
  198. package/src/extra/diagnostics/checks/controls.ts +148 -0
  199. package/src/extra/diagnostics/checks/dataset.ts +57 -0
  200. package/src/extra/diagnostics/checks/dom.ts +250 -0
  201. package/src/extra/diagnostics/checks/elementCommands.ts +175 -0
  202. package/src/extra/diagnostics/checks/events.ts +83 -0
  203. package/src/extra/diagnostics/checks/fetch.ts +135 -0
  204. package/src/extra/diagnostics/checks/forms.ts +163 -0
  205. package/src/extra/diagnostics/checks/index.ts +202 -0
  206. package/src/extra/diagnostics/checks/inspect.ts +427 -0
  207. package/src/extra/diagnostics/checks/next.ts +417 -0
  208. package/src/extra/diagnostics/checks/persist.ts +54 -0
  209. package/src/extra/diagnostics/checks/props.ts +56 -0
  210. package/src/extra/diagnostics/checks/public.d.ts +302 -0
  211. package/src/extra/diagnostics/checks/replies.ts +128 -0
  212. package/src/extra/diagnostics/checks/router.ts +100 -0
  213. package/src/extra/diagnostics/checks/rxjsHints.ts +88 -0
  214. package/src/extra/diagnostics/checks/shared.ts +203 -0
  215. package/src/extra/diagnostics/checks/shorthand.ts +115 -0
  216. package/src/extra/diagnostics/checks/sortable.ts +129 -0
  217. package/src/extra/diagnostics/checks/state.ts +148 -0
  218. package/src/extra/diagnostics/checks/statics.ts +48 -0
  219. package/src/extra/diagnostics/checks/strict.ts +55 -0
  220. package/src/extra/diagnostics/checks/timers.ts +80 -0
  221. package/src/extra/diagnostics/checks/viewTransitions.ts +47 -0
  222. package/src/extra/diagnostics/checks/virtual.ts +73 -0
  223. package/src/extra/diagnostics/checks/widgets.ts +109 -0
  224. package/src/extra/diagnostics/checks/wiring.ts +121 -0
  225. package/src/extra/diagnostics/codes.ts +477 -0
  226. package/src/extra/diagnostics/index.ts +353 -0
  227. package/src/extra/diagnostics/legacy.ts +76 -0
  228. package/src/extra/driverFactories.ts +172 -60
  229. package/src/extra/elementCommands.ts +53 -0
  230. package/src/extra/eventDriver.ts +4 -0
  231. package/src/extra/fetchDriver.ts +519 -0
  232. package/src/extra/flatten.ts +75 -0
  233. package/src/extra/focusWithin.ts +27 -0
  234. package/src/extra/form.ts +268 -0
  235. package/src/extra/formHelpers.ts +139 -0
  236. package/src/extra/head.ts +106 -0
  237. package/src/extra/hmr.ts +2 -3
  238. package/src/extra/owned.ts +24 -0
  239. package/src/extra/pager.ts +50 -0
  240. package/src/extra/persist.ts +133 -0
  241. package/src/extra/pwa.ts +1 -1
  242. package/src/extra/queryCache.ts +107 -0
  243. package/src/extra/reducers.ts +13 -6
  244. package/src/extra/reduxDevtools.ts +92 -0
  245. package/src/extra/replies.ts +54 -0
  246. package/src/extra/router.ts +323 -0
  247. package/src/extra/run.ts +94 -210
  248. package/src/extra/selection.ts +76 -0
  249. package/src/extra/socketDriver.ts +265 -0
  250. package/src/extra/sortable.ts +377 -0
  251. package/src/extra/ssr.ts +427 -160
  252. package/src/extra/standardSchema.ts +27 -0
  253. package/src/extra/testing.ts +3158 -190
  254. package/src/extra/timers.ts +95 -0
  255. package/src/extra/undo.ts +261 -0
  256. package/src/extra/viewTransitions.ts +38 -0
  257. package/src/extra/virtual.ts +513 -0
  258. package/src/extra/widget.ts +201 -0
  259. package/src/extra/xstreamExtras.ts +269 -0
  260. package/src/index.d.ts +3012 -87
  261. package/src/index.ts +32 -10
  262. package/src/jsx-runtime.ts +15 -1
  263. package/src/jsx.ts +2 -1
  264. package/src/lazy.ts +50 -7
  265. package/src/portal.ts +3 -1
  266. package/src/pragma/index.ts +262 -134
  267. package/src/react-peers.d.ts +5 -0
  268. package/src/react.d.ts +43 -0
  269. package/src/react.ts +110 -0
  270. package/src/shared.ts +48 -0
  271. package/src/slot.ts +1 -1
  272. package/src/suspense.ts +3 -1
  273. package/src/switchable.ts +6 -119
  274. package/src/transition.ts +3 -1
  275. package/src/ui/accordion.ts +64 -0
  276. package/src/ui/dialog.ts +129 -0
  277. package/src/ui/disclosure.ts +35 -0
  278. package/src/ui/popover.ts +45 -0
  279. package/src/ui/shared.ts +94 -0
  280. package/src/ui/tabs.ts +82 -0
  281. package/src/ui/toaster.ts +198 -0
  282. package/src/ui/tooltip.ts +70 -0
  283. package/src/ui/zag/combobox.ts +115 -0
  284. package/src/ui/zag/menu.ts +40 -0
  285. package/src/ui/zag/select.ts +54 -0
  286. package/src/ui/zag/shared.ts +43 -0
  287. package/src/ui-combobox.d.ts +20 -0
  288. package/src/ui-combobox.ts +6 -0
  289. package/src/ui-menu.d.ts +30 -0
  290. package/src/ui-menu.ts +6 -0
  291. package/src/ui-select.d.ts +17 -0
  292. package/src/ui-select.ts +6 -0
  293. package/src/ui-zag-types.d.ts +42 -0
  294. package/src/ui.d.ts +208 -0
  295. package/src/ui.ts +15 -0
  296. package/src/vike/+config.ts +9 -1
  297. package/src/vike/ClientOnly.ts +1 -1
  298. package/src/vike/onRenderClient.ts +144 -96
  299. package/src/vike/onRenderHtml.ts +69 -26
  300. package/src/vike/types.ts +27 -4
  301. package/src/vite/globalthis-shim.ts +18 -0
  302. package/src/vite/globalthis.ts +56 -0
  303. package/src/vite/plugin.d.ts +114 -2
  304. package/src/vite/plugin.ts +920 -56
  305. package/src/zag.d.ts +64 -0
  306. package/src/zag.ts +238 -0
  307. package/dist/astro/astro/client.d.ts +0 -5
  308. package/dist/astro/astro/index.d.ts +0 -16
  309. package/dist/astro/astro/server.d.ts +0 -12
  310. package/dist/astro/client.d.ts +0 -5
  311. package/dist/astro/client.esm.js +0 -4665
  312. package/dist/astro/collection.d.ts +0 -12
  313. package/dist/astro/component.d.ts +0 -22
  314. package/dist/astro/cycle/dom/BodyDOMSource.d.ts +0 -10
  315. package/dist/astro/cycle/dom/DOMSource.d.ts +0 -11
  316. package/dist/astro/cycle/dom/DocumentDOMSource.d.ts +0 -12
  317. package/dist/astro/cycle/dom/ElementFinder.d.ts +0 -8
  318. package/dist/astro/cycle/dom/EventDelegator.d.ts +0 -34
  319. package/dist/astro/cycle/dom/IsolateModule.d.ts +0 -23
  320. package/dist/astro/cycle/dom/MainDOMSource.d.ts +0 -32
  321. package/dist/astro/cycle/dom/PriorityQueue.d.ts +0 -7
  322. package/dist/astro/cycle/dom/ScopeChecker.d.ts +0 -9
  323. package/dist/astro/cycle/dom/SymbolTree.d.ts +0 -9
  324. package/dist/astro/cycle/dom/VNodeWrapper.d.ts +0 -8
  325. package/dist/astro/cycle/dom/enrichEventStream.d.ts +0 -24
  326. package/dist/astro/cycle/dom/fromEvent.d.ts +0 -6
  327. package/dist/astro/cycle/dom/index.d.ts +0 -8
  328. package/dist/astro/cycle/dom/isolate.d.ts +0 -9
  329. package/dist/astro/cycle/dom/makeDOMDriver.d.ts +0 -11
  330. package/dist/astro/cycle/dom/mockDOMSource.d.ts +0 -17
  331. package/dist/astro/cycle/dom/modules.d.ts +0 -5
  332. package/dist/astro/cycle/dom/snabbdom.d.ts +0 -22
  333. package/dist/astro/cycle/dom/styleModule.d.ts +0 -13
  334. package/dist/astro/cycle/dom/thunk.d.ts +0 -11
  335. package/dist/astro/cycle/dom/utils.d.ts +0 -8
  336. package/dist/astro/cycle/isolate/index.d.ts +0 -42
  337. package/dist/astro/cycle/run/adapt.d.ts +0 -6
  338. package/dist/astro/cycle/run/index.d.ts +0 -36
  339. package/dist/astro/cycle/run/internals.d.ts +0 -8
  340. package/dist/astro/cycle/run/types.d.ts +0 -49
  341. package/dist/astro/cycle/state/Collection.d.ts +0 -29
  342. package/dist/astro/cycle/state/StateSource.d.ts +0 -20
  343. package/dist/astro/cycle/state/index.d.ts +0 -5
  344. package/dist/astro/cycle/state/pickCombine.d.ts +0 -3
  345. package/dist/astro/cycle/state/pickMerge.d.ts +0 -3
  346. package/dist/astro/cycle/state/types.d.ts +0 -18
  347. package/dist/astro/cycle/state/withState.d.ts +0 -17
  348. package/dist/astro/extra/classes.d.ts +0 -7
  349. package/dist/astro/extra/devtools.d.ts +0 -78
  350. package/dist/astro/extra/dragDriver.d.ts +0 -20
  351. package/dist/astro/extra/driverFactories.d.ts +0 -12
  352. package/dist/astro/extra/eventDriver.d.ts +0 -9
  353. package/dist/astro/extra/exactState.d.ts +0 -1
  354. package/dist/astro/extra/hmr.d.ts +0 -17
  355. package/dist/astro/extra/logDriver.d.ts +0 -2
  356. package/dist/astro/extra/processDrag.d.ts +0 -19
  357. package/dist/astro/extra/processForm.d.ts +0 -15
  358. package/dist/astro/extra/run.d.ts +0 -13
  359. package/dist/astro/extra/xstreamCompat.d.ts +0 -5
  360. package/dist/astro/index.d.ts +0 -19
  361. package/dist/astro/index.esm.js +0 -27
  362. package/dist/astro/jsx-dev-runtime.d.ts +0 -1
  363. package/dist/astro/jsx-runtime.d.ts +0 -4
  364. package/dist/astro/jsx.d.ts +0 -2
  365. package/dist/astro/pragma/fn.d.ts +0 -7
  366. package/dist/astro/pragma/index.d.ts +0 -7
  367. package/dist/astro/pragma/is.d.ts +0 -10
  368. package/dist/astro/server.d.ts +0 -12
  369. package/dist/astro/server.esm.js +0 -25
  370. package/dist/astro/switchable.d.ts +0 -7
  371. package/dist/collection.d.ts +0 -12
  372. package/dist/component.d.ts +0 -22
  373. package/dist/cycle/dom/BodyDOMSource.d.ts +0 -10
  374. package/dist/cycle/dom/DOMSource.d.ts +0 -11
  375. package/dist/cycle/dom/DocumentDOMSource.d.ts +0 -12
  376. package/dist/cycle/dom/ElementFinder.d.ts +0 -8
  377. package/dist/cycle/dom/EventDelegator.d.ts +0 -34
  378. package/dist/cycle/dom/IsolateModule.d.ts +0 -23
  379. package/dist/cycle/dom/MainDOMSource.d.ts +0 -32
  380. package/dist/cycle/dom/PriorityQueue.d.ts +0 -7
  381. package/dist/cycle/dom/ScopeChecker.d.ts +0 -9
  382. package/dist/cycle/dom/SymbolTree.d.ts +0 -9
  383. package/dist/cycle/dom/VNodeWrapper.d.ts +0 -8
  384. package/dist/cycle/dom/enrichEventStream.d.ts +0 -24
  385. package/dist/cycle/dom/fromEvent.d.ts +0 -6
  386. package/dist/cycle/dom/index.d.ts +0 -8
  387. package/dist/cycle/dom/isolate.d.ts +0 -9
  388. package/dist/cycle/dom/makeDOMDriver.d.ts +0 -11
  389. package/dist/cycle/dom/mockDOMSource.d.ts +0 -17
  390. package/dist/cycle/dom/modules.d.ts +0 -5
  391. package/dist/cycle/dom/snabbdom.d.ts +0 -22
  392. package/dist/cycle/dom/styleModule.d.ts +0 -13
  393. package/dist/cycle/dom/thunk.d.ts +0 -11
  394. package/dist/cycle/dom/utils.d.ts +0 -8
  395. package/dist/cycle/isolate/index.d.ts +0 -42
  396. package/dist/cycle/run/adapt.d.ts +0 -6
  397. package/dist/cycle/run/index.d.ts +0 -36
  398. package/dist/cycle/run/internals.d.ts +0 -8
  399. package/dist/cycle/run/types.d.ts +0 -49
  400. package/dist/cycle/state/Collection.d.ts +0 -29
  401. package/dist/cycle/state/StateSource.d.ts +0 -20
  402. package/dist/cycle/state/index.d.ts +0 -5
  403. package/dist/cycle/state/pickCombine.d.ts +0 -3
  404. package/dist/cycle/state/pickMerge.d.ts +0 -3
  405. package/dist/cycle/state/types.d.ts +0 -18
  406. package/dist/cycle/state/withState.d.ts +0 -17
  407. package/dist/extra/classes.d.ts +0 -7
  408. package/dist/extra/devtools.d.ts +0 -78
  409. package/dist/extra/dragDriver.d.ts +0 -20
  410. package/dist/extra/driverFactories.d.ts +0 -12
  411. package/dist/extra/eventDriver.d.ts +0 -9
  412. package/dist/extra/exactState.d.ts +0 -1
  413. package/dist/extra/hmr.d.ts +0 -17
  414. package/dist/extra/logDriver.d.ts +0 -2
  415. package/dist/extra/processDrag.d.ts +0 -19
  416. package/dist/extra/processForm.d.ts +0 -15
  417. package/dist/extra/run.d.ts +0 -13
  418. package/dist/extra/xstreamCompat.d.ts +0 -5
  419. package/dist/jsx-dev-runtime.d.ts +0 -1
  420. package/dist/jsx-dev-runtime.js +0 -224
  421. package/dist/jsx-runtime.d.ts +0 -4
  422. package/dist/jsx-runtime.js +0 -224
  423. package/dist/jsx.d.ts +0 -2
  424. package/dist/pragma/fn.d.ts +0 -7
  425. package/dist/pragma/index.d.ts +0 -7
  426. package/dist/pragma/is.d.ts +0 -10
  427. package/dist/switchable.d.ts +0 -7
  428. package/dist/vike/+config.cjs.js +0 -65
  429. package/src/component.ts +0 -2256
  430. package/src/cycle/isolate/index.ts +0 -196
  431. package/src/cycle/run/index.ts +0 -151
  432. package/src/cycle/run/internals.ts +0 -143
  433. package/src/cycle/state/Collection.ts +0 -174
  434. package/src/cycle/state/index.ts +0 -5
  435. package/src/cycle/state/pickCombine.ts +0 -167
  436. package/src/cycle/state/pickMerge.ts +0 -122
  437. package/src/cycle/state/withState.ts +0 -47
  438. package/src/pragma/fn.ts +0 -55
@@ -4,15 +4,24 @@ import {Scope} from './isolate';
4
4
  import {isEqualNamespace} from './utils';
5
5
  import SymbolTree from './SymbolTree';
6
6
 
7
+ // G-356 (D196): the element an event bubbles to and a scope walk goes up to: a moved element's
8
+ // home (`__sygnalHome`), else its parent. G-381: a home inside the element (a cycle) isn't
9
+ // followed, nor more than 98 homes per walk (`c` counts them: two elements naming each other)
10
+ export const upOf = (e: any, c: any): any => {
11
+ const h = e.__sygnalHome;
12
+ return h && !e.contains(h) && (c.$h = (c.$h | 0) + 1) < 99 ? h : e.parentNode;
13
+ };
14
+
7
15
  export class IsolateModule {
8
- private namespaceTree = new SymbolTree<Element, Scope>(x => x.scope);
9
- private namespaceByElement: Map<Element, Array<Scope>>;
16
+ // G-144: a scope can own several root elements (a fragment-rooted component)
17
+ private namespaceTree = new SymbolTree<Set<Element>, Scope>(x => x.scope);
18
+ private namespaceByElement: WeakMap<Element, Array<Scope>>;
10
19
  private eventDelegator: EventDelegator | undefined;
11
20
 
12
- private vnodesBeingRemoved: Array<VNode>;
21
+ private vnodesBeingRemoved: Array<Element>;
13
22
 
14
23
  constructor() {
15
- this.namespaceByElement = new Map<Element, Array<Scope>>();
24
+ this.namespaceByElement = new WeakMap<Element, Array<Scope>>();
16
25
  this.vnodesBeingRemoved = [];
17
26
  }
18
27
 
@@ -22,22 +31,23 @@ export class IsolateModule {
22
31
 
23
32
  private insertElement(namespace: Array<Scope>, el: Element): void {
24
33
  this.namespaceByElement.set(el, namespace);
25
- this.namespaceTree.set(namespace, el);
34
+ this.namespaceTree.get(namespace, () => new Set())!.add(el);
26
35
  }
27
36
 
37
+ // the element keeps its scope (a leaving element under a Transition still is the
38
+ // child's); only the scope's set of root elements forgets it
28
39
  private removeElement(elm: Element): void {
29
- this.namespaceByElement.delete(elm);
30
- const namespace = this.getNamespace(elm);
31
- if (namespace) {
32
- this.namespaceTree.delete(namespace);
40
+ const namespace = this.namespaceByElement.get(elm);
41
+ const els = namespace && this.namespaceTree.get(namespace);
42
+ if (els) {
43
+ els.delete(elm);
44
+ // P45-A: an unmounted scope leaves no node behind
45
+ if (!els.size) this.namespaceTree.delete(namespace!);
33
46
  }
34
47
  }
35
48
 
36
- public getElement(
37
- namespace: Array<Scope>,
38
- max?: number
39
- ): Element | undefined {
40
- return this.namespaceTree.get(namespace, undefined, max);
49
+ public getElements(namespace: Array<Scope>): Array<Element> {
50
+ return [...(this.namespaceTree.get(namespace) || [])];
41
51
  }
42
52
 
43
53
  public getRootElement(elm: Element): Element | undefined {
@@ -45,13 +55,17 @@ export class IsolateModule {
45
55
  return elm;
46
56
  }
47
57
 
58
+ // G-356 (D196): an element a hook moved out of its component's DOM (a toaster region
59
+ // re-parented into an open modal <dialog>) names where it belongs as `__sygnalHome` (an
60
+ // element of its component), so it stays in its component's scope. With no scope root above
61
+ // elm (moved without one, or out of the app) the event has no scope here (before: threw
62
+ // 'No root element found'). G-381: upOf guards against a home cycle
48
63
  let curr = elm;
64
+ const c = {};
49
65
  while (!this.namespaceByElement.has(curr)) {
50
- curr = curr.parentNode as Element;
51
- if (!curr) {
66
+ curr = upOf(curr, c);
67
+ if (!curr || curr.tagName === 'HTML') {
52
68
  return undefined;
53
- } else if (curr.tagName === 'HTML') {
54
- throw new Error('No root element found, this should not happen at all');
55
69
  }
56
70
  }
57
71
  return curr;
@@ -67,14 +81,35 @@ export class IsolateModule {
67
81
 
68
82
  public createModule() {
69
83
  const self = this;
84
+ // G-564: a vnode can be in the old tree and the new one (a component's cached vnode, a
85
+ // Collection item's copy, a hoisted vnode). When an ancestor is recreated (`alt ? <ol>{c}</ol>
86
+ // : <ul>{c}</ul>`, a new key), snabbdom creates it again and gives it the new element before it
87
+ // destroys the old subtree, so destroy hooks saw the new element (a widget inside wasn't
88
+ // unmounted, its scope lost the new element). A created element notes its children's elements
89
+ // (M: a child with one is mounted, or was), before they are created; a destroyed vnode gives
90
+ // its noted children their old elements back for their destroy hooks (and theirs, down the
91
+ // subtree), and they get the new ones again when the removal starts (S), before the insert
92
+ // hooks. (A vnode that moves to another parent still gives its own destroy hook the new one)
93
+ const M = new Map<any, any>(), S: any[] = [];
94
+ // G-573: a vnode in the new tree twice: its first note (its element before the patch) wins.
95
+ // A destroy hook that throws ends the patch before remove / post: the next patch first gives
96
+ // the vnodes their new elements back and forgets the notes (pre)
97
+ const back = (c: any) => M.has(c) && (S.push(c, c.elm), c.elm = M.get(c));
98
+ const ret = () => { for (let e; S.length; ) e = S.pop(), S.pop().elm = e; };
70
99
  return {
100
+ pre() {
101
+ ret();
102
+ M.clear();
103
+ },
104
+
71
105
  create(emptyVNode: VNode, vNode: VNode) {
72
- const {elm, data = {}} = vNode;
106
+ const {elm, data = {}, children} = vNode;
73
107
  const namespace: Array<Scope> = (data as any).isolate;
74
108
 
75
109
  if (Array.isArray(namespace)) {
76
110
  self.insertElement(namespace, elm as Element);
77
111
  }
112
+ children?.forEach((c: any) => c?.elm && M.set(c, M.get(c) || c.elm));
78
113
  },
79
114
 
80
115
  update(oldVNode: VNode, vNode: VNode) {
@@ -93,32 +128,27 @@ export class IsolateModule {
93
128
  }
94
129
  },
95
130
 
131
+ // (the elements as they are now: post runs after the vnodes got their new ones back)
96
132
  destroy(vNode: VNode) {
97
- self.vnodesBeingRemoved.push(vNode);
133
+ vNode.children?.forEach(back);
134
+ self.vnodesBeingRemoved.push(vNode.elm as Element);
98
135
  },
99
136
 
100
137
  remove(vNode: VNode, cb: Function) {
101
- self.vnodesBeingRemoved.push(vNode);
138
+ self.vnodesBeingRemoved.push(vNode.elm as Element);
139
+ ret();
102
140
  cb();
103
141
  },
104
142
 
105
143
  post() {
106
- const vnodesBeingRemoved = self.vnodesBeingRemoved;
107
- for (let i = vnodesBeingRemoved.length - 1; i >= 0; i--) {
108
- const vnode = vnodesBeingRemoved[i];
109
- const namespace =
110
- vnode.data !== undefined
111
- ? (vnode.data as any).isolation
112
- : undefined;
113
- if (namespace !== undefined) {
114
- self.removeElement(namespace);
115
- }
116
- (self.eventDelegator as EventDelegator).removeElement(
117
- vnode.elm as Element,
118
- namespace
119
- );
144
+ // G-144: a removed root element is no longer one of its scope's roots (an element no
145
+ // scope has as a root isn't in any set: removing it does nothing)
146
+ for (const elm of self.vnodesBeingRemoved) {
147
+ self.removeElement(elm);
148
+ (self.eventDelegator as EventDelegator).removeElement(elm);
120
149
  }
121
150
  self.vnodesBeingRemoved = [];
151
+ M.clear();
122
152
  },
123
153
  };
124
154
  }
@@ -8,9 +8,11 @@ import {BodyDOMSource} from './BodyDOMSource';
8
8
  import {VNode} from './snabbdom';
9
9
  import {enrichEventStream, EnrichedEventStream} from './enrichEventStream';
10
10
  import {ElementFinder} from './ElementFinder';
11
- import {makeIsolateSink, getScopeObj, Scope, IsolateSink} from './isolate';
11
+ import {makeIsolateSink, makeIsolateValue, getScopeObj, Scope, IsolateSink} from './isolate';
12
12
  import {IsolateModule} from './IsolateModule';
13
13
  import {EventDelegator} from './EventDelegator';
14
+ // [diagnostics hook] no-op when diagnostics are off
15
+ import {onSelector} from '../../extra/diagnostics/index';
14
16
 
15
17
  export interface SpecialSelector {
16
18
  body: BodyDOMSource;
@@ -36,6 +38,7 @@ export class MainDOMSource {
36
38
  source._name
37
39
  );
38
40
  this.isolateSink = makeIsolateSink(this._namespace) as any;
41
+ this.isolateValue = makeIsolateValue(this._namespace);
39
42
  }
40
43
 
41
44
  private _elements(): Stream<Array<Element>> {
@@ -77,7 +80,9 @@ export class MainDOMSource {
77
80
  selector: T
78
81
  ): SpecialSelector[T];
79
82
  public select(selector: string): MainDOMSource;
80
- public select(selector: string): DOMSource {
83
+ public select(selector: any): DOMSource {
84
+ // CT-1: a control (controls()) selects its elements by its marker, [data-control="<Key>"]
85
+ if (selector?.__sygnalControl) selector = '' + selector;
81
86
  if (typeof selector !== 'string') {
82
87
  throw new Error(
83
88
  `DOM driver's select() expects the argument to be a ` +
@@ -91,6 +96,8 @@ export class MainDOMSource {
91
96
  return new BodyDOMSource(this._name);
92
97
  }
93
98
 
99
+ if (selector !== ':root') onSelector(this, selector.trim());
100
+
94
101
  const namespace =
95
102
  selector === ':root'
96
103
  ? []
@@ -111,6 +118,9 @@ export class MainDOMSource {
111
118
  options?: EventsFnOptions,
112
119
  bubbles?: boolean
113
120
  ): EnrichedEventStream<HTMLElementEventMap[K]>;
121
+ // PLAN-5 0-S6: any other name (a custom element's 'wa-hover', a widget's or element's
122
+ // CustomEvent): the overload above only typed the built-in names (types only)
123
+ public events(eventType: string, options?: EventsFnOptions, bubbles?: boolean): EnrichedEventStream<Event>;
114
124
  public events(
115
125
  eventType: string,
116
126
  options: EventsFnOptions = {},
@@ -140,4 +150,5 @@ export class MainDOMSource {
140
150
 
141
151
  public isolateSource: (source: MainDOMSource, scope: string) => MainDOMSource;
142
152
  public isolateSink: IsolateSink<VNode>;
153
+ public isolateValue: (node: any, scope: string) => any;
143
154
  }
@@ -20,13 +20,15 @@ export default class PriorityQueue<T> {
20
20
  }
21
21
  }
22
22
 
23
- public delete(t: T): void {
23
+ // returns how many are left
24
+ public delete(t: T): number {
24
25
  for (let i = 0; i < this.arr.length; i++) {
25
26
  if (this.arr[i] === t) {
26
27
  this.arr.splice(i, 1);
27
28
  this.prios.splice(i, 1);
28
- return;
29
+ break;
29
30
  }
30
31
  }
32
+ return this.arr.length;
31
33
  }
32
34
  }
@@ -1,56 +1,30 @@
1
- type Node<Payload> = [Payload | undefined, InternalTree<Payload>];
1
+ // [payload, children, number of children]: the count makes delete's "is this node empty" O(1)
2
+ // (G-290: Object.keys(children) per removal made removing n siblings O(n²))
3
+ type Node<Payload> = [Payload | undefined, InternalTree<Payload>, number];
2
4
 
3
5
  interface InternalTree<Payload> {
4
6
  [name: string]: Node<Payload>;
5
7
  }
6
8
 
7
9
  export default class SymbolTree<Payload, T> {
8
- private tree: Node<Payload> = [undefined, {}];
10
+ private tree: Node<Payload> = [, {}, 0];
9
11
 
10
12
  constructor(private mapper: (t: T) => string) {}
11
13
 
12
- public set(path: Array<T>, element: Payload | undefined, max?: number): void {
13
- let curr = this.tree;
14
- const _max = max !== undefined ? max : path.length;
15
- for (let i = 0; i < _max; i++) {
16
- const n = this.mapper(path[i]);
17
- let child: Node<Payload> = curr[1][n];
18
- if (!child) {
19
- child = [undefined, {}];
20
- curr[1][n] = child;
21
- }
22
- curr = child;
23
- }
24
- curr[0] = element;
25
- }
26
-
27
- public getDefault(
28
- path: Array<T>,
29
- mkDefaultElement: () => Payload,
30
- max?: number
31
- ): Payload {
32
- return this.get(path, mkDefaultElement, max) as Payload;
33
- }
34
-
35
14
  public get(
36
15
  path: Array<T>,
37
16
  mkDefaultElement?: () => Payload,
38
- max?: number
17
+ max = path.length
39
18
  ): Payload | undefined {
40
19
  let curr = this.tree;
41
- const _max = max !== undefined ? max : path.length;
42
- for (let i = 0; i < _max; i++) {
20
+ for (let i = 0; i < max; i++) {
43
21
  const n = this.mapper(path[i]);
44
- let child: Node<Payload> = curr[1][n];
45
- if (!child) {
46
- if (mkDefaultElement) {
47
- child = [undefined, {}];
48
- curr[1][n] = child;
49
- } else {
50
- return undefined;
51
- }
22
+ if (!curr[1][n]) {
23
+ if (!mkDefaultElement) return undefined;
24
+ curr[2]++; // G-290: count the children
25
+ curr[1][n] = [, {}, 0];
52
26
  }
53
- curr = child;
27
+ curr = curr[1][n];
54
28
  }
55
29
  if (mkDefaultElement && !curr[0]) {
56
30
  curr[0] = mkDefaultElement();
@@ -58,15 +32,12 @@ export default class SymbolTree<Payload, T> {
58
32
  return curr[0];
59
33
  }
60
34
 
61
- public delete(path: Array<T>): void {
62
- let curr = this.tree;
63
- for (let i = 0; i < path.length - 1; i++) {
64
- const child = curr[1][this.mapper(path[i])];
65
- if (!child) {
66
- return;
67
- }
68
- curr = child;
69
- }
70
- delete curr[1][this.mapper(path[path.length - 1])];
35
+ // P45-A: drop the payload at path and prune the nodes left empty; true when node is empty
36
+ public delete(path: Array<T>, max = path.length, node = this.tree, i = 0): boolean {
37
+ if (i < max) {
38
+ const k = this.mapper(path[i]), child = node[1][k];
39
+ if (child && this.delete(path, max, child, i + 1)) delete node[1][k], node[2]--;
40
+ } else node[0] = undefined;
41
+ return !node[0] && !node[2];
71
42
  }
72
43
  }
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Snabbdom module that unsets a removed `className` prop (B-012).
3
+ *
4
+ * Problem: `className` goes through snabbdom's propsModule, which writes new
5
+ * and changed props but never unsets a prop that disappears. So when snabbdom
6
+ * reuses an element (`<p className="placeholder">` -> `<p>`), the old class
7
+ * stays. A nullish `className` is worse: propsModule writes the string
8
+ * "null"/"false".
9
+ *
10
+ * Fix: runs after propsModule. When `className` is gone (or nullish/false),
11
+ * drop the classes it had set, keeping the classes from the selector
12
+ * (`p.foo`) and the truthy `class={{...}}` entries.
13
+ */
14
+
15
+ import type {VNode} from 'snabbdom/build/vnode.js';
16
+
17
+ function classObject(vnode: VNode): Array<string> {
18
+ const out: Array<string> = [];
19
+ const klass: any = vnode.data?.class;
20
+ if (klass && typeof klass === 'object') {
21
+ for (const name in klass) if (klass[name]) out.push(name);
22
+ }
23
+ return out;
24
+ }
25
+
26
+ function baseClasses(vnode: VNode): Array<string> {
27
+ const sel = vnode.sel || '';
28
+ const hashIdx = sel.indexOf('#');
29
+ const dotIdx = sel.indexOf('.', hashIdx);
30
+ const fromSel = dotIdx > 0 ? sel.slice(dotIdx + 1).split('.') : [];
31
+ return fromSel.concat(classObject(vnode));
32
+ }
33
+
34
+ function addAll(elm: any, names: Array<string>): void {
35
+ for (const name of names) if (name) elm.classList.add(name);
36
+ }
37
+
38
+ const isSet = (cn: any) => cn != null && cn !== false;
39
+ const tokens = (cn: any) => (typeof cn === 'string' ? cn.split(/\s+/).filter(Boolean) : []);
40
+
41
+ function syncClassName(oldVnode: VNode, vnode: VNode): void {
42
+ const props: any = vnode.data?.props;
43
+ const oldProps: any = oldVnode.data?.props;
44
+ const hasKey = !!props && 'className' in props;
45
+ const oldCn = oldProps ? oldProps.className : undefined;
46
+ // P45-A: keyed on the prop (B-012), not the tag: nothing to do when neither vnode has one
47
+ if (!hasKey && !isSet(oldCn)) return;
48
+ const elm = vnode.elm as any;
49
+ if (!elm || !elm.classList) return;
50
+ const cn = hasKey ? props.className : undefined;
51
+ if (isSet(cn)) {
52
+ // propsModule replaced the whole attribute: put the selector classes and the
53
+ // class={{...}} entries back
54
+ if (!oldProps || oldProps.className !== cn) addAll(elm, baseClasses(vnode));
55
+ return;
56
+ }
57
+ if (hasKey) {
58
+ // propsModule wrote String(cn) over the whole attribute: rebuild it
59
+ if (!oldProps || oldProps.className !== cn) {
60
+ elm.className = baseClasses(vnode).join(' ');
61
+ if (elm.className === '') elm.removeAttribute('class');
62
+ }
63
+ return;
64
+ }
65
+ const keep = baseClasses(vnode);
66
+ for (const name of tokens(oldCn)) {
67
+ if (keep.indexOf(name) === -1) elm.classList.remove(name);
68
+ }
69
+ addAll(elm, keep);
70
+ if (elm.getAttribute('class') === '') elm.removeAttribute('class');
71
+ }
72
+
73
+ export const classNameModule = {
74
+ create: syncClassName,
75
+ update: syncClassName,
76
+ };
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Snabbdom module that keeps controlled form fields in sync with the vnode (B-004).
3
+ *
4
+ * Problem: snabbdom's propsModule only writes `value`/`checked` when the prop
5
+ * differs from the previous vnode's prop. If the user types 'x' and an action
6
+ * resets the state to '' within one render window, the 'x' render is
7
+ * coalesced away: the vnodes go '' -> '' and the typed text stays in the DOM.
8
+ *
9
+ * Fix: after propsModule has run, compare `value`/`checked` props against the
10
+ * live element and write them when they differ. Only form fields (INPUT,
11
+ * TEXTAREA, SELECT; not input type=file) are controlled: `value` compares as a
12
+ * string, `checked` as a boolean (1H-7). A present-but-nullish `value` keeps an
13
+ * input/textarea at '' and a nullish `checked` at false (D49); an absent prop
14
+ * leaves the field to the user. D196: a form-associated custom element is a field
15
+ * too (its value is written as the prop). Other elements with a value prop
16
+ * (<progress>, <meter>, custom elements that aren't form-associated) are left alone.
17
+ *
18
+ * (PLAN-4.6 R6, G-347: G-146's input stamps are gone with the old core: the core renders a
19
+ * state in the flush it is written in, so no render shows an older state than the field.)
20
+ */
21
+
22
+ import type {VNode} from 'snabbdom/build/vnode.js';
23
+
24
+ // P45-A: a form field by its vnode's tag (sel), checked before any other work: most vnodes aren't.
25
+ // D196: a form-associated custom element (a hyphenated tag whose class has `static
26
+ // formAssociated = true`, e.g. Web Awesome's wa-input / wa-rating) is a field too; only a
27
+ // hyphenated tag's element is read
28
+ export const isField = (vnode: VNode): any =>
29
+ /^(input|textarea|select)(?![\w-])/i.test(vnode.sel as string) || /^\w+-/.test(vnode.sel as string) && (vnode.elm as any).constructor.formAssociated;
30
+
31
+ function syncControlled(oldVnode: VNode, vnode: VNode): void {
32
+ if (!isField(vnode)) return;
33
+ const props = vnode.data?.props;
34
+ const elm = vnode.elm as any;
35
+ if (!props || !elm || elm.type == 'file') return;
36
+ const oldProps: any = oldVnode.data?.props || {};
37
+ const {value, checked} = props;
38
+ // Only the case propsModule skipped (prop unchanged); it handles real changes.
39
+ // A nullish <select> value is left alone: on create the browser shows the first option.
40
+ if ('value' in props && value === oldProps.value && (value != null || elm.tagName != 'SELECT')) {
41
+ const v = value == null ? '' : String(value);
42
+ // a custom element's value can be a number: compared as a string, written as the prop
43
+ if (String(elm.value) !== v) elm.value = elm.constructor.formAssociated ? value : v;
44
+ }
45
+ if ('checked' in props && checked === oldProps.checked && elm.checked !== !!checked) {
46
+ elm.checked = !!checked;
47
+ }
48
+ }
49
+
50
+ export const controlledInputModule = {update: syncControlled};
@@ -15,8 +15,16 @@ export interface EnrichedEventStream<T = Event> extends Stream<T> {
15
15
 
16
16
  key(): EnrichedEventStream<string>;
17
17
  key<R>(fn: (key: string) => R): EnrichedEventStream<R>;
18
+
19
+ /** e.detail: a CustomEvent's payload (a widget's emit(name, detail), a web component's event) */
20
+ detail<D = any>(): EnrichedEventStream<D>;
21
+ detail<R, D = any>(fn: (detail: D) => R): EnrichedEventStream<R>;
18
22
  }
19
23
 
24
+ // one enricher: a method that maps each event through `get`, then `fn` when given
25
+ const pick = (s$: any, get: (e: any) => any) => (fn?: (v: any) => any): any =>
26
+ enrichEventStream(s$.map((e: any) => (e = get(e), fn ? fn(e) : e)))
27
+
20
28
  /**
21
29
  * Adds chainable convenience methods to a DOM event stream.
22
30
  *
@@ -26,53 +34,29 @@ export interface EnrichedEventStream<T = Event> extends Stream<T> {
26
34
  * DOM.click('.item').data('id', Number)
27
35
  * DOM.change('.checkbox').checked()
28
36
  * DOM.keydown('.field').key()
37
+ * DOM.select('.due').events('change').detail()
29
38
  */
30
39
  export function enrichEventStream(stream$: any): any {
31
- // .value(fn?) — extract e.target.value
32
- stream$.value = function value(fn?: (val: any) => any): any {
33
- const mapped = stream$.map((e: any) => {
34
- const val = e?.target?.value
35
- return fn ? fn(val) : val
36
- });
37
- return enrichEventStream(mapped);
38
- }
39
-
40
- // .checked(fn?) — extract e.target.checked
41
- stream$.checked = function checked(fn?: (val: any) => any): any {
42
- const mapped = stream$.map((e: any) => {
43
- const val = !!e?.target?.checked
44
- return fn ? fn(val) : val
45
- });
46
- return enrichEventStream(mapped);
47
- }
48
-
49
- // .data(name, fn?) — extract e.target.dataset[name]
50
- stream$.data = function data(name: string, fn?: (val: any) => any): any {
51
- const mapped = stream$.map((e: any) => {
52
- const el = e?.target instanceof Element ? e.target.closest(`[data-${name}]`) || e.target : e?.target
53
- const val = el?.dataset?.[name]
54
- return fn ? fn(val) : val
55
- });
56
- return enrichEventStream(mapped);
40
+ // .value(fn?) — e.target.value; .checked(fn?) — e.target.checked as a boolean
41
+ stream$.value = pick(stream$, (e: any) => e?.target?.value)
42
+ stream$.checked = pick(stream$, (e: any) => !!e?.target?.checked)
43
+ // .data(name, fn?) — dataset[name] from e.target or its nearest ancestor that has it.
44
+ // dataset keys are camelCase but attributes are kebab-case (`taskId` is `data-task-id`), so the
45
+ // closest() selector converts (B-028). The name may be given either way: `.data('taskId')` and
46
+ // `.data('task-id')` read the same attribute (3E/R3).
47
+ stream$.data = (name: string, fn?: (v: any) => any): any => {
48
+ const key = String(name).replace(/-([a-z])/g, (_, c) => c.toUpperCase())
49
+ const attr = `[data-${key.replace(/[A-Z]/g, c => '-' + c.toLowerCase())}]`
50
+ return pick(stream$, (e: any) => {
51
+ const t = e?.target
52
+ const el = typeof t?.closest == 'function' ? t.closest(attr) || t : t
53
+ return el?.dataset?.[key]
54
+ })(fn)
57
55
  }
58
-
59
- // .target(fn?) — extract e.target
60
- stream$.target = function target(fn?: (el: any) => any): any {
61
- const mapped = stream$.map((e: any) => {
62
- const el = e?.target
63
- return fn ? fn(el) : el
64
- });
65
- return enrichEventStream(mapped);
66
- }
67
-
68
- // .key(fn?) — extract e.key (keyboard events)
69
- stream$.key = function key(fn?: (val: any) => any): any {
70
- const mapped = stream$.map((e: any) => {
71
- const val = e?.key
72
- return fn ? fn(val) : val
73
- });
74
- return enrichEventStream(mapped);
75
- }
76
-
56
+ // .target(fn?) — e.target; .key(fn?) — e.key (keyboard events)
57
+ stream$.target = pick(stream$, (e: any) => e?.target)
58
+ stream$.key = pick(stream$, (e: any) => e?.key)
59
+ // .detail(fn?) — e.detail (CustomEvents: widgets' emit(), web components) (PLAN-5 W-3)
60
+ stream$.detail = pick(stream$, (e: any) => e?.detail)
77
61
  return stream$
78
62
  }
@@ -0,0 +1,7 @@
1
+ import {Fragment as _Fragment} from 'snabbdom/build/jsx.js';
2
+
3
+ // Tag Fragment so we can identify it even after minification mangles Function.name.
4
+ // Its own module so the JSX runtime entries (which keep snabbdom external, D188) take it
5
+ // without the rest of the snabbdom barrel
6
+ (_Fragment as any).__sygnalFragment = true;
7
+ export const Fragment = _Fragment;
@@ -15,37 +15,40 @@ export type IsolateSink<T extends VNode> = (
15
15
  export function makeIsolateSink<T extends VNode>(
16
16
  namespace: Array<Scope>
17
17
  ): IsolateSink<T> {
18
- return (sink, scope) => {
19
- if (scope === ':root') {
20
- return sink;
21
- }
18
+ const value = makeIsolateValue(namespace);
19
+ return (sink, scope) => scope === ':root' ? sink : sink.map(node => value(node, scope) as T);
20
+ }
22
21
 
23
- return sink.map(node => {
24
- if (!node) {
25
- return node;
26
- }
27
- const scopeObj = getScopeObj(scope);
28
- const newNode = {
29
- ...(node as any),
30
- data: {
31
- ...node.data,
32
- isolate:
33
- !node.data || !Array.isArray((node.data as any).isolate)
34
- ? namespace.concat([scopeObj])
35
- : (node.data as any).isolate,
36
- },
37
- };
38
- return {
39
- ...newNode,
40
- key:
41
- newNode.key !== undefined
42
- ? newNode.key
43
- : JSON.stringify(newNode.data.isolate),
44
- } as T;
45
- });
22
+ /**
23
+ * PLAN-4.6: the value-level isolateSink (the core scopes each instance's vnode without a
24
+ * stream per instance): the same mapping, applied to one vnode
25
+ */
26
+ export function makeIsolateValue(namespace: Array<Scope>): (node: any, scope: string) => any {
27
+ return (node, scope) => {
28
+ if (scope === ':root' || !node) {
29
+ return node;
30
+ }
31
+ const isolate = namespace.concat([getScopeObj(scope)]);
32
+ const newNode = scoped(node, isolate);
33
+ return {
34
+ ...newNode,
35
+ key:
36
+ newNode.key !== undefined
37
+ ? newNode.key
38
+ : JSON.stringify((newNode.data && newNode.data.isolate) || isolate),
39
+ };
46
40
  };
47
41
  }
48
42
 
43
+ // G-144: a fragment has no element of its own, so each of its top-level elements (through
44
+ // nested fragments) carries the scope; the fragment keeps the key
45
+ function scoped(node: any, isolate: Array<Scope>): any {
46
+ return !node || typeof node != 'object' ? node
47
+ : node.sel ? {...node, data: {...node.data, isolate: node.data && Array.isArray(node.data.isolate) ? node.data.isolate : isolate}}
48
+ : node.children ? {...node, children: node.children.map((c: any) => scoped(c, isolate))}
49
+ : node;
50
+ }
51
+
49
52
  export function getScopeObj(scope: string): Scope {
50
53
  return {
51
54
  type: isClassOrId(scope) ? 'sibling' : 'total',