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
@@ -1,27 +1,1057 @@
1
1
  'use strict';
2
2
 
3
+ var fs = require('node:fs');
4
+ var path = require('node:path');
5
+ var node_module = require('node:module');
6
+ var node_url = require('node:url');
7
+
8
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
9
+ /**
10
+ * G-099: xstream does `require('globalthis').getPolyfill()`, which pulls the
11
+ * `globalthis` polyfill and its dependency chain (define-properties,
12
+ * get-intrinsic, object-keys, has-symbols, ...; ~4 KB gzip) into every app
13
+ * bundle. Every runtime Sygnal supports has a native `globalThis`, so
14
+ * `sygnal/vite` (and the sygnal/astro integration) alias the package to
15
+ * dist/shims/globalthis.cjs (src/vite/globalthis-shim.ts) unless
16
+ * `nativeGlobalThis: false`. A `resolve.alias`, not a resolveId hook: Vite's
17
+ * dependency pre-bundling only applies aliases.
18
+ */
19
+ // Node built-ins (this runs in Node). The package has no @types/node.
20
+ // @ts-ignore
21
+ /**
22
+ * Absolute path of the stub in the sygnal package this code belongs to (found
23
+ * by walking up from this file: dist/vite, dist/astro or src/vite), or
24
+ * undefined when it is missing (e.g. sygnal not built).
25
+ */
26
+ function globalThisShim() {
27
+ try {
28
+ let dir = path.dirname(node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs.js', document.baseURI).href))));
29
+ while (dir !== path.dirname(dir)) {
30
+ const pkgFile = path.join(dir, 'package.json');
31
+ if (fs.existsSync(pkgFile) && JSON.parse(fs.readFileSync(pkgFile, 'utf8')).name === 'sygnal') {
32
+ const file = path.join(dir, 'dist', 'shims', 'globalthis.cjs');
33
+ return fs.existsSync(file) ? file : undefined;
34
+ }
35
+ dir = path.dirname(dir);
36
+ }
37
+ }
38
+ catch (_) { }
39
+ return undefined;
40
+ }
41
+ /**
42
+ * Whether a Vite `resolve.alias` value (object or array form) already maps
43
+ * `globalthis` (R2-7): the user's alias wins and the stub is not added.
44
+ */
45
+ function hasGlobalThisAlias(alias) {
46
+ if (!alias)
47
+ return false;
48
+ if (!Array.isArray(alias))
49
+ return Object.prototype.hasOwnProperty.call(alias, 'globalthis');
50
+ return alias.some((a) => a && (a.find instanceof RegExp ? a.find.test('globalthis') : a.find === 'globalthis'));
51
+ }
52
+ /**
53
+ * Vite `resolve.alias` entries for the stub (empty when it is missing, or
54
+ * when `userAlias` — the user's `resolve.alias` — already maps `globalthis`).
55
+ */
56
+ function globalThisAlias(userAlias) {
57
+ const shim = hasGlobalThisAlias(userAlias) ? undefined : globalThisShim();
58
+ return shim ? [{ find: /^globalthis$/, replacement: shim }] : [];
59
+ }
60
+
61
+ /**
62
+ * Sygnal Vite Plugin
63
+ *
64
+ * Auto-configures JSX, wires up HMR with state preservation and, in dev,
65
+ * turns on Sygnal's diagnostics (runtime checks and the static checker).
66
+ * Nothing it adds in dev reaches a production build.
67
+ *
68
+ * Usage:
69
+ * import sygnal from 'sygnal/vite'
70
+ * export default defineConfig({ plugins: [sygnal()] })
71
+ *
72
+ * What it does:
73
+ * 1. Configures the automatic JSX transform with sygnal as the import source:
74
+ * `oxc` (Vite 8), plus `esbuild` under Vite 7 and older
75
+ * 2. Detects files that call `run()` from sygnal and auto-injects HMR wiring.
76
+ * A module that calls `defineElement()` from 'sygnal/element' at the top level
77
+ * (and doesn't import run()) gets `if (import.meta.hot) import.meta.hot.accept()`
78
+ * appended: re-running it swaps the elements' component, keeping their state
79
+ * 3. Dev mode (`vite` / `vite dev` only; never `vite build`). Into every
80
+ * file that imports `run` from sygnal (including entries with manual HMR
81
+ * wiring or `disableHmr`) it inserts, on an existing line:
82
+ *
83
+ * if (globalThis.__SYGNAL_DEV__ === undefined) globalThis.__SYGNAL_DEV__ = true;
84
+ * import 'sygnal/diagnostics';import 'virtual:sygnal/dev';
85
+ *
86
+ * The flag turns on runtime diagnostics in 'warn' mode; 'sygnal/diagnostics'
87
+ * registers the runtime checks (SYG101-106, 201, 202, 301, 401, ...);
88
+ * 'virtual:sygnal/dev' logs static-check results in the browser console
89
+ * (see 5). With `diagnostics: { strict: true }` the snippet also sets
90
+ * `globalThis.__SYGNAL_STRICT__ = true` (same guard), which turns on the
91
+ * strict (SYG5xx) runtime checks of 'sygnal/diagnostics'. The snippet goes
92
+ * after any shebang line and directive prologue ('use strict',
93
+ * 'use client'); line numbers are unchanged and the transform returns a
94
+ * sourcemap. Opt out per app with `run(App, drivers, { diagnostics: 'off' })`
95
+ * or for the whole dev server with `sygnal({ diagnostics: 'off' })`.
96
+ * 4. `diagnostics` option. The runtime core only understands
97
+ * `__SYGNAL_DEV__ === true` ('warn'), so another mode or an ignore list
98
+ * is passed as run()'s own `diagnostics` option: imports of 'sygnal'
99
+ * from the entry files above resolve to a dev-only wrapper module
100
+ * ('\0sygnal-dev:runtime') that re-exports sygnal with a run() that adds
101
+ * `diagnostics: { mode, ignore }` unless the call sets `diagnostics`
102
+ * itself. With the default ('warn', no ignore list) there is no wrapper.
103
+ * 5. `check` option: runs sygnal-check (an optional dependency, loaded
104
+ * lazily from the project; `strict` defaults to `diagnostics.strict`)
105
+ * over `include` (default: the existing ones of src/, pages/ and
106
+ * renderer/, else the project root, with a notice) when the dev
107
+ * server starts and again after every source file change. Results go to
108
+ * the terminal in sygnal-check's format, and to the browser as a
109
+ * 'sygnal:check' HMR event that the dev client ('virtual:sygnal/dev')
110
+ * logs with console.warn (non-disruptive). The dev client asks for the
111
+ * current findings when the page loads ('sygnal:check:request'), and only
112
+ * that client is answered; after a source change the new findings go to
113
+ * every connected client, and only when they changed. Error-severity
114
+ * findings also open Vite's error overlay (`overlay: false`: never):
115
+ * SYG112, SYG124, SYG125, SYG128, SYG405 and the checker's other
116
+ * error-severity codes. The a11y lane SYG701-708 is a warning, also
117
+ * under `diagnostics.strict` (D144, amending D111); `check.a11y: 'error'`
118
+ * makes it an error (and opens the overlay). Without that opt-in a 7xx
119
+ * finding never opens the overlay, even from an older sygnal-check that
120
+ * reports it as an error under strict. Everything else is a warning or
121
+ * info and goes to the console. Warnings never use the overlay: while
122
+ * one is open Vite's client reloads the page on the next HMR update
123
+ * (`overlay: 'warn'` is treated as 'error', with a notice). The dev
124
+ * client closes a sygnal-check overlay before each update, and the
125
+ * server sends it again after the re-check, so it never causes a reload
126
+ * and doesn't go stale. A missing sygnal-check is skipped silently; a
127
+ * checker that throws only logs a warning.
128
+ * 6. Vitest (process.env.VITEST): appends the package's 'sygnal/diagnostics'
129
+ * ESM file to `test.setupFiles` (merged with a string or array value;
130
+ * not added twice), so renderComponent tests get the runtime checks.
131
+ * Its directory is added to the resolved `server.fs.allow` (G-050):
132
+ * in jsdom / happy-dom environments Vitest loads setup files through
133
+ * Vite's /@fs/ URLs, which a linked sygnal outside the workspace would
134
+ * otherwise fail. Opt out with `vitestSetup: false`. Under Vitest the transform adds
135
+ * nothing (no flags, HMR wiring, run() wrapper, dev client or checker):
136
+ * a __SYGNAL_DEV__ / __SYGNAL_STRICT__ flag set by one test file would
137
+ * leak into later test files of the same worker, and renderComponent()
138
+ * manages the diagnostics modes itself.
139
+ * 7. Vike and Astro (G-014): the app is started by sygnal's own client
140
+ * entry, which user code doesn't import. Client-side imports of
141
+ * 'sygnal/vike/onRenderClient' resolve to a dev wrapper that sets the
142
+ * flag and loads the checks first. That entry is excluded from
143
+ * pre-bundling in dev (B-020), so it shares the pages' core. Astro resolves its renderer entry on
144
+ * the server and the browser loads the file itself, so the same snippet
145
+ * is added to sygnal's 'astro/client' file by the transform. That file
146
+ * imports the public 'sygnal' entry (one shared core, B-019), so its
147
+ * 'sygnal' import gets the run() wrapper too: every `diagnostics` mode
148
+ * and ignore list works for islands. The sygnal/astro integration adds
149
+ * this plugin in `astro dev`.
150
+ * 8. `nativeGlobalThis` (G-099, default true): a `resolve.alias` from
151
+ * `globalthis` (xstream's `require('globalthis').getPolyfill()`) to the
152
+ * package's dist/shims/globalthis.cjs, which returns the native
153
+ * globalThis. Drops the polyfill chain (~4 KB gzip) from every bundle,
154
+ * in dev (including pre-bundling), build and Vitest. Dependencies left
155
+ * external (SSR, Vitest) still load the real package from Node. The
156
+ * sygnal/astro integration adds the same alias in `astro build`. Any
157
+ * dependency's `require('globalthis')` gets the stub; a `globalthis`
158
+ * entry in the user's own `resolve.alias` wins (R2-7).
159
+ * 9. `devtools` option (D77, default true): in dev the same files (run()
160
+ * importers, the Vike wrapper, the Astro client) also get
161
+ * `import 'sygnal/devtools';`, first, which installs the DevTools bridge
162
+ * (window.__SYGNAL_DEVTOOLS__) for the browser extension. Independent of
163
+ * `diagnostics` ('off' still injects it). Never in `vite build` or under
164
+ * Vitest: production builds carry no DevTools code. `devtools: false`
165
+ * injects nothing. PLAN-4 3-E: `devtools: { redux: true }` also calls
166
+ * connectReduxDevtools() (actions + state to the Redux DevTools extension).
167
+ *
168
+ * Why not Vite's `define`? Vite's dependency optimizer does not apply user
169
+ * `define` replacements to pre-bundled dependencies (only process.env.NODE_ENV),
170
+ * so a `define` would never reach sygnal's own code when sygnal is pre-bundled.
171
+ * Vite's client does copy `define` entries onto globalThis at runtime, but only
172
+ * when `/@vite/client` is loaded (not under SSR or Vitest, where it would also
173
+ * switch diagnostics on for every test run). Injecting the flag into the
174
+ * entry file that calls run() is deterministic and scoped to the dev app; it
175
+ * runs before run() is called, which is when the diagnostics mode is resolved.
176
+ *
177
+ * The HMR transform finds the pattern:
178
+ * import { run } from 'sygnal'
179
+ * import App from './App.jsx'
180
+ * run(App)
181
+ *
182
+ * And appends:
183
+ * if (import.meta.hot) {
184
+ * import.meta.hot.accept('./App.jsx', __sygnal.hmr)
185
+ * import.meta.hot.dispose(__sygnal.dispose)
186
+ * }
187
+ *
188
+ * HMR wiring is only added for a recognized top-level (column 0) run()
189
+ * statement whose result reference is actually defined (see RUN_CALL_RE). It
190
+ * is skipped — the dev flag is still injected — for any other shape (e.g.
191
+ * `app = run(App)`, nested or indented calls), for test files (*.test.*,
192
+ * *.spec.*) and under Vitest (process.env.VITEST).
193
+ */
194
+ // Node built-ins (the plugin runs in Node). The package has no @types/node.
195
+ // @ts-ignore
196
+ const nodeProcess = globalThis.process;
197
+ // Virtual modules (dev server only)
198
+ const DEV_CLIENT = 'virtual:sygnal/dev';
199
+ const DEV_CLIENT_ID = '\0' + DEV_CLIENT;
200
+ const RUNTIME_ID = '\0sygnal-dev:runtime';
201
+ const VIKE_CLIENT = 'sygnal/vike/onRenderClient';
202
+ const VIKE_CLIENT_ID = '\0sygnal-dev:vike-client';
203
+ const CHECK_EVENT = 'sygnal:check';
204
+ // Sent by the dev client when it loads: the server answers that client only
205
+ const CHECK_REQUEST = 'sygnal:check:request';
206
+ const OVERLAY_PLUGIN = 'sygnal-check';
207
+ // Register the runtime checks with the core that loaded last (see the Vike wrapper)
208
+ const REINSTALL_IMPORT = `import { installChecks as __sygnalInstallChecks } from 'sygnal/diagnostics';`;
209
+ const REINSTALL_CALL = 'try { __sygnalInstallChecks() } catch (e) { console.warn(e) }\n';
210
+ function sygnal(options = {}) {
211
+ const { disableJsx = false, disableHmr = false, vitestSetup = true, nativeGlobalThis = true } = options;
212
+ const diagnostics = normalizeDiagnostics(options.diagnostics);
213
+ const devOn = diagnostics.mode !== 'off';
214
+ // A mode other than the flag's 'warn', or an ignore list, needs run()'s option
215
+ const wrapRun = devOn && (diagnostics.mode !== 'warn' || diagnostics.ignore.length > 0);
216
+ let isServe = false;
217
+ let isVitest = false;
218
+ let root = nodeProcess.cwd();
219
+ // Files whose `import ... from 'sygnal'` resolves to the run() wrapper
220
+ const runtimeImporters = new Set();
221
+ // Statements run before the app starts: dev flag (+ strict flag)
222
+ const flags = DEV_FLAG + (diagnostics.strict ? STRICT_FLAG : '');
223
+ const devImports = `import 'sygnal/diagnostics';import '${DEV_CLIENT}';`;
224
+ // D77: the DevTools bridge, dev only. First, so the diagnostics entry finds it.
225
+ const devtoolsOn = options.devtools !== false;
226
+ const redux = typeof options.devtools == 'object' && !!options.devtools?.redux;
227
+ const devtoolsImport = !devtoolsOn ? ''
228
+ : redux ? `import { connectReduxDevtools as __sygnalReduxDevtools } from 'sygnal/devtools';__sygnalReduxDevtools();`
229
+ : `import 'sygnal/devtools';`;
230
+ // What a dev entry gets: DevTools, then (unless diagnostics are 'off') flags + checks
231
+ const devSnippet = devtoolsImport + (devOn ? flags + devImports : '');
232
+ const devInject = devOn || devtoolsOn;
233
+ let astroClient;
234
+ return {
235
+ name: 'vite-plugin-sygnal',
236
+ config(config, env) {
237
+ isServe = env.command === 'serve';
238
+ isVitest = !!nodeProcess?.env?.VITEST;
239
+ root = config?.root ? path.resolve(config.root) : nodeProcess.cwd();
240
+ const result = {
241
+ // Ensure sygnal is bundled for SSR rather than externalized.
242
+ // Without this, Node fails to resolve sygnal's exports from
243
+ // Vike's server chunks in production builds.
244
+ ssr: {
245
+ noExternal: ['sygnal'],
246
+ },
247
+ };
248
+ // G-099: xstream's `require('globalthis')` gets the native-globalThis
249
+ // stub. An alias (not resolveId) so it also applies to pre-bundling.
250
+ // R2-7: not when the user's config already aliases `globalthis`.
251
+ const alias = nativeGlobalThis ? globalThisAlias(config?.resolve?.alias) : [];
252
+ if (alias.length)
253
+ result.resolve = { alias };
254
+ if (!disableJsx) {
255
+ result.oxc = {
256
+ jsx: {
257
+ runtime: 'automatic',
258
+ importSource: 'sygnal',
259
+ },
260
+ };
261
+ // Vite 7 and older (Astro 6, Vitest on Vite 7) compile JSX with
262
+ // esbuild and ignore `oxc` (B-027); Vite 8 warns about `esbuild`
263
+ // from a plugin, so it is only set below Vite 8.
264
+ if (viteMajor(this, root) < 8) {
265
+ result.esbuild = { jsx: 'automatic', jsxImportSource: 'sygnal' };
266
+ }
267
+ // Vite 8's dependency scanner doesn't use the `oxc` options: without
268
+ // this it compiles JSX for React, fails to resolve
269
+ // react/jsx-dev-runtime and skips pre-bundling (a reload on first load).
270
+ if (isServe && !isVitest) {
271
+ result.optimizeDeps = { rolldownOptions: { transform: { jsx: { runtime: 'automatic', importSource: 'sygnal' } } } };
272
+ }
273
+ }
274
+ if (isVitest) {
275
+ if (vitestSetup) {
276
+ const setup = diagnosticsSetupFile(root);
277
+ const existing = [].concat(config?.test?.setupFiles || []);
278
+ const loaded = existing.some(f => typeof f === 'string' &&
279
+ (f === 'sygnal/diagnostics' || (!!setup && path.resolve(root, f) === setup)));
280
+ // Vite merges arrays (and a string with an array) by concatenation
281
+ if (setup && !loaded)
282
+ result.test = { setupFiles: [setup] };
283
+ }
284
+ }
285
+ else if (isServe && devInject && sygnalInNodeModules(root)) {
286
+ // The dependency scan reads the original sources, which don't import
287
+ // the checks (or DevTools) entry: pre-bundle it with sygnal so the first
288
+ // page load doesn't trigger a re-optimization. Only for an installed
289
+ // sygnal: a linked one is served from source, and pre-bundling the
290
+ // checks alone would give them their own copy of the core.
291
+ const include = [...(devtoolsOn ? ['sygnal/devtools'] : []), ...(devOn ? ['sygnal/diagnostics'] : [])];
292
+ result.optimizeDeps = { ...result.optimizeDeps, include };
293
+ }
294
+ // B-020: Vike adds its client entry 'sygnal/vike/onRenderClient' to
295
+ // optimizeDeps.include. With a linked sygnal, the pages' 'sygnal' is
296
+ // served from source while that pre-bundle inlines a second copy of the
297
+ // core. Unbundled, the entry's own `import 'sygnal'` resolves like the
298
+ // pages' imports (source when linked, the shared pre-bundle when
299
+ // installed): one core. Vike honours the exclude list.
300
+ // G-098: Vite doesn't discover the imports of an excluded dependency, so for an
301
+ // installed sygnal 'sygnal' is pre-bundled up front (pages that reach it only through
302
+ // the JSX runtime would otherwise get it, and its CommonJS xstream, unbundled).
303
+ if (isServe && !isVitest) {
304
+ const include = result.optimizeDeps?.include || [];
305
+ result.optimizeDeps = {
306
+ ...result.optimizeDeps,
307
+ exclude: [VIKE_CLIENT],
308
+ ...(sygnalInNodeModules(root) ? { include: [...include, 'sygnal'] } : {}),
309
+ };
310
+ }
311
+ return result;
312
+ },
313
+ configResolved(config) {
314
+ if (config?.root)
315
+ root = config.root;
316
+ // G-050: Vitest loads setup files by URL (/@fs/...) in browser-like
317
+ // environments (jsdom, happy-dom), and Vite refuses files outside
318
+ // server.fs.allow, which is the project's workspace by default. A linked
319
+ // (or hoisted) sygnal lives outside it, so allow its setup file's
320
+ // directory. The resolved list already holds Vite's defaults.
321
+ if (isVitest) {
322
+ const setup = diagnosticsSetupFile(root);
323
+ const allow = config?.server?.fs?.allow;
324
+ if (setup && Array.isArray(allow)) {
325
+ const dir = path.dirname(setup);
326
+ const inside = (base) => {
327
+ const rel = path.relative(path.resolve(base), dir);
328
+ return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel));
329
+ };
330
+ if (!allow.some(inside))
331
+ allow.push(dir);
332
+ }
333
+ }
334
+ },
335
+ resolveId: {
336
+ order: 'pre',
337
+ async handler(source, importer, opts) {
338
+ if (!isServe || isVitest)
339
+ return null;
340
+ if (source === DEV_CLIENT)
341
+ return DEV_CLIENT_ID;
342
+ if (source === 'sygnal' && importer && wrapRun && runtimeImporters.has(cleanId(importer))) {
343
+ return RUNTIME_ID;
344
+ }
345
+ if (source === VIKE_CLIENT && devInject && !opts?.ssr) {
346
+ if (importer !== VIKE_CLIENT_ID)
347
+ return VIKE_CLIENT_ID;
348
+ // The wrapper's own import of the real entry: resolve it normally.
349
+ // The real Vike client's run() then gets the run() wrapper too, when
350
+ // it is served unbundled (a pre-bundled copy stays in 'warn' mode).
351
+ const real = await this.resolve(source, importer, { ...opts, skipSelf: true });
352
+ if (real && wrapRun)
353
+ runtimeImporters.add(cleanId(real.id));
354
+ return real;
355
+ }
356
+ return null;
357
+ },
358
+ },
359
+ load(id) {
360
+ if (id === DEV_CLIENT_ID)
361
+ return devClientModule();
362
+ if (id === RUNTIME_ID)
363
+ return runtimeModule(diagnostics);
364
+ // The checks register again once the real entry has loaded: a
365
+ // pre-bundled copy of it can carry its own copy of the Sygnal core
366
+ // (e.g. with a linked sygnal), which then holds the diagnostics bridge.
367
+ if (id === VIKE_CLIENT_ID) {
368
+ if (!devOn)
369
+ return `${devtoolsImport}\nexport * from '${VIKE_CLIENT}';\n`;
370
+ return `${devtoolsImport}${devImports}${REINSTALL_IMPORT}\nexport * from '${VIKE_CLIENT}';\n${flags}\n${REINSTALL_CALL}`;
371
+ }
372
+ return null;
373
+ },
374
+ configureServer(server) {
375
+ if (isVitest || options.check === false)
376
+ return;
377
+ const checkOptions = typeof options.check === 'object' && options.check ? options.check : {};
378
+ // Deferred: the dev server doesn't wait for the first check
379
+ const checkDefaults = { strict: diagnostics.strict, ignore: diagnostics.ignore };
380
+ setTimeout(() => {
381
+ startChecker(server, root, checkOptions, checkDefaults, options.check !== undefined)
382
+ .catch(err => server?.config?.logger?.warn?.(`[sygnal] sygnal-check could not start: ${err?.message || err}`));
383
+ }, 0);
384
+ },
385
+ transform(code, id, opts) {
386
+ // SYG666 (PLAN-5 W-2): an adapter entry imported without its optional peers; every mode
387
+ const adapters = adapterImports(this, code, id);
388
+ if (adapters)
389
+ return checkPeers(this, adapters, id).then(() => devTransform.call(this, code, id, opts));
390
+ return devTransform.call(this, code, id, opts);
391
+ },
392
+ };
393
+ function devTransform(code, id, opts) {
394
+ if (!isServe)
395
+ return null;
396
+ // sygnal/astro/client (Astro islands): flags + checks first. It imports
397
+ // the public 'sygnal' entry (the app's core, B-019), which resolves to
398
+ // the run() wrapper when the diagnostics option needs it.
399
+ if (devInject && !isVitest && !opts?.ssr) {
400
+ astroClient = astroClient || astroClientFiles(root);
401
+ if (astroClient.has(cleanId(id))) {
402
+ if (wrapRun)
403
+ runtimeImporters.add(cleanId(id));
404
+ return withSourcemap(code, [[0, devSnippet]], '', id);
405
+ }
406
+ }
407
+ // Only transform JS/TS/JSX/TSX files
408
+ if (!/\.[jt]sx?$/.test(id))
409
+ return null;
410
+ // Skip node_modules
411
+ if (id.includes('node_modules'))
412
+ return null;
413
+ // Must import run from sygnal
414
+ if (!code.includes('sygnal'))
415
+ return null;
416
+ // Match against the code with comments blanked out (same offsets), so
417
+ // e.g. `// run(App)` or a commented-out import is never matched.
418
+ const noComments = blankOut(code, false);
419
+ // Find: import { run, ... } from 'sygnal'
420
+ const runImportRe = /import\s+\{[^}]*\brun\b[^}]*\}\s+from\s+['"]sygnal['"]/;
421
+ if (!runImportRe.test(noComments)) {
422
+ return disableHmr || isVitest ? null : elementHmr(code, noComments, id);
423
+ }
424
+ // Dev snippet: injected into every file that imports run() — also when
425
+ // HMR wiring below is skipped. Inserted after any shebang line and
426
+ // directive prologue, without adding a line. Nothing under Vitest: a
427
+ // global flag set by one test file would leak dev/strict mode into the
428
+ // later test files of the same worker; there the checks come from
429
+ // test.setupFiles and renderComponent() manages the modes.
430
+ const inserts = [];
431
+ if (devInject && !isVitest) {
432
+ inserts.push(flagInsertion(code, devSnippet));
433
+ if (wrapRun)
434
+ runtimeImporters.add(cleanId(id));
435
+ }
436
+ const done = (tail = '') => (inserts.length || tail ? withSourcemap(code, inserts, tail, id) : null);
437
+ // Skip HMR wiring if disabled, in tests, or already manually wired
438
+ if (disableHmr || isVitest || /\.(test|spec)\.[jt]sx?$/.test(id))
439
+ return done();
440
+ if (noComments.includes('import.meta.hot'))
441
+ return done();
442
+ // Strings and template literals blanked out too: a statement-level match only
443
+ const runCall = RUN_CALL_RE.exec(blankOut(code, true));
444
+ if (!runCall)
445
+ return done();
446
+ const [, binding, componentName] = runCall;
447
+ // Find the import path for this component
448
+ // Handles: import App from './App.jsx'
449
+ // import App from "./App"
450
+ const componentImportRe = new RegExp(`import\\s+${componentName.replace(/\$/g, '\\$')}\\s+from\\s+['"]([^'"]+)['"]`);
451
+ const componentImportMatch = noComments.match(componentImportRe);
452
+ if (!componentImportMatch)
453
+ return done();
454
+ const componentPath = componentImportMatch[1];
455
+ // Pattern 3: bare run(App, ...) — no result captured → const __sygnal = run(
456
+ if (!binding) {
457
+ inserts.push([runCall.index, 'const __sygnal = ']);
458
+ return done(hmrBlock(componentPath, '__sygnal.hmr', '__sygnal.dispose'));
459
+ }
460
+ // Pattern 2: const app = run(App, ...)
461
+ if (binding[0] !== '{') {
462
+ return done(hmrBlock(componentPath, `${binding}.hmr`, `${binding}.dispose`));
463
+ }
464
+ // Pattern 1: const { hmr, dispose, ... } = run(App, ...) — only when both
465
+ // are bound under their own names (a rename would leave them undefined)
466
+ const names = binding.slice(1, -1).split(',').map(s => s.trim());
467
+ if (names.includes('hmr') && names.includes('dispose')) {
468
+ return done(hmrBlock(componentPath, 'hmr', 'dispose'));
469
+ }
470
+ return done();
471
+ }
472
+ }
473
+ // PLAN-5 W-2 (D209): the adapter entries and the optional peer dependencies each one imports
474
+ // (the Zag packages pinned together: they depend on each other's exact versions)
475
+ const ZAG = '~1.45.0';
476
+ const ADAPTER_PEERS = {
477
+ react: ['react', 'react-dom'],
478
+ zag: ['@zag-js/vanilla'],
479
+ // D211: one subpath per Zag part, each needing only its own machine
480
+ 'ui/menu': ['@zag-js/vanilla', '@zag-js/menu'],
481
+ 'ui/select': ['@zag-js/vanilla', '@zag-js/select'],
482
+ 'ui/combobox': ['@zag-js/vanilla', '@zag-js/combobox'],
483
+ };
484
+ // G-440: a dynamic import's specifier may be a template literal without substitutions
485
+ const ADAPTER_RE = /(?:\bfrom|\bimport)\s*\(?\s*(['"`])sygnal\/(react|zag|ui\/(?:menu|select|combobox))\1/g;
486
+ const ADAPTER_ID = /^sygnal\/(react|zag|ui\/(?:menu|select|combobox))$/;
487
+ /**
488
+ * The adapter entries an app module imports (statically, dynamically or in a re-export), or null.
489
+ * G-415: real imports only. The module's AST from the plugin context's parse() (Vite and Rollup
490
+ * provide it; the code is plain JS by then); when there is none, or the code doesn't parse, a
491
+ * scan of the code with comments blanked whose `from` / `import` keyword isn't inside a string
492
+ * or template literal. A literal that mentions an entry (a docs snippet) is never an import.
493
+ */
494
+ function adapterImports(ctx, code, id) {
495
+ if (!code.includes('sygnal/') || id.includes('node_modules') || !/\.[cm]?[jt]sx?$/.test(cleanId(id)))
496
+ return null;
497
+ const noComments = blankOut(code, false);
498
+ if (!ADAPTER_RE.test(noComments))
499
+ return null;
500
+ ADAPTER_RE.lastIndex = 0;
501
+ const found = new Set();
502
+ let ast = null;
503
+ try {
504
+ ast = typeof ctx?.parse == 'function' ? ctx.parse(code) : null;
505
+ }
506
+ catch (_) { }
507
+ if (ast) {
508
+ const walk = (n) => {
509
+ if (!n || typeof n != 'object')
510
+ return;
511
+ if (Array.isArray(n))
512
+ return n.forEach(walk);
513
+ if (/^(Import|Export(Named|All))Declaration$|^ImportExpression$/.test(n.type)) {
514
+ // G-440: import(`sygnal/zag`): a template literal without substitutions is a known specifier
515
+ const src = n.source, q = src?.type == 'TemplateLiteral' && !src.expressions?.length ? src.quasis?.[0]?.value?.cooked : src?.value;
516
+ const m = ADAPTER_ID.exec(q ?? '');
517
+ if (m)
518
+ found.add(m[1]);
519
+ }
520
+ for (const k in n)
521
+ if (k != 'type' && typeof n[k] == 'object')
522
+ walk(n[k]);
523
+ };
524
+ walk(ast);
525
+ }
526
+ else {
527
+ // strings and templates blanked too: a keyword there is text, not an import
528
+ const noStrings = blankOut(code, true);
529
+ for (const m of noComments.matchAll(ADAPTER_RE)) {
530
+ if (noStrings.startsWith(m[0].slice(0, m[0][0] == 'f' ? 4 : 6), m.index))
531
+ found.add(m[2]);
532
+ }
533
+ }
534
+ return found.size ? [...found] : null;
535
+ }
536
+ /** SYG666: resolves each entry's peers from the importing module; reports the missing ones */
537
+ async function checkPeers(ctx, entries, id) {
538
+ for (const e of entries) {
539
+ const missing = [];
540
+ for (const peer of ADAPTER_PEERS[e]) {
541
+ let r = null;
542
+ try {
543
+ r = await ctx.resolve(peer, id, { skipSelf: true });
544
+ }
545
+ catch (_) { }
546
+ if (!r)
547
+ missing.push(peer);
548
+ }
549
+ if (!missing.length)
550
+ continue;
551
+ const install = missing.map(m => (m.startsWith('@zag-js/') ? `${m}@${ZAG}` : m)).join(' ');
552
+ ctx.error(`[Sygnal SYG666] 'sygnal/${e}' needs ${missing.join(', ')}, which ${missing.length > 1 ? "aren't" : "isn't"} installed: npm install ${install}.` +
553
+ (e == 'react' ? " (For Preact: alias react, react-dom and react-dom/client to preact/compat.)" : '') +
554
+ ' https://sygnal.js.org/reference/errors#syg666');
555
+ }
556
+ }
557
+ /**
558
+ * Major version of the running Vite: from the plugin context (this.meta,
559
+ * Vite 7+), else from the vite package the project resolves. Infinity when
560
+ * unknown (treated as Vite 8+: no `esbuild` option).
561
+ */
562
+ function viteMajor(ctx, root) {
563
+ const fromMeta = ctx?.meta?.viteVersion;
564
+ if (typeof fromMeta === 'string')
565
+ return parseInt(fromMeta, 10);
566
+ if (ctx?.meta?.rolldownVersion)
567
+ return 8;
568
+ try {
569
+ const req = node_module.createRequire(path.join(root, 'package.json'));
570
+ const v = JSON.parse(fs.readFileSync(req.resolve('vite/package.json'), 'utf8')).version;
571
+ const major = parseInt(v, 10);
572
+ if (major > 0)
573
+ return major;
574
+ }
575
+ catch (_) { }
576
+ return Infinity;
577
+ }
578
+ const MODES = ['off', 'collect', 'warn', 'error'];
579
+ function normalizeDiagnostics(value) {
580
+ const o = typeof value === 'string' ? { mode: value } : value || {};
581
+ const mode = o.mode === undefined ? 'warn' : o.mode;
582
+ if (!MODES.includes(mode)) {
583
+ throw new Error(`[vite-plugin-sygnal] diagnostics mode must be one of ${MODES.map(m => `'${m}'`).join(', ')}; got ${JSON.stringify(mode)}`);
584
+ }
585
+ return { mode, strict: !!o.strict, ignore: Array.isArray(o.ignore) ? o.ignore.map(String) : [] };
586
+ }
587
+ /** Module id without a query or hash. */
588
+ function cleanId(id) {
589
+ return id.replace(/[?#].*$/, '');
590
+ }
591
+ /** 'virtual:sygnal/dev': logs sygnal-check results in the browser console. */
592
+ function devClientModule() {
593
+ // Vite's client reloads the page on the first HMR update while an error
594
+ // overlay is open. A sygnal-check overlay is closed before each update (the
595
+ // server sends it again after the re-check), so it never causes a reload.
596
+ return `if (import.meta.hot) {
597
+ let shown = 0;
598
+ let ours = false;
599
+ const closeOurs = () => {
600
+ if (!ours || typeof document === 'undefined') return;
601
+ document.querySelectorAll('vite-error-overlay').forEach((n) => n.close ? n.close() : n.remove());
602
+ ours = false;
603
+ };
604
+ import.meta.hot.on('vite:error', (payload) => {
605
+ ours = !!(payload && payload.err && payload.err.plugin === '${OVERLAY_PLUGIN}');
606
+ });
607
+ import.meta.hot.on('vite:beforeUpdate', closeOurs);
608
+ import.meta.hot.on('${CHECK_EVENT}', (payload) => {
609
+ const list = (payload && payload.diagnostics) || [];
610
+ if (!list.some((d) => d.severity === 'error')) closeOurs();
611
+ if (!list.length) {
612
+ if (shown) console.info('[sygnal-check] all findings resolved');
613
+ shown = 0;
614
+ return;
615
+ }
616
+ shown = list.length;
617
+ for (const d of list) console[d.severity === 'error' ? 'error' : 'warn']('[sygnal-check] ' + d.text);
618
+ console.info('[sygnal-check] ' + payload.summary);
619
+ });
620
+ import.meta.hot.send('${CHECK_REQUEST}');
621
+ }
622
+ `;
623
+ }
624
+ /** '\0sygnal-dev:runtime': sygnal with a run() that adds the plugin's diagnostics option. */
625
+ function runtimeModule(d) {
626
+ const option = JSON.stringify({ mode: d.mode, ignore: d.ignore });
627
+ return `import { run as __run } from 'sygnal';
628
+ export * from 'sygnal';
629
+ export function run(app, drivers, options) {
630
+ if (options && options.diagnostics !== undefined) return __run(app, drivers, options);
631
+ return __run(app, drivers, Object.assign({}, options, { diagnostics: ${option} }));
632
+ }
633
+ `;
634
+ }
635
+ /** Directory of the 'sygnal' package the project resolves, or undefined. */
636
+ function sygnalPackageDir(root) {
637
+ try {
638
+ const req = node_module.createRequire(path.join(root, 'package.json'));
639
+ let dir = path.dirname(req.resolve('sygnal'));
640
+ while (dir !== path.dirname(dir)) {
641
+ const pkgFile = path.join(dir, 'package.json');
642
+ if (fs.existsSync(pkgFile) && JSON.parse(fs.readFileSync(pkgFile, 'utf8')).name === 'sygnal')
643
+ return dir;
644
+ dir = path.dirname(dir);
645
+ }
646
+ }
647
+ catch (_) { }
648
+ return undefined;
649
+ }
650
+ /** Real paths of sygnal's 'astro/client' ESM file. */
651
+ function astroClientFiles(root) {
652
+ const files = new Set();
653
+ const dir = sygnalPackageDir(root);
654
+ if (!dir)
655
+ return files;
656
+ try {
657
+ const pkg = JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf8'));
658
+ const entry = pkg.exports?.['./astro/client'];
659
+ const rel = typeof entry === 'string' ? entry : entry?.import;
660
+ if (typeof rel !== 'string')
661
+ return files;
662
+ const file = path.resolve(dir, rel);
663
+ files.add(file.split(path.sep).join('/'));
664
+ files.add(fs.realpathSync(file).split(path.sep).join('/'));
665
+ }
666
+ catch (_) { }
667
+ return files;
668
+ }
669
+ function sygnalInNodeModules(root) {
670
+ const dir = sygnalPackageDir(root);
671
+ if (!dir)
672
+ return false;
673
+ try {
674
+ return fs.realpathSync(dir).split(path.sep).includes('node_modules');
675
+ }
676
+ catch (_) {
677
+ return false;
678
+ }
679
+ }
680
+ /**
681
+ * Absolute path of the ESM build of 'sygnal/diagnostics' (its "import"
682
+ * condition), so the checks share the core instance the tests import.
683
+ */
684
+ function diagnosticsSetupFile(root) {
685
+ const dir = sygnalPackageDir(root);
686
+ if (!dir)
687
+ return undefined;
688
+ try {
689
+ const pkg = JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf8'));
690
+ const entry = pkg.exports?.['./diagnostics'];
691
+ const rel = typeof entry === 'string' ? entry : entry?.import?.default || entry?.import || entry?.default;
692
+ if (typeof rel !== 'string')
693
+ return undefined;
694
+ const file = path.resolve(dir, rel);
695
+ return fs.existsSync(file) ? file : undefined;
696
+ }
697
+ catch (_) {
698
+ return undefined;
699
+ }
700
+ }
701
+ /** Load sygnal-check from the project (optional dependency); undefined when it is missing. */
702
+ async function loadSygnalCheck(root) {
703
+ try {
704
+ const file = node_module.createRequire(path.join(root, 'package.json')).resolve('sygnal-check');
705
+ return await import(/* @vite-ignore */ node_url.pathToFileURL(file).href);
706
+ }
707
+ catch (_) { }
708
+ try {
709
+ const name = 'sygnal-check';
710
+ return await import(/* @vite-ignore */ name);
711
+ }
712
+ catch (_) {
713
+ return undefined;
714
+ }
715
+ }
716
+ const SOURCE_RE = /\.[cm]?[jt]sx?$/;
717
+ /** sygnal-check's one-line format: `file:line:col CODE [severity] Component: message (fix)` */
718
+ function formatLine(d) {
719
+ const where = d.file ? `${d.file}:${d.line}:${d.column}` : '<sygnal-check>';
720
+ const sev = d.severity === 'warn' ? '' : ` [${d.severity}]`;
721
+ return `${where} ${d.code}${sev} ${d.component ? d.component + ': ' : ''}${d.message}${d.fix ? ` (${d.fix})` : ''}`;
722
+ }
723
+ // Source directories checked by default, those that exist (Vike apps use
724
+ // pages/ and renderer/, often without src/)
725
+ const DEFAULT_INCLUDE = ['src', 'pages', 'renderer'];
726
+ /**
727
+ * What sygnal-check checks: `include` when given, else the existing default
728
+ * directories, else the project root (sygnal-check skips node_modules, dist
729
+ * and other build output). Logs one notice when the default finds no
730
+ * directory, or when none of the given paths exists, so an empty check is
731
+ * never a silent all-clear.
732
+ */
733
+ function checkInclude(root, include, notice) {
734
+ const exists = (p) => /[*?[{]/.test(p) || fs.existsSync(path.resolve(root, p));
735
+ if (include && include.length) {
736
+ if (!include.some(exists))
737
+ notice(`[sygnal] sygnal-check: none of check.include (${include.join(', ')}) exists under ${root}, so nothing is checked`);
738
+ return include;
739
+ }
740
+ const dirs = DEFAULT_INCLUDE.filter(exists);
741
+ if (dirs.length)
742
+ return dirs;
743
+ notice(`[sygnal] sygnal-check: no ${DEFAULT_INCLUDE.join('/, ')}/ directory under ${root}; checking the project root (set check.include to choose)`);
744
+ return ['.'];
745
+ }
746
+ /** Run sygnal-check now and after source changes; report to the terminal and the browser. */
747
+ async function startChecker(server, root, opts, defaults, explicit) {
748
+ const mod = await loadSygnalCheck(root);
749
+ const logger = server?.config?.logger || console;
750
+ if (!mod || typeof mod.check !== 'function') {
751
+ if (explicit)
752
+ logger.info('[sygnal] sygnal-check is not installed, so static checks are off (npm i -D sygnal-check)');
753
+ return;
754
+ }
755
+ const include = checkInclude(root, opts.include, (m) => logger.info(m));
756
+ const ignore = opts.ignore || defaults.ignore;
757
+ const strict = opts.strict === undefined ? defaults.strict : !!opts.strict;
758
+ // D144: the a11y lane is a warning unless asked for as an error, under strict too
759
+ const a11y = opts.a11y === 'error' ? 'error' : 'warn';
760
+ // Only error-severity findings open Vite's overlay: while an overlay is open
761
+ // Vite's client reloads the page on the first HMR update, so warnings stay
762
+ // in the terminal and the browser console. overlay: 'warn' is treated as
763
+ // 'error' (with a one-time notice).
764
+ if (opts.overlay === 'warn') {
765
+ logger.info("[sygnal] check.overlay: 'warn' is treated as 'error': warnings go to the browser console, not Vite's error overlay (an open overlay makes Vite reload the page on the next update)");
766
+ }
767
+ const overlay = opts.overlay !== false;
768
+ let lastKey;
769
+ let payload = null;
770
+ let overlayErr = null;
771
+ const event = () => ({ type: 'custom', event: CHECK_EVENT, data: payload });
772
+ const errorMessage = () => ({ type: 'error', err: overlayErr });
773
+ // Every connected client (after a source change). An error with no client
774
+ // connected would be buffered by Vite and shown on the next page load.
775
+ const broadcast = (findingsChanged) => {
776
+ const ws = server.ws;
777
+ if (!ws || typeof ws.send !== 'function')
778
+ return;
779
+ try {
780
+ if (findingsChanged && payload)
781
+ ws.send(event());
782
+ if (overlayErr && !(ws.clients && ws.clients.size === 0))
783
+ ws.send(errorMessage());
784
+ }
785
+ catch (_) { }
786
+ };
787
+ const run = (initial = false) => {
788
+ let diags;
789
+ try {
790
+ diags = mod.check(include, { cwd: root, strict, ignore, a11y });
791
+ }
792
+ catch (err) {
793
+ logger.warn(`[sygnal] sygnal-check failed: ${err?.message || err}`, { timestamp: true });
794
+ return;
795
+ }
796
+ // A sygnal-check from before D144 reports SYG7xx as errors under strict: keep them warnings
797
+ if (a11y !== 'error') {
798
+ diags = diags.map(d => d && d.severity === 'error' && /^SYG7\d\d$/.test(d.code) ? { ...d, severity: 'warn' } : d);
799
+ }
800
+ const shown = diags.filter(d => d.severity !== 'info');
801
+ const lines = shown.map(formatLine);
802
+ const key = lines.join('\n');
803
+ const changed = key !== lastKey;
804
+ if (changed) {
805
+ lastKey = key;
806
+ const text = typeof mod.formatDiagnostics === 'function'
807
+ ? mod.formatDiagnostics(diags)
808
+ : lines.concat(`sygnal-check: ${shown.length} finding(s)`).join('\n');
809
+ const summary = text.split('\n').pop() || '';
810
+ if (shown.length)
811
+ logger.warn(text, { timestamp: true });
812
+ else
813
+ logger.info(summary, { timestamp: true });
814
+ payload = {
815
+ summary,
816
+ diagnostics: shown.map((d, i) => ({ code: d.code, severity: d.severity, file: d.file, line: d.line, column: d.column, text: lines[i] })),
817
+ };
818
+ const forOverlay = overlay ? shown.filter(d => d.severity === 'error') : [];
819
+ const first = forOverlay[0];
820
+ overlayErr = first ? {
821
+ plugin: OVERLAY_PLUGIN,
822
+ message: forOverlay.map(formatLine).join('\n'),
823
+ stack: '',
824
+ id: path.resolve(root, first.file || ''),
825
+ loc: { file: path.resolve(root, first.file || ''), line: first.line, column: first.column },
826
+ } : null;
827
+ }
828
+ // The first check runs before any page is open; pages ask for the
829
+ // findings when they load (CHECK_REQUEST). After a change the overlay is
830
+ // sent again even when the findings are the same: the HMR update closed it.
831
+ if (!initial)
832
+ broadcast(changed);
833
+ };
834
+ run(true);
835
+ // A page that loads (or reloads) asks for the current findings: answer
836
+ // that client only, never every client.
837
+ try {
838
+ server.ws?.on?.(CHECK_REQUEST, (_data, client) => {
839
+ try {
840
+ if (payload)
841
+ client?.send?.(event());
842
+ if (overlayErr)
843
+ client?.send?.(errorMessage());
844
+ }
845
+ catch (_) { }
846
+ });
847
+ }
848
+ catch (_) { }
849
+ let timer;
850
+ const onChange = (file) => {
851
+ if (!SOURCE_RE.test(file) || file.split(/[\\/]/).includes('node_modules'))
852
+ return;
853
+ clearTimeout(timer);
854
+ timer = setTimeout(run, 100);
855
+ };
856
+ const watcher = server?.watcher;
857
+ if (watcher && typeof watcher.on === 'function') {
858
+ watcher.on('change', onChange);
859
+ watcher.on('add', onChange);
860
+ watcher.on('unlink', onChange);
861
+ }
862
+ try {
863
+ server.httpServer?.once?.('close', () => clearTimeout(timer));
864
+ }
865
+ catch (_) { }
866
+ }
867
+ const DEV_FLAG = 'if (globalThis.__SYGNAL_DEV__ === undefined) globalThis.__SYGNAL_DEV__ = true;';
868
+ const STRICT_FLAG = 'if (globalThis.__SYGNAL_STRICT__ === undefined) globalThis.__SYGNAL_STRICT__ = true;';
869
+ // A top-level (column 0) run(Component, ...) statement: bare, or declaring a
870
+ // new binding. Assignments to existing variables, nested calls and indented
871
+ // calls (e.g. inside a function or test callback) do not match (B-007). It is
872
+ // matched against the code with comments and strings blanked out.
873
+ const RUN_CALL_RE = /^(?:(?:const|let|var)\s+(\{[^}]*\}|[\w$]+)\s*=\s*)?run\s*\(\s*([A-Z][\w$]*)/m;
874
+ // Comments, string literals and template literals (a regex literal containing
875
+ // a quote or `//` can over-blank; that only ever skips HMR wiring).
876
+ const COMMENT_OR_STRING_RE = /\/\/[^\n]*|\/\*[\s\S]*?(?:\*\/|$)|(['"])(?:\\.|(?!\1)[^\\\n])*\1?|`(?:\\[\s\S]|[^\\`])*`?/g;
877
+ /** Replace comments (and, with `strings`, string/template literals) by spaces, keeping offsets and newlines. */
878
+ function blankOut(code, strings) {
879
+ return code.replace(COMMENT_OR_STRING_RE, m => !strings && m[0] !== '/' ? m : m.replace(/[^\n]/g, ' '));
880
+ }
881
+ // One directive ('use strict', "use client", ...) with any leading whitespace
882
+ // and comments. It must end with `;` (group 2) or at the end of its line.
883
+ const DIRECTIVE_RE = /(?:\s|\/\/[^\n]*|\/\*[\s\S]*?\*\/)*(['"])(?:\\.|(?!\1)[^\\\n])*\1(?:[ \t]*(;)|(?=[ \t]*(?:\/\/[^\n]*|\/\*[^\n]*?\*\/)?[ \t]*(?:\r?\n|$)))/y;
884
+ /** Insert `text` (the dev snippet) after a shebang line and the directive prologue. */
885
+ function flagInsertion(code, text) {
886
+ let at = code.startsWith('#!') ? (code.indexOf('\n') + 1 || code.length) : 0;
887
+ let semicolon = true;
888
+ DIRECTIVE_RE.lastIndex = at;
889
+ let m;
890
+ while ((m = DIRECTIVE_RE.exec(code))) {
891
+ at = DIRECTIVE_RE.lastIndex;
892
+ semicolon = !!m[2];
893
+ }
894
+ return [at, (semicolon ? '' : ';') + text];
895
+ }
896
+ const B64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
897
+ function vlq(n) {
898
+ let v = n < 0 ? (-n << 1) | 1 : n << 1;
899
+ let out = '';
900
+ do {
901
+ let digit = v & 31;
902
+ v >>>= 5;
903
+ if (v)
904
+ digit |= 32;
905
+ out += B64[digit];
906
+ } while (v);
907
+ return out;
908
+ }
909
+ /**
910
+ * Apply single-line insertions (at offsets in the original code) plus an
911
+ * appended tail, and build a v3 sourcemap without extra dependencies. No line
912
+ * is added before the tail, so every original line maps to itself; on a line
913
+ * with an insertion, the text after it maps back to its original column.
914
+ */
915
+ function withSourcemap(code, inserts, tail, id) {
916
+ inserts.sort((a, b) => a[0] - b[0]);
917
+ let out = '';
918
+ let last = 0;
919
+ for (const [at, text] of inserts) {
920
+ out += code.slice(last, at) + text;
921
+ last = at;
922
+ }
923
+ out += code.slice(last) + tail;
924
+ let offset = 0;
925
+ let k = 0;
926
+ let prevLine = 0;
927
+ let prevCol = 0;
928
+ const mappings = code.split('\n').map((line, i) => {
929
+ const segments = [[0, 0]]; // [generated column, original column]
930
+ let shift = 0;
931
+ while (k < inserts.length && inserts[k][0] <= offset + line.length) {
932
+ const col = inserts[k][0] - offset;
933
+ shift += inserts[k][1].length;
934
+ segments.push([col + shift, col]);
935
+ k++;
936
+ }
937
+ offset += line.length + 1;
938
+ let genCol = 0;
939
+ return segments.map(([gen, col]) => {
940
+ const seg = vlq(gen - genCol) + 'A' + vlq(i - prevLine) + vlq(col - prevCol);
941
+ genCol = gen;
942
+ prevLine = i;
943
+ prevCol = col;
944
+ return seg;
945
+ }).join(',');
946
+ }).join(';');
947
+ return {
948
+ code: out,
949
+ map: { version: 3, sources: [id], sourcesContent: [code], names: [], mappings },
950
+ };
951
+ }
952
+ // A top-level (column 0) defineElement(...) call, as a statement or a declaration's value
953
+ const DEFINE_ELEMENT_CALL_RE = /^(?:(?:export\s+)?(?:const|let|var)\s+[\w$]+\s*=\s*)?defineElement\s*\(/m;
954
+ const ELEMENT_IMPORT_RE = /import\s+\{[^}]*\bdefineElement\b[^}]*\}\s+from\s+['"]sygnal\/element['"]/;
955
+ /**
956
+ * PLAN-4 GS-13: a module that defines custom elements with 'sygnal/element' accepts its own
957
+ * hot updates. Re-running it calls defineElement again for the same tags, which swaps the
958
+ * component in every live element and keeps each one's state; an edited component module it
959
+ * imports reaches it the same way. Only for a top-level defineElement call, outside test
960
+ * files, when the module has no HMR code of its own and doesn't import run() (an entry's
961
+ * run() wiring decides there).
962
+ */
963
+ function elementHmr(code, noComments, id) {
964
+ if (/\.(test|spec)\.[jt]sx?$/.test(id))
965
+ return null;
966
+ if (!ELEMENT_IMPORT_RE.test(noComments) || noComments.includes('import.meta.hot'))
967
+ return null;
968
+ if (!DEFINE_ELEMENT_CALL_RE.test(blankOut(code, true)))
969
+ return null;
970
+ return withSourcemap(code, [], ELEMENT_HMR_BLOCK, id);
971
+ }
972
+ const ELEMENT_HMR_BLOCK = `
973
+ if (import.meta.hot) import.meta.hot.accept()
974
+ `;
975
+ function hmrBlock(componentPath, hmrRef, disposeRef) {
976
+ return `
977
+ if (import.meta.hot) {
978
+ import.meta.hot.accept('${componentPath}', ${hmrRef})
979
+ import.meta.hot.dispose(${disposeRef})
980
+ }
981
+ `;
982
+ }
983
+
3
984
  const SYGNAL_RENDERER_NAME = '@sygnal/astro';
4
- function sygnalAstroIntegration() {
985
+ // PLAN-4 GS-11 / D120: both island entries import this; it re-exports the default export of the
986
+ // module the `onError` option names (undefined without it)
987
+ const ON_ERROR_ID = 'virtual:sygnal/astro-on-error';
988
+ /** The Vite plugin serving ON_ERROR_ID; `file` is absolute (undefined: no hook) */
989
+ function onErrorPlugin(file) {
990
+ return {
991
+ name: 'sygnal:astro-on-error',
992
+ resolveId: (id) => id === ON_ERROR_ID ? '\0' + ON_ERROR_ID : undefined,
993
+ load: (id) => id === '\0' + ON_ERROR_ID
994
+ ? (file ? `export { default } from ${JSON.stringify(file)}` : 'export default undefined')
995
+ : undefined,
996
+ // Vite 6+ (Astro 6 renders in its own 'prerender' / 'ssr' environments): the island server
997
+ // entry imports the virtual module, so Vite must load it (not Node). `ssr.noExternal`
998
+ // below covers the 'ssr' environment and older Vite
999
+ configEnvironment: (name) => name === 'client' ? undefined : { resolve: { noExternal: ['sygnal'] } },
1000
+ };
1001
+ }
1002
+ /** The project root as a directory path (Astro gives a file: URL) */
1003
+ const rootDir = (root) =>
1004
+ // @ts-ignore — Node's process
1005
+ !root ? process.cwd() : typeof root === 'string' ? root : node_url.fileURLToPath(root);
1006
+ function sygnalAstroIntegration(options = {}) {
5
1007
  return {
6
1008
  name: SYGNAL_RENDERER_NAME,
7
1009
  hooks: {
8
- 'astro:config:setup': ({ addRenderer, updateConfig }) => {
1010
+ 'astro:config:setup': ({ addRenderer, updateConfig, command, config }) => {
9
1011
  addRenderer({
10
1012
  name: SYGNAL_RENDERER_NAME,
11
1013
  clientEntrypoint: 'sygnal/astro/client',
12
1014
  serverEntrypoint: 'sygnal/astro/server',
13
1015
  });
14
- updateConfig({
15
- vite: {
16
- esbuild: {
17
- jsx: 'automatic',
18
- jsxImportSource: 'sygnal',
19
- },
1016
+ const vite = {
1017
+ esbuild: {
1018
+ jsx: 'automatic',
1019
+ jsxImportSource: 'sygnal',
20
1020
  },
21
- });
1021
+ // D120: the island entries import the virtual onError module, so they stay on Vite:
1022
+ // not pre-bundled with it, and not externalized (loaded by Node) during SSR
1023
+ optimizeDeps: { exclude: [ON_ERROR_ID] },
1024
+ ssr: { noExternal: ['sygnal'] },
1025
+ };
1026
+ const hook = options.onError ? path.resolve(rootDir(config?.root), options.onError) : undefined;
1027
+ // Dev mode (G-014): islands are started by sygnal/astro/client, which
1028
+ // user code never imports, so the sygnal Vite plugin wraps that entry
1029
+ // in dev to install DevTools, set the dev flag and load the runtime checks first. It
1030
+ // also runs sygnal-check. `astro build` only gets the `globalthis` alias.
1031
+ if (command === 'dev') {
1032
+ vite.plugins = [sygnal({
1033
+ disableJsx: true,
1034
+ disableHmr: true,
1035
+ vitestSetup: false,
1036
+ diagnostics: options.diagnostics,
1037
+ check: options.check,
1038
+ nativeGlobalThis: options.nativeGlobalThis,
1039
+ devtools: options.devtools,
1040
+ })];
1041
+ }
1042
+ else if (options.nativeGlobalThis !== false) {
1043
+ // G-099: the same `globalthis` alias the plugin adds in dev (R2-7: unless the
1044
+ // user's vite config already aliases `globalthis`)
1045
+ const alias = globalThisAlias(config?.vite?.resolve?.alias);
1046
+ if (alias.length)
1047
+ vite.resolve = { alias };
1048
+ }
1049
+ vite.plugins = [...(vite.plugins || []), onErrorPlugin(hook)];
1050
+ updateConfig({ vite });
22
1051
  },
23
1052
  },
24
1053
  };
25
1054
  }
26
1055
 
27
1056
  module.exports = sygnalAstroIntegration;
1057
+ //# sourceMappingURL=index.cjs.js.map