sygnal 5.4.0 → 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 (316) hide show
  1. package/CHANGELOG.md +646 -0
  2. package/README.md +24 -9
  3. package/dist/astro/client.cjs.js +16 -9
  4. package/dist/astro/client.cjs.js.map +1 -1
  5. package/dist/astro/client.mjs +16 -9
  6. package/dist/astro/client.mjs.map +1 -1
  7. package/dist/astro/index.cjs.js +362 -91
  8. package/dist/astro/index.cjs.js.map +1 -1
  9. package/dist/astro/index.mjs +362 -92
  10. package/dist/astro/index.mjs.map +1 -1
  11. package/dist/astro/server.cjs.js +3396 -165
  12. package/dist/astro/server.cjs.js.map +1 -1
  13. package/dist/astro/server.mjs +3396 -165
  14. package/dist/astro/server.mjs.map +1 -1
  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 +3032 -296
  20. package/dist/diagnostics.cjs.js.map +1 -1
  21. package/dist/diagnostics.esm.js +3032 -296
  22. package/dist/diagnostics.esm.js.map +1 -1
  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 +13178 -5769
  67. package/dist/index.cjs.js.map +1 -1
  68. package/dist/index.d.ts +2908 -276
  69. package/dist/index.esm.js +13149 -5779
  70. package/dist/index.esm.js.map +1 -1
  71. package/dist/jsx-dev-runtime.cjs.js +26 -334
  72. package/dist/jsx-dev-runtime.cjs.js.map +1 -1
  73. package/dist/jsx-dev-runtime.esm.js +19 -327
  74. package/dist/jsx-dev-runtime.esm.js.map +1 -1
  75. package/dist/jsx-runtime.cjs.js +26 -334
  76. package/dist/jsx-runtime.cjs.js.map +1 -1
  77. package/dist/jsx-runtime.esm.js +19 -327
  78. package/dist/jsx-runtime.esm.js.map +1 -1
  79. package/dist/jsx.cjs.js +10 -314
  80. package/dist/jsx.cjs.js.map +1 -1
  81. package/dist/jsx.esm.js +8 -315
  82. package/dist/jsx.esm.js.map +1 -1
  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 +1 -1
  89. package/dist/sygnal.min.js.map +1 -1
  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 +4 -14
  107. package/dist/vike/ClientOnly.cjs.js.map +1 -1
  108. package/dist/vike/ClientOnly.mjs +4 -14
  109. package/dist/vike/ClientOnly.mjs.map +1 -1
  110. package/dist/vike/{+config.js → config/+config.js} +9 -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 +165 -95
  114. package/dist/vike/onRenderClient.cjs.js.map +1 -1
  115. package/dist/vike/onRenderClient.mjs +165 -95
  116. package/dist/vike/onRenderClient.mjs.map +1 -1
  117. package/dist/vike/onRenderHtml.cjs.js +59 -24
  118. package/dist/vike/onRenderHtml.cjs.js.map +1 -1
  119. package/dist/vike/onRenderHtml.mjs +60 -25
  120. package/dist/vike/onRenderHtml.mjs.map +1 -1
  121. package/dist/vite/plugin.cjs.js +323 -88
  122. package/dist/vite/plugin.cjs.js.map +1 -1
  123. package/dist/vite/plugin.mjs +323 -89
  124. package/dist/vite/plugin.mjs.map +1 -1
  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 +166 -103
  130. package/package.json +98 -14
  131. package/src/astro/client.ts +27 -16
  132. package/src/astro/index.d.ts +24 -0
  133. package/src/astro/index.ts +69 -3
  134. package/src/astro/server.ts +8 -2
  135. package/src/collection.ts +6 -93
  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 +9 -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 +9 -7
  162. package/src/cycle/dom/controlledInputModule.ts +23 -6
  163. package/src/cycle/dom/enrichEventStream.ts +25 -47
  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 -56
  167. package/src/cycle/dom/mockDOMSource.ts +21 -1
  168. package/src/cycle/dom/modules.ts +16 -3
  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 +19 -3
  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 +101 -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 +1 -1
  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 +20 -11
  201. package/src/extra/diagnostics/checks/elementCommands.ts +175 -0
  202. package/src/extra/diagnostics/checks/events.ts +17 -2
  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 +97 -4
  206. package/src/extra/diagnostics/checks/inspect.ts +140 -32
  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 +10 -5
  210. package/src/extra/diagnostics/checks/public.d.ts +98 -7
  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 +1 -1
  214. package/src/extra/diagnostics/checks/shared.ts +86 -2
  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 +100 -7
  218. package/src/extra/diagnostics/checks/statics.ts +48 -0
  219. package/src/extra/diagnostics/checks/strict.ts +10 -67
  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 +66 -10
  225. package/src/extra/diagnostics/codes.ts +268 -23
  226. package/src/extra/diagnostics/index.ts +34 -9
  227. package/src/extra/diagnostics/legacy.ts +17 -0
  228. package/src/extra/driverFactories.ts +83 -19
  229. package/src/extra/elementCommands.ts +53 -0
  230. package/src/extra/fetchDriver.ts +519 -0
  231. package/src/extra/focusWithin.ts +27 -0
  232. package/src/extra/form.ts +268 -0
  233. package/src/extra/formHelpers.ts +139 -0
  234. package/src/extra/head.ts +106 -0
  235. package/src/extra/hmr.ts +2 -3
  236. package/src/extra/owned.ts +24 -0
  237. package/src/extra/pager.ts +50 -0
  238. package/src/extra/persist.ts +133 -0
  239. package/src/extra/pwa.ts +1 -1
  240. package/src/extra/queryCache.ts +107 -0
  241. package/src/extra/reducers.ts +1 -1
  242. package/src/extra/reduxDevtools.ts +92 -0
  243. package/src/extra/replies.ts +54 -0
  244. package/src/extra/router.ts +323 -0
  245. package/src/extra/run.ts +90 -217
  246. package/src/extra/selection.ts +76 -0
  247. package/src/extra/socketDriver.ts +265 -0
  248. package/src/extra/sortable.ts +377 -0
  249. package/src/extra/ssr.ts +427 -160
  250. package/src/extra/standardSchema.ts +27 -0
  251. package/src/extra/testing.ts +2433 -175
  252. package/src/extra/timers.ts +95 -0
  253. package/src/extra/undo.ts +261 -0
  254. package/src/extra/viewTransitions.ts +38 -0
  255. package/src/extra/virtual.ts +513 -0
  256. package/src/extra/widget.ts +201 -0
  257. package/src/index.d.ts +2631 -117
  258. package/src/index.ts +25 -4
  259. package/src/jsx-runtime.ts +15 -1
  260. package/src/jsx.ts +2 -1
  261. package/src/lazy.ts +50 -7
  262. package/src/portal.ts +3 -1
  263. package/src/pragma/index.ts +256 -133
  264. package/src/react-peers.d.ts +5 -0
  265. package/src/react.d.ts +43 -0
  266. package/src/react.ts +110 -0
  267. package/src/shared.ts +48 -0
  268. package/src/slot.ts +1 -1
  269. package/src/suspense.ts +3 -1
  270. package/src/switchable.ts +6 -121
  271. package/src/transition.ts +3 -1
  272. package/src/ui/accordion.ts +64 -0
  273. package/src/ui/dialog.ts +129 -0
  274. package/src/ui/disclosure.ts +35 -0
  275. package/src/ui/popover.ts +45 -0
  276. package/src/ui/shared.ts +94 -0
  277. package/src/ui/tabs.ts +82 -0
  278. package/src/ui/toaster.ts +198 -0
  279. package/src/ui/tooltip.ts +70 -0
  280. package/src/ui/zag/combobox.ts +115 -0
  281. package/src/ui/zag/menu.ts +40 -0
  282. package/src/ui/zag/select.ts +54 -0
  283. package/src/ui/zag/shared.ts +43 -0
  284. package/src/ui-combobox.d.ts +20 -0
  285. package/src/ui-combobox.ts +6 -0
  286. package/src/ui-menu.d.ts +30 -0
  287. package/src/ui-menu.ts +6 -0
  288. package/src/ui-select.d.ts +17 -0
  289. package/src/ui-select.ts +6 -0
  290. package/src/ui-zag-types.d.ts +42 -0
  291. package/src/ui.d.ts +208 -0
  292. package/src/ui.ts +15 -0
  293. package/src/vike/+config.ts +9 -1
  294. package/src/vike/ClientOnly.ts +1 -1
  295. package/src/vike/onRenderClient.ts +144 -96
  296. package/src/vike/onRenderHtml.ts +69 -26
  297. package/src/vike/types.ts +7 -1
  298. package/src/vite/globalthis-shim.ts +18 -0
  299. package/src/vite/globalthis.ts +56 -0
  300. package/src/vite/plugin.d.ts +22 -3
  301. package/src/vite/plugin.ts +222 -24
  302. package/src/zag.d.ts +64 -0
  303. package/src/zag.ts +238 -0
  304. package/dist/vike/+config.cjs.js +0 -66
  305. package/dist/vike/+config.cjs.js.map +0 -1
  306. package/dist/vike/+config.js.map +0 -1
  307. package/src/component.ts +0 -2301
  308. package/src/cycle/isolate/index.ts +0 -196
  309. package/src/cycle/run/index.ts +0 -151
  310. package/src/cycle/run/internals.ts +0 -143
  311. package/src/cycle/state/Collection.ts +0 -184
  312. package/src/cycle/state/index.ts +0 -5
  313. package/src/cycle/state/pickCombine.ts +0 -201
  314. package/src/cycle/state/pickMerge.ts +0 -122
  315. package/src/cycle/state/withState.ts +0 -47
  316. package/src/pragma/fn.ts +0 -55
@@ -0,0 +1,201 @@
1
+ /**
2
+ * PLAN-5 W-1 (D189/D190/D196): `defineWidget`, a framework-agnostic third-party widget (a date
3
+ * picker, a chart, an editor) as a JSX tag (canonical) that also works as a control spec.
4
+ *
5
+ * const DatePicker = defineWidget({
6
+ * tag: 'input',
7
+ * mount: (el, props, dispatch) => flatpickr(el, { defaultDate: props.value, onChange: ([d]) => dispatch('pick', d) }),
8
+ * update: (fp, props) => fp.setDate(props.value, false),
9
+ * unmount: (fp) => fp.destroy(),
10
+ * events: ['pick'],
11
+ * commands: { open: (fp) => fp.open() },
12
+ * })
13
+ * // view: <label>Due <DatePicker className="due" value={state.due} /></label>
14
+ * // intent: DUE: DOM.select('.due').events('pick').detail()
15
+ * // model: OPEN_DUE: { ELEMENT: { open: '.due' } }
16
+ * // alt: const { Due } = controls({ Due: DatePicker }); DOM.select(Due).events('pick'), { open: Due }
17
+ *
18
+ * 0 B in the core when unused: everything is in this module, and the marker handler is registered
19
+ * by the first defineWidget() call, not on import.
20
+ * - The tag is a function carrying the pragma's control render hook (`__sygnalControl`, CT-1), so
21
+ * `<DatePicker …/>` never becomes a component. It is also a control spec object (D101/D116:
22
+ * `kind`, `vnode(props, children, h)`, `commands`), so `controls({ Due: DatePicker })` works.
23
+ * - `vnode()` returns a `widget` marker; the owner's reconcile walk rewrites it through the marker
24
+ * registry (`pres.widget`, given the marker's path) into the host vnode, with the owner instance
25
+ * at hand (onError). The host has no children (opaque to snabbdom) and carries the newest props
26
+ * in `data.wp`; its hooks read the vnode they are given, so `update` always gets the props of
27
+ * the render being patched (no closure over mount-time props). Each host has its own hook
28
+ * object: the widget's, then a `ref`'s (the host element), then a `<Transition>`'s (G-363).
29
+ * - 1-R (G-360): the host's key names the widget and the instance (its key in the parent, or its
30
+ * place when unkeyed), so snabbdom never patches a host into another vnode (a plain element of
31
+ * the same tag, another widget, the error fallback) or the reverse: the host is destroyed and
32
+ * the widget unmounts.
33
+ * - The record `{ w (the tag), p (props), i (instance), e (dispatch) }` lives on the host element
34
+ * as the non-enumerable `__sw` (D200: short, the core reads it), so the instance survives re-renders and keyed moves
35
+ * (snabbdom moves the element). Mount runs on insert, or on the first patch of an element that
36
+ * has none (SSR hydration). `update` runs when the props change (shallow; an object host prop
37
+ * such as `style` one level deep, G-362); without `update`, a change remounts (G-367: a mount
38
+ * that throws then is SYG660 and leaves no record). `unmount` on destroy (a removed Portal
39
+ * destroys its content too, G-359).
40
+ * - `className` goes to the host as class-module tokens (G-364): a change toggles only those, not
41
+ * the classes the library added (flatpickr's `flatpickr-input`).
42
+ * - `dispatch(name, detail)` (mount's third parameter) dispatches a bubbling CustomEvent on the
43
+ * host: the intent reads it like any DOM event (`.detail()`); isolation (Collection items)
44
+ * applies as for any element.
45
+ * - Commands: D102's `spec.commands[name](hostElement, options)` resolves the instance from the
46
+ * host. For selector targets each command whose name the element doesn't already have is also
47
+ * a method of the host (D190); a declared command whose name is a native method (`focus`,
48
+ * `close`) is found by the core through `__sw` and wins over the native one, with the
49
+ * options object (D196, D200).
50
+ * - A widget tag is not a selector: `DOM.select(DatePicker)` matches nothing (SYG143 in dev).
51
+ * - G-413: `ownProps` names props that stay off the host although they'd go there (a part that
52
+ * puts `aria-label` on its own control).
53
+ * - G-409: mount's fourth parameter `error(e)` reports a later failure the widget caught itself
54
+ * (fromZag's machine-driven redraws): handled as a throwing `update` (SYG661 + fallback; G-580:
55
+ * the dev message says the widget reported it through error(e)).
56
+ * - A `mount`/`update` that throws (SYG660/661): reported to the app's onError with phase
57
+ * 'widget' (D105), and the owner's next render shows its `onError` fallback in that instance's
58
+ * place (G-361: per instance; a render with other props tries again, and the failure is
59
+ * forgotten when the fallback leaves the page). `unmount` (SYG662): reported, nothing to replace.
60
+ * - Inside `<Portal>`: the Portal's children are rewritten here too (Portal children are not
61
+ * walked by the core), so a widget works in a portal.
62
+ * - SSR (extra/ssr.ts): the host, with `fallback` inside it; the client patch replaces it with
63
+ * the keyed host and mounts.
64
+ *
65
+ * Dev text lives in the 'sygnal/diagnostics' entry (checks/widgets.ts), reached through the core
66
+ * bridge as `widget(code, widgetTag, owner, extra)`: SYG140 (dispatch of an undeclared event),
67
+ * SYG143, SYG144 (a declared event the host fires natively), SYG660–662. Without the entry, a
68
+ * thrown mount/update/unmount is logged as `[Sygnal SYG66x]` with the error.
69
+ */
70
+ import {pres} from '../core/registry'
71
+ import {chainHooks} from '../pragma/index'
72
+
73
+ const W = '__sw'
74
+
75
+ // props that also go to the host element (every prop but key goes to the widget; ref is the host's)
76
+ const HOST = /^(id|class(Name)?|style|title|name|placeholder|role|tab[iI]ndex|hidden|lang|dir|attrs)$|^(aria|data)-/
77
+
78
+ /** the dev entry's reporter (checks/widgets.ts); returns the diagnostic when one was reported
79
+ * (r: G-580, a 661 the widget reported through error(e), not a throwing update) */
80
+ const dev = (code: number, w: any, o?: any, x?: any, r?: any): any => (globalThis as any).__SYGNAL_DIAGNOSTICS__?.widget?.(code, w, o, x, r)
81
+
82
+ let ids = 0
83
+
84
+ // shallow; G-362: an object host prop (style, attrs, a class map) compares one level deep, so a
85
+ // new object with the same entries is no change (snabbdom patches the host from it anyway)
86
+ const same = (a: any, b: any, d?: any): any => {
87
+ const k = Object.keys(a)
88
+ return k.length == Object.keys(b).length && k.every(x => a[x] === b[x] ||
89
+ !d && HOST.test(x) && typeof a[x] == 'object' && typeof b[x] == 'object' && a[x] && b[x] && same(a[x], b[x], 1))
90
+ }
91
+
92
+ // k: the host's key, the failure's place; [error, the props of the fallback's last render]; r:
93
+ // reported through error(e)
94
+ function fail(o: any, w: any, k: any, code: number, e: any, r?: any) {
95
+ e = e instanceof Error ? e : Error(e)
96
+ dev(code, w, o, e, r) || console.error(`[Sygnal SYG${code}]`, e)
97
+ o.app.appError(o, e, 'widget')
98
+ if (code < 662 && !o.disposed) (o.$wf ||= new Map()).set(k, [e]), o.refresh()
99
+ }
100
+
101
+ function mount(v: any) {
102
+ const el = v.elm, {ww: w, wp: p, wo: o} = v.data
103
+ const d = (n: string, detail?: any) => { dev(140, w, o, n); el.dispatchEvent(new CustomEvent(n, {detail, bubbles: true})) }
104
+ let i: any
105
+ dev(144, w, o, el)
106
+ // G-409: mount's fourth parameter reports a later failure (an adapter's own redraw): SYG661,
107
+ // the owner's onError fallback in this instance's place, as for a throwing update (G-580: the
108
+ // dev text says error(e) reported it)
109
+ const err = (x: any) => { el[W] && fail(o, w, v.key, 661, x, 1) }
110
+ try { i = w.def.mount(el, p, d, err) } catch (x) { return fail(o, w, v.key, 660, x) }
111
+ Object.defineProperty(el, W, {value: {w, p, i, e: d}, configurable: true})
112
+ // the tag form's commands: a host method for each one the element doesn't have (D190)
113
+ for (const m in w.def.commands) m in el || (el[m] = (x: any) => el[W]?.w.commands[m]?.(el, x))
114
+ }
115
+
116
+ function destroy(v: any) {
117
+ const el = v.elm, s = el[W]
118
+ if (s) {
119
+ delete el[W]
120
+ try { s.w.def.unmount?.(s.i, el) } catch (x) { fail(v.data.wo, s.w, v.key, 662, x) }
121
+ }
122
+ }
123
+
124
+ const hooks: any = {
125
+ insert: mount,
126
+ postpatch(_: any, v: any) {
127
+ const el = v.elm, p = v.data.wp, s = el[W]
128
+ // SSR hydration (the element was patched in place, never inserted): mount now
129
+ if (!s) return mount(v)
130
+ const u = s.w.def.update
131
+ if (same(s.p, p)) return
132
+ // G-367: without update, a change remounts
133
+ if (!u) return destroy(v), mount(v)
134
+ try { u(s.i, p, el); s.p = p } catch (x) { fail(v.data.wo, s.w, v.key, 661, x) }
135
+ },
136
+ destroy,
137
+ }
138
+
139
+ /** the host vnode for a widget marker (client: the hooks, the owner and the key k; SSR adds the fallback) */
140
+ function host(n: any, o?: any, k?: any): any {
141
+ const {ww: w, wp: p, h, attrs, r} = n.data, def = w.def, hp: any = {ref: r}
142
+ for (const x in p) if ((HOST.test(x) || def.hostProps?.includes(x)) && !def.ownProps?.includes(x)) hp[x] = p[x]
143
+ if (hp.className) hp.class = [hp.class, hp.className], delete hp.className
144
+ const v = h(def.tag || 'div', hp), d = v.data
145
+ if (attrs) d.attrs = {...d.attrs, ...attrs}
146
+ if (o) {
147
+ v.key = k
148
+ d.ww = w; d.wp = p; d.wo = o; v.children = undefined
149
+ // a hook object per host: a ref's hooks (from h), the widget's, then a Transition's (marker)
150
+ chainHooks(d, hooks)
151
+ n.data.hook && chainHooks(d, n.data.hook)
152
+ }
153
+ return v
154
+ }
155
+
156
+ /** pres.widget: the host, or the owner's fallback where this instance failed */
157
+ function rewrite(n: any, o: any, path: string): any {
158
+ const w = n.data.ww, p = n.data.wp, wf = o.$wf
159
+ // the instance: the widget and its key, or its place when unkeyed
160
+ const k = 'w' + w.$i + (n.key == null ? path : '#' + n.key)
161
+ let f = wf?.get(k)
162
+ // a render with other props than the fallback's last one tries again
163
+ if (f && f[1] && !same(f[1], p)) wf.delete(k), f = 0
164
+ if (!f) return host(n, o, k)
165
+ f[1] = p
166
+ const def = o.def, x = n.data.h('div', {attrs: {'data-sygnal-error': def.name}})
167
+ let r: any = x
168
+ try { r = def.onError?.(f[0], {componentName: def.name}) || x } catch (_) {}
169
+ // its own key; the failure is forgotten when it leaves the page (a reopened panel tries again)
170
+ chainHooks((r = {...r, key: k + '!', data: {...r.data}}).data, {destroy: () => wf.delete(k)})
171
+ return r
172
+ }
173
+
174
+ /** widget markers among a Portal's children (the core doesn't walk them) */
175
+ const inPortal = (c: any[], o: any, x: string): any[] =>
176
+ c.map((n, i) => n?.sel == 'widget' ? rewrite(n, o, x + '.' + i) : n?.children ? {...n, children: inPortal(n.children, o, x + '.' + i)} : n)
177
+
178
+ export function defineWidget(def: any): any {
179
+ pres.widget ||= rewrite
180
+ const p: any = pres.portal
181
+ if (p && !p.$w) ((pres.portal = (n: any, o: any, x: string) => p({...n, children: inPortal(n.children || [], o, x)}, o, x)) as any).$w = 1
182
+ const w: any = () => {}, commands: any = {}
183
+ // D200: any name, `close` and `togglePopover` too (the core passes a widget command the options)
184
+ for (const m in def.commands) commands[m] = (el: any, o: any) => el[W] && def.commands[m](el[W].i, o || {}, el)
185
+ return Object.assign(w, {
186
+ kind: 'widget',
187
+ def,
188
+ $i: ++ids,
189
+ events: def.events || [],
190
+ commands,
191
+ // D101/D116: the control spec's vnode(props, children, h): one (marker) element vnode; also
192
+ // the tag form's pragma render hook (no data-control stamp)
193
+ vnode: w.__sygnalControl = (props: any, _: any, h: any) => {
194
+ const {key, ref, ...p} = props || {}
195
+ return {sel: 'widget', data: {ww: w, wp: p, h, r: ref}, children: undefined, text: undefined, key}
196
+ },
197
+ $ssr: host,
198
+ // D190/D199: a widget tag is not a selector (SYG143 in dev): select its className or a control
199
+ toString: () => (dev(143, w), ':not(*)'),
200
+ })
201
+ }