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,379 @@
1
+ /**
2
+ * PLAN-4 3-E (GS-10): the DevTools action log, in the dev-only 'sygnal/devtools' entry (0 B in
3
+ * apps: nothing in the core calls it).
4
+ *
5
+ * It records every action of every component instance through 2-C's recorder
6
+ * (./diagnostics/checks/actionLog: actionHooks), a hook layer every app reads from the core's
7
+ * diagnostics bridge (globalThis.__SYGNAL_DIAGNOSTICS__.layers), so it records with diagnostics
8
+ * off too. On top of 2-C's record it keeps:
9
+ * seq, at a sequence number, ms since the session started
10
+ * parent the parent instance id (null: a root)
11
+ * before, after the instance's state around the action's STATE reducer (onReducer), when it
12
+ * changed the state (`after` without calculated fields)
13
+ * replySink for a reply action (and RESOURCE): the source that delivered it, and
14
+ * replyKind 'fetch' when that source is makeFetchDriver's (renderComponent fakes it)
15
+ *
16
+ * A session runs from the recorder's start (or the last clearActions()) to now. getSession()
17
+ * turns it into a SessionRecording for one instance (./copyAsTest generates the test).
18
+ */
19
+ import {clockNow, actionHooks} from './diagnostics/checks/actionLog'
20
+ import {addLayer, devFacade} from './devtoolsNext'
21
+ import type {ActionListener, ActionRecord, ActionCause} from './diagnostics/checks/actionLog'
22
+
23
+ export type {ActionCause}
24
+
25
+ export interface DevtoolsAction {
26
+ seq: number
27
+ type: string
28
+ data: any
29
+ component: string
30
+ instance: string
31
+ parent: string | null
32
+ /** live: fills in as the action's reducers run */
33
+ sinks: string[]
34
+ cause: ActionCause
35
+ /** ms since the session started */
36
+ at: number
37
+ before?: any
38
+ after?: any
39
+ replySink?: string
40
+ replyKind?: 'fetch' | 'other'
41
+ /** an intent action whose data is the instance's own state (an intent over STATE.stream) */
42
+ echo?: true
43
+ }
44
+
45
+ export interface SessionAction {
46
+ type: string
47
+ data: any
48
+ cause: ActionCause
49
+ sinks: string[]
50
+ at: number
51
+ replySink?: string
52
+ replyKind?: 'fetch' | 'other'
53
+ echo?: true
54
+ }
55
+
56
+ /** One instance's session: what copyAsTest() needs (plain data, raw action data) */
57
+ export interface SessionRecording {
58
+ version: 1
59
+ component: string
60
+ instance: string
61
+ /** the state when the session started for this instance (undefined: unknown) */
62
+ initialState?: any
63
+ /** the component's own `initialState` (renderComponent's default) */
64
+ definitionInitialState?: any
65
+ finalState: any
66
+ /** the action names the component can be sent (model keys, behavior actions); undefined: any */
67
+ actionNames?: string[]
68
+ /** source names beyond DOM / EVENTS / STATE / LOG / CHILD / PARENT / READY */
69
+ drivers: string[]
70
+ /** those of `drivers` renderComponent fakes (makeFetchDriver sources: t.respond / t.fail) */
71
+ fakeable: string[]
72
+ /** the instance's own actions, in order */
73
+ actions: SessionAction[]
74
+ /** state changes in descendant instances a root-level replay can't reproduce */
75
+ foreign: Array<{type: string; component: string; instance: string; cause: ActionCause}>
76
+ /** the session lost its oldest actions (more than the recorder keeps) */
77
+ truncated?: boolean
78
+ }
79
+
80
+ export interface ActionFilter {
81
+ component?: string
82
+ instance?: string | number
83
+ type?: string | RegExp
84
+ cause?: ActionCause | ActionCause[]
85
+ }
86
+
87
+ interface Inst {
88
+ c: any
89
+ id: string
90
+ name: string
91
+ parent: string | null
92
+ stateName: string
93
+ /** created after the session started */
94
+ inSession: boolean
95
+ hasInitial: boolean
96
+ initial?: any
97
+ disposed: boolean
98
+ }
99
+
100
+ const MAX = 5000
101
+ const STANDARD = /^(DOM|EVENTS|LOG|CHILD|PARENT|READY|props\$|children\$|dispose\$)$/
102
+
103
+ let actions: DevtoolsAction[] = []
104
+ let seq = 0
105
+ let epoch = clockNow()
106
+ let truncated = false
107
+ let created = 0
108
+ const insts = new Map<string, Inst>()
109
+ const byRec = new WeakMap<ActionRecord, DevtoolsAction>()
110
+ /** instance -> the action whose STATE reducer just produced a value (its onReducer follows) */
111
+ const pendingState = new WeakMap<any, DevtoolsAction>()
112
+ const subscribers = new Set<(a: DevtoolsAction | null, kind: 'add' | 'update' | 'reset') => void>()
113
+
114
+ const notify = (a: DevtoolsAction | null, kind: 'add' | 'update' | 'reset') => {
115
+ for (const s of subscribers) try { s(a, kind) } catch (_) { /* a subscriber never breaks the app */ }
116
+ }
117
+
118
+ const idOf = (c: any) => String(c && c._componentNumber)
119
+
120
+ function ensure(c: any): Inst {
121
+ const id = idOf(c)
122
+ let i = insts.get(id)
123
+ if (!i || i.c !== c) {
124
+ const p = c && c.__next && c.__next.parentId
125
+ i = {c, id, name: c && c.name, parent: typeof p == 'number' ? String(p) : null, stateName: (c && c.stateSourceName) || 'STATE',
126
+ inSession: true, hasInitial: false, disposed: false}
127
+ ;(i as any).order = ++created
128
+ insts.set(id, i)
129
+ }
130
+ return i
131
+ }
132
+
133
+ function clean(c: any, s: any): any {
134
+ try { return typeof c.cleanupCalculated == 'function' ? c.cleanupCalculated(s) : s } catch (_) { return s }
135
+ }
136
+
137
+ const listener: ActionListener = {
138
+ action(r, c) {
139
+ const info = ensure(c)
140
+ // the instance's state when its session started: INITIALIZE's data (its initial state), else
141
+ // the state it had at its first action
142
+ if (r.type == 'INITIALIZE' && info.inSession) { info.initial = r.data; info.hasInitial = true }
143
+ else if (!info.hasInitial) { info.initial = c.currentState; info.hasInitial = true }
144
+ const a: DevtoolsAction = {seq: ++seq, type: r.type, data: r.data, component: r.component, instance: r.instance,
145
+ parent: info.parent, sinks: r.sinks, cause: r.cause, at: r.time - epoch}
146
+ const slot = (r as any).source
147
+ if (slot !== undefined && (r.cause == 'reply' || r.type == 'RESOURCE')) {
148
+ a.replySink = slot
149
+ a.replyKind = c.sources && c.sources[slot] && c.sources[slot].__sygnalStatic === 'resources' ? 'fetch' : 'other'
150
+ }
151
+ if (r.cause == 'intent' && isStateEcho(r.data, c.currentState)) a.echo = true
152
+ byRec.set(r, a)
153
+ actions.push(a)
154
+ if (actions.length > MAX) { actions.shift(); truncated = true }
155
+ notify(a, 'add')
156
+ },
157
+ sink(r, sink) {
158
+ const a = byRec.get(r)
159
+ if (!a) return
160
+ const info = insts.get(r.instance)
161
+ if (info && info.c && sink == info.stateName) pendingState.set(info.c, a)
162
+ notify(a, 'update')
163
+ },
164
+ }
165
+
166
+ function onReducer(c: any, name: string, prev: any, next: any): void {
167
+ const a = pendingState.get(c)
168
+ if (!a || a.type !== name || 'after' in a) return
169
+ pendingState.delete(c)
170
+ a.before = prev
171
+ a.after = clean(c, next)
172
+ notify(a, 'update')
173
+ }
174
+
175
+ function onDispose(c: any): void {
176
+ const i = insts.get(idOf(c))
177
+ if (i && i.c === c) { i.disposed = true; i.c = undefined }
178
+ }
179
+
180
+ let unregister: (() => void) | undefined
181
+
182
+ /** PLAN-4.6 R4: the same recorder on the core, from its hooks (per app; a facade per instance) */
183
+ function nextLayer(api: any): any {
184
+ const L: ActionListener = {
185
+ action: (r, iv) => listener.action(r, devFacade(iv, api)),
186
+ sink: (r, sink, reducer) => listener.sink!(r, sink, reducer),
187
+ }
188
+ const log = actionHooks(L)
189
+ return {
190
+ ...log,
191
+ onCreate(iv: any) { ensure(devFacade(iv, api)); log.onCreate(iv) },
192
+ onReducer(iv: any, name: string, prev: any, next: any) { onReducer(devFacade(iv, api), name, prev, next) },
193
+ onDispose(iv: any) { onDispose(devFacade(iv, api)) },
194
+ }
195
+ }
196
+
197
+ /**
198
+ * Start recording actions (idempotent; 'sygnal/devtools' does it on import in a browser). Only
199
+ * components created afterwards are recorded. Returns a function that stops recording.
200
+ */
201
+ export function recordActions(): () => void {
202
+ if (!unregister) {
203
+ const core = (globalThis as any).__SYGNAL_DIAGNOSTICS__
204
+ if (!core) return () => {}
205
+ unregister = addLayer(nextLayer)
206
+ }
207
+ return stopRecording
208
+ }
209
+
210
+ function stopRecording(): void {
211
+ if (unregister) { unregister(); unregister = undefined }
212
+ }
213
+
214
+ export const isRecording = (): boolean => !!unregister
215
+
216
+ /** Start a new session: forget the recorded actions; each live instance's state is its new initial state. */
217
+ export function clearActions(): void {
218
+ actions = []
219
+ epoch = clockNow()
220
+ truncated = false
221
+ for (const [id, i] of insts) {
222
+ if (i.disposed) { insts.delete(id); continue }
223
+ i.inSession = false
224
+ i.initial = i.c && i.c.currentState
225
+ i.hasInitial = true
226
+ }
227
+ notify(null, 'reset')
228
+ }
229
+
230
+ const matches = (a: DevtoolsAction, f: ActionFilter) =>
231
+ (f.component === undefined || a.component === f.component) &&
232
+ (f.instance === undefined || a.instance === String(f.instance)) &&
233
+ (f.type === undefined || (typeof f.type == 'string' ? a.type === f.type : f.type.test(a.type))) &&
234
+ (f.cause === undefined || ([] as ActionCause[]).concat(f.cause).includes(a.cause))
235
+
236
+ /** The session's actions (oldest first), optionally filtered by component, instance, type or cause. */
237
+ export function getActions(filter?: ActionFilter): DevtoolsAction[] {
238
+ return filter ? actions.filter(a => matches(a, filter)) : actions.slice()
239
+ }
240
+
241
+ /** Subscribe to the log: (action, 'add' | 'update') and (null, 'reset'). Returns unsubscribe. */
242
+ export function onAction(fn: (a: DevtoolsAction | null, kind: 'add' | 'update' | 'reset') => void): () => void {
243
+ subscribers.add(fn)
244
+ return () => { subscribers.delete(fn) }
245
+ }
246
+
247
+ /** the live instances, newest first */
248
+ const live = () => [...insts.values()].filter(i => !i.disposed && i.c).sort((a, b) => (b as any).order - (a as any).order)
249
+
250
+ /**
251
+ * The instance a session target names: undefined (the newest live root), an instance id, a
252
+ * component function (its newest live instance) or run()'s result (its root, by DOM source).
253
+ */
254
+ export function resolveInstance(target?: any): Inst | undefined {
255
+ const all = live()
256
+ if (target === undefined || target === null) return all.find(i => i.parent === null)
257
+ if (typeof target == 'string' || typeof target == 'number') return insts.get(String(target))
258
+ if (typeof target == 'function') return all.find(i => i.c.view === target)
259
+ if (typeof target == 'object') {
260
+ const s = target.sources
261
+ if (s && typeof s == 'object') {
262
+ return all.find(i => i.parent === null && Object.keys(s).some(k => k != 'STATE' && s[k] && i.c.sources && i.c.sources[k] === s[k])) ||
263
+ all.find(i => i.parent === null)
264
+ }
265
+ }
266
+ return undefined
267
+ }
268
+
269
+ function descendants(id: string): Set<string> {
270
+ const out = new Set<string>()
271
+ let grew = true
272
+ while (grew) {
273
+ grew = false
274
+ for (const i of insts.values()) if (i.parent !== null && (i.parent === id || out.has(i.parent)) && !out.has(i.id)) { out.add(i.id); grew = true }
275
+ }
276
+ // instances already pruned: their actions still name their parent
277
+ for (const a of actions) if (a.parent !== null && (a.parent === id || out.has(a.parent))) out.add(a.instance)
278
+ return out
279
+ }
280
+
281
+ const REPLAYED = new Set<ActionCause>(['intent', 'simulateAction', 'behavior', 'reply'])
282
+
283
+ /**
284
+ * The session of one instance (see resolveInstance for `target`) as plain data: its initial
285
+ * and final state, its own actions, and the state changes of its descendants (a replay at this
286
+ * instance can't reproduce them).
287
+ */
288
+ export function getSession(target?: any): SessionRecording {
289
+ const info = resolveInstance(target)
290
+ if (!info) throw new Error('[Sygnal DevTools] getSession: no live component instance matches' + (target === undefined ? ' (no root recorded: import sygnal/devtools before run())' : ''))
291
+ const c = info.c
292
+ const desc = descendants(info.id)
293
+ const stateNameOf = (id: string) => insts.get(id)?.stateName || 'STATE'
294
+ const model = c.model && typeof c.model == 'object' ? Object.keys(c.model).map(k => k.split('|')[0].trim()) : undefined
295
+ const behaviors = c._behaviorActions && typeof c._behaviorActions == 'object' ? Object.keys(c._behaviorActions) : []
296
+ const sources = c.sources || {}
297
+ const drivers = (c.sourceNames || Object.keys(sources)).filter((n: string) =>
298
+ !STANDARD.test(n) && n !== info.stateName && n != 'STATE' && n != 'state' && !n.startsWith('__'))
299
+ return {
300
+ version: 1,
301
+ component: info.name,
302
+ instance: info.id,
303
+ initialState: info.hasInitial ? info.initial : undefined,
304
+ definitionInitialState: c.view ? c.view.initialState : undefined,
305
+ finalState: c.currentState,
306
+ actionNames: model ? [...model, ...behaviors] : undefined,
307
+ drivers,
308
+ fakeable: drivers.filter((n: string) => sources[n] && sources[n].__sygnalStatic === 'resources'),
309
+ actions: actions.filter(a => a.instance === info.id).map(a => ({
310
+ type: a.type, data: a.data, cause: a.cause, sinks: [...a.sinks], at: a.at,
311
+ ...(a.replySink !== undefined ? {replySink: a.replySink, replyKind: a.replyKind} : {}),
312
+ ...(a.echo ? {echo: true as const} : {}),
313
+ })),
314
+ foreign: actions.filter(a => desc.has(a.instance) && REPLAYED.has(a.cause) && a.sinks.includes(stateNameOf(a.instance)))
315
+ .map(a => ({type: a.type, component: a.component, instance: a.instance, cause: a.cause})),
316
+ ...(truncated ? {truncated: true} : {}),
317
+ }
318
+ }
319
+
320
+ /** A JSON-safe copy for the panel: DOM elements and events become short descriptions. */
321
+ export function preview(v: any): any {
322
+ if (v === undefined) return undefined
323
+ const seen = new WeakSet<object>()
324
+ try {
325
+ return JSON.parse(JSON.stringify(v, (_k, x) => {
326
+ if (typeof x == 'function') return `[Function ${x.name || 'anonymous'}]`
327
+ if (typeof x == 'symbol') return String(x)
328
+ if (typeof x == 'bigint') return `${x}n`
329
+ if (x && typeof x == 'object') {
330
+ if (isElement(x)) return describeElement(x)
331
+ if (isEvent(x)) return `[${x.constructor && x.constructor.name || 'Event'} ${x.type}]`
332
+ if (x instanceof Map) return {'[Map]': [...x.entries()]}
333
+ if (x instanceof Set) return {'[Set]': [...x.values()]}
334
+ if (seen.has(x)) return '[Circular]'
335
+ seen.add(x)
336
+ }
337
+ return x
338
+ }))
339
+ } catch (_) {
340
+ return '[unserializable]'
341
+ }
342
+ }
343
+
344
+ const isPlain = (x: any) => !!x && typeof x == 'object' && (Object.getPrototypeOf(x) === Object.prototype || Object.getPrototypeOf(x) === null)
345
+
346
+ export function deepEqual(a: any, b: any): boolean {
347
+ if (Object.is(a, b)) return true
348
+ if (!a || !b || typeof a != 'object' || typeof b != 'object') return false
349
+ if (Array.isArray(a) !== Array.isArray(b)) return false
350
+ const ka = Object.keys(a).filter(k => a[k] !== undefined), kb = Object.keys(b).filter(k => b[k] !== undefined)
351
+ return ka.length == kb.length && ka.every(k => deepEqual(a[k], b[k]))
352
+ }
353
+
354
+ /**
355
+ * The data is the state itself (STATE.stream in the intent; calculated fields may be added): the
356
+ * replay sends it again by itself, so it isn't replayed.
357
+ */
358
+ function isStateEcho(data: any, state: any): boolean {
359
+ if (!isPlain(data) || !isPlain(state)) return false
360
+ const keys = Object.keys(state)
361
+ return keys.length > 0 && (data === state || keys.every(k => deepEqual(data[k], state[k])))
362
+ }
363
+
364
+ export const isElement = (x: any): boolean => !!x && typeof x == 'object' && x.nodeType === 1 && typeof x.tagName == 'string'
365
+ export const isEvent = (x: any): boolean => !!x && typeof x == 'object' && typeof x.type == 'string' && typeof x.preventDefault == 'function' && 'target' in x
366
+
367
+ const describeElement = (el: any) => {
368
+ const cls = typeof el.className == 'string' && el.className.trim() ? '.' + el.className.trim().split(/\s+/).join('.') : ''
369
+ return `<${String(el.tagName).toLowerCase()}${el.id ? '#' + el.id : ''}${cls}>`
370
+ }
371
+
372
+ /** test seam: forget everything (sessions, instances); recording stays as it is */
373
+ export function _resetActionLog(): void {
374
+ actions = []
375
+ seq = 0
376
+ epoch = clockNow()
377
+ truncated = false
378
+ insts.clear()
379
+ }
@@ -0,0 +1,9 @@
1
+ import type {SygnalDevTools} from './devtools';
2
+
3
+ /**
4
+ * The installed DevTools bridge, or undefined (D77: the bridge itself lives in the
5
+ * 'sygnal/devtools' dev entry, which sygnal/vite injects in dev).
6
+ */
7
+ export function getDevTools(): SygnalDevTools | undefined {
8
+ return (globalThis as any).__SYGNAL_DEVTOOLS__;
9
+ }
@@ -0,0 +1,83 @@
1
+ /**
2
+ * PLAN-4.6 R4: 'sygnal/devtools' on the next component core (04 §3.5).
3
+ *
4
+ * The core calls no `window.__SYGNAL_DEVTOOLS__` method itself: each app reads the dev
5
+ * entries' hook layers once (`__SYGNAL_DIAGNOSTICS__.layers`), and this file's layer maps the
6
+ * hooks onto the bridge's existing methods (onComponentCreated, onStateChanged, ...). The bridge
7
+ * keeps a facade per instance with the fields it reads from today's instances (currentState,
8
+ * model, sourceNames, ...); time travel and the debug toggle go through the app's runtime API
9
+ * (`setState`, `setDebug`) instead of `sinks.STATE.shamefullySendNext` and `instance._debug`.
10
+ */
11
+ const facades = new WeakMap<object, any>()
12
+
13
+ /** the bridge's view of a core instance (an InstanceView + its app's runtime API) */
14
+ export function devFacade(iv: any, api: any): any {
15
+ let f = facades.get(iv)
16
+ if (f) return f
17
+ f = {
18
+ __next: iv,
19
+ __api: api,
20
+ get _componentNumber() { return iv.id },
21
+ get name() { return iv.name },
22
+ get isSubComponent() { return !iv.isRoot },
23
+ get parentId() { return iv.parentId },
24
+ get view() { return iv.def.view },
25
+ get model() {
26
+ const m: Record<string, any> = {}
27
+ iv.def.handlers.forEach((hs: any[], a: string) => { const e: any = m[a] = {}; for (const [s, fn] of hs) e[s] = fn })
28
+ return m
29
+ },
30
+ get intent() { return iv.def.intent },
31
+ get context() { return iv.def.view.context },
32
+ get calculated() { return iv.def.view.calculated },
33
+ get _behaviorActions() { return iv.def.behaviorActions },
34
+ get currentState() { return iv.state },
35
+ get currentContext() { return iv.context },
36
+ get currentProps() { return iv.props },
37
+ get sources() { return iv.sources },
38
+ get sourceNames() { return Object.keys(iv.sources) },
39
+ stateSourceName: 'STATE',
40
+ get _debug() { return false },
41
+ /** the state without its calculated fields (as today's cleanupCalculated) */
42
+ cleanupCalculated(s: any) {
43
+ const c = iv.def.calcNames
44
+ if (!c || !s || typeof s != 'object' || Array.isArray(s)) return s
45
+ const out = {...s}
46
+ c.forEach((k: string) => { delete out[k] })
47
+ return out
48
+ },
49
+ }
50
+ facades.set(iv, f)
51
+ return f
52
+ }
53
+
54
+ /** the hook layer of the DevTools bridge `dt` for one app */
55
+ export function devtoolsHooks(dt: any, api: any): any {
56
+ const mounted = new WeakSet<object>()
57
+ return {
58
+ onCreate(iv: any) {
59
+ const f = devFacade(iv, api)
60
+ dt.onComponentCreated(iv.id, iv.name, f)
61
+ if (iv.parentId !== undefined) dt.onSubComponentRegistered(iv.parentId, iv.id)
62
+ // a Collection's first item (today's onCollectionMounted)
63
+ if (iv.kind == 'item' && iv.parentId !== undefined) {
64
+ const p = api.get(iv.parentId)
65
+ if (p && !mounted.has(p)) { mounted.add(p); dt.onCollectionMounted(p.id, p.name, iv.name, null) }
66
+ }
67
+ },
68
+ onStateChanged(iv: any, s: any) { dt.connected && dt.onStateChanged(iv.id, iv.name, s) },
69
+ onPropsChanged(iv: any, p: any) { dt.connected && dt.onPropsChanged(iv.id, iv.name, p) },
70
+ onContextChanged(iv: any, c: any) { dt.connected && dt.onContextChanged(iv.id, iv.name, c) },
71
+ onAction(iv: any, a: any) { dt.connected && dt.onActionDispatched(iv.id, iv.name, a.type, a.data) },
72
+ onReady(p: any, c: any, ready: boolean) { dt.connected && dt.onReadyChanged(p.id, p.name, c.name, ready) },
73
+ onDispose(iv: any) { dt.onComponentDisposed(iv.id, iv.name) },
74
+ }
75
+ }
76
+
77
+ /** register a hook layer factory with the core (read by each app at its start) */
78
+ export function addLayer(f: (api: any) => any): () => void {
79
+ const core = (globalThis as any).__SYGNAL_DIAGNOSTICS__
80
+ if (!core) return () => {}
81
+ ;(core.layers ||= new Set()).add(f)
82
+ return () => { core.layers?.delete(f) }
83
+ }
@@ -0,0 +1,108 @@
1
+ /**
2
+ * PLAN-4 2-C (GS-10): the action log. Records every action a component instance runs as
3
+ * { type, data, component, instance, sinks, cause, time }
4
+ * for renderComponent's t.actions / t.explain() (src/extra/testing.ts), inspect({ actions }) in
5
+ * the 'sygnal/diagnostics' dev entry (./inspect.ts) and the DevTools action log
6
+ * (src/extra/devtoolsActions.ts).
7
+ *
8
+ * 0 B in apps: nothing in the core calls this. actionHooks() is a hook layer of the core
9
+ * (04-hooks-contract §3.3): onAction opens the record (the core passes the cause: 'intent',
10
+ * 'next', 'reply', 'built-in', 'simulateAction'; an intent action a behavior owns is
11
+ * 'behavior'), wrapHandler sees which sinks produced a value. (The old core's version patched
12
+ * each instance; R5 removed it.)
13
+ *
14
+ * Sinks: a function reducer counts when it returns a value: not ABORT (or another symbol, which
15
+ * the core drops), and for STATE not the state it was given (GS-4: no change); EFFECT counts when
16
+ * the handler ran without ABORT. A constant / `true` entry always sends. A throwing reducer
17
+ * sends nothing.
18
+ */
19
+ import {isAbort, ORIGINAL} from '../../../shared'
20
+
21
+ export type ActionCause = 'intent' | 'next' | 'reply' | 'built-in' | 'simulateAction' | 'behavior'
22
+
23
+ export interface ActionRecord {
24
+ type: string
25
+ data: any
26
+ /** the component's name */
27
+ component: string
28
+ /** the instance's id (its component number, as inspect()'s component ids) */
29
+ instance: string
30
+ /** sinks that produced a value for this action (live: STATE fills in when the reducer runs) */
31
+ sinks: string[]
32
+ cause: ActionCause
33
+ /** clock time (fake-timer aware) when the action reached the model */
34
+ time: number
35
+ /** a reply: the source that delivered it */
36
+ source?: string
37
+ }
38
+
39
+ export interface ActionListener {
40
+ action(record: ActionRecord, component: any): void
41
+ /** a sink produced a value for `record` (reducer: the model's function, when there is one) */
42
+ sink?(record: ActionRecord, sink: string, reducer: any): void
43
+ }
44
+
45
+ const BUILT_IN = /^(BOOTSTRAP|INITIALIZE|DISPOSE|RESOURCE)$/
46
+
47
+ /** now on the test's fake clock when there is one (vi.useFakeTimers()), else Date.now() */
48
+ export const clockNow = (): number => {
49
+ const c = (setTimeout as any).clock
50
+ return c ? c.now : Date.now()
51
+ }
52
+
53
+ /**
54
+ * PLAN-4.6 R4: the same log on the core, from its hooks (04 §3.3) instead of instance
55
+ * patches: onAction opens the record (the core passes the cause: 'intent', 'next', 'reply',
56
+ * 'built-in', 'simulateAction'), wrapHandler sees which sinks produced a value. Same records,
57
+ * same cause rules: a built-in type is 'built-in' unless simulated; an intent action a behavior
58
+ * owns is 'behavior'. `only(inst)`: the instances to record (renderComponent: its own tree).
59
+ */
60
+ export function actionHooks(listener: ActionListener, only?: (inst: any) => boolean): any {
61
+ const cur = new WeakMap<object, [ActionRecord, string[]]>()
62
+ // INITIALIZE: the core writes the initial state at creation (no action, unless the model
63
+ // has an INITIALIZE entry); today's log has an INITIALIZE record with STATE, so it is opened here
64
+ const init = new WeakMap<object, ActionRecord>()
65
+ return {
66
+ onCreate(inst: any) {
67
+ const d = inst.def
68
+ if ((only && !only(inst)) || d.initialState === undefined || !(inst.isRoot || d.isolated)) return
69
+ const rec: ActionRecord = {type: 'INITIALIZE', data: d.initialState, component: inst.name, instance: String(inst.id), sinks: [], cause: 'built-in', time: clockNow()}
70
+ init.set(inst, rec)
71
+ try { listener.action(rec, inst) } catch (_) { /* ignore */ }
72
+ addSink(listener, rec, ['STATE'], 'STATE', undefined)
73
+ },
74
+ onAction(inst: any, a: any) {
75
+ if (only && !only(inst)) return
76
+ const type = String(a.type), owned = inst.def.behaviorActions
77
+ const hs = inst.def.handlers.get(type) || [], order = hs.map((h: any) => h[0])
78
+ const opened = type == 'INITIALIZE' && init.get(inst)
79
+ if (opened) { init.delete(inst); cur.set(inst, [opened, order]); return }
80
+ const cause: ActionCause = a.cause == 'simulateAction' ? a.cause : BUILT_IN.test(type) ? 'built-in'
81
+ : a.cause == 'next' || a.cause == 'reply' ? a.cause
82
+ : owned && Object.prototype.hasOwnProperty.call(owned, type) ? 'behavior' : 'intent'
83
+ const rec: ActionRecord = {type, data: a.data, component: inst.name, instance: String(inst.id), sinks: [], cause, time: clockNow(), ...(a.source !== undefined && {source: a.source})}
84
+ cur.set(inst, [rec, order])
85
+ try { listener.action(rec, inst) } catch (_) { /* a listener never breaks the app */ }
86
+ // a constant / `true` entry always sends (EFFECT runs functions only)
87
+ for (const [sink, h] of hs) if (typeof h != 'function' && sink != 'EFFECT') addSink(listener, rec, order, sink, undefined)
88
+ },
89
+ wrapHandler(inst: any, type: string, sink: string, fn: any) {
90
+ const c = cur.get(inst)
91
+ if (!c || c[0].type !== type || typeof fn != 'function') return
92
+ const [rec, order] = c, isState = sink == 'STATE', isEffect = sink == 'EFFECT'
93
+ return function (this: any, state: any) {
94
+ const r = fn.apply(this, arguments)
95
+ if (!isAbort(r) && (isEffect || typeof r != 'symbol') && !(isState && r === state)) addSink(listener, rec, order, sink, fn[ORIGINAL] || fn)
96
+ return r
97
+ }
98
+ },
99
+ }
100
+ }
101
+
102
+ function addSink(l: ActionListener, rec: ActionRecord, order: string[], sink: string, reducer: any): void {
103
+ if (!rec.sinks.includes(sink)) {
104
+ rec.sinks.push(sink)
105
+ rec.sinks.sort((a, b) => order.indexOf(a) - order.indexOf(b))
106
+ }
107
+ try { l.sink?.(rec, sink, reducer) } catch (_) { /* ignore */ }
108
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * PLAN-4 GS-1, runtime behavior checks (dev entry only; the static `uses` resolution is 3-D's).
3
+ *
4
+ * SYG127 (error), once per component name (not per Collection item; again in each renderComponent):
5
+ * - a `uses` key that the host's own `initialState` static already has (the behavior's slice
6
+ * replaces it);
7
+ * - a `uses` value that isn't a defineBehavior() result (no `merge`): the core skips it, so
8
+ * state[key] and its actions never exist.
9
+ * A host intent or model entry named like a behavior action ('pager.NEXT') is an override,
10
+ * not a collision.
11
+ * Mechanism: onModel (every instance gets one, with or without a model) reads the static
12
+ * `view.uses` and `view.initialState`.
13
+ */
14
+ import type {DiagnosticCheck} from '../index'
15
+ import {devReport, nameOf, once} from './shared'
16
+
17
+ const what = (v: any): string =>
18
+ v === null || v === undefined ? String(v)
19
+ : typeof v == 'function' ? 'a function (a defineBehavior factory not called?)'
20
+ : typeof v == 'object' ? 'a plain object'
21
+ : `a ${typeof v}`
22
+
23
+ export const behaviorsCheck: DiagnosticCheck = {
24
+ id: 'behaviors',
25
+
26
+ onModel(component) {
27
+ const view = component?.view, uses = view?.uses
28
+ if (!uses || typeof uses != 'object' || !once('SYG127:' + nameOf(component))) return
29
+ const init = view.initialState
30
+ for (const key of Object.keys(uses)) {
31
+ const b = uses[key]
32
+ if (typeof b?.merge != 'function') {
33
+ devReport('SYG127', {
34
+ component,
35
+ message: `uses entry '${key}' is ${what(b)}, not a defineBehavior() result; it was skipped, so state.${key} and its '${key}.*' actions don't exist`,
36
+ fix: `Use a defineBehavior() factory's result: uses = { ${key}: behavior(options) }`,
37
+ data: {key, reason: 'unresolvable'},
38
+ })
39
+ } else if (init && typeof init == 'object' && key in init) {
40
+ devReport('SYG127', {
41
+ component,
42
+ message: `uses key '${key}' is also a key of ${nameOf(component)}'s initialState; the behavior's slice replaces that value`,
43
+ fix: `Remove '${key}' from initialState (pass its values as the behavior's options), or rename the uses key`,
44
+ data: {key, reason: 'initialState'},
45
+ })
46
+ }
47
+ }
48
+ },
49
+ }