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
@@ -0,0 +1,314 @@
1
+ /**
2
+ * PLAN-4.6 R0: the extension contract of the component core (types only: 0 bytes in any bundle).
3
+ * R1-R4 implemented it; R5 deleted the old core's instance patching it replaces. The prose
4
+ * contract, with the consumers mapped to these hooks, is
5
+ * dev-plans/research/core-rewrite/04-hooks-contract.md.
6
+ *
7
+ * Three layers:
8
+ * 1. Registries (module level, filled on import): what a feature module adds to the core without
9
+ * the core naming it: hosts, markers (pre/post processors), view resolvers, definition hooks,
10
+ * statics. An app that never imports the module pays nothing (D157).
11
+ * 2. Hooks (per app, from run() / renderComponent / the dev entries): observation and wrapping
12
+ * points for diagnostics, devtools, testing and the dev action log. Every hook is optional and
13
+ * the core calls it as `hooks.x?.(...)`.
14
+ * 3. The runtime API handed to hooks: inspection views and `setState`, so no consumer needs a raw
15
+ * instance or a stream internal (`shamefullySendNext`, `_v`, `_n`).
16
+ *
17
+ * Invariants the hooks must not break (the flush contract, PLAN-4.6 §2 change 4):
18
+ * - Actions drain run-to-completion, FIFO: an action dispatched while another is processed (a
19
+ * driver emitting synchronously during sink delivery, an EFFECT, a PARENT, a hook) is appended
20
+ * to the queue, never run nested.
21
+ * - A STATE reducer is applied when its action is processed. Every other sink of that action gets
22
+ * the state from before it.
23
+ * - A flush (one microtask after the first commit of a batch) repeats { render top-down, recompute
24
+ * statics, drain the queue } until nothing changed, then emits ONE root vnode (one patch), then
25
+ * runs ELEMENT commands and dispatches BOOTSTRAP for the instances created in it.
26
+ * - Loop guard: at most 100 passes per flush and 100 flushes per macrotask; past that the next
27
+ * flush waits for a MessageChannel message. No timer anywhere in startup, flush or teardown.
28
+ * - Hooks run synchronously inside these steps. A hook may dispatch (it is queued), but must not
29
+ * render, patch or dispose.
30
+ */
31
+
32
+ // ---------------------------------------------------------------------------------- shared types
33
+
34
+ /** A component function with its statics (view + `.intent`, `.model`, `.initialState`, ...) */
35
+ export type ComponentFn = ((input: any) => any) & Record<string, any>
36
+
37
+ /** One normalized model entry: the sink and its handler (a function, or a constant value) */
38
+ export type Handler = [sink: string, fn: any]
39
+
40
+ /**
41
+ * What a definition hook may read and edit: the component's statics, before normalization.
42
+ * Behaviors' existing `merge(component, key)` runs on a shim with these fields (spike finding 5),
43
+ * so `uses`, `undo`, `selection`, `pager` and `persist` work unchanged, once per component
44
+ * function instead of once per instance.
45
+ */
46
+ export interface DefSource {
47
+ model: Record<string, any> | undefined
48
+ intent: ((sources: any) => Record<string, any>) | undefined
49
+ initialState: any
50
+ /** defaults of missing state keys (a behavior's slice or a resource's `{status: 'idle'}` on a sub-component) */
51
+ idle: Record<string, any> | null
52
+ calculated: Record<string, any> | undefined
53
+ context: Record<string, (state: any) => any> | undefined
54
+ /** action -> behavior key, for action logs (`pager.NEXT` comes from `pager`) */
55
+ behaviorActions: Record<string, string>
56
+ }
57
+
58
+ /** The normalized definition: computed once per component function (WeakMap) */
59
+ export interface Def {
60
+ readonly name: string
61
+ readonly view: ComponentFn
62
+ readonly intent?: (sources: any) => Record<string, any>
63
+ /** action -> handlers in model order; a function entry is STATE */
64
+ readonly handlers: ReadonlyMap<string, readonly Handler[]>
65
+ readonly sinks: ReadonlySet<string>
66
+ readonly initialState: any
67
+ readonly idle: Record<string, any> | null
68
+ readonly isolated: boolean
69
+ /** calculated fields in topological order (SYG206 / SYG209 thrown at definition) */
70
+ readonly calculated: ReadonlyArray<[field: string, fn: (s: any) => any, deps: string[] | null]> | null
71
+ readonly context: ReadonlyArray<[key: string, fn: (s: any) => any]> | null
72
+ /** the statics this definition declares that some driver takes (`__sygnalStatic`) */
73
+ readonly statics: ReadonlyArray<string>
74
+ readonly behaviorActions: Readonly<Record<string, string>>
75
+ readonly onError?: (error: any, info: {componentName: string}) => any
76
+ /**
77
+ * R4 (renderComponent's root only): the model actions the test may dispatch with
78
+ * simulateAction that the intent doesn't name (wiring's SYG101/SYG102, inspect(); today's
79
+ * `__sygnalTestActions` on the intent object)
80
+ */
81
+ readonly testActions?: readonly string[]
82
+ }
83
+
84
+ /** Where an action came from (testing's t.actions `cause`, devtools, the action log) */
85
+ export type ActionCause = 'intent' | 'next' | 'reply' | 'built-in' | 'simulateAction' | 'behavior' | 'parent' | 'setState'
86
+
87
+ /**
88
+ * A read-only view of a live instance: everything devtools, diagnostics and testing read today
89
+ * from raw instance fields (`_componentNumber`, `name`, `currentState`, `currentProps`,
90
+ * `currentContext`, `isSubComponent`, `sources.__parentComponentNumber`, `_disposed`, ...).
91
+ * Getters are live; the object is stable for the instance's life.
92
+ */
93
+ export interface InstanceView {
94
+ /** stable id (inspect()'s component id; today `_componentNumber`) */
95
+ readonly id: number
96
+ readonly parentId: number | undefined
97
+ readonly name: string
98
+ readonly def: Def
99
+ /** the state the view gets (calculated fields included; `currentState` + `addCalculated`) */
100
+ readonly state: any
101
+ readonly props: Record<string, any>
102
+ readonly context: Record<string, any>
103
+ readonly isRoot: boolean
104
+ /** 'item' (Collection), 'page' (Switchable), 'child' (tag), 'root' */
105
+ readonly kind: 'root' | 'child' | 'item' | 'page'
106
+ /** Switchable page: shown now (hidden pages skip render, keep actions and background statics) */
107
+ readonly shown: boolean
108
+ readonly disposed: boolean
109
+ /** the uid() root of this instance (`__uid`) */
110
+ readonly uid: string
111
+ /** its children, in render order */
112
+ children(): InstanceView[]
113
+ /** the sources its intent got (after wrapSources), e.g. to compare with run()'s sources */
114
+ readonly sources: Readonly<Record<string, any>>
115
+ }
116
+
117
+ /** An action as the queue holds it */
118
+ export interface ActionRecord {
119
+ readonly type: string
120
+ readonly data: any
121
+ readonly cause: ActionCause
122
+ /** the instance that runs it */
123
+ readonly target: InstanceView
124
+ /** a reply: the source (driver name) that delivered it (R4: devtools' replySink) */
125
+ readonly source?: string
126
+ }
127
+
128
+ // ---------------------------------------------------------------------------------- 2. hooks
129
+
130
+ export interface Hooks {
131
+ // ------------------------------------------------------------------ definition time
132
+ /**
133
+ * Called once per component function, before normalization, with the definition's statics.
134
+ * Return a new (or the same, edited) DefSource. Runs for every app on the page (definitions are
135
+ * shared), so it must depend only on `view`. Behaviors, undo, selection, pager, persist's model
136
+ * rewrite and resources' RESOURCE entry use the module registry (`defHooks`) instead; this hook
137
+ * is for a per-app consumer that needs the same point (diagnostics' SYG222 reducer wrapping,
138
+ * strict checks of the model's shape).
139
+ */
140
+ transformDef?(src: DefSource, view: ComponentFn): DefSource | void
141
+
142
+ // ------------------------------------------------------------------ instance lifetime
143
+ /** after the instance's state cell and INITIALIZE, before its intent subscribes */
144
+ onCreate?(inst: InstanceView): void
145
+ /** at the start of dispose (DISPOSE has been queued; its streams are not stopped yet) */
146
+ onDispose?(inst: InstanceView): void
147
+ /** after the instance's view ran and its children were injected (only when it re-rendered) */
148
+ onRender?(inst: InstanceView, vnode: any): void
149
+ /** after the root vnode was patched (one per flush that changed the vnode) */
150
+ onPatch?(vnode: any): void
151
+
152
+ // ------------------------------------------------------------------ sources
153
+ /**
154
+ * The sources an instance's intent gets. Return a wrapper (a Proxy that records selectors, a
155
+ * fake for a driverless sink, a checking DOM source). Called once per instance, before the
156
+ * intent; `fake(name)` style sources added here take part in replies/statics detection, which
157
+ * happens after this hook (today testing mutates `sources`/`sourceNames` from onIntent).
158
+ */
159
+ wrapSources?(inst: InstanceView, sources: Record<string, any>): Record<string, any>
160
+ /** the intent's action names (the wiring checks, inspect()) */
161
+ onIntent?(inst: InstanceView, actionNames: string[]): void
162
+
163
+ // ------------------------------------------------------------------ actions
164
+ /** an action is about to be processed (dequeued); `cause` says where it came from */
165
+ onAction?(inst: InstanceView, action: ActionRecord): void
166
+ /**
167
+ * Wrap one handler of an action. `fn` is the model entry (a function or a constant). Return a
168
+ * replacement with the same contract; ABORT / the same state still mean "no change". Used by
169
+ * the action log (which sinks produced a value), SYG222 checks, devtools.
170
+ */
171
+ wrapHandler?(inst: InstanceView, type: string, sink: string, fn: any): any
172
+ /** the STATE reducer of an action ran (`next` is what was written; `prev === next`: no change) */
173
+ onReducer?(inst: InstanceView, type: string, prev: any, next: any): void
174
+ /**
175
+ * a non-STATE sink produced a value (before it is stamped with `__emitterId`/`__emitterName`).
176
+ * R4: a declaration static sent to a driver (`{ resources }`, `{ connections }`, `{ timers }`,
177
+ * ...) comes here too, with `type` null
178
+ */
179
+ onSink?(inst: InstanceView, type: string | null, sink: string, value: any): void
180
+ /**
181
+ * R4 (04 §4 #3): a host's props when it is created and each time its owner re-renders it
182
+ * (`sel`: the marker's, a Collection's or a VirtualCollection's), before it renders; the Collection checks (SYG401
183
+ * for a missing `from`) read them here. `data`: the marker's vnode data (4-H: the buckets a
184
+ * removed wrapper element would have had: style, class, attrs, ...)
185
+ */
186
+ onHostProps?(owner: InstanceView, sel: string, props: Record<string, any>, data?: Record<string, any>): void
187
+ /** a model next(type, data, ms) was scheduled (replaces testing's NEXT_LOG debug-text parsing) */
188
+ onNext?(inst: InstanceView, type: string, data: any, ms: number): void
189
+ /**
190
+ * an ELEMENT command (or an array of them) was sent; it runs after the next patch (testing
191
+ * records, diagnostics checks). `false`: not run (renderComponent's mock DOM records only)
192
+ */
193
+ onElementCommand?(inst: InstanceView, command: any): void | false
194
+
195
+ // ------------------------------------------------------------------ state, context, readiness
196
+ /** an instance's (calculated) state changed in this flush (devtools onStateChanged) */
197
+ onStateChanged?(inst: InstanceView, state: any): void
198
+ /** an instance's props changed (devtools onPropsChanged, SYG props checks) */
199
+ onPropsChanged?(inst: InstanceView, props: any): void
200
+ /** an instance's context changed; `keys`: the keys that changed (D168) */
201
+ onContextChanged?(inst: InstanceView, context: any, keys: string[]): void
202
+ /**
203
+ * D174: an `isolatedState` child bound to a slice that already exists (state="key" or a lens,
204
+ * without `resetState`) keeps the parent's data instead of its initialState. R4's dev warning
205
+ * reports the keys `initialState` defines that the slice lacks.
206
+ */
207
+ onStateSeed?(inst: InstanceView, slice: any, initialState: any): void
208
+ /** D169: a Collection item key (id, or raw index) that appears more than once; only its first element renders. R4's dev warning */
209
+ onDuplicateKey?(owner: InstanceView, key: any): void
210
+ /** a child's READY flag changed (devtools, Suspense diagnostics) */
211
+ onReady?(inst: InstanceView, child: InstanceView, ready: boolean): void
212
+ /**
213
+ * D168 safety net (dev only; R4): context tracking skipped this view's re-render (the context
214
+ * changed, but no key the view read). `render(ctx)` calls the view again with the instance's
215
+ * current inputs and that context (a fresh template, nothing injected or patched), so the
216
+ * consumer can compare `render(prev)` with `render(next)` on a sample of skips and report a
217
+ * difference (sygnal/diagnostics: SYG423). `keysRead`: the keys the last view call read.
218
+ */
219
+ onContextSkip?(inst: InstanceView, render: (context: any) => any, prev: any, next: any, keysRead: string[]): void
220
+
221
+ // ------------------------------------------------------------------ errors
222
+ /** the app-level error hook (run()'s `onError`, GS-11), with the phase the error came from */
223
+ onError?(error: any, info: {componentName: string; phase: 'view' | 'model' | 'intent' | 'calculated' | 'context' | 'widget' | 'driver'; action?: string}): void
224
+ }
225
+
226
+ /**
227
+ * What the runtime hands to hooks and tools (devtools, testing, sygnal/element, HMR, Vike). It
228
+ * replaces every `sinks.STATE.shamefullySendNext(...)` and `STATE.stream._v` reach-in.
229
+ */
230
+ export interface RuntimeAPI {
231
+ /** the root instance (devtools tree, inspect()) */
232
+ readonly root: InstanceView
233
+ /** find an instance by id (devtools selection, time travel) */
234
+ get(id: number): InstanceView | undefined
235
+ /** the current root state, synchronously (today `STATE.stream._v`) */
236
+ getState(): any
237
+ /**
238
+ * Replace the state of `target` (the root, or an instance's own cell: a Collection item, an
239
+ * isolatedState component) as a 'setState' action: queued, applied run-to-completion, one patch.
240
+ * A function gets the current state. Devtools time travel, element prop sync, HMR state
241
+ * restore, Vike page swaps, persist RESTORE.
242
+ */
243
+ setState(target: 'root' | InstanceView | number, state: any | ((current: any) => any)): void
244
+ /** dispatch an action to an instance, as if its intent emitted it (testing's simulateAction) */
245
+ dispatch(target: 'root' | InstanceView | number, type: string, data?: any, cause?: ActionCause): void
246
+ /** add / remove hooks on a live app (devtools connecting late; sygnal/diagnostics installed after run()) */
247
+ addHooks(hooks: Hooks): () => void
248
+ /** a resolved promise after the current flush (testing's settle without polling) */
249
+ flushed(): Promise<void>
250
+ /** R4: debug logging for one instance on / off (the DevTools toggle; core/debug.ts) */
251
+ setDebug(target: 'root' | InstanceView | number, on: boolean): void
252
+ }
253
+
254
+ // ---------------------------------------------------------------------------------- 1. registries
255
+
256
+ /**
257
+ * A child that renders in place of a marker vnode (Collection, Switchable). The registry entries
258
+ * are core modules: they get the owner's raw instance (R2), unlike hooks.
259
+ */
260
+ export interface Host {
261
+ /** render with the latest props; return the vnode to inject (the cached one when nothing changed) */
262
+ render(): any
263
+ /** the latest props and children; `marker` / `id`: the marker vnode and its id in the owner */
264
+ setProps(props: Record<string, any>, children: any[], marker?: any, id?: string): void
265
+ dispose(): void
266
+ /** READY of its instances (Suspense); Collection and Switchable stay ready, as today */
267
+ readonly ready: boolean
268
+ /** its instances (byId, InstanceView.children) */
269
+ insts(): any[]
270
+ }
271
+
272
+ export interface Registry {
273
+ /** marker sel -> host factory (Collection, Switchable) */
274
+ hosts: Record<string, (owner: any, props: Record<string, any>, children: any[], id: string, marker: any) => Host>
275
+ /**
276
+ * marker sel -> template rewrite during the reconcile walk (Portal, Transition, ClientOnly,
277
+ * Slot): replace the marker with a plain vnode and keep walking its children.
278
+ */
279
+ pres: Record<string, (vnode: any, owner: any) => any>
280
+ /** marker sel -> post-processor of the injected vnode of an instance whose template had it (Suspense) */
281
+ posts: Record<string, (vnode: any, owner: any) => any>
282
+ /**
283
+ * component function -> the function to instantiate (lazy: the loaded component once resolved;
284
+ * `owner.refresh()` renders the owner again when it loads)
285
+ */
286
+ resolvers: Array<(view: ComponentFn, owner: any) => ComponentFn | undefined>
287
+ /** definition time, every app: behaviors (`uses`), undo, selection, pager, persist, resources */
288
+ defHooks: Array<(src: DefSource, view: ComponentFn) => DefSource | void>
289
+ }
290
+
291
+ /**
292
+ * The statics contract (unchanged from today's generic path, `__sygnalStatic`): a driver source
293
+ * that names a static (`__sygnalStatic: 'timers'`) gets each declaring instance's value of
294
+ * `view[static](state)` on its sink, recomputed on commits that changed that instance's state,
295
+ * dropped when deep-equal to the last (objIsEqual), filtered to `background: true` entries while
296
+ * the instance is on a hidden Switchable page, stamped with `__emitterId` / `__emitterName`.
297
+ * A source with `__sygnalReplies: true` and `replies(emitterId)` sends reply actions back to
298
+ * exactly that instance. Optional `isolateValue(value, scope)` lets a driver scope a sink value
299
+ * without a stream per instance (03 §5); without it the core falls back to `isolateSink`.
300
+ */
301
+ export interface StaticsSource {
302
+ __sygnalStatic?: string
303
+ __sygnalReplies?: true
304
+ replies?(emitterId: number): any
305
+ isolateSource?(source: any, scope: string): any
306
+ isolateSink?(sink$: any, scope: string): any
307
+ isolateValue?(value: any, scope: string): any
308
+ }
309
+
310
+ /** Options of run() the core reads; `hooks` is internal (dev entries, testing), not documented */
311
+ export interface InternalRunOptions {
312
+ /** hooks of this app (testing, devtools, diagnostics install theirs through these) */
313
+ __hooks?: Hooks
314
+ }
@@ -0,0 +1,325 @@
1
+ /**
2
+ * PLAN-4.6 core: the Collection host (03-proposal §2 hosts/, R2). Registered on import (the
3
+ * public `Collection` module imports this file); the core only looks `hosts.collection` up.
4
+ *
5
+ * It stands where the `<Collection>` marker was in its owner's template and renders the items
6
+ * inside the owner's render: no stream of its own, no pickCombine.
7
+ * - `of`: a component function (D163: no names). `from`: a state key (SYG409 on a calculated
8
+ * one), a `{ get, set }` lens (SYG412 without get(); SYG401 for a non-array) or none (the
9
+ * owner's state is the array).
10
+ * - Items are keyed by `id`, an id-less item by its raw index (D169); one key -> index map per
11
+ * array identity serves every item (cell.ts indexer). A duplicate key renders its first element
12
+ * only; the dev warning is R4's (hooks.onDuplicateKey is the hook point).
13
+ * - `filter` / `sort` (every form today's core accepts; SYG418 for an invalid one) change what
14
+ * renders and in which order; the state array keeps its order, and an item writes back to its
15
+ * own element. An item returning `undefined` removes itself.
16
+ * - The other props go to every item, and the Collection's children are each item's children.
17
+ * - 4-H (D229): no element of its own. It renders a keyed fragment of the items' vnodes (its key:
18
+ * the marker's, else its id), which the DOM driver splices into the parent's children before
19
+ * each patch (utils.ts flat): the items are the parent element's own children, and their keys
20
+ * take the fragment's, so two sibling Collections' items never collide. The wrapper `div` of
21
+ * 5.x is gone: `className` / `style` / `class` / ... on the marker are a removed-form error in development
22
+ * (checks/next.ts) and are ignored.
23
+ * - Removed items are disposed synchronously in the render that drops them (G-257: a move between
24
+ * two Collections is one patch).
25
+ * - PLAN-5 A-1: `viewTransitionName="card"` styles each keyed item's root element with
26
+ * `view-transition-name: card-<id>` (shared.ts vtStyle) and `view-transition-class:
27
+ * card`, the item's own style winning, so a `viewTransitions` action animates each item between
28
+ * its places, across Collections with the same prefix too. Id-less items (keyed by index) and
29
+ * fragment roots get none.
30
+ */
31
+ import {hosts, resolvers} from '../registry'
32
+ import {Inst, shallowEq} from '../instance'
33
+ import {Cell, Index, indexer, itemCell, keyCell, keyOf, keyName} from '../cell'
34
+ import {CoreDef, isObj} from '../define'
35
+ import {uidPart, vtStyle} from '../../shared'
36
+ import {viewOf} from '../view'
37
+ import {warn, error as logError, fail} from '../../extra/diagnostics/legacy'
38
+
39
+ const SORT_FIX = "Use a field name, { field: 'asc'|'desc'|1|-1 }, or a function"
40
+ const sortError = (msg: string, value: any): undefined => void logError('SYG418', 'Collection', msg, SORT_FIX, value)
41
+ const base = (a: any, b: any, asc = true) => (a > b ? (asc ? 1 : -1) : a < b ? (asc ? -1 : 1) : 0)
42
+
43
+ function fromObj(item: Record<string, any>): ((a: any, b: any) => number) | undefined {
44
+ const e = Object.entries(item)
45
+ if (e.length > 1) return sortError('sort object must have one key; ignored', item)
46
+ const [f, d] = e[0]
47
+ let asc
48
+ if (typeof d == 'string') {
49
+ const x = d.toLowerCase()
50
+ if (x != 'asc' && x != 'desc') return sortError("sort direction must be 'asc' or 'desc'; ignored", item)
51
+ asc = x == 'asc'
52
+ } else if (typeof d == 'number') {
53
+ if (d !== 1 && d !== -1) return sortError('sort direction must be 1 or -1; ignored', item)
54
+ asc = d === 1
55
+ } else return sortError('sort direction must be a string or number; ignored', item)
56
+ return (a, b) => base(a[f], b[f], asc)
57
+ }
58
+
59
+ /** the comparator of a `sort` prop (today's sortFunctionFromProp) */
60
+ export function sortFn(p: any): ((a: any, b: any) => number) | undefined {
61
+ if (!p) return
62
+ if (typeof p == 'function') return p
63
+ if (typeof p == 'string') {
64
+ const d = p.toLowerCase()
65
+ if (d == 'asc' || d == 'desc') return (a, b) => base(a, b, d == 'asc')
66
+ return (a, b) => base(a[p], b[p])
67
+ }
68
+ if (Array.isArray(p)) {
69
+ const fs: any[] = p.map(i => typeof i == 'function' ? i
70
+ : typeof i == 'string' ? (['asc', 'desc'].includes(i.toLowerCase()) ? undefined : (a: any, b: any) => base(a[i], b[i]))
71
+ : isObj(i) ? fromObj(i) : undefined).filter(f => typeof f == 'function')
72
+ return (a, b) => fs.reduce((r, f) => (r !== 0 ? r : f(a, b)), 0)
73
+ }
74
+ if (isObj(p)) return fromObj(p)
75
+ return sortError('Invalid sort prop; ignored', p)
76
+ }
77
+
78
+ /** the Collection's own props (`idfield`, removed in 6.0 (D164), is still kept off the items) */
79
+ const OWN = new Set(['of', 'from', 'filter', 'sort', 'idfield', 'className', 'viewTransitionName'])
80
+ const NONE: any[] = []
81
+
82
+ /** the array cell for `from` (D178: a missing key renders once it appears), or null for an invalid `from` (renders nothing) */
83
+ function arrayCell(owner: Inst, from: any): Cell | null {
84
+ const oc = owner.cell, name = owner.def.name
85
+ if (from === undefined) {
86
+ // the owner's state is the array (or its `value`, as today)
87
+ return {
88
+ get: () => { const s = oc.get(); return !Array.isArray(s) && Array.isArray(s?.value) ? s.value : s },
89
+ set: (v) => oc.set(v),
90
+ }
91
+ }
92
+ if (typeof from == 'string') {
93
+ const cs = oc.get(), calc = owner.def.calcNames?.has(from)
94
+ if (isObj(cs) && !(from in cs) && !calc) {
95
+ const arrays = Object.keys(cs).filter(k => Array.isArray(cs[k]))
96
+ warn('SYG401', name, `Collection from="${from}" is not in state${arrays.length ? ` (array fields: '${arrays.join("', '")}')` : ''}; it renders nothing until it exists`, 'Set it to an array in initialState')
97
+ } else if (isObj(cs) && !Array.isArray(cs[from])) warn('SYG401', name, `Collection 'from' field '${from}' is not an array; it renders nothing`, 'Set it to an array in initialState')
98
+ return keyCell(oc, from, calc && name, undefined, 'Collection')
99
+ }
100
+ if (isObj(from) && typeof from.get == 'function') {
101
+ let lp: any = {}, lv: any
102
+ return {
103
+ get() {
104
+ const p = oc.get()
105
+ if (p !== lp) {
106
+ lp = p
107
+ let g: any
108
+ try { g = from.get(p) } catch (e) {
109
+ // G-298: keeps the items it had
110
+ logError('SYG412', name, "Collection 'from' getter threw; it keeps its items", 'Guard the getter against missing data', e)
111
+ owner.app.appError(owner, e, 'view')
112
+ return lv
113
+ }
114
+ lv = g
115
+ if (!Array.isArray(lv)) { warn('SYG401', name, "Collection 'from' getter returned a non-array; it renders nothing", 'Return an array from get()', lv); lv = NONE }
116
+ }
117
+ return lv
118
+ },
119
+ set(v) {
120
+ if (typeof from.set != 'function') return
121
+ const p = oc.get(), n = from.set(p, v)
122
+ if (n !== p) oc.set(n)
123
+ },
124
+ }
125
+ }
126
+ logError('SYG412', name, "Collection 'from' prop is invalid; it renders nothing", 'Use a state key string or { get, set }', from)
127
+ return null
128
+ }
129
+
130
+ /** a component function through the view resolvers (lazy: the loaded one; the owner renders again when it loads) */
131
+ export function resolve(view: any, owner: Inst) {
132
+ for (const r of resolvers) view = r(view, owner) || view
133
+ return view
134
+ }
135
+
136
+ export class CollectionHost {
137
+ /** key -> item instance */
138
+ items = new Map<any, Inst>()
139
+ /** the items shown, in render order */
140
+ shown: Inst[] = []
141
+ arr: Cell | null
142
+ index: Index | null
143
+ def!: CoreDef
144
+ ready = true
145
+ disposed = false
146
+ outv: any; last: any; lr = true
147
+ ip: Record<string, any> = {}
148
+ kids: any[] = NONE
149
+ props!: Record<string, any>
150
+ // the inputs of the last item list: array, filter, sort prop, comparator
151
+ la: any; lf: any; ls: any; cmp: any
152
+ uidBase: string
153
+ /** the fragment's key (the marker's, else the Collection's id) */
154
+ key: any
155
+ tr: any
156
+ /** the app's render epoch it last rendered at (G-311) */
157
+ ep = 0
158
+
159
+ constructor(public owner: Inst, props: Record<string, any>, children: any[], id: string, marker: any) {
160
+ this.hostProps(props, marker)
161
+ const of = props.of
162
+ if (!of) fail('SYG411', owner, "Collection is missing 'of'", 'Use of={ItemComponent}')
163
+ if (typeof of != 'function') fail('SYG411', owner, `Collection 'of' is a ${typeof of}`, 'Use of={ItemComponent}')
164
+ this.uidBase = owner.uid(uidPart(id.replace(/.*::(r\.)?/, '')))
165
+ this.arr = arrayCell(owner, props.from)
166
+ this.index = this.arr && indexer(this.arr)
167
+ this.def = owner.app.def(this.view = resolve(of, owner))
168
+ this.setProps(props, children, marker, id)
169
+ }
170
+
171
+ /**
172
+ * onHostProps (R4): the Collection checks of the dev entry (SYG401 for a missing `from`, D173's
173
+ * string `of`, 4-H's wrapper props: the marker's data); the marker's sel tells a
174
+ * VirtualCollection from a Collection
175
+ */
176
+ hostProps(props: Record<string, any>, m: any) {
177
+ const H = this.owner.app.hooks
178
+ if (H.onHostProps) H.onHostProps(viewOf(this.owner), m.sel, props, m.data)
179
+ }
180
+
181
+ /** the item component (a lazy() one: the loaded component once it has loaded, G-317) */
182
+ view: any
183
+
184
+ setProps(props: Record<string, any>, children: any[], marker?: any, id?: string) {
185
+ // (the constructor called the hook before its own checks)
186
+ if (this.props) this.hostProps(props, marker)
187
+ const v = typeof props.of == 'function' ? resolve(props.of, this.owner) : this.view
188
+ if (v !== this.view) {
189
+ // another item component (or a lazy one loaded): the items are made again
190
+ this.def = this.owner.app.def(this.view = v)
191
+ this.clear()
192
+ }
193
+ this.props = props
194
+ if (marker) {
195
+ // tr: a <Transition> around it, applied to each item (4-I G-559, markers/transition.ts):
196
+ // the fragment is made again on each of the owner's renders while there is one (or was)
197
+ const k = marker.key ?? id
198
+ if (this.tr !== (this.tr = marker.data?.tr) || k !== this.key) { this.key = k; this.outv = undefined }
199
+ }
200
+ const ip: Record<string, any> = {}
201
+ for (const k in props) if (!OWN.has(k)) ip[k] = props[k]
202
+ const kids = children.length ? children : NONE
203
+ if (!shallowEq(ip, this.ip) || kids !== this.kids) {
204
+ this.ip = ip
205
+ this.kids = kids
206
+ this.items.forEach(i => i.setProps(ip, kids))
207
+ }
208
+ }
209
+
210
+ clear() {
211
+ this.items.forEach(i => i.dispose())
212
+ this.items.clear()
213
+ this.shown = []
214
+ this.la = undefined
215
+ }
216
+
217
+ /** the item instances in the order shown (byId, InstanceView.children) */
218
+ insts(): Inst[] { return this.shown }
219
+
220
+ /** the visible keys in order: filter and sort over the raw array; a duplicate key once */
221
+ list(a: any[], m: Map<any, number>): any[] {
222
+ const {filter, sort} = this.props
223
+ const cmp = sort !== this.ls ? sortFn(sort) : this.cmp
224
+ let idx: number[] | null = null
225
+ if (typeof filter == 'function' || cmp) {
226
+ idx = []
227
+ for (let i = 0; i < a.length; i++) if (typeof filter != 'function' || filter(a[i], i, a)) idx.push(i)
228
+ if (cmp) idx.sort((x, y) => cmp(a[x], a[y]))
229
+ }
230
+ // G-311: the inputs are kept only once the list was made (a throwing filter / sort is retried)
231
+ this.ls = sort; this.cmp = cmp
232
+ const n = idx ? idx.length : a.length, keys: any[] = []
233
+ for (let x = 0; x < n; x++) {
234
+ const i = idx ? idx[x] : x, k = keyOf(a[i], i)
235
+ // D169: a duplicate key renders its first element (R4 reports it)
236
+ if (m.get(k) !== i) { const H = this.owner.app.hooks; H.onDuplicateKey && H.onDuplicateKey(viewOf(this.owner), k[0] == '\0' ? i : a[i].id); continue }
237
+ keys.push(k)
238
+ }
239
+ return keys
240
+ }
241
+
242
+ /**
243
+ * G-319: on a hidden Switchable page (no render): the items follow the array (removed ones are
244
+ * disposed, new ones created, so their background statics and replies run), with no view call
245
+ */
246
+ sync() {
247
+ if (this.disposed) return
248
+ this.items_()
249
+ for (const i of this.shown) i.sync()
250
+ }
251
+
252
+ /** the item instances for the current array, filter and sort; true when the list changed */
253
+ items_(): boolean {
254
+ if (!this.index) return false
255
+ const app = this.owner.app
256
+ let changed = false
257
+ {
258
+ const [a, m] = this.index()
259
+ const {filter, sort} = this.props
260
+ if (a !== this.la || filter !== this.lf || sort !== this.ls) {
261
+ const keys = this.list(a, m), seen = new Set(keys)
262
+ this.la = a; this.lf = filter
263
+ for (const [k, inst] of this.items) if (!seen.has(k)) { inst.dispose(); this.items.delete(k) }
264
+ const o = this.owner, shown: Inst[] = []
265
+ for (const k of keys) {
266
+ let inst = this.items.get(k)
267
+ if (!inst) {
268
+ const scope = app.scope()
269
+ inst = new Inst(app, this.def, o, itemCell(this.arr!, this.index, k), o.dom && o.dom.isolateSource(o.dom, scope),
270
+ this.ip, this.kids, scope, this.uidBase + '-' + keyName(k), 'item')
271
+ this.items.set(k, inst);
272
+ // its key (A-1's view-transition name)
273
+ (inst as any).k = k
274
+ }
275
+ shown.push(inst)
276
+ }
277
+ if (shown.length != this.shown.length || shown.some((s, i) => s !== this.shown[i])) changed = true
278
+ this.shown = shown
279
+ }
280
+ }
281
+ return changed
282
+ }
283
+
284
+ render(): any {
285
+ if (this.disposed) return this.outv
286
+ // G-311: after a render that threw, every container is made again once
287
+ const app = this.owner.app
288
+ let changed = !this.outv || this.ep !== app.ep
289
+ this.ep = app.ep
290
+ if (this.items_()) changed = true
291
+ const shown = this.shown, out: any[] = Array(shown.length), vn = this.props.viewTransitionName
292
+ let j = 0
293
+ for (let i = 0; i < shown.length; i++) {
294
+ const inst: any = shown[i], v = inst.render()
295
+ if (v !== inst.last) { inst.last = v; changed = true }
296
+ // an item without state yet (or a removed one) is left out
297
+ if (v !== undefined) out[j++] = this.tr ? this.tr(vn ? named(inst, v, vn) : v) : vn ? named(inst, v, vn) : v
298
+ }
299
+ out.length = j
300
+ if (!changed) return this.outv
301
+ return (this.outv = {sel: undefined, data: {}, children: out, text: undefined, elm: undefined, key: this.key})
302
+ }
303
+
304
+ dispose() {
305
+ if (this.disposed) return
306
+ this.disposed = true
307
+ this.clear()
308
+ }
309
+ }
310
+
311
+ /**
312
+ * A-1: the item's vnode with its view-transition name (cached per item, so an unchanged item
313
+ * keeps its vnode). VirtualCollection's rows too (extra/virtual.ts, G-417)
314
+ */
315
+ export function named(inst: any, v: any, p: string): any {
316
+ const k = inst.k
317
+ if (!v.sel || k[0] == '\0') return v
318
+ if (inst.vi !== v || inst.vp !== p) {
319
+ inst.vi = v; inst.vp = p
320
+ inst.vo = {...v, data: {...v.data, style: vtStyle(p, k, v.data?.style)}}
321
+ }
322
+ return inst.vo
323
+ }
324
+
325
+ hosts.collection = (owner, props, children, id, marker) => new CollectionHost(owner, props, children, id, marker)