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
package/dist/ui.esm.js ADDED
@@ -0,0 +1,727 @@
1
+ import { sampleCombine, defineBehavior, xs, ABORT, dropRepeats, createElement, Collection, Transition } from 'sygnal';
2
+
3
+ /*
4
+ * PLAN-5 2-U: helpers the sygnal/ui parts share. Everything from the core comes through
5
+ * '../index', which the 'sygnal/ui' build turns into the external 'sygnal' (one core per app).
6
+ */
7
+ /** `v` as a quoted CSS string, for an attribute selector (`.tab[data-value="a b"]`) */
8
+ const lit = (v) => '"' + String(v).replace(/["\\]/g, '\\$&') + '"';
9
+ /**
10
+ * G-407: a part of an id: letters, digits and '-' as they are, anything else (whitespace, '_')
11
+ * as `_<code>_` (as the core's uidPart), so two values never make the same id ('a b' / 'a_b')
12
+ */
13
+ const part = (v) => String(v).replace(/[^A-Za-z0-9-]/g, (c) => '_' + c.charCodeAt(0) + '_');
14
+ /**
15
+ * The ids of one part's elements: `uid('<slice id>-<kind>-<value>')`. The slice id is the part's
16
+ * key in `uses` (keyed() below) unless an `id` option names it; uid() makes it unique per
17
+ * component instance. The slice id and the value are escaped (part()): no whitespace (aria-controls
18
+ * is a list of ids) and no collisions.
19
+ */
20
+ const idsOf = (s, uid, fallback) => (kind, v) => {
21
+ const n = `${part(s?.id ?? fallback)}-${kind}${v == null ? '' : '-' + part(v)}`;
22
+ return uid ? uid(n) : n;
23
+ };
24
+ /**
25
+ * an ELEMENT target whose `m` command runs `run(element, options)` (a D102 spec command). G-425:
26
+ * `__sel` is the selector renderComponent's `t.commands('ELEMENT')` logs in its place
27
+ */
28
+ const on = (sel, m, run) => ({ toString: () => '' + sel, __sel: sel, spec: { commands: { [m]: run } } });
29
+ /**
30
+ * G-400: SYNC's trigger for a dialog / popover behavior: `false` when its element left the page
31
+ * while the state says open (removed while open: no close / toggle event comes), and on the
32
+ * first look when the state says open but the element isn't (a host made again on a state that
33
+ * was open)
34
+ */
35
+ const gone = (DOM, STATE, sel, isOpen) => {
36
+ let first = true;
37
+ return DOM.select(sel).elements().compose(sampleCombine(STATE.stream)).filter(([e, s]) => {
38
+ const f = first;
39
+ first = false;
40
+ return !!s?.open && (!e?.length || (f && !isOpen(e[0])));
41
+ }).mapTo(false);
42
+ };
43
+ /**
44
+ * Writes the `uses` key into the slice's `id` (the prefix of the ids the attribute helpers make)
45
+ * when no `id` option set it. Runs after the behavior's own merge, on the copy of the host's
46
+ * initialState (or the sub-component default) that merge made. G-407: `id` is also a calculated
47
+ * field, so a host reducer that replaces the slice without it gets it back (the ids stay).
48
+ */
49
+ const keyed = (b) => {
50
+ const merge = b.merge;
51
+ // G-423: renderToString gives a missing `id` the same key (extra/ssr.ts withUses)
52
+ b.keyed = 1;
53
+ b.merge = (c, k) => {
54
+ const id = b.options?.id ?? k;
55
+ b.calculated = { ...b.calculated, id: (s) => s.id ?? id };
56
+ merge(c, k);
57
+ for (const f of ['initialState', '_idle']) {
58
+ const o = c[f];
59
+ if (o && o[k] && o[k].id == null)
60
+ o[k] = { ...o[k], id: k };
61
+ }
62
+ };
63
+ return b;
64
+ };
65
+ const mod = (e) => e.altKey || e.ctrlKey || e.metaKey;
66
+ /**
67
+ * Roving focus (WAI-ARIA APG): a keydown on one of `sel`'s elements becomes the `data-value` of
68
+ * the element to move to: `next` / `prev` keys step through them in DOM order (wrapping unless
69
+ * loop is false), Home / End go to the first / last. Disabled elements are skipped. The keys it
70
+ * handles have their default prevented (no page scroll); every other key passes through.
71
+ * Reads the elements of the host's own DOM (DOM.select(sel).elements()), so it needs a real
72
+ * DOM: on renderComponent's mock DOM, simulate the action with a value instead.
73
+ */
74
+ const keyNav = (DOM, sel, next, prev, loop) => {
75
+ const keys = [...next, ...prev, 'Home', 'End'], s = DOM.select(sel);
76
+ const ours = (e) => !mod(e) && keys.includes(e.key);
77
+ return s.events('keydown', { preventDefault: ours })
78
+ .compose(sampleCombine(s.elements()))
79
+ .map(([e, els]) => {
80
+ if (!ours(e))
81
+ return;
82
+ const list = [...(els || [])].filter((el) => !el.disabled), n = list.length, k = e.key;
83
+ const i = list.findIndex((el) => el.contains(e.target));
84
+ const j = k == 'Home' ? 0 : k == 'End' ? n - 1 : i + (next.includes(k) ? 1 : -1);
85
+ const to = loop === false ? list[j] : list[(j + n) % n];
86
+ return to?.getAttribute('data-value');
87
+ })
88
+ .filter((v) => v != null);
89
+ };
90
+
91
+ /*
92
+ * PLAN-5 2-U (S-3, from spike 0-S3): Dialog, a behavior over a native <dialog>.
93
+ *
94
+ * Settings.uses = { prefs: dialog({ dialog: '.prefs', trigger: '.open-prefs', close: '.close-prefs' }) }
95
+ *
96
+ * The host renders the <dialog> (aria-labelledby its heading) and its buttons. OPEN calls
97
+ * showModal() through ELEMENT: the browser traps the focus, makes the page inert, closes on
98
+ * Escape and returns the focus. `open` / `returnValue` follow the dialog's own close event,
99
+ * whichever way it closed (a close button, Escape, a form method="dialog", closedby="any"), and
100
+ * its toggle event when it opened without the model (commandfor="…" command="show-modal").
101
+ *
102
+ * Options: `dialog` (required; 3-W G-536: it must match only this dialog, not one nested in it,
103
+ * whose close / toggle / FAIL events it would take too), `trigger` and `close` (clicks dispatch OPEN / CLOSE), `modal`
104
+ * (true; false opens it with show()), `cancelable` (true; false keeps Escape from closing it:
105
+ * the cancel event is prevented, and OPEN sets closedby="none" (G-405: Chromium's CloseWatcher
106
+ * closes on a second Escape otherwise)), `returnFocus` (true: when the dialog closes and the
107
+ * focus was lost, which WebKit does after a mouse click, the element that opened it gets it
108
+ * (G-407: the clicked trigger, recorded by OPEN), else the trigger; a selector names another
109
+ * element; false: leave it to the browser. G-430: the opener is focused from the close event, so
110
+ * a dialog rendered only while open needs no command target).
111
+ * State: { open, returnValue }. Actions: OPEN, CLOSE (data: the returnValue), CLOSED (the close
112
+ * event's returnValue), TOGGLED (from the toggle event), CANCEL (Escape: a host entry can react;
113
+ * the cancel event, or with cancelable: false the Escape keydown in the dialog (G-429): closedby
114
+ * "none" stops the cancel event, and OPEN removes the attribute again when the dialog closes;
115
+ * G-457: not an Escape an element inside handled (defaultPrevented) or an IME one, and not for a
116
+ * non-modal dialog, which Escape doesn't cancel either way),
117
+ * SYNC (G-400: the dialog left the page while open: `open: false`; G-524: or OPEN's showModal()
118
+ * threw: no close event then).
119
+ * G-400: OPEN / CLOSE send commands that check the dialog itself (showModal only on a closed
120
+ * one, close only on an open one), so a state that is out of step can't block them.
121
+ */
122
+ // G-579: an open popover Escape closes before the dialog: an auto or hint one (the `popover`
123
+ // property: an engine without hint reads it as manual; the attribute where there is none). Not a
124
+ // manual one (a Toaster region moved into the modal, D198; a tooltip): Escape cancels the dialog
125
+ const first = (p) => { try {
126
+ return /^(auto|hint|)$/i.test(p.popover ?? p.getAttribute('popover')) && p.matches(':popover-open');
127
+ }
128
+ catch (_) {
129
+ return false;
130
+ } };
131
+ // G-429: Escape in this dialog (not in a dialog nested in it, nor with a popover open inside it
132
+ // that Escape closes first, G-579). G-457: not one an element inside handled (a Zag combobox or
133
+ // menu closing its list prevents it: the browser sends no cancel then either), nor one that ends
134
+ // an IME composition (Safari sends keyCode 229 with isComposing false)
135
+ const esc = (e) => e.key == 'Escape' && !e.defaultPrevented && !e.isComposing && e.keyCode != 229 &&
136
+ e.target?.closest?.('dialog') == e.ownerTarget && ![...(e.ownerTarget?.querySelectorAll?.('[popover]') ?? [])].some(first);
137
+ // the focus went nowhere: body, a detached element, or inside a dialog that just closed
138
+ const lost = () => {
139
+ const a = document.activeElement;
140
+ return !a || a == document.body || !a.isConnected || !!a.closest?.('dialog:not([open])');
141
+ };
142
+ // an ELEMENT target (D102 spec command): focus `sel` only when the focus was lost
143
+ const refocus = (sel) => on(sel, 'focus', (el, o) => { lost() && el.focus(o); });
144
+ // G-524: OPEN's showModal() threw (bubbles: the DOM driver listens at its root)
145
+ const FAIL = 'sygnaldialogfail';
146
+ const base$5 = /*#__PURE__*/ defineBehavior({
147
+ initialState: { open: false, returnValue: '' },
148
+ intent: ({ DOM, STATE }, { dialog: d, trigger, close, cancelable, modal }) => ({
149
+ ...(trigger && { OPEN: DOM.click(trigger) }),
150
+ ...(close && { CLOSE: DOM.click(close).mapTo('') }),
151
+ TOGGLED: DOM.toggle(d).map((e) => e.newState == 'open'),
152
+ CLOSED: DOM.close(d).map((e) => e.target?.returnValue ?? ''),
153
+ // G-429: with cancelable: false the dialog has closedby="none", so Escape fires no cancel
154
+ // event: CANCEL is the Escape keydown (the cancel event, which a browser without closedby
155
+ // still fires, is only prevented). G-457: a non-modal one (show()) gets no cancel event from
156
+ // Escape with cancelable: true either, so no CANCEL: only its cancel event, prevented
157
+ CANCEL: cancelable !== false
158
+ ? DOM.select(d).events('cancel')
159
+ : modal === false
160
+ ? DOM.select(d).events('cancel', { preventDefault: true })
161
+ : xs.merge(DOM.select(d).events('cancel', { preventDefault: true }).filter(() => false), DOM.select(d).events('keydown').filter(esc)),
162
+ // G-524: SYNC also when OPEN's showModal() threw (FAIL, below; true). 3-U G-533: only this
163
+ // behavior's dialog's own FAIL, not one bubbling from a dialog inside it (another behavior's)
164
+ SYNC: ((f) => STATE ? xs.merge(gone(DOM, STATE, d, (e) => e.open), f) : f)(DOM.select(d).events(FAIL).filter((e) => e.target === e.ownerTarget).mapTo(true)),
165
+ }),
166
+ model: {
167
+ OPEN: {
168
+ STATE: (s) => (s.open ? ABORT : { ...s, open: true, returnValue: '' }),
169
+ ELEMENT: (_s, d, _n, _p, o) => {
170
+ const m = o.modal === false ? 'show' : 'showModal', by = d?.ownerTarget;
171
+ return { [m]: on(o.dialog, m, (el) => {
172
+ if (el.open)
173
+ return;
174
+ // G-407: who opened it: the clicked trigger, else the element with the focus
175
+ const a = document.activeElement, op = by?.nodeType == 1 ? by : a != document.body ? a : null;
176
+ const cb = o.cancelable === false && !el.hasAttribute('closedby');
177
+ if (cb)
178
+ el.setAttribute('closedby', 'none');
179
+ // G-461: a showModal() that throws (a disconnected dialog, a popover open on it) leaves
180
+ // no closedby and arms no listener (a later close would focus this opener). G-488: and
181
+ // the state goes back to closed, so the next OPEN can open it; G-524: through SYNC (an
182
+ // internal FAIL event), not a close event: the host's close listeners don't run for a
183
+ // dialog that never opened, and no previous returnValue comes again. The error is the
184
+ // command's (thrown once)
185
+ try {
186
+ el[m]();
187
+ }
188
+ catch (e) {
189
+ cb && el.removeAttribute('closedby');
190
+ el.dispatchEvent(new Event(FAIL, { bubbles: true }));
191
+ throw e;
192
+ }
193
+ // on close: G-429 the closedby it set goes (it is the behavior's, not the host's); G-430
194
+ // the element that opened it gets the focus back when it was lost, here rather than by a
195
+ // command (a dialog the host renders only while open is gone by then), and nothing
196
+ // keeps the opener after that. Capture: at the target it runs before the DOM driver's
197
+ // listener, so before CLOSED (whose trigger fallback would take the focus first: a
198
+ // browser-sent event runs the microtasks between listeners)
199
+ el.addEventListener('close', () => {
200
+ cb && el.removeAttribute('closedby');
201
+ if ((o.returnFocus ?? true) === true && op?.isConnected && lost())
202
+ op.focus();
203
+ }, { once: true, capture: true });
204
+ }) };
205
+ },
206
+ },
207
+ CLOSE: { ELEMENT: (_s, rv, _n, _p, o) => ({ close: on(o.dialog, 'close', (el, x) => { el.open && el.close(x.returnValue); }), returnValue: typeof rv == 'string' ? rv : '' }) },
208
+ TOGGLED: (s, open) => (open && !s.open ? { ...s, open, returnValue: '' } : ABORT),
209
+ CLOSED: {
210
+ STATE: (s, returnValue) => (!s.open && s.returnValue === returnValue ? ABORT : { ...s, open: false, returnValue }),
211
+ ELEMENT: (s, _d, _n, _p, o) => {
212
+ const f = o.returnFocus ?? true, sel = f === true ? o.trigger : f;
213
+ if (!s.open || !sel)
214
+ return ABORT;
215
+ // true: the element that opened it (OPEN's close listener, G-430), else the trigger; a
216
+ // selector: that element (each only when the focus was lost)
217
+ return { focus: refocus(sel) };
218
+ },
219
+ },
220
+ CANCEL: () => ABORT,
221
+ // G-534: after a failed OPEN the returnValue is '' (also when OPEN's STATE aborted: the state
222
+ // was open while the element was closed)
223
+ SYNC: (s, failed) => (s.open ? { ...s, open: false, ...(failed === true && { returnValue: '' }) } : ABORT),
224
+ },
225
+ });
226
+ /** A native <dialog> as a behavior: `uses = { help: dialog({ dialog: '.help', trigger: '.open-help', close: '.close-help' }) }`. */
227
+ const dialog = (options = {}) => base$5({ ...options, open: false, returnValue: '' });
228
+
229
+ /*
230
+ * PLAN-5 2-U (S-3, from spike 0-S3): Popover, a behavior over the Popover API.
231
+ *
232
+ * Filters.uses = { filters: popover({ popover: '.filters', close: '.filters-done' }) }
233
+ * <button popovertarget={uid('filters')}>Filters</button>
234
+ * <div className="filters" id={uid('filters')} popover="auto">…</div>
235
+ *
236
+ * The browser does the work: a `popovertarget` button opens and closes it, sets aria-expanded,
237
+ * light-dismisses it (a click outside, Escape) and returns the focus. The behavior mirrors
238
+ * `open` from the popover's toggle event and adds OPEN / CLOSE / TOGGLE for the model (ELEMENT
239
+ * showPopover / hidePopover / togglePopover). Open it from elsewhere with a host intent:
240
+ * `'filters.OPEN': DOM.click('.edit-filters')`. (No `trigger` option: a button that toggles an
241
+ * auto popover through the model reopens it, because the press outside light-dismisses it first;
242
+ * `popovertarget` buttons are exempt.)
243
+ *
244
+ * Options: `popover` (required), `close` (a button inside; its click dispatches CLOSE).
245
+ * State: { open }. Actions: OPEN, CLOSE, TOGGLE, TOGGLED (data: open, from the toggle event),
246
+ * SYNC (G-400: the popover left the page while open: `open: false`).
247
+ * G-400 / G-406: OPEN and CLOSE send commands that check the popover itself (`:popover-open`),
248
+ * not the state, which follows the asynchronous toggle event: OPEN then CLOSE in one tick ends
249
+ * closed, and a popover removed while open opens again.
250
+ */
251
+ const isOpen = (el) => { try {
252
+ return el.matches(':popover-open');
253
+ }
254
+ catch (_) {
255
+ return false;
256
+ } };
257
+ const base$4 = /*#__PURE__*/ defineBehavior({
258
+ initialState: { open: false },
259
+ intent: ({ DOM, STATE }, { popover: p, close }) => ({
260
+ ...(close && { CLOSE: DOM.click(close) }),
261
+ TOGGLED: DOM.toggle(p).map((e) => e.newState == 'open'),
262
+ ...(STATE && { SYNC: gone(DOM, STATE, p, isOpen) }),
263
+ }),
264
+ model: {
265
+ OPEN: { ELEMENT: (_s, _d, _n, _p, o) => ({ showPopover: on(o.popover, 'showPopover', (el) => { isOpen(el) || el.showPopover(); }) }) },
266
+ CLOSE: { ELEMENT: (_s, _d, _n, _p, o) => ({ hidePopover: on(o.popover, 'hidePopover', (el) => { isOpen(el) && el.hidePopover(); }) }) },
267
+ TOGGLE: { ELEMENT: (_s, _d, _n, _p, o) => ({ togglePopover: o.popover }) },
268
+ TOGGLED: (s, open) => (s.open == open ? ABORT : { ...s, open }),
269
+ SYNC: (s) => (s.open ? { ...s, open: false } : ABORT),
270
+ },
271
+ });
272
+ /** A popover (Popover API) as a behavior: `uses = { filters: popover({ popover: '.filters' }) }`. */
273
+ const popover = (options = {}) => base$4({ ...options, open: false });
274
+
275
+ /*
276
+ * PLAN-5 2-U (S-3, from spike 0-S3): Tooltip, a manual popover placed by CSS anchor positioning,
277
+ * shown on hover / focus after a delay and hidden after a delay (D197 `timers`).
278
+ *
279
+ * Toolbar.uses = { saveTip: tooltip({ trigger: '.save', tip: '.save-tip' }) }
280
+ *
281
+ * The host renders the trigger with aria-describedby (the tip's id) and `anchor-name`, and the
282
+ * tip with role="tooltip", popover="manual", `position-anchor` and `position-area` (styles; see
283
+ * the guide). No JavaScript positioning.
284
+ *
285
+ * Options: `trigger`, `tip` (required), `showDelay` (500 ms), `hideDelay` (100 ms).
286
+ * State: { open, pending: null | 'show' | 'hide', hover, focus }. Actions: ENTER / LEAVE (data
287
+ * 'hover' | 'focus': the pointer on the trigger or the tip (it stays open while hovered, WCAG
288
+ * 1.4.13), or the focus on the trigger), SHOW / HIDE (the timers), ESCAPE (hides it at once),
289
+ * TOGGLED. Timers (joined to the host's `timers`): '<key>.show' / '<key>.hide'; one whose state
290
+ * goes away is cancelled, so leaving before the delay never shows the tip. Needs
291
+ * makeTimerDriver() (tests: fake timers).
292
+ * G-403: the pointer and the focus are tracked apart (it hides once both have left: a mouse
293
+ * leaving doesn't hide a tip the keyboard focus still shows); touch pointer events are ignored
294
+ * (a tap focuses the trigger instead); the document keydown listener for Escape is there only
295
+ * while the tip is shown or about to be, so a page of tooltips has at most the open one's.
296
+ */
297
+ const mouse = (e) => e?.pointerType != 'touch';
298
+ const which = (k) => (k == 'focus' ? 'focus' : 'hover');
299
+ const base$3 = /*#__PURE__*/ defineBehavior({
300
+ initialState: { open: false, pending: null, hover: false, focus: false },
301
+ timers: (s, o) => ({
302
+ show: s?.pending == 'show' && { after: o.showDelay ?? 500, action: 'SHOW' },
303
+ hide: s?.pending == 'hide' && { after: o.hideDelay ?? 100, action: 'HIDE' },
304
+ }),
305
+ intent: ({ DOM, STATE }, { trigger, tip }) => ({
306
+ ENTER: xs.merge(xs.merge(DOM.pointerenter(trigger), DOM.pointerenter(tip)).filter(mouse).mapTo('hover'), DOM.focus(trigger).mapTo('focus')),
307
+ LEAVE: xs.merge(xs.merge(DOM.pointerleave(trigger), DOM.pointerleave(tip)).filter(mouse).mapTo('hover'), DOM.blur(trigger).mapTo('focus')),
308
+ ESCAPE: (STATE ? STATE.stream.map((s) => !!(s?.open || s?.pending)).compose(dropRepeats()) : xs.of(true))
309
+ .map((on) => (on ? DOM.keydown('document').key().filter((k) => k == 'Escape') : xs.never()))
310
+ .flatten(),
311
+ TOGGLED: DOM.toggle(tip).map((e) => e.newState == 'open'),
312
+ }),
313
+ model: {
314
+ ENTER: (s, k) => {
315
+ const n = { ...s, [which(k)]: true }, pending = s.open ? null : 'show';
316
+ return s[which(k)] && s.pending == pending ? ABORT : { ...n, pending };
317
+ },
318
+ LEAVE: (s, k) => {
319
+ const n = { ...s, [which(k)]: false };
320
+ // still hovered or focused: as it was
321
+ const pending = n.hover || n.focus ? s.pending : s.open ? 'hide' : null;
322
+ return !s[which(k)] && s.pending == pending ? ABORT : { ...n, pending };
323
+ },
324
+ SHOW: {
325
+ STATE: (s) => ({ ...s, pending: null }),
326
+ ELEMENT: (s, _d, _n, _p, o) => (s.open ? ABORT : { showPopover: o.tip }),
327
+ },
328
+ HIDE: {
329
+ STATE: (s) => ({ ...s, pending: null }),
330
+ ELEMENT: (s, _d, _n, _p, o) => (s.open ? { hidePopover: o.tip } : ABORT),
331
+ },
332
+ ESCAPE: {
333
+ STATE: (s) => (s.open || s.pending ? { ...s, pending: null } : ABORT),
334
+ ELEMENT: (s, _d, _n, _p, o) => (s.open ? { hidePopover: o.tip } : ABORT),
335
+ },
336
+ TOGGLED: (s, open) => (s.open == open ? ABORT : { ...s, open }),
337
+ },
338
+ });
339
+ /** A tooltip as a behavior: `uses = { tip: tooltip({ trigger: '.save', tip: '.save-tip', showDelay: 500 }) }`. */
340
+ const tooltip = (options = {}) => base$3({ ...options, open: false, pending: null, hover: false, focus: false });
341
+
342
+ /*
343
+ * PLAN-5 2-U (S-4): Tabs, a behavior that wires the host's own markup (WAI-ARIA APG tabs).
344
+ *
345
+ * Settings.uses = { tabs: tabs({ tab: '.tab', selected: 'general' }) }
346
+ * const a = tabsAttrs(state.tabs, uid)
347
+ * <div {...a.list} aria-label="Settings">
348
+ * <button className="tab" {...a.tab('general')}>General</button> …
349
+ * </div>
350
+ * <section {...a.panel('general')}>…</section> …
351
+ *
352
+ * The host renders the tabs and panels; `tabsAttrs` gives each its attributes from the slice:
353
+ * roles, ids (from `uid`, so every instance has its own), aria-selected / aria-controls /
354
+ * aria-labelledby, the roving tabindex, `hidden` on the other panels, and the hooks
355
+ * `data-value` / `data-state` ('active' | 'inactive'). A click on a tab selects it; the arrow
356
+ * keys move the focus between the tabs (and select, unless `activation: 'manual'`), Home / End
357
+ * go to the first / last; disabled tabs are skipped.
358
+ *
359
+ * Options: `tab` (required: the tabs' selector), `selected` (the start; none: the first tab
360
+ * rendered), `orientation` ('horizontal' | 'vertical': which arrow keys), `activation`
361
+ * ('automatic' | 'manual'), `loop` (true), `id` (the ids' prefix; default: the key in `uses`).
362
+ * State: { id, selected, orientation }. Actions: SELECT (a value, or a click), MOVE (a value:
363
+ * focus it, and select it unless manual).
364
+ * G-397: `tabsAttrs(slice, uid, values)` with the tabs' values shows the first one selected when
365
+ * `selected` isn't among them (a removed tab); a host that removes tabs re-selects a neighbour
366
+ * and moves the focus to it in its own reducer (the guide's closable tabs).
367
+ */
368
+ const base$2 = /*#__PURE__*/ defineBehavior({
369
+ initialState: { id: null, selected: null, orientation: 'horizontal' },
370
+ intent: ({ DOM }, { tab, orientation, loop }) => {
371
+ const v = orientation == 'vertical';
372
+ return {
373
+ SELECT: DOM.click(tab).data('value'),
374
+ MOVE: keyNav(DOM, tab, [v ? 'ArrowDown' : 'ArrowRight'], [v ? 'ArrowUp' : 'ArrowLeft'], loop),
375
+ };
376
+ },
377
+ model: {
378
+ SELECT: (s, v) => (v == null || String(v) === s.selected ? ABORT : { ...s, selected: String(v) }),
379
+ MOVE: {
380
+ STATE: (s, v, _n, _p, o) => (o.activation == 'manual' || v === s.selected ? ABORT : { ...s, selected: v }),
381
+ ELEMENT: (_s, v, _n, _p, o) => ({ focus: o.tab + '[data-value=' + lit(v) + ']' }),
382
+ },
383
+ },
384
+ });
385
+ /** Tabs as a behavior over the host's markup: `uses = { tabs: tabs({ tab: '.tab', selected: 'general' }) }`; render with `tabsAttrs`. */
386
+ const tabs = (options = {}) => keyed(base$2({ ...options, ...(options.selected != null && { selected: String(options.selected) }) }));
387
+ /**
388
+ * The attributes of a tab set, from its slice: `list` (the tablist), `tab(value)` and
389
+ * `panel(value)`. Spread them on the host's elements: `<button className="tab" {...a.tab('general')}>`.
390
+ * `values` (optional): the tabs' values in order (leave disabled ones out). With it, a `selected`
391
+ * that isn't one of them (its tab was removed) shows the first one selected (G-397); without it,
392
+ * the first tab rendered is selected only while nothing is.
393
+ */
394
+ const tabsAttrs = (s, uid, values) => {
395
+ const id = idsOf(s, uid, 'tabs'), state = (b) => (b ? 'active' : 'inactive');
396
+ const vs = values && values.map(String);
397
+ let first = vs?.[0], sel = s?.selected == null ? null : String(s.selected);
398
+ if (vs && sel != null && !vs.includes(sel))
399
+ sel = null;
400
+ // no selection (or a removed one): the first value, or the first tab (or panel) rendered
401
+ const on = (v) => {
402
+ v = String(v);
403
+ if (sel != null)
404
+ return v === sel;
405
+ first ?? (first = v);
406
+ return v === first;
407
+ };
408
+ return {
409
+ list: { role: 'tablist', 'aria-orientation': s?.orientation || 'horizontal' },
410
+ tab: (v) => {
411
+ const b = on(v);
412
+ return { type: 'button', id: id('tab', v), role: 'tab', 'aria-selected': b, 'aria-controls': id('panel', v), tabindex: b ? '0' : '-1', 'data-value': String(v), 'data-state': state(b) };
413
+ },
414
+ panel: (v) => {
415
+ const b = on(v);
416
+ return { id: id('panel', v), role: 'tabpanel', 'aria-labelledby': id('tab', v), tabindex: '0', hidden: !b, 'data-state': state(b) };
417
+ },
418
+ };
419
+ };
420
+
421
+ /*
422
+ * PLAN-5 2-U (S-4): Accordion, a behavior that wires the host's own markup (WAI-ARIA APG
423
+ * accordion).
424
+ *
425
+ * Faq.uses = { faq: accordion({ trigger: '.faq-trigger' }) }
426
+ * const a = accordionAttrs(state.faq, uid)
427
+ * <h3><button className="faq-trigger" {...a.trigger('ship')}>Shipping</button></h3>
428
+ * <div {...a.panel('ship')}>…</div>
429
+ *
430
+ * `accordionAttrs` gives the triggers aria-expanded / aria-controls (and aria-disabled on the one
431
+ * open panel when it can't be collapsed), the panels role="region" / aria-labelledby / hidden,
432
+ * ids from `uid`, and the hooks `data-value` / `data-state` ('open' | 'closed'). A click on a
433
+ * trigger toggles its panel; Up / Down / Home / End move the focus between the triggers.
434
+ *
435
+ * Options: `trigger` (required), `multiple` (false: opening one closes the others),
436
+ * `collapsible` (true; false: the last open panel stays open), `expanded` (the start: a value or
437
+ * an array), `loop` (true), `id` (the ids' prefix; default: the key in `uses`).
438
+ * State: { id, expanded: string[], collapsible }. Actions: TOGGLE, EXPAND, COLLAPSE (a value, or
439
+ * a click), MOVE (a value: focus that trigger).
440
+ */
441
+ const expand = (s, v, o) => {
442
+ v = String(v);
443
+ return s.expanded.includes(v) ? ABORT : { ...s, expanded: o.multiple ? [...s.expanded, v] : [v] };
444
+ };
445
+ const collapse = (s, v) => {
446
+ v = String(v);
447
+ return !s.expanded.includes(v) || (s.collapsible === false && s.expanded.length == 1) ? ABORT
448
+ : { ...s, expanded: s.expanded.filter((x) => x !== v) };
449
+ };
450
+ const base$1 = /*#__PURE__*/ defineBehavior({
451
+ initialState: { id: null, expanded: [], collapsible: true },
452
+ intent: ({ DOM }, { trigger, loop }) => ({
453
+ TOGGLE: DOM.click(trigger).data('value'),
454
+ MOVE: keyNav(DOM, trigger, ['ArrowDown'], ['ArrowUp'], loop),
455
+ }),
456
+ model: {
457
+ TOGGLE: (s, v, _n, _p, o) => (v == null ? ABORT : s.expanded.includes(String(v)) ? collapse(s, v) : expand(s, v, o)),
458
+ EXPAND: (s, v, _n, _p, o) => (v == null ? ABORT : expand(s, v, o)),
459
+ COLLAPSE: (s, v) => (v == null ? ABORT : collapse(s, v)),
460
+ MOVE: { ELEMENT: (_s, v, _n, _p, o) => ({ focus: o.trigger + '[data-value=' + lit(v) + ']' }) },
461
+ },
462
+ });
463
+ /** An accordion as a behavior over the host's markup: `uses = { faq: accordion({ trigger: '.faq-trigger' }) }`; render with `accordionAttrs`. */
464
+ const accordion = (options = {}) => keyed(base$1({ ...options, ...(options.expanded != null && { expanded: [].concat(options.expanded).map(String) }) }));
465
+ /** The attributes of an accordion, from its slice: `trigger(value)` and `panel(value)`. */
466
+ const accordionAttrs = (s, uid) => {
467
+ const id = idsOf(s, uid, 'accordion'), ex = s?.expanded || [];
468
+ const on = (v) => ex.includes(String(v)), state = (v) => (on(v) ? 'open' : 'closed');
469
+ const only = s?.collapsible === false && ex.length == 1;
470
+ return {
471
+ trigger: (v) => ({
472
+ type: 'button', id: id('trigger', v), 'aria-expanded': on(v), 'aria-controls': id('panel', v),
473
+ 'aria-disabled': only && on(v) ? true : undefined, 'data-value': String(v), 'data-state': state(v),
474
+ }),
475
+ panel: (v) => ({ id: id('panel', v), role: 'region', 'aria-labelledby': id('trigger', v), hidden: !on(v), 'data-state': state(v) }),
476
+ };
477
+ };
478
+
479
+ /*
480
+ * PLAN-5 2-U (S-4): Disclosure, a button that shows and hides a panel (WAI-ARIA APG disclosure).
481
+ *
482
+ * Card.uses = { more: disclosure({ trigger: '.more-toggle' }) }
483
+ * const a = disclosureAttrs(state.more, uid)
484
+ * <button className="more-toggle" {...a.trigger}>Details</button>
485
+ * <div {...a.panel}>…</div>
486
+ *
487
+ * Options: `trigger` (required), `open` (the start, false), `id` (the ids' prefix; default: the
488
+ * key in `uses`). State: { id, open }. Actions: TOGGLE (a click), OPEN, CLOSE.
489
+ */
490
+ const base = /*#__PURE__*/ defineBehavior({
491
+ initialState: { id: null, open: false },
492
+ intent: ({ DOM }, { trigger }) => ({ TOGGLE: DOM.click(trigger) }),
493
+ model: {
494
+ TOGGLE: (s) => ({ ...s, open: !s.open }),
495
+ OPEN: (s) => (s.open ? ABORT : { ...s, open: true }),
496
+ CLOSE: (s) => (s.open ? { ...s, open: false } : ABORT),
497
+ },
498
+ });
499
+ /** A disclosure as a behavior over the host's markup: `uses = { more: disclosure({ trigger: '.more-toggle' }) }`; render with `disclosureAttrs`. */
500
+ const disclosure = (options = {}) => keyed(base(options));
501
+ /** The attributes of a disclosure, from its slice: `trigger` and `panel`. */
502
+ const disclosureAttrs = (s, uid) => {
503
+ const id = idsOf(s, uid, 'disclosure'), open = !!s?.open, state = open ? 'open' : 'closed';
504
+ return {
505
+ trigger: { type: 'button', 'aria-expanded': open, 'aria-controls': id('panel'), 'data-state': state },
506
+ panel: { id: id('panel'), hidden: !open, 'data-state': state },
507
+ };
508
+ };
509
+
510
+ /*
511
+ * PLAN-5 2-U (T-1, D198, from spike 0-S4): the Toaster component.
512
+ *
513
+ * anywhere: SAVE: { EVENTS: event('TOAST', { text: 'Saved', kind: 'success' }) }
514
+ * once: <Toaster /> (main.js: run(App, { TIMER: makeTimerDriver() }))
515
+ *
516
+ * - TOAST adds { id, text, kind ('info' | 'success' | 'warning' | 'error'; default 'info'),
517
+ * timeoutMs (default 5000; 0 = until dismissed) }. A string is the text. A TOAST with the `id`
518
+ * of a shown toast replaces it in place and restarts its timer ('Saving…' → 'Saved').
519
+ * TOAST_DISMISS removes the toast with that id (no id: all of them). G-398: ids compare as
520
+ * strings (the Collection's keys); an automatic id is 't<n>', never one a shown toast has.
521
+ * - Each toast is a Collection item: its `timers` static auto-dismisses it (GS-7; fake-timer
522
+ * testable), its Dismiss button removes it, Transition animates it (`transition` names the
523
+ * classes, `duration` is how long a leaving toast stays: the leave animation's length).
524
+ * - Two persistent live regions: role="status" (polite) for every kind but errors, role="alert"
525
+ * for errors. They are rendered while empty, so a toast added later is announced.
526
+ * - While the pointer or the focus is in the region, the timers stop (and start over when both
527
+ * have left; G-399: `hover` and `focus` are tracked apart): `pauseOnHover={false}` turns this
528
+ * off. A focused Dismiss button moves the focus to the next toast's (else the previous one's,
529
+ * else where the focus came from) before its toast goes; a focused element removed any other
530
+ * way gets a focusout sent (Chromium sends none), so the region never stays paused.
531
+ * - The region is a `popover="manual"` element (top layer, above the page), re-parented into the
532
+ * topmost open modal <dialog> while one is open and back when it closes or is removed (a
533
+ * MutationObserver in the region's hooks, D198): outside the modal it would be drawn but inert
534
+ * (spike 0-S4). `__sygnalHome` keeps its events in this component (G-356). The region is the
535
+ * only child of a wrapper (`.toaster-home`), so the moved element has no siblings to patch.
536
+ * G-404: the dialogs of the region's own root (a shadow root) are looked at and observed too.
537
+ * G-426: the focus is that root's activeElement (in a shadow root the document's is the host).
538
+ *
539
+ * Class hooks: .toaster-home, .toaster (+ `className`), .toaster-status, .toaster-alert,
540
+ * .toaster-list, .toast, .toast-text, .toast-dismiss. Data attributes: data-kind on .toast,
541
+ * data-paused on .toaster.
542
+ */
543
+ // ── the region's placement (D198) ────────────────────────────────────
544
+ // the open modal dialogs, in the order they became modal (the last one is on top)
545
+ const order = [];
546
+ const modal = (d) => { try {
547
+ return d.matches(':modal');
548
+ }
549
+ catch (_) {
550
+ return false;
551
+ } };
552
+ // G-404: the dialogs of the document and of the region's own root (a shadow root: sygnal/element)
553
+ const topModal = (root) => {
554
+ const all = [...document.querySelectorAll('dialog')];
555
+ if (root !== document && root?.querySelectorAll)
556
+ all.push(...root.querySelectorAll('dialog'));
557
+ const open = all.filter(modal);
558
+ for (let i = order.length; i--;)
559
+ if (!open.includes(order[i]))
560
+ order.splice(i, 1);
561
+ for (const d of open)
562
+ if (!order.includes(d))
563
+ order.push(d);
564
+ return order[order.length - 1];
565
+ };
566
+ const show = (el) => { try {
567
+ el.matches(':popover-open') || el.showPopover();
568
+ }
569
+ catch (_) { } };
570
+ // the element with the focus in `el`'s root
571
+ const act = (el) => (el.getRootNode?.() || document).activeElement;
572
+ // G-428: a focusout that leaves `t`: not to an element inside it, and with no relatedTarget not
573
+ // while the focus is still inside (the window lost the focus: it comes back to the same element)
574
+ const left = (t, e) => !(t && t.contains?.(e.relatedTarget || act(t)));
575
+ // a toast on its way out (its Transition's leave classes)
576
+ const leaving = (b) => /-leave-/.test(b.closest?.('.toast')?.className || '');
577
+ const placement = {
578
+ insert: (v) => {
579
+ const el = v.elm, home = el.parentNode, root = el.getRootNode?.() || document;
580
+ el.__sygnalHome = home;
581
+ show(el);
582
+ // G-399: the focus in the region, and where it came from (where it goes back to). G-432: a
583
+ // focus from nowhere (the region's own refocus after a move, the browser's after a modal
584
+ // closed, the window focused again) keeps the last element it came from. G-458: but not one
585
+ // a press in the region gave: the user comes back from nowhere after a click on the page took
586
+ // the focus, and a mouse Dismiss would focus (and scroll to) an element left long ago. (A focus
587
+ // that comes back from another element names that one; a focus that left to a modal comes
588
+ // back from nowhere when it closes and keeps it: G-432)
589
+ // G-499: the press is its time, and counts for a focus within a second (a press released
590
+ // outside, a right-click or a touch scroll gets no focusin or click to clear it); a cancelled
591
+ // one (the browser took it for a scroll) at once
592
+ el.addEventListener('pointerdown', (e) => { el._p = e.timeStamp; });
593
+ el.addEventListener('pointercancel', () => { el._p = 0; });
594
+ el.addEventListener('focusin', (e) => {
595
+ if (!el.contains(e.relatedTarget)) {
596
+ el._f = 1;
597
+ el._from = e.relatedTarget || (el._p && e.timeStamp - el._p < 1e3 ? null : el._from);
598
+ }
599
+ el._p = 0;
600
+ });
601
+ el.addEventListener('focusout', (e) => { if (left(el, e))
602
+ el._f = 0; });
603
+ // a Dismiss button with the focus (keyboard; a click that focused it): the focus moves to the
604
+ // next toast's Dismiss button, else the previous one's, else back where it came from, before
605
+ // the button goes (a removed focused element gets no focusout in Chromium)
606
+ el.addEventListener('click', (e) => {
607
+ el._p = 0;
608
+ const b = e.target?.closest?.('.toast-dismiss');
609
+ // G-426: the root's activeElement (in a shadow root, the document's is the host)
610
+ if (!b || !b.contains(act(el)))
611
+ return;
612
+ const bs = [...el.querySelectorAll('.toast-dismiss')].filter((x) => x === b || !leaving(x)), i = bs.indexOf(b);
613
+ const to = bs[i + 1] || bs[i - 1] || (el._from?.isConnected && !el.contains(el._from) && el._from);
614
+ to ? to.focus() : b.blur();
615
+ });
616
+ if (typeof MutationObserver == 'undefined')
617
+ return;
618
+ const place = () => {
619
+ const to = topModal(root) || home;
620
+ if (el.parentNode !== to) {
621
+ // a move blurs a focused Dismiss button: give the focus back
622
+ const a = act(el), f = el.contains(a) && a;
623
+ to.appendChild(el);
624
+ f && f.focus();
625
+ }
626
+ // a moved popover is closed: show it again (on top of the dialog it is in)
627
+ show(el);
628
+ };
629
+ // `open` flips on showModal / close; a dialog removed while open takes the region with it
630
+ const mo = el._mo = new MutationObserver((rs) => {
631
+ // G-399: the focused element was removed (a toast dismissed some other way): no focusout
632
+ // in Chromium, so the region would stay paused; send one
633
+ if (el._f && !el.contains(act(el))) {
634
+ el._f = 0;
635
+ el.dispatchEvent(new FocusEvent('focusout', { bubbles: true }));
636
+ }
637
+ if (home.isConnected && (!el.isConnected || (el.parentNode !== home && !modal(el.parentNode)) || rs.some((r) => r.type == 'attributes')))
638
+ place();
639
+ });
640
+ const opts = { subtree: true, childList: true, attributes: true, attributeFilter: ['open'] };
641
+ mo.observe(document.body, opts);
642
+ // G-404: a region in a shadow root sees that root's dialogs open and close too
643
+ if (root !== document && root.nodeType == 11)
644
+ mo.observe(root, opts);
645
+ place();
646
+ },
647
+ // removed with its wrapper while in a dialog: take it out of the dialog too
648
+ destroy: (v) => {
649
+ const el = v.elm;
650
+ el._mo?.disconnect();
651
+ el.parentNode !== el.__sygnalHome && el.remove();
652
+ },
653
+ };
654
+ // ── one toast ──────────────────────────────────────────────────────
655
+ // (statics through a /*#__PURE__*/ Object.assign, so every bundler drops an unused Toaster; a
656
+ // componentName, so diagnostics and DevTools name them in minified builds too)
657
+ const ToastItem = /*#__PURE__*/ Object.assign(function ToastItem({ state, dismissLabel, transition, duration }) {
658
+ return createElement(Transition, { name: transition, duration }, createElement('div', { className: 'toast', 'data-kind': state.kind }, createElement('span', { className: 'toast-text' }, state.text), createElement('button', { type: 'button', className: 'toast-dismiss', 'aria-label': dismissLabel + ': ' + state.text }, dismissLabel)));
659
+ }, {
660
+ componentName: 'ToastItem',
661
+ intent: ({ DOM }) => ({ DISMISS: DOM.click('.toast-dismiss') }),
662
+ // a replaced toast (rev) gets a new timer name, so its timer starts over
663
+ timers: (s) => ({ ['expire' + (s?.rev || '')]: s?.timeoutMs > 0 && !s.paused && { after: s.timeoutMs, action: 'EXPIRE' } }),
664
+ model: { DISMISS: () => undefined, EXPIRE: () => undefined },
665
+ });
666
+ // ── the toaster ──────────────────────────────────────────────────────
667
+ const polite = (t) => t.kind != 'error';
668
+ const urgent = (t) => t.kind == 'error';
669
+ // entering or leaving the region (not moving between its children)
670
+ const crossing = (e) => !e.ownerTarget?.contains?.(e.relatedTarget);
671
+ const paused = (s, p) => ({ ...s, paused: p, toasts: s.toasts.map((t) => ({ ...t, paused: p })) });
672
+ // the pointer or the focus came in or left: paused while either is in (unless pauseOnHover={false})
673
+ const pause = (s, k, on, p) => {
674
+ if (s[k] === on)
675
+ return ABORT;
676
+ const n = { ...s, [k]: on }, z = p.pauseOnHover !== false && !!(n.hover || n.focus);
677
+ return z === s.paused ? n : paused(n, z);
678
+ };
679
+ // ids compare as strings (the Collection's keys do: 7 and '7' are one toast)
680
+ const same = (a, b) => '' + a === '' + b;
681
+ /** Renders the toasts that `event('TOAST', { text, kind, timeoutMs })` sends from anywhere. Render it once: `<Toaster />`. */
682
+ const Toaster = /*#__PURE__*/ Object.assign(function Toaster({ state, label = 'Notifications', dismissLabel = 'Dismiss', transition = 'toast', duration = 200, className }) {
683
+ const list = (filter) => createElement('div', { className: 'toaster-list' }, createElement(Collection, { of: ToastItem, from: 'toasts', filter, dismissLabel, transition, duration }));
684
+ return createElement('div', { className: 'toaster-home' }, createElement('section', {
685
+ className: className ? 'toaster ' + className : 'toaster', 'aria-label': label, attrs: { popover: 'manual' },
686
+ 'data-paused': state.paused ? '' : undefined, hook: placement,
687
+ }, createElement('div', { className: 'toaster-status', role: 'status', 'aria-live': 'polite' }, list(polite)), createElement('div', { className: 'toaster-alert', role: 'alert' }, list(urgent))));
688
+ }, {
689
+ componentName: 'Toaster',
690
+ isolatedState: true,
691
+ initialState: { toasts: [], next: 1, paused: false, hover: false, focus: false },
692
+ intent: ({ EVENTS, DOM }) => ({
693
+ TOAST: EVENTS.select('TOAST'),
694
+ DISMISS: EVENTS.select('TOAST_DISMISS'),
695
+ // G-399: the pointer and the focus apart (the timers stop while either is in the region)
696
+ HOVER: xs.merge(DOM.pointerover('.toaster').filter(crossing).mapTo(true), DOM.pointerout('.toaster').filter(crossing).mapTo(false)),
697
+ FOCUS: xs.merge(DOM.focusin('.toaster').filter(crossing).mapTo(true), DOM.focusout('.toaster').filter((e) => left(e.ownerTarget, e)).mapTo(false)),
698
+ }),
699
+ model: {
700
+ TOAST: (s, d) => {
701
+ const t = typeof d == 'string' ? { text: d } : d || {};
702
+ // G-398: an automatic id is 't<n>', one no shown toast has (a user's 2 or '2' never meets it)
703
+ const i = t.id == null ? -1 : s.toasts.findIndex((x) => same(x.id, t.id));
704
+ let n = s.next, id = t.id;
705
+ if (id == null) {
706
+ while (s.toasts.some((x) => same(x.id, 't' + n)))
707
+ n++;
708
+ id = 't' + n++;
709
+ }
710
+ const toast = { ...t, id, kind: t.kind || 'info', timeoutMs: t.timeoutMs ?? 5000, paused: s.paused, rev: i < 0 ? 0 : s.toasts[i].rev + 1 };
711
+ return {
712
+ ...s,
713
+ next: n,
714
+ toasts: i < 0 ? [...s.toasts, toast] : s.toasts.map((x, j) => (j == i ? toast : x)),
715
+ };
716
+ },
717
+ DISMISS: (s, id) => {
718
+ const toasts = id == null ? [] : s.toasts.filter((x) => !same(x.id, id));
719
+ return toasts.length == s.toasts.length ? ABORT : { ...s, toasts };
720
+ },
721
+ HOVER: (s, on, _n, p) => pause(s, 'hover', on, p),
722
+ FOCUS: (s, on, _n, p) => pause(s, 'focus', on, p),
723
+ },
724
+ });
725
+
726
+ export { Toaster, accordion, accordionAttrs, dialog, disclosure, disclosureAttrs, popover, tabs, tabsAttrs, tooltip };
727
+ //# sourceMappingURL=ui.esm.js.map