sygnal 5.4.0 → 6.1.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 (360) hide show
  1. package/CHANGELOG.md +716 -0
  2. package/README.md +24 -9
  3. package/dist/ai.cjs.js +115 -0
  4. package/dist/ai.cjs.js.map +1 -0
  5. package/dist/ai.esm.js +2 -0
  6. package/dist/ai.esm.js.map +1 -0
  7. package/dist/astro/client.cjs.js +16 -9
  8. package/dist/astro/client.cjs.js.map +1 -1
  9. package/dist/astro/client.mjs +16 -9
  10. package/dist/astro/client.mjs.map +1 -1
  11. package/dist/astro/index.cjs.js +958 -92
  12. package/dist/astro/index.cjs.js.map +1 -1
  13. package/dist/astro/index.mjs +958 -93
  14. package/dist/astro/index.mjs.map +1 -1
  15. package/dist/astro/server.cjs.js +3396 -165
  16. package/dist/astro/server.cjs.js.map +1 -1
  17. package/dist/astro/server.mjs +3396 -165
  18. package/dist/astro/server.mjs.map +1 -1
  19. package/dist/devtools.cjs.js +1840 -0
  20. package/dist/devtools.cjs.js.map +1 -0
  21. package/dist/devtools.esm.js +1827 -0
  22. package/dist/devtools.esm.js.map +1 -0
  23. package/dist/diagnostics.cjs.js +3190 -296
  24. package/dist/diagnostics.cjs.js.map +1 -1
  25. package/dist/diagnostics.esm.js +3190 -296
  26. package/dist/diagnostics.esm.js.map +1 -1
  27. package/dist/element.cjs.js +230 -0
  28. package/dist/element.cjs.js.map +1 -0
  29. package/dist/element.esm.js +228 -0
  30. package/dist/element.esm.js.map +1 -0
  31. package/dist/guide/accessibility.md +310 -0
  32. package/dist/guide/adapters.md +221 -0
  33. package/dist/guide/agent.md +588 -0
  34. package/dist/guide/ai-chat.md +693 -0
  35. package/dist/guide/ai-decisions.md +330 -0
  36. package/dist/guide/behaviors.md +312 -0
  37. package/dist/guide/browser-sources.md +203 -0
  38. package/dist/guide/drag-and-drop.md +342 -0
  39. package/dist/guide/element-commands.md +306 -0
  40. package/dist/guide/error-boundaries.md +169 -0
  41. package/dist/guide/forms-reference.md +409 -0
  42. package/dist/guide/forms.md +251 -0
  43. package/dist/guide/http.md +301 -0
  44. package/dist/guide/inputs.md +173 -0
  45. package/dist/guide/mcp-apps.md +272 -0
  46. package/dist/guide/persistence.md +245 -0
  47. package/dist/guide/recipes/ai-form-fill.md +163 -0
  48. package/dist/guide/recipes/ai-summarize.md +155 -0
  49. package/dist/guide/recipes/ai-support-inbox.md +190 -0
  50. package/dist/guide/recipes/carousel.md +155 -0
  51. package/dist/guide/recipes/charts.md +177 -0
  52. package/dist/guide/recipes/code-editor.md +135 -0
  53. package/dist/guide/recipes/data-grid.md +155 -0
  54. package/dist/guide/recipes/data-table.md +196 -0
  55. package/dist/guide/recipes/i18n.md +222 -0
  56. package/dist/guide/recipes/icons.md +115 -0
  57. package/dist/guide/recipes/overview.md +43 -0
  58. package/dist/guide/recipes/rich-text.md +154 -0
  59. package/dist/guide/resources.md +471 -0
  60. package/dist/guide/ssr.md +255 -0
  61. package/dist/guide/timers.md +178 -0
  62. package/dist/guide/ui/accordion.md +93 -0
  63. package/dist/guide/ui/combobox.md +144 -0
  64. package/dist/guide/ui/dialog.md +124 -0
  65. package/dist/guide/ui/disclosure.md +60 -0
  66. package/dist/guide/ui/menu.md +125 -0
  67. package/dist/guide/ui/overview.md +166 -0
  68. package/dist/guide/ui/popover.md +101 -0
  69. package/dist/guide/ui/select.md +114 -0
  70. package/dist/guide/ui/tabs.md +161 -0
  71. package/dist/guide/ui/toaster.md +152 -0
  72. package/dist/guide/ui/tooltip.md +103 -0
  73. package/dist/guide/undo.md +178 -0
  74. package/dist/guide/virtual-collections.md +183 -0
  75. package/dist/guide/web-components.md +179 -0
  76. package/dist/guide/webmcp.md +226 -0
  77. package/dist/guide/widgets.md +217 -0
  78. package/dist/index.cjs.js +19288 -7408
  79. package/dist/index.cjs.js.map +1 -1
  80. package/dist/index.d.ts +4466 -552
  81. package/dist/index.esm.js +19274 -7461
  82. package/dist/index.esm.js.map +1 -1
  83. package/dist/jsx-dev-runtime.cjs.js +26 -334
  84. package/dist/jsx-dev-runtime.cjs.js.map +1 -1
  85. package/dist/jsx-dev-runtime.esm.js +19 -327
  86. package/dist/jsx-dev-runtime.esm.js.map +1 -1
  87. package/dist/jsx-runtime.cjs.js +26 -334
  88. package/dist/jsx-runtime.cjs.js.map +1 -1
  89. package/dist/jsx-runtime.esm.js +19 -327
  90. package/dist/jsx-runtime.esm.js.map +1 -1
  91. package/dist/jsx.cjs.js +10 -314
  92. package/dist/jsx.cjs.js.map +1 -1
  93. package/dist/jsx.esm.js +8 -315
  94. package/dist/jsx.esm.js.map +1 -1
  95. package/dist/react.cjs.js +117 -0
  96. package/dist/react.cjs.js.map +1 -0
  97. package/dist/react.esm.js +115 -0
  98. package/dist/react.esm.js.map +1 -0
  99. package/dist/shims/globalthis.cjs +20 -0
  100. package/dist/sygnal.min.js +1 -1
  101. package/dist/sygnal.min.js.map +1 -1
  102. package/dist/ui-combobox.cjs.js +169 -0
  103. package/dist/ui-combobox.cjs.js.map +1 -0
  104. package/dist/ui-combobox.esm.js +148 -0
  105. package/dist/ui-combobox.esm.js.map +1 -0
  106. package/dist/ui-menu.cjs.js +87 -0
  107. package/dist/ui-menu.cjs.js.map +1 -0
  108. package/dist/ui-menu.esm.js +66 -0
  109. package/dist/ui-menu.esm.js.map +1 -0
  110. package/dist/ui-select.cjs.js +104 -0
  111. package/dist/ui-select.cjs.js.map +1 -0
  112. package/dist/ui-select.esm.js +83 -0
  113. package/dist/ui-select.esm.js.map +1 -0
  114. package/dist/ui.cjs.js +738 -0
  115. package/dist/ui.cjs.js.map +1 -0
  116. package/dist/ui.esm.js +727 -0
  117. package/dist/ui.esm.js.map +1 -0
  118. package/dist/vike/ClientOnly.cjs.js +4 -14
  119. package/dist/vike/ClientOnly.cjs.js.map +1 -1
  120. package/dist/vike/ClientOnly.mjs +4 -14
  121. package/dist/vike/ClientOnly.mjs.map +1 -1
  122. package/dist/vike/{+config.js → config/+config.js} +9 -1
  123. package/dist/vike/config/+config.js.map +1 -0
  124. package/dist/vike/config/package.json +6 -0
  125. package/dist/vike/onRenderClient.cjs.js +165 -95
  126. package/dist/vike/onRenderClient.cjs.js.map +1 -1
  127. package/dist/vike/onRenderClient.mjs +165 -95
  128. package/dist/vike/onRenderClient.mjs.map +1 -1
  129. package/dist/vike/onRenderHtml.cjs.js +59 -24
  130. package/dist/vike/onRenderHtml.cjs.js.map +1 -1
  131. package/dist/vike/onRenderHtml.mjs +60 -25
  132. package/dist/vike/onRenderHtml.mjs.map +1 -1
  133. package/dist/vite/plugin.cjs.js +919 -89
  134. package/dist/vite/plugin.cjs.js.map +1 -1
  135. package/dist/vite/plugin.mjs +919 -90
  136. package/dist/vite/plugin.mjs.map +1 -1
  137. package/dist/zag.cjs.js +408 -0
  138. package/dist/zag.cjs.js.map +1 -0
  139. package/dist/zag.esm.js +405 -0
  140. package/dist/zag.esm.js.map +1 -0
  141. package/llms.txt +172 -103
  142. package/package.json +112 -14
  143. package/src/ai.d.ts +1186 -0
  144. package/src/ai.ts +23 -0
  145. package/src/astro/client.ts +27 -16
  146. package/src/astro/index.d.ts +24 -0
  147. package/src/astro/index.ts +69 -3
  148. package/src/astro/server.ts +8 -2
  149. package/src/collection.ts +6 -93
  150. package/src/core/actions.ts +134 -0
  151. package/src/core/cell.ts +202 -0
  152. package/src/core/debug.ts +23 -0
  153. package/src/core/define.ts +242 -0
  154. package/src/core/hooks.ts +314 -0
  155. package/src/core/hosts/collection.ts +325 -0
  156. package/src/core/hosts/switchable.ts +146 -0
  157. package/src/core/instance.ts +592 -0
  158. package/src/core/markers/clientonly.ts +13 -0
  159. package/src/core/markers/lazy.ts +40 -0
  160. package/src/core/markers/portal.ts +96 -0
  161. package/src/core/markers/suspense.ts +41 -0
  162. package/src/core/markers/transition.ts +70 -0
  163. package/src/core/registry.ts +25 -0
  164. package/src/core/runtime.ts +573 -0
  165. package/src/core/statics.ts +104 -0
  166. package/src/core/teardown.ts +60 -0
  167. package/src/core/view.ts +37 -0
  168. package/src/cycle/dom/DocumentDOMSource.ts +13 -8
  169. package/src/cycle/dom/ElementFinder.ts +7 -9
  170. package/src/cycle/dom/EventDelegator.ts +174 -223
  171. package/src/cycle/dom/IsolateModule.ts +65 -35
  172. package/src/cycle/dom/MainDOMSource.ts +9 -2
  173. package/src/cycle/dom/PriorityQueue.ts +4 -2
  174. package/src/cycle/dom/SymbolTree.ts +18 -47
  175. package/src/cycle/dom/classNameModule.ts +9 -7
  176. package/src/cycle/dom/controlledInputModule.ts +23 -6
  177. package/src/cycle/dom/enrichEventStream.ts +25 -47
  178. package/src/cycle/dom/fragment.ts +7 -0
  179. package/src/cycle/dom/isolate.ts +30 -27
  180. package/src/cycle/dom/makeDOMDriver.ts +115 -56
  181. package/src/cycle/dom/mockDOMSource.ts +21 -1
  182. package/src/cycle/dom/modules.ts +16 -3
  183. package/src/cycle/dom/propsModule.ts +65 -0
  184. package/src/cycle/dom/selectModule.ts +22 -17
  185. package/src/cycle/dom/snabbdom.ts +1 -6
  186. package/src/cycle/dom/thunk.ts +3 -0
  187. package/src/cycle/dom/utils.ts +98 -0
  188. package/src/cycle/dom/viewTransition.ts +43 -0
  189. package/src/cycle/state/StateSource.ts +19 -3
  190. package/src/cycle/state/objIsEqual.ts +50 -0
  191. package/src/cycle/state/types.ts +0 -10
  192. package/src/defineComponent.ts +34 -0
  193. package/src/devtools.d.ts +170 -0
  194. package/src/devtools.ts +37 -0
  195. package/src/element.d.ts +59 -0
  196. package/src/element.ts +235 -0
  197. package/src/extra/ai/agent/index.ts +484 -0
  198. package/src/extra/ai/answers.ts +115 -0
  199. package/src/extra/ai/chat/behavior.ts +336 -0
  200. package/src/extra/ai/chat/driver.ts +271 -0
  201. package/src/extra/ai/chat/memoryTransport.ts +61 -0
  202. package/src/extra/ai/chat/output.ts +37 -0
  203. package/src/extra/ai/commandBar.ts +281 -0
  204. package/src/extra/ai/decide.ts +104 -0
  205. package/src/extra/ai/index.ts +42 -0
  206. package/src/extra/ai/link.ts +90 -0
  207. package/src/extra/ai/mcpApp.ts +314 -0
  208. package/src/extra/ai/messages.ts +51 -0
  209. package/src/extra/ai/schema/index.ts +166 -0
  210. package/src/extra/ai/schema/jsonSchema.ts +72 -0
  211. package/src/extra/ai/schema/strict.ts +152 -0
  212. package/src/extra/ai/transports/agui.ts +177 -0
  213. package/src/extra/ai/transports/anthropicMessages.ts +175 -0
  214. package/src/extra/ai/transports/chatCompletions.ts +105 -0
  215. package/src/extra/ai/transports/chromePrompt.ts +77 -0
  216. package/src/extra/ai/transports/encodeOpenResponses.ts +87 -0
  217. package/src/extra/ai/transports/fromAISDK.ts +126 -0
  218. package/src/extra/ai/transports/openResponses.ts +105 -0
  219. package/src/extra/ai/transports/shared.ts +125 -0
  220. package/src/extra/ai/transports/tools.ts +59 -0
  221. package/src/extra/ai/transports/uiMessageStream.ts +107 -0
  222. package/src/extra/ai/webmcp.ts +260 -0
  223. package/src/extra/backoff.ts +9 -0
  224. package/src/extra/behaviors.ts +169 -0
  225. package/src/extra/browserSignals.ts +23 -0
  226. package/src/extra/browserSources.ts +326 -0
  227. package/src/extra/command.ts +3 -3
  228. package/src/extra/controls.ts +47 -0
  229. package/src/extra/copyAsTest.ts +286 -0
  230. package/src/extra/devMcp.ts +386 -0
  231. package/src/extra/devtools.ts +101 -31
  232. package/src/extra/devtoolsActions.ts +379 -0
  233. package/src/extra/devtoolsHook.ts +9 -0
  234. package/src/extra/devtoolsNext.ts +83 -0
  235. package/src/extra/diagnostics/checks/actionLog.ts +108 -0
  236. package/src/extra/diagnostics/checks/behaviors.ts +49 -0
  237. package/src/extra/diagnostics/checks/browserSources.ts +96 -0
  238. package/src/extra/diagnostics/checks/chat.ts +71 -0
  239. package/src/extra/diagnostics/checks/collections.ts +1 -1
  240. package/src/extra/diagnostics/checks/controls.ts +148 -0
  241. package/src/extra/diagnostics/checks/dataset.ts +57 -0
  242. package/src/extra/diagnostics/checks/dom.ts +20 -11
  243. package/src/extra/diagnostics/checks/elementCommands.ts +175 -0
  244. package/src/extra/diagnostics/checks/events.ts +17 -2
  245. package/src/extra/diagnostics/checks/fetch.ts +135 -0
  246. package/src/extra/diagnostics/checks/forms.ts +171 -0
  247. package/src/extra/diagnostics/checks/index.ts +103 -4
  248. package/src/extra/diagnostics/checks/inspect.ts +140 -32
  249. package/src/extra/diagnostics/checks/next.ts +417 -0
  250. package/src/extra/diagnostics/checks/persist.ts +54 -0
  251. package/src/extra/diagnostics/checks/props.ts +10 -5
  252. package/src/extra/diagnostics/checks/public.d.ts +115 -7
  253. package/src/extra/diagnostics/checks/replies.ts +128 -0
  254. package/src/extra/diagnostics/checks/router.ts +100 -0
  255. package/src/extra/diagnostics/checks/rxjsHints.ts +1 -1
  256. package/src/extra/diagnostics/checks/shared.ts +86 -2
  257. package/src/extra/diagnostics/checks/shorthand.ts +115 -0
  258. package/src/extra/diagnostics/checks/sortable.ts +129 -0
  259. package/src/extra/diagnostics/checks/state.ts +100 -7
  260. package/src/extra/diagnostics/checks/statics.ts +48 -0
  261. package/src/extra/diagnostics/checks/strict.ts +10 -67
  262. package/src/extra/diagnostics/checks/timers.ts +80 -0
  263. package/src/extra/diagnostics/checks/viewTransitions.ts +47 -0
  264. package/src/extra/diagnostics/checks/virtual.ts +73 -0
  265. package/src/extra/diagnostics/checks/widgets.ts +109 -0
  266. package/src/extra/diagnostics/checks/wiring.ts +69 -10
  267. package/src/extra/diagnostics/codes.ts +335 -23
  268. package/src/extra/diagnostics/index.ts +34 -9
  269. package/src/extra/diagnostics/legacy.ts +17 -0
  270. package/src/extra/driverFactories.ts +83 -19
  271. package/src/extra/elementCommands.ts +53 -0
  272. package/src/extra/fetchDriver.ts +519 -0
  273. package/src/extra/focusWithin.ts +27 -0
  274. package/src/extra/form.ts +284 -0
  275. package/src/extra/formHelpers.ts +139 -0
  276. package/src/extra/formTool.ts +150 -0
  277. package/src/extra/head.ts +106 -0
  278. package/src/extra/hmr.ts +2 -3
  279. package/src/extra/owned.ts +24 -0
  280. package/src/extra/pager.ts +50 -0
  281. package/src/extra/persist.ts +133 -0
  282. package/src/extra/pwa.ts +1 -1
  283. package/src/extra/queryCache.ts +107 -0
  284. package/src/extra/reducers.ts +1 -1
  285. package/src/extra/reduxDevtools.ts +92 -0
  286. package/src/extra/replies.ts +54 -0
  287. package/src/extra/router.ts +323 -0
  288. package/src/extra/run.ts +90 -217
  289. package/src/extra/selection.ts +76 -0
  290. package/src/extra/socketDriver.ts +265 -0
  291. package/src/extra/sortable.ts +377 -0
  292. package/src/extra/ssr.ts +427 -160
  293. package/src/extra/standardSchema.ts +27 -0
  294. package/src/extra/testing.ts +2550 -175
  295. package/src/extra/timers.ts +95 -0
  296. package/src/extra/undo.ts +261 -0
  297. package/src/extra/viewTransitions.ts +38 -0
  298. package/src/extra/virtual.ts +513 -0
  299. package/src/extra/widget.ts +201 -0
  300. package/src/index.d.ts +2754 -127
  301. package/src/index.ts +45 -4
  302. package/src/jsx-runtime.ts +15 -1
  303. package/src/jsx.ts +2 -1
  304. package/src/lazy.ts +50 -7
  305. package/src/portal.ts +3 -1
  306. package/src/pragma/index.ts +256 -133
  307. package/src/react-peers.d.ts +5 -0
  308. package/src/react.d.ts +43 -0
  309. package/src/react.ts +110 -0
  310. package/src/shared.ts +57 -0
  311. package/src/slot.ts +1 -1
  312. package/src/suspense.ts +3 -1
  313. package/src/switchable.ts +6 -121
  314. package/src/transition.ts +3 -1
  315. package/src/ui/accordion.ts +64 -0
  316. package/src/ui/dialog.ts +129 -0
  317. package/src/ui/disclosure.ts +35 -0
  318. package/src/ui/popover.ts +45 -0
  319. package/src/ui/shared.ts +94 -0
  320. package/src/ui/tabs.ts +82 -0
  321. package/src/ui/toaster.ts +198 -0
  322. package/src/ui/tooltip.ts +70 -0
  323. package/src/ui/zag/combobox.ts +115 -0
  324. package/src/ui/zag/menu.ts +40 -0
  325. package/src/ui/zag/select.ts +54 -0
  326. package/src/ui/zag/shared.ts +43 -0
  327. package/src/ui-combobox.d.ts +20 -0
  328. package/src/ui-combobox.ts +6 -0
  329. package/src/ui-menu.d.ts +30 -0
  330. package/src/ui-menu.ts +6 -0
  331. package/src/ui-select.d.ts +17 -0
  332. package/src/ui-select.ts +6 -0
  333. package/src/ui-zag-types.d.ts +42 -0
  334. package/src/ui.d.ts +208 -0
  335. package/src/ui.ts +15 -0
  336. package/src/vike/+config.ts +9 -1
  337. package/src/vike/ClientOnly.ts +1 -1
  338. package/src/vike/onRenderClient.ts +144 -96
  339. package/src/vike/onRenderHtml.ts +69 -26
  340. package/src/vike/types.ts +7 -1
  341. package/src/vite/globalthis-shim.ts +18 -0
  342. package/src/vite/globalthis.ts +56 -0
  343. package/src/vite/mcp.ts +568 -0
  344. package/src/vite/plugin.d.ts +47 -3
  345. package/src/vite/plugin.ts +262 -25
  346. package/src/zag.d.ts +64 -0
  347. package/src/zag.ts +238 -0
  348. package/dist/vike/+config.cjs.js +0 -66
  349. package/dist/vike/+config.cjs.js.map +0 -1
  350. package/dist/vike/+config.js.map +0 -1
  351. package/src/component.ts +0 -2301
  352. package/src/cycle/isolate/index.ts +0 -196
  353. package/src/cycle/run/index.ts +0 -151
  354. package/src/cycle/run/internals.ts +0 -143
  355. package/src/cycle/state/Collection.ts +0 -184
  356. package/src/cycle/state/index.ts +0 -5
  357. package/src/cycle/state/pickCombine.ts +0 -201
  358. package/src/cycle/state/pickMerge.ts +0 -122
  359. package/src/cycle/state/withState.ts +0 -47
  360. package/src/pragma/fn.ts +0 -55
@@ -17,15 +17,59 @@
17
17
  * | SYG104 | intent selector only matches inside a child component | dom.ts |
18
18
  * | SYG105 | EVENTS type emitted-not-selected / selected-not-emitted| events.ts |
19
19
  * | SYG106 | parent prop overwritten by a reserved view argument | props.ts |
20
+ * | SYG112 | reply action has no model entry | replies.ts |
21
+ * | SYG630 | cached request that isn't idempotent (POST + cache) | fetch.ts |
22
+ * | SYG631 | validate is not a Standard Schema | fetch.ts |
23
+ * | SYG632 | invalidate matched nothing (info) | fetch.ts |
24
+ * | SYG633 | abort names a lane its requests don't use | fetch.ts |
25
+ * | SYG635 | cache: true / staleTime / prefetch without queryCache() | fetch.ts |
26
+ * | SYG115 | unknown DOM event shorthand (DOM.key(...)) | shorthand.ts |
27
+ * | SYG124 | component where a control or selector is expected | controls.ts |
28
+ * | SYG140 | widget emitted an event it doesn't declare | widgets.ts |
29
+ * | SYG142 | widget command not declared (also a reserved name) | elementCommands.ts, widgets.ts |
30
+ * | SYG143 | widget tag used as a selector | widgets.ts |
31
+ * | SYG144 | declared widget event the host also fires (info) | widgets.ts |
32
+ * | SYG660 | widget mount / update / unmount threw (660/661/662) | widgets.ts |
33
+ * | SYG430 | VirtualCollection: no bounded height; SYG431 items without ids; SYG432 item not one element; SYG433 scroll target not in the list; SYG434 bad estimateSize / overscan | virtual.ts |
34
+ * | SYG125 | control given component statics / bad spec vnode() | controls.ts |
35
+ * | SYG127 | behavior key in initialState / unresolvable uses entry | behaviors.ts |
36
+ * | SYG230 | form: field name not in values; SYG231 not a Standard Schema; SYG232 submit dropped (info); SYG233 value missing from the schema output | forms.ts |
37
+ * | SYG234 | form submit action has no model entry; SYG235 check names an unknown field / sets reply fields; SYG236 rows without an id | forms.ts |
38
+ * | SYG145 | sortable: item without its id attribute; SYG146 item / handle selector matches nothing; SYG147 from is not an array | sortable.ts |
39
+ * | SYG116 | EVENTS value with no string type (a function) | events.ts |
40
+ * | SYG130 | href() names no route / leaves out a param | router.ts |
41
+ * | SYG131 | route params the pattern doesn't use | router.ts |
42
+ * | SYG132 | declaration static never sent: a root without initialState | router.ts |
43
+ * | SYG133 | SPA router inside a Vike app | router.ts |
44
+ * | SYG422 | timer spec makeTimerDriver() can't run | timers.ts |
45
+ * | SYG643 | timers/connections/resources/browser with no driver | timers.ts |
46
+ * | SYG663 | browser entry / BROWSER command that can't run | browserSources.ts |
47
+ * | SYG664 | browser source the driver wasn't made with | browserSources.ts |
48
+ * | SYG665 | browser source failed with no error action | browserSources.ts |
49
+ * | SYG668 | intersection / resize with no element to observe | browserSources.ts |
50
+ * | SYG673 | malformed chat stream event (makeChatDriver) | chat.ts |
51
+ * | SYG675 | tool sent non-strict under strict (L-2 transports, info)| chat.ts |
52
+ * | SYG677 | chat request sent from outside a component | chat.ts |
53
+ * | SYG238 | a root with a model but no initialState: renders nothing | state.ts |
54
+ * | SYG223 | persist pick/omit key not in initialState | persist.ts |
55
+ * | SYG224 | persist on a component that isn't the root | persist.ts |
56
+ * | SYG645 | viewTransitions without makeViewTransitionDOMDriver(), or not an array | viewTransitions.ts |
20
57
  * | SYG201 | STATE reducer dropped keys | state.ts |
21
58
  * | SYG202 | STATE reducer returned undefined | state.ts |
59
+ * | SYG221 | set() called with a string | state.ts |
60
+ * | SYG222 | same object returned after an in-place mutation | state.ts |
22
61
  * | SYG301 | RxJS operator used on an xstream stream | rxjsHints.ts |
23
62
  * | SYG401 | Collection `from` missing or not an array | collections.ts |
24
- * | SYG501 | strict: view uses positional (props, state, ...) args | strict.ts |
25
- * | SYG502 | strict: STATE reducer returned the unchanged state | strict.ts |
26
- * | SYG504 | strict: 'ACTION | SINK' shorthand model key | strict.ts |
63
+ * | SYG421 | invalid data (dataset) key in a view | dataset.ts |
64
+ * | SYG612 | a form 6.0 removed (also SYG501/504 statically) | next.ts |
65
+ * | SYG502 | retired in 6.0 (never reported; GS-4) | — |
66
+ * | SYG508 | strict: select()/errors() round trip on a reply source | replies.ts |
67
+ * | — | D152: shared statics frozen (initialState deep) | statics.ts |
27
68
  * | — | inspect(): the runtime app graph (2B) | inspect.ts |
28
69
  *
70
+ * SYG112, SYG130-133 (PLAN-3), SYG115/116/221/421 (G-143) SYG124/125 (PLAN-4 CT-1) and SYG127 (GS-1) are dev-entry-only codes: their severities live in
71
+ * DEV_CODE_SEVERITY (codes.ts), registered by ./shared, not in the main bundle.
72
+ *
29
73
  * Strict checks (SYG5xx) only report after configureStrict(true) (or
30
74
  * renderComponent(C, { strict: true }), or globalThis.__SYGNAL_STRICT__).
31
75
  */
@@ -38,16 +82,35 @@ import {eventsCheck} from './events'
38
82
  import {propsCheck} from './props'
39
83
  import {collectionsCheck} from './collections'
40
84
  import {domCheck} from './dom'
85
+ import {shorthandCheck} from './shorthand'
86
+ import {controlsCheck, installControlHooks} from './controls'
87
+ import {elementCommandsCheck, installElementCommandHooks} from './elementCommands'
88
+ import {installWidgetHooks} from './widgets'
89
+ import {installVirtualHooks} from './virtual'
90
+ import {behaviorsCheck} from './behaviors'
91
+ import {formsCheck, installFormHooks} from './forms'
92
+ import {installSortableHooks} from './sortable'
93
+ import {datasetCheck} from './dataset'
41
94
  import {strictCheck} from './strict'
95
+ import {repliesCheck} from './replies'
96
+ import {routerCheck, installRouterHooks} from './router'
97
+ import {fetchCheck} from './fetch'
98
+ import {timersCheck, installTimerHooks} from './timers'
99
+ import {installBrowserSourceHooks} from './browserSources'
100
+ import {installChatHooks} from './chat'
101
+ import {persistCheck} from './persist'
102
+ import {viewTransitionsCheck} from './viewTransitions'
103
+ import {staticsCheck} from './statics'
42
104
  import {installRxjsHints} from './rxjsHints'
43
105
  import {inspectCheck, installInspect} from './inspect'
106
+ import {nextHooks} from './next'
44
107
 
45
108
  export {checkEventBus} from './events'
46
109
  export {configureStrict, isStrictEnabled} from './strict'
47
110
  export type {EventBusSummary} from './events'
48
111
  export {RXJS_HINTS} from './rxjsHints'
49
112
  export {inspect} from './inspect'
50
- export type {InspectGraph, InspectComponent, InspectAction, InspectActionTrigger, InspectChild, InspectSelector, InspectDiagnostic, InspectOptions} from './public'
113
+ export type {InspectResource, InspectCacheEntry, InspectGraph, InspectComponent, InspectAction, InspectActionTrigger, InspectChild, InspectSelector, InspectControl, InspectDiagnostic, InspectOptions, InspectRecentAction} from './public'
51
114
  export {listCodes, getCodeInfo} from '../codes'
52
115
  export type {DiagnosticCodeInfo} from '../codes'
53
116
 
@@ -59,7 +122,20 @@ export const checks: DiagnosticCheck[] = [
59
122
  propsCheck,
60
123
  collectionsCheck,
61
124
  domCheck,
125
+ shorthandCheck,
126
+ controlsCheck,
127
+ elementCommandsCheck,
128
+ behaviorsCheck,
129
+ formsCheck,
130
+ datasetCheck,
62
131
  strictCheck,
132
+ repliesCheck,
133
+ routerCheck,
134
+ fetchCheck,
135
+ timersCheck,
136
+ persistCheck,
137
+ viewTransitionsCheck,
138
+ staticsCheck,
63
139
  inspectCheck,
64
140
  ]
65
141
 
@@ -75,10 +151,33 @@ export function installChecks(): () => void {
75
151
  const unregister = checks.map(check => core.registerCheck(check))
76
152
  const uninstallHints = installRxjsHints(Stream && Stream.prototype)
77
153
  const uninstallInspect = installInspect()
154
+ const uninstallRouter = installRouterHooks()
155
+ const uninstallControls = installControlHooks()
156
+ const uninstallTimers = installTimerHooks()
157
+ const uninstallBrowser = installBrowserSourceHooks()
158
+ const uninstallChat = installChatHooks()
159
+ const uninstallElementCommands = installElementCommandHooks()
160
+ const uninstallWidgets = installWidgetHooks()
161
+ const uninstallVirtual = installVirtualHooks()
162
+ const uninstallForms = installFormHooks()
163
+ const uninstallSortable = installSortableHooks()
164
+ // PLAN-4.6 R4: the core reads its hooks from the bridge once per app (checks/next.ts)
165
+ ;(core.layers ||= new Set()).add(nextHooks)
78
166
  const uninstall = () => {
167
+ core.layers?.delete(nextHooks)
79
168
  unregister.forEach(fn => fn())
80
169
  uninstallHints()
81
170
  uninstallInspect()
171
+ uninstallRouter()
172
+ uninstallControls()
173
+ uninstallTimers()
174
+ uninstallBrowser()
175
+ uninstallChat()
176
+ uninstallElementCommands()
177
+ uninstallWidgets()
178
+ uninstallVirtual()
179
+ uninstallForms()
180
+ uninstallSortable()
82
181
  if (core.__uninstallChecks === uninstall) core.__uninstallChecks = undefined
83
182
  }
84
183
  core.__uninstallChecks = uninstall
@@ -6,16 +6,19 @@
6
6
  * onIntent registers the instance (name, parent, kind) and its intent
7
7
  * action names; claims the EVENTS.select() types seen since the
8
8
  * previous onIntent (intent runs synchronously right before it)
9
- * onModel action -> sinks; and wraps the component's own EVENTS model
10
- * stream (component.model$.EVENTS, before initSinks merges it)
11
- * in an identity map that records the emitted types. Since
12
- * B-023 the driver-side emitter name (onBusEmit) is the
13
- * emitting component's, but it is only a name, and this
14
- * graph is per instance, so the per-instance tap stays.
15
- * onReducer which model-only actions actually ran (=> dispatched by next())
9
+ * onModel action -> sinks
10
+ * onSink (checks/next.ts: eventEmitted) the EVENTS types the instance emitted. Since
11
+ * B-023 the driver-side emitter name (onBusEmit) is the emitting
12
+ * component's, but it is only a name, and this graph is per instance
13
+ * onReducer which model-only actions actually ran (=> dispatched by next(),
14
+ * unless a request named them as reply actions: replies.ts, 'reply')
16
15
  * onBusEmit EVENTS types seen on the bus
17
16
  * onBusSelect EVENTS types selected (see onIntent)
17
+ * onRender (PLAN-4 CT-1) the controls the instance renders: its own vtree, up to the
18
+ * isolated child components, through ./controls' vnode -> control map
18
19
  * onDispose prunes the instance
20
+ * (PLAN-4 2-C) the action log (./actionLog: actionHooks, a layer of checks/next.ts) feeds
21
+ * inspect({ actions }): the recent actions (the last RECENT_MAX, any instance)
19
22
  * Selectors come from the DOM check (real DOM) or from renderComponent (mock
20
23
  * DOM, passed in as options.selectors). The same shape is produced statically
21
24
  * by `sygnal-check --graph`; the JSON Schema is
@@ -27,10 +30,13 @@
27
30
  * (window.__SYGNAL_DEVTOOLS__, which is getDevTools()) once it exists.
28
31
  */
29
32
  import type {DiagnosticCheck} from '../index'
30
- import type {InspectGraph, InspectComponent, InspectOptions, InspectSelector, InspectDiagnostic, InspectChild} from './public'
31
- import {bridge, onReset, nameOf, isPlainObject, BUILTIN_ACTIONS} from './shared'
33
+ import type {InspectGraph, InspectComponent, InspectOptions, InspectSelector, InspectDiagnostic, InspectChild, InspectResource, InspectControl, InspectRecentAction} from './public'
34
+ import {clockNow} from './actionLog'
35
+ import type {ActionListener, ActionRecord} from './actionLog'
36
+ import {bridge, onReset, nameOf, isPlainObject, BUILTIN_ACTIONS, replySeen} from './shared'
32
37
  import {checkEventBus} from './events'
33
38
  import {selectorStatus} from './dom'
39
+ import {controlOfVnode, keyOfSelector} from './controls'
34
40
 
35
41
  type Kind = InspectComponent['kind']
36
42
 
@@ -47,34 +53,42 @@ interface Rec {
47
53
  fired: Set<string>
48
54
  eventsSelected: Set<string>
49
55
  eventsEmitted: Set<string>
56
+ /** CT-1: controls seen in its renders, by key (first-seen order) */
57
+ controls: Map<string, {element: string | null; kind?: string}>
50
58
  }
51
59
 
52
60
  let records = new Map<any, Rec>()
53
61
  let pendingSelects: string[] = []
54
62
  /** every EVENTS type seen on the bus */
55
63
  let busTypes = new Set<string>()
64
+ /** PLAN-4 2-C (GS-10): the most recent actions of any instance, oldest first */
65
+ const RECENT_MAX = 200
66
+ let recent: ActionRecord[] = []
67
+ let epoch = clockNow()
68
+ export const actionListener: ActionListener = {
69
+ action(r) { if (recent.push(r) > RECENT_MAX) recent.shift() },
70
+ }
56
71
 
57
72
  onReset(() => {
58
73
  records = new Map()
59
74
  pendingSelects = []
60
75
  busTypes = new Set()
76
+ recent = []
77
+ epoch = clockNow()
61
78
  })
62
79
  const uniq = <T>(list: Iterable<T>): T[] => [...new Set(list)]
63
80
 
81
+ const NEXT_KIND: Record<string, Kind> = {root: 'root', child: 'child', item: 'collection-item', page: 'switchable'}
82
+
64
83
  function kindOf(c: any): Kind {
65
- const s = (c && c.sources) || {}
66
- if (typeof s.__parentComponentNumber !== 'number') return 'root'
67
- // Collection items get PARENT: null (src/component.ts instantiateCollection)
68
- if ('PARENT' in s && s.PARENT === null) return 'collection-item'
69
- // switchable() adds a lower-case `state` source next to the component's own (src/switchable.ts)
70
- if (c.stateSourceName !== 'state' && 'state' in s && s.state !== s[c.stateSourceName]) return 'switchable'
71
- return 'child'
84
+ // PLAN-4.6 R4: the core's instance view says it (checks/next.ts)
85
+ return (c && c.__next && NEXT_KIND[c.__next.kind]) || 'child'
72
86
  }
73
87
 
74
88
  function ensure(c: any): Rec {
75
89
  let r = records.get(c)
76
90
  if (!r) {
77
- const parent = c && c.sources && c.sources.__parentComponentNumber
91
+ const parent = c && c.__next && c.__next.parentId
78
92
  r = {
79
93
  instance: c,
80
94
  id: String(c && c._componentNumber),
@@ -87,6 +101,7 @@ function ensure(c: any): Rec {
87
101
  fired: new Set(),
88
102
  eventsSelected: new Set(),
89
103
  eventsEmitted: new Set(),
104
+ controls: new Map(),
90
105
  }
91
106
  records.set(c, r)
92
107
  }
@@ -116,7 +131,7 @@ export const inspectCheck: DiagnosticCheck = {
116
131
  attachDevtools()
117
132
  const r = ensure(component)
118
133
  const intent$ = component && component.intent$
119
- r.intentActions = intent$ && typeof intent$.addListener === 'function' ? null : (actionNames || [])
134
+ r.intentActions = actionNames || []
120
135
  r.injected = new Set((intent$ && typeof intent$ === 'object' && intent$.__sygnalTestActions) || [])
121
136
  for (const t of pendingSelects) r.eventsSelected.add(t)
122
137
  pendingSelects = []
@@ -125,16 +140,11 @@ export const inspectCheck: DiagnosticCheck = {
125
140
  onModel(component, modelMap) {
126
141
  const r = ensure(component)
127
142
  r.modelMap = modelMap || {}
128
- const model$ = component && component.model$
129
- const events$ = model$ && model$.EVENTS
130
- if (events$ && typeof events$.map === 'function' && !events$.__sygnalInspect) {
131
- const tapped = events$.map((ev: any) => {
132
- if (ev && typeof ev.type === 'string') r.eventsEmitted.add(ev.type)
133
- return ev
134
- })
135
- tapped.__sygnalInspect = true
136
- model$.EVENTS = tapped
137
- }
143
+ },
144
+
145
+ onRender(component, root) {
146
+ const r = records.get(component)
147
+ if (r) collectControls(root, r.controls, true)
138
148
  },
139
149
 
140
150
  onReducer(component, action) {
@@ -151,6 +161,45 @@ export const inspectCheck: DiagnosticCheck = {
151
161
  },
152
162
  }
153
163
 
164
+ /** PLAN-4.6 R4 (onSink): an EVENTS value the instance sent */
165
+ export function eventEmitted(component: any, ev: any): void {
166
+ const r = records.get(component)
167
+ if (r && ev && typeof ev.type === 'string') r.eventsEmitted.add(ev.type)
168
+ }
169
+
170
+ /**
171
+ * CT-1: record the controls in a component's rendered tree (data-control="<Key>"), stopping at
172
+ * isolated child components (their root carries data.isolate on the real DOM, a '.___<scope>'
173
+ * class in the mock DOM): the controls inside belong to the child.
174
+ */
175
+ function collectControls(v: any, out: Rec['controls'], root: boolean): void {
176
+ if (!v || typeof v != 'object') return
177
+ if (!root && typeof v.sel == 'string' && ((v.data && v.data.isolate) || v.sel.includes('.___'))) return
178
+ const key = v.data && v.data.attrs && v.data.attrs['data-control']
179
+ if (typeof key == 'string' && !out.has(key)) {
180
+ const control = controlOfVnode(v)
181
+ const spec = control && control.spec
182
+ out.set(key, spec && typeof spec == 'object'
183
+ ? {element: null, kind: String(spec.kind)}
184
+ : {element: typeof spec == 'string' ? spec : typeof v.sel == 'string' ? v.sel.split(/[.#]/)[0] : null})
185
+ }
186
+ for (const k of [].concat(v.children || [], (v.data && v.data.portalChildren) || [])) collectControls(k, out, false)
187
+ }
188
+
189
+ /** CT-1: the controls a component rendered, `listened` from its intent's selectors */
190
+ function controlsOf(r: Rec, selectors: InspectSelector[]): InspectControl[] | undefined {
191
+ if (!r.controls.size) return undefined
192
+ const listened = new Set<string>()
193
+ for (const s of selectors) for (const m of s.selector.matchAll(/\[data-control="([^"]+)"\]/g)) listened.add(m[1])
194
+ return [...r.controls].map(([name, {element, kind}]) => ({name, element, ...(kind ? {kind} : {}), listened: listened.has(name)}))
195
+ }
196
+
197
+ /** CT-1: mark a selector that is a control ([data-control="<Key>"]) with its key */
198
+ const withControl = (s: InspectSelector): InspectSelector => {
199
+ const key = keyOfSelector(s.selector)
200
+ return key ? {...s, control: key} : s
201
+ }
202
+
154
203
  const slim = (d: any): InspectDiagnostic => {
155
204
  const out: InspectDiagnostic = {code: d.code, severity: d.severity, message: d.message}
156
205
  if (d.component) out.component = d.component
@@ -166,10 +215,12 @@ const slim = (d: any): InspectDiagnostic => {
166
215
  function actionsOf(r: Rec): InspectComponent['actions'] {
167
216
  const intent = (r.intentActions || []).filter(a => !r.injected.has(a))
168
217
  const names = uniq([...intent, ...Object.keys(r.modelMap)]).filter(a => typeof a === 'string' && !a.startsWith('__'))
218
+ const replies = replySeen.get(r.instance)
169
219
  return names.map(name => ({
170
220
  name,
171
221
  trigger: BUILTIN_ACTIONS.has(name) ? 'builtin'
172
222
  : intent.includes(name) ? 'intent'
223
+ : replies?.has(name) ? 'reply'
173
224
  : !r.injected.has(name) && r.fired.has(name) ? 'next'
174
225
  : 'unknown',
175
226
  sinks: [...(r.modelMap[name] || [])],
@@ -181,6 +232,32 @@ function stateKeysOf(c: any, calculated: string[]): string[] {
181
232
  return isPlainObject(s) ? Object.keys(s).filter(k => !calculated.includes(k)) : []
182
233
  }
183
234
 
235
+ /** PLAN-3 5-3: the instance's resources (`resources` static) and their state slots */
236
+ function resourcesOf(c: any): InspectResource[] | undefined {
237
+ const res = c && c.view && c.view.resources
238
+ if (!res || typeof res !== 'object') return undefined
239
+ const s = c.currentState || {}
240
+ return Object.keys(res).map(name => {
241
+ const r = s[name] || {}
242
+ return {name, status: r.status ?? 'idle', refreshing: !!r.refreshing, hasData: r.data !== undefined, error: r.error ? String(r.error.message ?? r.error) : undefined}
243
+ })
244
+ }
245
+
246
+ /** PLAN-3 5-3: the cache entries of every makeFetchDriver source the instances use, by sink name (sinks with an empty cache left out) */
247
+ function cacheOf(recs: Rec[]): InspectGraph['cache'] {
248
+ const out: NonNullable<InspectGraph['cache']> = {}
249
+ for (const r of recs) {
250
+ const sources = r.instance && r.instance.sources
251
+ if (!sources || typeof sources !== 'object') continue
252
+ for (const k of Object.keys(sources)) {
253
+ const src = sources[k]
254
+ if (out[k] || !src || src.__sygnalStatic !== 'resources' || typeof src.__inspect !== 'function') continue
255
+ try { const list = src.__inspect().cache; if (list.length) out[k] = list } catch (_) { /* a driver without the cache listing */ }
256
+ }
257
+ }
258
+ return out
259
+ }
260
+
184
261
  /**
185
262
  * renderComponent's mock DOM (src/extra/testing.ts passes its listener registry):
186
263
  * listener paths are the select() chain with isolation scopes as '.___<scope>' entries;
@@ -219,16 +296,16 @@ function mockSelectors(mock: MockDom): Record<string, InspectSelector[]> {
219
296
 
220
297
  function selectorsOf(r: Rec, options: InspectOptions, diags: any[]): InspectSelector[] {
221
298
  const given = options.selectors && options.selectors[r.id]
222
- if (given) return given.map(s => ({...s}))
299
+ if (given) return given.map(s => withControl({...s}))
223
300
  return (selectorStatus(r.instance) || []).map(({selector, matched, crossed}) => {
224
301
  const hit = diags.find(d => d.code === 'SYG104' && d.component === r.name && d.data && d.data.selector === selector)
225
302
  const missed = diags.some(d => d.code === 'SYG103' && d.component === r.name && d.data && d.data.selector === selector)
226
- return {
303
+ return withControl({
227
304
  selector,
228
305
  events: null,
229
306
  matched: matched === null && missed ? false : matched,
230
307
  isolationHit: crossed ? ((hit && hit.data.child) || 'a child component') : null,
231
- }
308
+ })
232
309
  })
233
310
  }
234
311
 
@@ -267,6 +344,8 @@ export function inspect(options: InspectOptions = {}): InspectGraph {
267
344
  const components: InspectComponent[] = recs.map(r => {
268
345
  const c = r.instance
269
346
  const calculated = c && c.calculated && typeof c.calculated === 'object' ? Object.keys(c.calculated) : []
347
+ const selectors = selectorsOf(r, options, diags)
348
+ const controls = controlsOf(r, selectors)
270
349
  return {
271
350
  name: r.name,
272
351
  id: r.id,
@@ -280,11 +359,14 @@ export function inspect(options: InspectOptions = {}): InspectGraph {
280
359
  eventsEmitted: [...r.eventsEmitted],
281
360
  eventsSelected: [...r.eventsSelected],
282
361
  children: childrenOf(r, all),
283
- selectors: selectorsOf(r, options, diags),
362
+ selectors,
363
+ ...(controls ? {controls} : {}),
284
364
  diagnostics: diags.filter(d => d && d.component === r.name).map(slim),
365
+ ...(resourcesOf(c) ? {resources: resourcesOf(c)} : {}),
285
366
  }
286
367
  })
287
368
 
369
+ const cache = cacheOf(recs) || {}
288
370
  const events: InspectGraph['events'] = {}
289
371
  const ev = (type: string) => events[type] || (events[type] = {emitters: [], selectors: []})
290
372
  const add = (list: string[], name: string) => { if (!list.includes(name)) list.push(name) }
@@ -301,9 +383,35 @@ export function inspect(options: InspectOptions = {}): InspectGraph {
301
383
  components,
302
384
  events,
303
385
  diagnostics: diags.filter(d => d && (!d.component || !names.has(d.component))).map(slim),
386
+ ...(Object.keys(cache).length ? {cache} : {}),
387
+ ...(options.actions ? {recentActions: recentActions(options.actions, ids)} : {}),
304
388
  }
305
389
  }
306
390
 
391
+ /** a JSON-safe copy of an action's data (dropped when it doesn't serialize, or is large: a DOM event) */
392
+ function jsonData(d: any): {data?: any} {
393
+ if (d === undefined) return {}
394
+ try {
395
+ const text = JSON.stringify(d)
396
+ return text === undefined || text.length > 1000 ? {} : {data: JSON.parse(text)}
397
+ } catch (_) { return {} }
398
+ }
399
+
400
+ /** PLAN-4 2-C: the last `limit` actions (true: all kept) of the listed instances */
401
+ function recentActions(limit: true | number, ids: Set<string> | undefined): InspectRecentAction[] {
402
+ const list = ids ? recent.filter(r => ids.has(r.instance)) : recent
403
+ const n = limit === true ? list.length : Math.max(0, Math.floor(limit))
404
+ return list.slice(list.length - n).map(r => ({
405
+ type: r.type,
406
+ ...jsonData(r.data),
407
+ component: r.component,
408
+ instance: r.instance,
409
+ sinks: [...r.sinks],
410
+ cause: r.cause,
411
+ at: r.time - epoch,
412
+ }))
413
+ }
414
+
307
415
  /** Publish inspect() on the core bridge and the devtools object. Returns an uninstall function. */
308
416
  export function installInspect(): () => void {
309
417
  const core = bridge()