sigmx 0.1.0 → 0.1.1

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 (251) hide show
  1. package/README.md +52 -41
  2. package/dist/cli.js +3 -1
  3. package/dist/cli.js.map +2 -2
  4. package/dist/kernel/compile.js.map +2 -2
  5. package/dist/kernel/contracts.d.ts +1 -8
  6. package/dist/kernel/index.d.ts +10 -11
  7. package/dist/kernel/index.js +10 -7
  8. package/dist/kernel/index.js.map +3 -3
  9. package/dist/kernel/precompile.d.ts +0 -2
  10. package/dist/kernel/precompile.js +11 -4
  11. package/dist/kernel/precompile.js.map +2 -2
  12. package/dist/kernel/precompiled.js.map +2 -2
  13. package/dist/kernel/reactive.d.ts +6 -10
  14. package/dist/kernel/reactive.js +4 -8
  15. package/dist/kernel/reactive.js.map +2 -2
  16. package/dist/kernel/runtime.js +19 -7
  17. package/dist/kernel/runtime.js.map +2 -2
  18. package/dist/kernel/scan.d.ts +1 -10
  19. package/dist/kernel/scan.js +24 -7
  20. package/dist/kernel/scan.js.map +2 -2
  21. package/dist/kernel/state.d.ts +1 -5
  22. package/dist/kernel/state.js +49 -22
  23. package/dist/kernel/state.js.map +2 -2
  24. package/dist/kernel/strict-csp.js.map +1 -1
  25. package/dist/lib/casing.js.map +2 -2
  26. package/dist/lib/objects.d.ts +0 -1
  27. package/dist/lib/objects.js +4 -1
  28. package/dist/lib/objects.js.map +2 -2
  29. package/dist/lib/schedule.d.ts +0 -2
  30. package/dist/lib/schedule.js.map +2 -2
  31. package/dist/lib/sse.d.ts +0 -1
  32. package/dist/lib/sse.js +3 -2
  33. package/dist/lib/sse.js.map +2 -2
  34. package/dist/plugins/directives/attribute-sync.js.map +1 -1
  35. package/dist/plugins/directives/boost.js +2 -1
  36. package/dist/plugins/directives/boost.js.map +2 -2
  37. package/dist/plugins/directives/busy-flag.js.map +1 -1
  38. package/dist/plugins/directives/class-toggle.js.map +1 -1
  39. package/dist/plugins/directives/cloak.js.map +1 -1
  40. package/dist/plugins/directives/collapse.js.map +1 -1
  41. package/dist/plugins/directives/declare.js.map +1 -1
  42. package/dist/plugins/directives/derive.js +4 -1
  43. package/dist/plugins/directives/derive.js.map +2 -2
  44. package/dist/plugins/directives/element-ref.js.map +1 -1
  45. package/dist/plugins/directives/event-listener.js +4 -1
  46. package/dist/plugins/directives/event-listener.js.map +2 -2
  47. package/dist/plugins/directives/frame-loop.js.map +1 -1
  48. package/dist/plugins/directives/html.js.map +1 -1
  49. package/dist/plugins/directives/inline-style.js +1 -1
  50. package/dist/plugins/directives/inline-style.js.map +2 -2
  51. package/dist/plugins/directives/mask.js.map +1 -1
  52. package/dist/plugins/directives/media-query.js +2 -1
  53. package/dist/plugins/directives/media-query.js.map +2 -2
  54. package/dist/plugins/directives/on-mount.js +4 -1
  55. package/dist/plugins/directives/on-mount.js.map +2 -2
  56. package/dist/plugins/directives/patch-listener.js.map +1 -1
  57. package/dist/plugins/directives/remove-me.js.map +1 -1
  58. package/dist/plugins/directives/scroll-to.js.map +1 -1
  59. package/dist/plugins/directives/size-watch.js.map +1 -1
  60. package/dist/plugins/directives/state-dump.js.map +1 -1
  61. package/dist/plugins/directives/storage-sync.js.map +1 -1
  62. package/dist/plugins/directives/teleport.js.map +1 -1
  63. package/dist/plugins/directives/text-content.js.map +1 -1
  64. package/dist/plugins/directives/timer.js.map +1 -1
  65. package/dist/plugins/directives/transition-name.js.map +1 -1
  66. package/dist/plugins/directives/transition.js.map +1 -1
  67. package/dist/plugins/directives/trap.js +8 -2
  68. package/dist/plugins/directives/trap.js.map +2 -2
  69. package/dist/plugins/directives/tween.js.map +2 -2
  70. package/dist/plugins/directives/two-way-bind.js +37 -7
  71. package/dist/plugins/directives/two-way-bind.js.map +2 -2
  72. package/dist/plugins/directives/url-params.js +2 -1
  73. package/dist/plugins/directives/url-params.js.map +2 -2
  74. package/dist/plugins/directives/url-replace.js.map +1 -1
  75. package/dist/plugins/directives/validity.js.map +1 -1
  76. package/dist/plugins/directives/viewport.js +4 -1
  77. package/dist/plugins/directives/viewport.js.map +2 -2
  78. package/dist/plugins/directives/visibility.js.map +1 -1
  79. package/dist/plugins/directives/watch.d.ts +0 -1
  80. package/dist/plugins/directives/watch.js.map +2 -2
  81. package/dist/plugins/functions/bulk-set.js +5 -3
  82. package/dist/plugins/functions/bulk-set.js.map +2 -2
  83. package/dist/plugins/functions/bulk-toggle.js +5 -3
  84. package/dist/plugins/functions/bulk-toggle.js.map +2 -2
  85. package/dist/plugins/functions/confirm.js.map +1 -1
  86. package/dist/plugins/functions/copy-text.js.map +1 -1
  87. package/dist/plugins/functions/dispatch.js.map +2 -2
  88. package/dist/plugins/functions/locale-format.js.map +1 -1
  89. package/dist/plugins/functions/range-map.js.map +1 -1
  90. package/dist/plugins/functions/request.js +19 -5
  91. package/dist/plugins/functions/request.js.map +2 -2
  92. package/dist/plugins/functions/untracked-read.js.map +1 -1
  93. package/dist/plugins/functions/websocket.js +5 -1
  94. package/dist/plugins/functions/websocket.js.map +2 -2
  95. package/dist/plugins/index.d.ts +36 -36
  96. package/dist/plugins/index.js +33 -33
  97. package/dist/plugins/index.js.map +2 -2
  98. package/dist/plugins/server-events/apply-elements.js +4 -1
  99. package/dist/plugins/server-events/apply-elements.js.map +2 -2
  100. package/dist/plugins/server-events/apply-state.js.map +1 -1
  101. package/dist/plugins/server-events/morph.d.ts +0 -2
  102. package/dist/plugins/server-events/morph.js +31 -8
  103. package/dist/plugins/server-events/morph.js.map +2 -2
  104. package/dist/presets/all.d.ts +0 -1
  105. package/dist/presets/all.js +23 -23
  106. package/dist/presets/all.js.map +2 -2
  107. package/dist/presets/essentials.d.ts +0 -1
  108. package/dist/presets/essentials.js +27 -9
  109. package/dist/presets/essentials.js.map +2 -2
  110. package/dist/presets/minimal.d.ts +0 -1
  111. package/dist/presets/minimal.js +2 -2
  112. package/dist/presets/minimal.js.map +2 -2
  113. package/dist/server.d.ts +102 -0
  114. package/dist/server.js +190 -0
  115. package/dist/server.js.map +7 -0
  116. package/dist/sigmx.standalone.js +1 -1
  117. package/dist/standalone.js.map +2 -2
  118. package/dist/vite.d.ts +2 -2
  119. package/dist/vite.js +31 -8
  120. package/dist/vite.js.map +2 -2
  121. package/package.json +19 -2
  122. package/dist/auto.d.ts +0 -1
  123. package/dist/auto.js +0 -7
  124. package/dist/auto.js.map +0 -7
  125. package/dist/core/csp.d.ts +0 -7
  126. package/dist/core/csp.js +0 -20
  127. package/dist/core/csp.js.map +0 -7
  128. package/dist/core/engine.d.ts +0 -10
  129. package/dist/core/engine.js +0 -200
  130. package/dist/core/engine.js.map +0 -7
  131. package/dist/core/expr.d.ts +0 -12
  132. package/dist/core/expr.js +0 -94
  133. package/dist/core/expr.js.map +0 -7
  134. package/dist/core/index.d.ts +0 -16
  135. package/dist/core/index.js +0 -46
  136. package/dist/core/index.js.map +0 -7
  137. package/dist/core/signals.d.ts +0 -42
  138. package/dist/core/signals.js +0 -195
  139. package/dist/core/signals.js.map +0 -7
  140. package/dist/core/store.d.ts +0 -32
  141. package/dist/core/store.js +0 -185
  142. package/dist/core/store.js.map +0 -7
  143. package/dist/core/types.d.ts +0 -101
  144. package/dist/core/types.js +0 -1
  145. package/dist/core/types.js.map +0 -7
  146. package/dist/plugins/actions/clipboard.d.ts +0 -2
  147. package/dist/plugins/actions/clipboard.js +0 -11
  148. package/dist/plugins/actions/clipboard.js.map +0 -7
  149. package/dist/plugins/actions/fit.d.ts +0 -2
  150. package/dist/plugins/actions/fit.js +0 -14
  151. package/dist/plugins/actions/fit.js.map +0 -7
  152. package/dist/plugins/actions/intl.d.ts +0 -2
  153. package/dist/plugins/actions/intl.js +0 -21
  154. package/dist/plugins/actions/intl.js.map +0 -7
  155. package/dist/plugins/actions/peek.d.ts +0 -2
  156. package/dist/plugins/actions/peek.js +0 -6
  157. package/dist/plugins/actions/peek.js.map +0 -7
  158. package/dist/plugins/actions/setAll.d.ts +0 -2
  159. package/dist/plugins/actions/setAll.js +0 -11
  160. package/dist/plugins/actions/setAll.js.map +0 -7
  161. package/dist/plugins/actions/toggleAll.d.ts +0 -2
  162. package/dist/plugins/actions/toggleAll.js +0 -11
  163. package/dist/plugins/actions/toggleAll.js.map +0 -7
  164. package/dist/plugins/attributes/attr.d.ts +0 -2
  165. package/dist/plugins/attributes/attr.js +0 -20
  166. package/dist/plugins/attributes/attr.js.map +0 -7
  167. package/dist/plugins/attributes/bind.d.ts +0 -6
  168. package/dist/plugins/attributes/bind.js +0 -81
  169. package/dist/plugins/attributes/bind.js.map +0 -7
  170. package/dist/plugins/attributes/class.d.ts +0 -2
  171. package/dist/plugins/attributes/class.js +0 -22
  172. package/dist/plugins/attributes/class.js.map +0 -7
  173. package/dist/plugins/attributes/computed.d.ts +0 -2
  174. package/dist/plugins/attributes/computed.js +0 -20
  175. package/dist/plugins/attributes/computed.js.map +0 -7
  176. package/dist/plugins/attributes/customValidity.d.ts +0 -2
  177. package/dist/plugins/attributes/customValidity.js +0 -14
  178. package/dist/plugins/attributes/customValidity.js.map +0 -7
  179. package/dist/plugins/attributes/effect.d.ts +0 -2
  180. package/dist/plugins/attributes/effect.js +0 -12
  181. package/dist/plugins/attributes/effect.js.map +0 -7
  182. package/dist/plugins/attributes/indicator.d.ts +0 -2
  183. package/dist/plugins/attributes/indicator.js +0 -20
  184. package/dist/plugins/attributes/indicator.js.map +0 -7
  185. package/dist/plugins/attributes/init.d.ts +0 -2
  186. package/dist/plugins/attributes/init.js +0 -14
  187. package/dist/plugins/attributes/init.js.map +0 -7
  188. package/dist/plugins/attributes/jsonSignals.d.ts +0 -2
  189. package/dist/plugins/attributes/jsonSignals.js +0 -15
  190. package/dist/plugins/attributes/jsonSignals.js.map +0 -7
  191. package/dist/plugins/attributes/matchMedia.d.ts +0 -2
  192. package/dist/plugins/attributes/matchMedia.js +0 -19
  193. package/dist/plugins/attributes/matchMedia.js.map +0 -7
  194. package/dist/plugins/attributes/on.d.ts +0 -5
  195. package/dist/plugins/attributes/on.js +0 -28
  196. package/dist/plugins/attributes/on.js.map +0 -7
  197. package/dist/plugins/attributes/onIntersect.d.ts +0 -2
  198. package/dist/plugins/attributes/onIntersect.js +0 -28
  199. package/dist/plugins/attributes/onIntersect.js.map +0 -7
  200. package/dist/plugins/attributes/onInterval.d.ts +0 -2
  201. package/dist/plugins/attributes/onInterval.js +0 -18
  202. package/dist/plugins/attributes/onInterval.js.map +0 -7
  203. package/dist/plugins/attributes/onRaf.d.ts +0 -1
  204. package/dist/plugins/attributes/onRaf.js +0 -19
  205. package/dist/plugins/attributes/onRaf.js.map +0 -7
  206. package/dist/plugins/attributes/onResize.d.ts +0 -1
  207. package/dist/plugins/attributes/onResize.js +0 -17
  208. package/dist/plugins/attributes/onResize.js.map +0 -7
  209. package/dist/plugins/attributes/onSignalPatch.d.ts +0 -5
  210. package/dist/plugins/attributes/onSignalPatch.js +0 -35
  211. package/dist/plugins/attributes/onSignalPatch.js.map +0 -7
  212. package/dist/plugins/attributes/persist.d.ts +0 -6
  213. package/dist/plugins/attributes/persist.js +0 -16
  214. package/dist/plugins/attributes/persist.js.map +0 -7
  215. package/dist/plugins/attributes/queryString.d.ts +0 -5
  216. package/dist/plugins/attributes/queryString.js +0 -54
  217. package/dist/plugins/attributes/queryString.js.map +0 -7
  218. package/dist/plugins/attributes/ref.d.ts +0 -2
  219. package/dist/plugins/attributes/ref.js +0 -13
  220. package/dist/plugins/attributes/ref.js.map +0 -7
  221. package/dist/plugins/attributes/replaceUrl.d.ts +0 -1
  222. package/dist/plugins/attributes/replaceUrl.js +0 -11
  223. package/dist/plugins/attributes/replaceUrl.js.map +0 -7
  224. package/dist/plugins/attributes/scrollIntoView.d.ts +0 -2
  225. package/dist/plugins/attributes/scrollIntoView.js +0 -19
  226. package/dist/plugins/attributes/scrollIntoView.js.map +0 -7
  227. package/dist/plugins/attributes/show.d.ts +0 -2
  228. package/dist/plugins/attributes/show.js +0 -19
  229. package/dist/plugins/attributes/show.js.map +0 -7
  230. package/dist/plugins/attributes/signals.d.ts +0 -2
  231. package/dist/plugins/attributes/signals.js +0 -13
  232. package/dist/plugins/attributes/signals.js.map +0 -7
  233. package/dist/plugins/attributes/style.d.ts +0 -2
  234. package/dist/plugins/attributes/style.js +0 -25
  235. package/dist/plugins/attributes/style.js.map +0 -7
  236. package/dist/plugins/attributes/text.d.ts +0 -1
  237. package/dist/plugins/attributes/text.js +0 -13
  238. package/dist/plugins/attributes/text.js.map +0 -7
  239. package/dist/plugins/attributes/viewTransition.d.ts +0 -1
  240. package/dist/plugins/attributes/viewTransition.js +0 -11
  241. package/dist/plugins/attributes/viewTransition.js.map +0 -7
  242. package/dist/sigmx.auto.js +0 -5
  243. package/dist/utils/object.d.ts +0 -9
  244. package/dist/utils/object.js +0 -26
  245. package/dist/utils/object.js.map +0 -7
  246. package/dist/utils/text.d.ts +0 -7
  247. package/dist/utils/text.js +0 -15
  248. package/dist/utils/text.js.map +0 -7
  249. package/dist/utils/timing.d.ts +0 -14
  250. package/dist/utils/timing.js +0 -58
  251. package/dist/utils/timing.js.map +0 -7
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/directives/patch-listener.ts"],
4
- "sourcesContent": ["import { attribute, withTiming } from '../../kernel/index.js'\n\nconst touches = (patch: Record<string, any>, path: string): boolean => {\n let cur: any = patch\n for (const k of path.split('.')) {\n if (cur == null || typeof cur !== 'object' || !(k in cur)) return false\n cur = cur[k]\n }\n return true\n}\n\n/**\n * Runs after signals change, with the patch as `patch`. A key narrows it to one path:\n * `on-signal-patch:user.name=\"...\"`.\n */\nexport const onSignalPatch = attribute({\n name: 'on-signal-patch',\n value: 'required',\n returns: false,\n args: ['patch'],\n mount({ key, cased, mods, evaluate, listen }) {\n const path = key ? cased() : ''\n let running = false\n const run = withTiming((patch: Record<string, any>) => {\n if (running) return\n running = true\n try {\n evaluate(undefined, patch)\n } finally {\n running = false\n }\n }, mods)\n listen(document, 'sigmx-signal-patch', (e: CustomEvent) => {\n if (!path || touches(e.detail, path)) run(e.detail)\n })\n },\n})\n"],
4
+ "sourcesContent": ["import { attribute, withTiming } from '../../kernel/index.js';\n\nconst touches = (patch: Record<string, any>, path: string): boolean => {\n let cur: any = patch;\n for (const k of path.split('.')) {\n if (cur == null || typeof cur !== 'object' || !(k in cur)) return false;\n cur = cur[k];\n }\n return true;\n};\n\n/**\n * Runs after signals change, with the patch as `patch`. A key narrows it to one path:\n * `on-signal-patch:user.name=\"...\"`.\n */\nexport const onSignalPatch = attribute({\n name: 'on-signal-patch',\n value: 'required',\n returns: false,\n args: ['patch'],\n mount({ key, cased, mods, evaluate, listen }) {\n const path = key ? cased() : '';\n let running = false;\n const run = withTiming((patch: Record<string, any>) => {\n if (running) return;\n running = true;\n try {\n evaluate(undefined, patch);\n } finally {\n running = false;\n }\n }, mods);\n listen(document, 'sigmx-signal-patch', (e: CustomEvent) => {\n if (!path || touches(e.detail, path)) run(e.detail);\n });\n },\n});\n"],
5
5
  "mappings": "AAAA,SAAS,WAAW,kBAAkB;AAEtC,MAAM,UAAU,CAAC,OAA4B,SAA0B;AACrE,MAAI,MAAW;AACf,aAAW,KAAK,KAAK,MAAM,GAAG,GAAG;AAC/B,QAAI,OAAO,QAAQ,OAAO,QAAQ,YAAY,EAAE,KAAK,KAAM,QAAO;AAClE,UAAM,IAAI,CAAC;AAAA,EACb;AACA,SAAO;AACT;AAMO,MAAM,gBAAgB,UAAU;AAAA,EACrC,MAAM;AAAA,EACN,OAAO;AAAA,EACP,SAAS;AAAA,EACT,MAAM,CAAC,OAAO;AAAA,EACd,MAAM,EAAE,KAAK,OAAO,MAAM,UAAU,OAAO,GAAG;AAC5C,UAAM,OAAO,MAAM,MAAM,IAAI;AAC7B,QAAI,UAAU;AACd,UAAM,MAAM,WAAW,CAAC,UAA+B;AACrD,UAAI,QAAS;AACb,gBAAU;AACV,UAAI;AACF,iBAAS,QAAW,KAAK;AAAA,MAC3B,UAAE;AACA,kBAAU;AAAA,MACZ;AAAA,IACF,GAAG,IAAI;AACP,WAAO,UAAU,sBAAsB,CAAC,MAAmB;AACzD,UAAI,CAAC,QAAQ,QAAQ,EAAE,QAAQ,IAAI,EAAG,KAAI,EAAE,MAAM;AAAA,IACpD,CAAC;AAAA,EACH;AACF,CAAC;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/directives/remove-me.ts"],
4
- "sourcesContent": ["import { attribute, toMs } from '../../kernel/index.js'\n\n/** Removes the element after a delay: `remove-me=\"3s\"` (default immediately). Handy for toasts. */\nexport const removeMe = attribute({\n name: 'remove-me',\n key: 'forbidden',\n mount({ el, value, cleanup }) {\n const t = setTimeout(() => el.remove(), toMs([value], 0))\n cleanup(() => clearTimeout(t))\n },\n})\n"],
4
+ "sourcesContent": ["import { attribute, toMs } from '../../kernel/index.js';\n\n/** Removes the element after a delay: `remove-me=\"3s\"` (default immediately). Handy for toasts. */\nexport const removeMe = attribute({\n name: 'remove-me',\n key: 'forbidden',\n mount({ el, value, cleanup }) {\n const t = setTimeout(() => el.remove(), toMs([value], 0));\n cleanup(() => clearTimeout(t));\n },\n});\n"],
5
5
  "mappings": "AAAA,SAAS,WAAW,YAAY;AAGzB,MAAM,WAAW,UAAU;AAAA,EAChC,MAAM;AAAA,EACN,KAAK;AAAA,EACL,MAAM,EAAE,IAAI,OAAO,QAAQ,GAAG;AAC5B,UAAM,IAAI,WAAW,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC;AACxD,YAAQ,MAAM,aAAa,CAAC,CAAC;AAAA,EAC/B;AACF,CAAC;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/directives/scroll-to.ts"],
4
- "sourcesContent": ["import { attribute } from '../../kernel/index.js'\n\nconst pick = (mods: Map<string, string[]>, names: string[], fallback: string) =>\n names.find((n) => mods.has(n)) ?? fallback\n\n/** Scrolls the element into view on mount. Modifiers: smooth/instant/auto, vstart..vnearest, hstart..hnearest, focus. */\nexport const scrollIntoView = attribute({\n name: 'scroll-into-view',\n key: 'forbidden',\n value: 'forbidden',\n mount({ el, mods }) {\n el.scrollIntoView({\n behavior: pick(mods, ['smooth', 'instant', 'auto'], 'smooth') as ScrollBehavior,\n block: pick(mods, ['vstart', 'vcenter', 'vend', 'vnearest'], 'vcenter').slice(1) as ScrollLogicalPosition,\n inline: pick(mods, ['hstart', 'hcenter', 'hend', 'hnearest'], 'hcenter').slice(1) as ScrollLogicalPosition,\n })\n if (mods.has('focus')) (el as HTMLElement).focus?.()\n },\n})\n"],
4
+ "sourcesContent": ["import { attribute } from '../../kernel/index.js';\n\nconst pick = (mods: Map<string, string[]>, names: string[], fallback: string) =>\n names.find((n) => mods.has(n)) ?? fallback;\n\n/** Scrolls the element into view on mount. Modifiers: smooth/instant/auto, vstart..vnearest, hstart..hnearest, focus. */\nexport const scrollIntoView = attribute({\n name: 'scroll-into-view',\n key: 'forbidden',\n value: 'forbidden',\n mount({ el, mods }) {\n el.scrollIntoView({\n behavior: pick(mods, ['smooth', 'instant', 'auto'], 'smooth') as ScrollBehavior,\n block: pick(mods, ['vstart', 'vcenter', 'vend', 'vnearest'], 'vcenter').slice(1) as ScrollLogicalPosition,\n inline: pick(mods, ['hstart', 'hcenter', 'hend', 'hnearest'], 'hcenter').slice(1) as ScrollLogicalPosition,\n });\n if (mods.has('focus')) (el as HTMLElement).focus?.();\n },\n});\n"],
5
5
  "mappings": "AAAA,SAAS,iBAAiB;AAE1B,MAAM,OAAO,CAAC,MAA6B,OAAiB,aAC1D,MAAM,KAAK,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,KAAK;AAG7B,MAAM,iBAAiB,UAAU;AAAA,EACtC,MAAM;AAAA,EACN,KAAK;AAAA,EACL,OAAO;AAAA,EACP,MAAM,EAAE,IAAI,KAAK,GAAG;AAClB,OAAG,eAAe;AAAA,MAChB,UAAU,KAAK,MAAM,CAAC,UAAU,WAAW,MAAM,GAAG,QAAQ;AAAA,MAC5D,OAAO,KAAK,MAAM,CAAC,UAAU,WAAW,QAAQ,UAAU,GAAG,SAAS,EAAE,MAAM,CAAC;AAAA,MAC/E,QAAQ,KAAK,MAAM,CAAC,UAAU,WAAW,QAAQ,UAAU,GAAG,SAAS,EAAE,MAAM,CAAC;AAAA,IAClF,CAAC;AACD,QAAI,KAAK,IAAI,OAAO,EAAG,CAAC,GAAmB,QAAQ;AAAA,EACrD;AACF,CAAC;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/directives/size-watch.ts"],
4
- "sourcesContent": ["import { attribute, withTiming } from '../../kernel/index.js'\n\nexport const onResize = attribute({\n name: 'on-resize',\n key: 'forbidden',\n value: 'required',\n returns: false,\n mount({ el, mods, evaluate }) {\n const run = withTiming(() => evaluate(), mods)\n const ro = new ResizeObserver(() => run())\n ro.observe(el)\n return () => ro.disconnect()\n },\n})\n"],
4
+ "sourcesContent": ["import { attribute, withTiming } from '../../kernel/index.js';\n\nexport const onResize = attribute({\n name: 'on-resize',\n key: 'forbidden',\n value: 'required',\n returns: false,\n mount({ el, mods, evaluate }) {\n const run = withTiming(() => evaluate(), mods);\n const ro = new ResizeObserver(() => run());\n ro.observe(el);\n return () => ro.disconnect();\n },\n});\n"],
5
5
  "mappings": "AAAA,SAAS,WAAW,kBAAkB;AAE/B,MAAM,WAAW,UAAU;AAAA,EAChC,MAAM;AAAA,EACN,KAAK;AAAA,EACL,OAAO;AAAA,EACP,SAAS;AAAA,EACT,MAAM,EAAE,IAAI,MAAM,SAAS,GAAG;AAC5B,UAAM,MAAM,WAAW,MAAM,SAAS,GAAG,IAAI;AAC7C,UAAM,KAAK,IAAI,eAAe,MAAM,IAAI,CAAC;AACzC,OAAG,QAAQ,EAAE;AACb,WAAO,MAAM,GAAG,WAAW;AAAA,EAC7B;AACF,CAAC;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/directives/state-dump.ts"],
4
- "sourcesContent": ["import { attribute } from '../../kernel/index.js'\n\n/** Renders the store (or a filtered part) as JSON. `__terse` for single-line output. */\nexport const jsonSignals = attribute({\n name: 'json-signals',\n key: 'forbidden',\n mount({ el, value, mods, evaluate, effect, store }) {\n const filter = value ? evaluate() : undefined\n effect(() => {\n el.textContent = JSON.stringify(store.snapshot(filter), null, mods.has('terse') ? 0 : 2)\n })\n },\n})\n"],
4
+ "sourcesContent": ["import { attribute } from '../../kernel/index.js';\n\n/** Renders the store (or a filtered part) as JSON. `__terse` for single-line output. */\nexport const jsonSignals = attribute({\n name: 'json-signals',\n key: 'forbidden',\n mount({ el, value, mods, evaluate, effect, store }) {\n const filter = value ? evaluate() : undefined;\n effect(() => {\n el.textContent = JSON.stringify(store.snapshot(filter), null, mods.has('terse') ? 0 : 2);\n });\n },\n});\n"],
5
5
  "mappings": "AAAA,SAAS,iBAAiB;AAGnB,MAAM,cAAc,UAAU;AAAA,EACnC,MAAM;AAAA,EACN,KAAK;AAAA,EACL,MAAM,EAAE,IAAI,OAAO,MAAM,UAAU,QAAQ,MAAM,GAAG;AAClD,UAAM,SAAS,QAAQ,SAAS,IAAI;AACpC,WAAO,MAAM;AACX,SAAG,cAAc,KAAK,UAAU,MAAM,SAAS,MAAM,GAAG,MAAM,KAAK,IAAI,OAAO,IAAI,IAAI,CAAC;AAAA,IACzF,CAAC;AAAA,EACH;AACF,CAAC;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/directives/storage-sync.ts"],
4
- "sourcesContent": ["import { attribute } from '../../kernel/index.js'\n\n/**\n * Saves matching signals to localStorage (`__session` for sessionStorage) and restores them on\n * mount. `persist:key` sets the storage key; the value is an optional `{ include, exclude }` filter.\n * Declare defaults with `signals:x__ifmissing` so restored values are not overwritten.\n */\nexport const persist = attribute({\n name: 'persist',\n mount({ key, value, mods, evaluate, store, effect }) {\n const storage = mods.has('session') ? sessionStorage : localStorage\n const name = key || 'sigmx'\n const filter = value ? evaluate() : undefined\n const saved = storage.getItem(name)\n if (saved) store.merge(JSON.parse(saved))\n effect(() => storage.setItem(name, JSON.stringify(store.snapshot(filter, { computed: false }))))\n },\n})\n"],
4
+ "sourcesContent": ["import { attribute } from '../../kernel/index.js';\n\n/**\n * Saves matching signals to localStorage (`__session` for sessionStorage) and restores them on\n * mount. `persist:key` sets the storage key; the value is an optional `{ include, exclude }` filter.\n * Declare defaults with `signals:x__ifmissing` so restored values are not overwritten.\n */\nexport const persist = attribute({\n name: 'persist',\n mount({ key, value, mods, evaluate, store, effect }) {\n const storage = mods.has('session') ? sessionStorage : localStorage;\n const name = key || 'sigmx';\n const filter = value ? evaluate() : undefined;\n const saved = storage.getItem(name);\n if (saved) store.merge(JSON.parse(saved));\n effect(() => storage.setItem(name, JSON.stringify(store.snapshot(filter, { computed: false }))));\n },\n});\n"],
5
5
  "mappings": "AAAA,SAAS,iBAAiB;AAOnB,MAAM,UAAU,UAAU;AAAA,EAC/B,MAAM;AAAA,EACN,MAAM,EAAE,KAAK,OAAO,MAAM,UAAU,OAAO,OAAO,GAAG;AACnD,UAAM,UAAU,KAAK,IAAI,SAAS,IAAI,iBAAiB;AACvD,UAAM,OAAO,OAAO;AACpB,UAAM,SAAS,QAAQ,SAAS,IAAI;AACpC,UAAM,QAAQ,QAAQ,QAAQ,IAAI;AAClC,QAAI,MAAO,OAAM,MAAM,KAAK,MAAM,KAAK,CAAC;AACxC,WAAO,MAAM,QAAQ,QAAQ,MAAM,KAAK,UAAU,MAAM,SAAS,QAAQ,EAAE,UAAU,MAAM,CAAC,CAAC,CAAC,CAAC;AAAA,EACjG;AACF,CAAC;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/directives/teleport.ts"],
4
- "sourcesContent": ["import { attribute } from '../../kernel/index.js'\n\n/**\n * Moves the element to another place in the document: `teleport=\"body\"` (a selector).\n * `__prepend` inserts at the start. The element and its signals keep working where it lands.\n */\nexport const teleport = attribute({\n name: 'teleport',\n key: 'forbidden',\n value: 'required',\n mount({ el, value, mods, error }) {\n const target = document.querySelector(value)\n if (!target) throw error(`no element matches \"${value}\"`)\n if (el.parentElement === target) return\n const before = mods.has('prepend') ? target.firstChild : null\n const t = target as Node & { moveBefore?: (n: Node, b: Node | null) => void }\n // `moveBefore` keeps state and avoids an unmount/remount; fall back to a plain move.\n if (t.moveBefore) t.moveBefore(el, before)\n else target.insertBefore(el, before)\n },\n})\n"],
4
+ "sourcesContent": ["import { attribute } from '../../kernel/index.js';\n\n/**\n * Moves the element to another place in the document: `teleport=\"body\"` (a selector).\n * `__prepend` inserts at the start. The element and its signals keep working where it lands.\n */\nexport const teleport = attribute({\n name: 'teleport',\n key: 'forbidden',\n value: 'required',\n mount({ el, value, mods, error }) {\n const target = document.querySelector(value);\n if (!target) throw error(`no element matches \"${value}\"`);\n if (el.parentElement === target) return;\n const before = mods.has('prepend') ? target.firstChild : null;\n const t = target as Node & { moveBefore?: (n: Node, b: Node | null) => void };\n // `moveBefore` keeps state and avoids an unmount/remount; fall back to a plain move.\n if (t.moveBefore) t.moveBefore(el, before);\n else target.insertBefore(el, before);\n },\n});\n"],
5
5
  "mappings": "AAAA,SAAS,iBAAiB;AAMnB,MAAM,WAAW,UAAU;AAAA,EAChC,MAAM;AAAA,EACN,KAAK;AAAA,EACL,OAAO;AAAA,EACP,MAAM,EAAE,IAAI,OAAO,MAAM,MAAM,GAAG;AAChC,UAAM,SAAS,SAAS,cAAc,KAAK;AAC3C,QAAI,CAAC,OAAQ,OAAM,MAAM,uBAAuB,KAAK,GAAG;AACxD,QAAI,GAAG,kBAAkB,OAAQ;AACjC,UAAM,SAAS,KAAK,IAAI,SAAS,IAAI,OAAO,aAAa;AACzD,UAAM,IAAI;AAEV,QAAI,EAAE,WAAY,GAAE,WAAW,IAAI,MAAM;AAAA,QACpC,QAAO,aAAa,IAAI,MAAM;AAAA,EACrC;AACF,CAAC;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/directives/text-content.ts"],
4
- "sourcesContent": ["import { attribute } from '../../kernel/index.js'\n\nexport const text = attribute({\n name: 'text',\n key: 'forbidden',\n value: 'required',\n mount: ({ el, evaluate, effect }) =>\n effect(() => {\n el.textContent = String(evaluate() ?? '')\n }),\n})\n"],
4
+ "sourcesContent": ["import { attribute } from '../../kernel/index.js';\n\nexport const text = attribute({\n name: 'text',\n key: 'forbidden',\n value: 'required',\n mount: ({ el, evaluate, effect }) =>\n effect(() => {\n el.textContent = String(evaluate() ?? '');\n }),\n});\n"],
5
5
  "mappings": "AAAA,SAAS,iBAAiB;AAEnB,MAAM,OAAO,UAAU;AAAA,EAC5B,MAAM;AAAA,EACN,KAAK;AAAA,EACL,OAAO;AAAA,EACP,OAAO,CAAC,EAAE,IAAI,UAAU,OAAO,MAC7B,OAAO,MAAM;AACX,OAAG,cAAc,OAAO,SAAS,KAAK,EAAE;AAAA,EAC1C,CAAC;AACL,CAAC;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/directives/timer.ts"],
4
- "sourcesContent": ["import { attribute, toMs, withViewTransition } from '../../kernel/index.js'\n\n/** `on-interval__duration.5s.leading=\"expr\"`. Default one second. */\nexport const onInterval = attribute({\n name: 'on-interval',\n key: 'forbidden',\n value: 'required',\n returns: false,\n mount({ mods, evaluate }) {\n const d = mods.get('duration')\n const run = withViewTransition(() => evaluate(), mods)\n if (d?.includes('leading')) run()\n const id = setInterval(run, toMs(d, 1000))\n return () => clearInterval(id)\n },\n})\n"],
4
+ "sourcesContent": ["import { attribute, toMs, withViewTransition } from '../../kernel/index.js';\n\n/** `on-interval__duration.5s.leading=\"expr\"`. Default one second. */\nexport const onInterval = attribute({\n name: 'on-interval',\n key: 'forbidden',\n value: 'required',\n returns: false,\n mount({ mods, evaluate }) {\n const d = mods.get('duration');\n const run = withViewTransition(() => evaluate(), mods);\n if (d?.includes('leading')) run();\n const id = setInterval(run, toMs(d, 1000));\n return () => clearInterval(id);\n },\n});\n"],
5
5
  "mappings": "AAAA,SAAS,WAAW,MAAM,0BAA0B;AAG7C,MAAM,aAAa,UAAU;AAAA,EAClC,MAAM;AAAA,EACN,KAAK;AAAA,EACL,OAAO;AAAA,EACP,SAAS;AAAA,EACT,MAAM,EAAE,MAAM,SAAS,GAAG;AACxB,UAAM,IAAI,KAAK,IAAI,UAAU;AAC7B,UAAM,MAAM,mBAAmB,MAAM,SAAS,GAAG,IAAI;AACrD,QAAI,GAAG,SAAS,SAAS,EAAG,KAAI;AAChC,UAAM,KAAK,YAAY,KAAK,KAAK,GAAG,GAAI,CAAC;AACzC,WAAO,MAAM,cAAc,EAAE;AAAA,EAC/B;AACF,CAAC;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/directives/transition-name.ts"],
4
- "sourcesContent": ["import { attribute } from '../../kernel/index.js'\n\nexport const viewTransition = attribute({\n name: 'view-transition',\n key: 'forbidden',\n value: 'required',\n mount: ({ el, evaluate, effect }) => effect(() => el.style.setProperty('view-transition-name', String(evaluate()))),\n})\n"],
4
+ "sourcesContent": ["import { attribute } from '../../kernel/index.js';\n\nexport const viewTransition = attribute({\n name: 'view-transition',\n key: 'forbidden',\n value: 'required',\n mount: ({ el, evaluate, effect }) => effect(() => el.style.setProperty('view-transition-name', String(evaluate()))),\n});\n"],
5
5
  "mappings": "AAAA,SAAS,iBAAiB;AAEnB,MAAM,iBAAiB,UAAU;AAAA,EACtC,MAAM;AAAA,EACN,KAAK;AAAA,EACL,OAAO;AAAA,EACP,OAAO,CAAC,EAAE,IAAI,UAAU,OAAO,MAAM,OAAO,MAAM,GAAG,MAAM,YAAY,wBAAwB,OAAO,SAAS,CAAC,CAAC,CAAC;AACpH,CAAC;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/directives/transition.ts"],
4
- "sourcesContent": ["import { attribute, toMs } from '../../kernel/index.js'\n\n/**\n * Shows and hides with a fade (and optional scale): `transition=\"$open\"`.\n * Modifiers: `__duration.200ms`, `__scale` (from 95%) or `__scale.90`, `__origin.top`.\n */\nexport const transition = attribute({\n name: 'transition',\n key: 'forbidden',\n value: 'required',\n mount({ el, mods, evaluate, effect }) {\n const style = (el as HTMLElement).style\n const duration = matchMedia('(prefers-reduced-motion: reduce)').matches ? 0 : toMs(mods.get('duration'), 200)\n const scale = mods.has('scale') ? +(mods.get('scale')?.[0] ?? 95) / 100 : 1\n const origin = mods.get('origin')?.join(' ')\n if (origin) style.transformOrigin = origin\n const hidden = { opacity: 0, transform: `scale(${scale})` }\n const shown = { opacity: 1, transform: 'scale(1)' }\n const initial = style.display === 'none' ? '' : style.display\n let anim: Animation | undefined\n let first = true\n let last: boolean | undefined\n effect(() => {\n const open = !!evaluate()\n if (open === last) return // a dependency changed but the outcome did not: leave the element alone\n last = open\n anim?.cancel()\n if (first) {\n first = false\n style.display = open ? initial : 'none'\n return\n }\n if (open) style.display = initial\n anim = el.animate(open ? [hidden, shown] : [shown, hidden], { duration, easing: 'ease-out', fill: 'forwards' })\n anim.onfinish = () => {\n anim?.cancel()\n if (!open) style.display = 'none'\n }\n })\n },\n})\n"],
4
+ "sourcesContent": ["import { attribute, toMs } from '../../kernel/index.js';\n\n/**\n * Shows and hides with a fade (and optional scale): `transition=\"$open\"`.\n * Modifiers: `__duration.200ms`, `__scale` (from 95%) or `__scale.90`, `__origin.top`.\n */\nexport const transition = attribute({\n name: 'transition',\n key: 'forbidden',\n value: 'required',\n mount({ el, mods, evaluate, effect }) {\n const style = (el as HTMLElement).style;\n const duration = matchMedia('(prefers-reduced-motion: reduce)').matches ? 0 : toMs(mods.get('duration'), 200);\n const scale = mods.has('scale') ? +(mods.get('scale')?.[0] ?? 95) / 100 : 1;\n const origin = mods.get('origin')?.join(' ');\n if (origin) style.transformOrigin = origin;\n const hidden = { opacity: 0, transform: `scale(${scale})` };\n const shown = { opacity: 1, transform: 'scale(1)' };\n const initial = style.display === 'none' ? '' : style.display;\n let anim: Animation | undefined;\n let first = true;\n let last: boolean | undefined;\n effect(() => {\n const open = !!evaluate();\n if (open === last) return; // a dependency changed but the outcome did not: leave the element alone\n last = open;\n anim?.cancel();\n if (first) {\n first = false;\n style.display = open ? initial : 'none';\n return;\n }\n if (open) style.display = initial;\n anim = el.animate(open ? [hidden, shown] : [shown, hidden], { duration, easing: 'ease-out', fill: 'forwards' });\n anim.onfinish = () => {\n anim?.cancel();\n if (!open) style.display = 'none';\n };\n });\n },\n});\n"],
5
5
  "mappings": "AAAA,SAAS,WAAW,YAAY;AAMzB,MAAM,aAAa,UAAU;AAAA,EAClC,MAAM;AAAA,EACN,KAAK;AAAA,EACL,OAAO;AAAA,EACP,MAAM,EAAE,IAAI,MAAM,UAAU,OAAO,GAAG;AACpC,UAAM,QAAS,GAAmB;AAClC,UAAM,WAAW,WAAW,kCAAkC,EAAE,UAAU,IAAI,KAAK,KAAK,IAAI,UAAU,GAAG,GAAG;AAC5G,UAAM,QAAQ,KAAK,IAAI,OAAO,IAAI,EAAE,KAAK,IAAI,OAAO,IAAI,CAAC,KAAK,MAAM,MAAM;AAC1E,UAAM,SAAS,KAAK,IAAI,QAAQ,GAAG,KAAK,GAAG;AAC3C,QAAI,OAAQ,OAAM,kBAAkB;AACpC,UAAM,SAAS,EAAE,SAAS,GAAG,WAAW,SAAS,KAAK,IAAI;AAC1D,UAAM,QAAQ,EAAE,SAAS,GAAG,WAAW,WAAW;AAClD,UAAM,UAAU,MAAM,YAAY,SAAS,KAAK,MAAM;AACtD,QAAI;AACJ,QAAI,QAAQ;AACZ,QAAI;AACJ,WAAO,MAAM;AACX,YAAM,OAAO,CAAC,CAAC,SAAS;AACxB,UAAI,SAAS,KAAM;AACnB,aAAO;AACP,YAAM,OAAO;AACb,UAAI,OAAO;AACT,gBAAQ;AACR,cAAM,UAAU,OAAO,UAAU;AACjC;AAAA,MACF;AACA,UAAI,KAAM,OAAM,UAAU;AAC1B,aAAO,GAAG,QAAQ,OAAO,CAAC,QAAQ,KAAK,IAAI,CAAC,OAAO,MAAM,GAAG,EAAE,UAAU,QAAQ,YAAY,MAAM,WAAW,CAAC;AAC9G,WAAK,WAAW,MAAM;AACpB,cAAM,OAAO;AACb,YAAI,CAAC,KAAM,OAAM,UAAU;AAAA,MAC7B;AAAA,IACF,CAAC;AAAA,EACH;AACF,CAAC;",
6
6
  "names": []
7
7
  }
@@ -8,7 +8,9 @@ const trap = attribute({
8
8
  let previous = null;
9
9
  let active = false;
10
10
  const inerted = [];
11
- const focusables = () => [...el.querySelectorAll(FOCUSABLE)].filter((e) => e.offsetParent !== null || e === document.activeElement);
11
+ const focusables = () => [...el.querySelectorAll(FOCUSABLE)].filter(
12
+ (e) => e.offsetParent !== null || e === document.activeElement
13
+ );
12
14
  const release = () => {
13
15
  if (!active) return;
14
16
  active = false;
@@ -33,7 +35,11 @@ const trap = attribute({
33
35
  previous = document.activeElement;
34
36
  if (mods.has("inert")) {
35
37
  for (let n = el; n && n !== document.body; n = n.parentElement) {
36
- for (const sib of n.parentElement?.children ?? []) if (sib !== n && !sib.hasAttribute("inert")) sib.setAttribute("inert", ""), inerted.push(sib);
38
+ for (const sib of n.parentElement?.children ?? [])
39
+ if (sib !== n && !sib.hasAttribute("inert")) {
40
+ sib.setAttribute("inert", "");
41
+ inerted.push(sib);
42
+ }
37
43
  }
38
44
  }
39
45
  queueMicrotask(() => (focusables()[0] ?? el).focus?.());
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/directives/trap.ts"],
4
- "sourcesContent": ["import { attribute } from '../../kernel/index.js'\n\nconst FOCUSABLE = 'a[href],button:not([disabled]),input:not([disabled]):not([type=hidden]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex=\"-1\"]),[contenteditable]'\n\n/**\n * Keeps keyboard focus inside the element while the expression is true and restores the previously\n * focused element when it turns false: `trap=\"$open\"`. `__inert` also makes the rest of the page inert.\n */\nexport const trap = attribute({\n name: 'trap',\n key: 'forbidden',\n value: 'required',\n mount({ el, mods, evaluate, effect, listen, cleanup }) {\n let previous: Element | null = null\n let active = false\n const inerted: Element[] = []\n const focusables = () => [...el.querySelectorAll<HTMLElement>(FOCUSABLE)].filter((e) => e.offsetParent !== null || e === document.activeElement)\n const release = () => {\n if (!active) return\n active = false\n for (const e of inerted.splice(0)) e.removeAttribute('inert')\n ;(previous as HTMLElement | null)?.focus?.()\n }\n listen(document, 'keydown', (e: KeyboardEvent) => {\n if (!active || e.key !== 'Tab') return\n const items = focusables()\n if (!items.length) return e.preventDefault()\n const i = items.indexOf(document.activeElement as HTMLElement)\n const next = e.shiftKey ? (i <= 0 ? items.length - 1 : i - 1) : i === items.length - 1 ? 0 : i + 1\n if (i < 0 || next !== i + (e.shiftKey ? -1 : 1)) {\n e.preventDefault()\n items[next].focus()\n }\n })\n effect(() => {\n if (evaluate()) {\n if (active) return\n active = true\n previous = document.activeElement\n if (mods.has('inert')) {\n for (let n: Element | null = el; n && n !== document.body; n = n.parentElement) {\n for (const sib of n.parentElement?.children ?? []) if (sib !== n && !sib.hasAttribute('inert')) (sib.setAttribute('inert', ''), inerted.push(sib))\n }\n }\n queueMicrotask(() => (focusables()[0] ?? (el as HTMLElement)).focus?.())\n } else release()\n })\n cleanup(release)\n },\n})\n"],
5
- "mappings": "AAAA,SAAS,iBAAiB;AAE1B,MAAM,YAAY;AAMX,MAAM,OAAO,UAAU;AAAA,EAC5B,MAAM;AAAA,EACN,KAAK;AAAA,EACL,OAAO;AAAA,EACP,MAAM,EAAE,IAAI,MAAM,UAAU,QAAQ,QAAQ,QAAQ,GAAG;AACrD,QAAI,WAA2B;AAC/B,QAAI,SAAS;AACb,UAAM,UAAqB,CAAC;AAC5B,UAAM,aAAa,MAAM,CAAC,GAAG,GAAG,iBAA8B,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,iBAAiB,QAAQ,MAAM,SAAS,aAAa;AAC/I,UAAM,UAAU,MAAM;AACpB,UAAI,CAAC,OAAQ;AACb,eAAS;AACT,iBAAW,KAAK,QAAQ,OAAO,CAAC,EAAG,GAAE,gBAAgB,OAAO;AAC3D,MAAC,UAAiC,QAAQ;AAAA,IAC7C;AACA,WAAO,UAAU,WAAW,CAAC,MAAqB;AAChD,UAAI,CAAC,UAAU,EAAE,QAAQ,MAAO;AAChC,YAAM,QAAQ,WAAW;AACzB,UAAI,CAAC,MAAM,OAAQ,QAAO,EAAE,eAAe;AAC3C,YAAM,IAAI,MAAM,QAAQ,SAAS,aAA4B;AAC7D,YAAM,OAAO,EAAE,WAAY,KAAK,IAAI,MAAM,SAAS,IAAI,IAAI,IAAK,MAAM,MAAM,SAAS,IAAI,IAAI,IAAI;AACjG,UAAI,IAAI,KAAK,SAAS,KAAK,EAAE,WAAW,KAAK,IAAI;AAC/C,UAAE,eAAe;AACjB,cAAM,IAAI,EAAE,MAAM;AAAA,MACpB;AAAA,IACF,CAAC;AACD,WAAO,MAAM;AACX,UAAI,SAAS,GAAG;AACd,YAAI,OAAQ;AACZ,iBAAS;AACT,mBAAW,SAAS;AACpB,YAAI,KAAK,IAAI,OAAO,GAAG;AACrB,mBAAS,IAAoB,IAAI,KAAK,MAAM,SAAS,MAAM,IAAI,EAAE,eAAe;AAC9E,uBAAW,OAAO,EAAE,eAAe,YAAY,CAAC,EAAG,KAAI,QAAQ,KAAK,CAAC,IAAI,aAAa,OAAO,EAAG,CAAC,IAAI,aAAa,SAAS,EAAE,GAAG,QAAQ,KAAK,GAAG;AAAA,UAClJ;AAAA,QACF;AACA,uBAAe,OAAO,WAAW,EAAE,CAAC,KAAM,IAAoB,QAAQ,CAAC;AAAA,MACzE,MAAO,SAAQ;AAAA,IACjB,CAAC;AACD,YAAQ,OAAO;AAAA,EACjB;AACF,CAAC;",
4
+ "sourcesContent": ["import { attribute } from '../../kernel/index.js';\n\nconst FOCUSABLE =\n 'a[href],button:not([disabled]),input:not([disabled]):not([type=hidden]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex=\"-1\"]),[contenteditable]';\n\n/**\n * Keeps keyboard focus inside the element while the expression is true and restores the previously\n * focused element when it turns false: `trap=\"$open\"`. `__inert` also makes the rest of the page inert.\n */\nexport const trap = attribute({\n name: 'trap',\n key: 'forbidden',\n value: 'required',\n mount({ el, mods, evaluate, effect, listen, cleanup }) {\n let previous: Element | null = null;\n let active = false;\n const inerted: Element[] = [];\n const focusables = () =>\n [...el.querySelectorAll<HTMLElement>(FOCUSABLE)].filter(\n (e) => e.offsetParent !== null || e === document.activeElement,\n );\n const release = () => {\n if (!active) return;\n active = false;\n for (const e of inerted.splice(0)) e.removeAttribute('inert');\n (previous as HTMLElement | null)?.focus?.();\n };\n listen(document, 'keydown', (e: KeyboardEvent) => {\n if (!active || e.key !== 'Tab') return;\n const items = focusables();\n if (!items.length) return e.preventDefault();\n const i = items.indexOf(document.activeElement as HTMLElement);\n const next = e.shiftKey ? (i <= 0 ? items.length - 1 : i - 1) : i === items.length - 1 ? 0 : i + 1;\n if (i < 0 || next !== i + (e.shiftKey ? -1 : 1)) {\n e.preventDefault();\n items[next].focus();\n }\n });\n effect(() => {\n if (evaluate()) {\n if (active) return;\n active = true;\n previous = document.activeElement;\n if (mods.has('inert')) {\n for (let n: Element | null = el; n && n !== document.body; n = n.parentElement) {\n for (const sib of n.parentElement?.children ?? [])\n if (sib !== n && !sib.hasAttribute('inert')) {\n sib.setAttribute('inert', '');\n inerted.push(sib);\n }\n }\n }\n queueMicrotask(() => (focusables()[0] ?? (el as HTMLElement)).focus?.());\n } else release();\n });\n cleanup(release);\n },\n});\n"],
5
+ "mappings": "AAAA,SAAS,iBAAiB;AAE1B,MAAM,YACJ;AAMK,MAAM,OAAO,UAAU;AAAA,EAC5B,MAAM;AAAA,EACN,KAAK;AAAA,EACL,OAAO;AAAA,EACP,MAAM,EAAE,IAAI,MAAM,UAAU,QAAQ,QAAQ,QAAQ,GAAG;AACrD,QAAI,WAA2B;AAC/B,QAAI,SAAS;AACb,UAAM,UAAqB,CAAC;AAC5B,UAAM,aAAa,MACjB,CAAC,GAAG,GAAG,iBAA8B,SAAS,CAAC,EAAE;AAAA,MAC/C,CAAC,MAAM,EAAE,iBAAiB,QAAQ,MAAM,SAAS;AAAA,IACnD;AACF,UAAM,UAAU,MAAM;AACpB,UAAI,CAAC,OAAQ;AACb,eAAS;AACT,iBAAW,KAAK,QAAQ,OAAO,CAAC,EAAG,GAAE,gBAAgB,OAAO;AAC5D,MAAC,UAAiC,QAAQ;AAAA,IAC5C;AACA,WAAO,UAAU,WAAW,CAAC,MAAqB;AAChD,UAAI,CAAC,UAAU,EAAE,QAAQ,MAAO;AAChC,YAAM,QAAQ,WAAW;AACzB,UAAI,CAAC,MAAM,OAAQ,QAAO,EAAE,eAAe;AAC3C,YAAM,IAAI,MAAM,QAAQ,SAAS,aAA4B;AAC7D,YAAM,OAAO,EAAE,WAAY,KAAK,IAAI,MAAM,SAAS,IAAI,IAAI,IAAK,MAAM,MAAM,SAAS,IAAI,IAAI,IAAI;AACjG,UAAI,IAAI,KAAK,SAAS,KAAK,EAAE,WAAW,KAAK,IAAI;AAC/C,UAAE,eAAe;AACjB,cAAM,IAAI,EAAE,MAAM;AAAA,MACpB;AAAA,IACF,CAAC;AACD,WAAO,MAAM;AACX,UAAI,SAAS,GAAG;AACd,YAAI,OAAQ;AACZ,iBAAS;AACT,mBAAW,SAAS;AACpB,YAAI,KAAK,IAAI,OAAO,GAAG;AACrB,mBAAS,IAAoB,IAAI,KAAK,MAAM,SAAS,MAAM,IAAI,EAAE,eAAe;AAC9E,uBAAW,OAAO,EAAE,eAAe,YAAY,CAAC;AAC9C,kBAAI,QAAQ,KAAK,CAAC,IAAI,aAAa,OAAO,GAAG;AAC3C,oBAAI,aAAa,SAAS,EAAE;AAC5B,wBAAQ,KAAK,GAAG;AAAA,cAClB;AAAA,UACJ;AAAA,QACF;AACA,uBAAe,OAAO,WAAW,EAAE,CAAC,KAAM,IAAoB,QAAQ,CAAC;AAAA,MACzE,MAAO,SAAQ;AAAA,IACjB,CAAC;AACD,YAAQ,OAAO;AAAA,EACjB;AACF,CAAC;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/directives/tween.ts"],
4
- "sourcesContent": ["import { attribute, toMs } from '../../kernel/index.js'\n\nconst easings: Record<string, (t: number) => number> = {\n linear: (t) => t,\n 'ease-in': (t) => t * t,\n 'ease-out': (t) => 1 - (1 - t) * (1 - t),\n 'ease-in-out': (t) => (t < 0.5 ? 2 * t * t : 1 - (-2 * t + 2) ** 2 / 2),\n}\nconst num = (s: string): { n: number; unit: string } | undefined => {\n const m = /^\\s*(-?\\d*\\.?\\d+)([a-z%]*)\\s*$/i.exec(s)\n return m ? { n: +m[1], unit: m[2] } : undefined\n}\n\n/**\n * `animate:opacity=\"$open ? 1 : 0\"` tweens a numeric CSS property (or attribute, for SVG) from its\n * current value to the expression's value whenever the expression changes.\n * Modifiers: `__duration.300ms`, `__easing.ease-in-out`. Non-numeric values apply immediately.\n */\nexport const animate = attribute({\n name: 'animate',\n key: 'required',\n value: 'required',\n mount({ el, mods, cased, evaluate, effect, cleanup }) {\n const prop = cased('kebab')\n const css = CSS.supports(prop, 'inherit')\n const duration = toMs(mods.get('duration'), 300)\n const ease = easings[mods.get('easing')?.[0] ?? 'ease-out'] ?? easings['ease-out']\n const instant = matchMedia('(prefers-reduced-motion: reduce)').matches\n // Prefer the inline value (which this directive wrote last time); computed styles report px only.\n const read = () => (css ? el.style.getPropertyValue(prop) || getComputedStyle(el).getPropertyValue(prop) : (el.getAttribute(prop) ?? ''))\n const write = (v: string) => (css ? el.style.setProperty(prop, v) : el.setAttribute(prop, v))\n let frame = 0\n let first = true\n let last: string | undefined\n effect(() => {\n const to = String(evaluate())\n if (to === last) return\n last = to\n cancelAnimationFrame(frame)\n let from = num(read())\n const target = num(to)\n // A px start and a % target are common for width/height: convert against the parent box.\n if (from && target && from.unit === 'px' && target.unit === '%' && (prop === 'width' || prop === 'height') && el.parentElement) {\n const size = prop === 'width' ? el.parentElement.clientWidth : el.parentElement.clientHeight\n if (size) from = { n: (from.n / size) * 100, unit: '%' }\n }\n if (first || instant || !from || !target || from.unit !== target.unit) {\n first = false\n return write(to)\n }\n const a = from.n\n const b = target.n\n const start = performance.now()\n const tick = (now: number) => {\n const p = Math.min(1, (now - start) / duration)\n write(`${a + (b - a) * ease(p)}${target.unit}`)\n if (p < 1) frame = requestAnimationFrame(tick)\n }\n frame = requestAnimationFrame(tick)\n })\n cleanup(() => cancelAnimationFrame(frame))\n },\n})\n"],
5
- "mappings": "AAAA,SAAS,WAAW,YAAY;AAEhC,MAAM,UAAiD;AAAA,EACrD,QAAQ,CAAC,MAAM;AAAA,EACf,WAAW,CAAC,MAAM,IAAI;AAAA,EACtB,YAAY,CAAC,MAAM,KAAK,IAAI,MAAM,IAAI;AAAA,EACtC,eAAe,CAAC,MAAO,IAAI,MAAM,IAAI,IAAI,IAAI,KAAK,KAAK,IAAI,MAAM,IAAI;AACvE;AACA,MAAM,MAAM,CAAC,MAAuD;AAClE,QAAM,IAAI,kCAAkC,KAAK,CAAC;AAClD,SAAO,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,IAAI;AACxC;AAOO,MAAM,UAAU,UAAU;AAAA,EAC/B,MAAM;AAAA,EACN,KAAK;AAAA,EACL,OAAO;AAAA,EACP,MAAM,EAAE,IAAI,MAAM,OAAO,UAAU,QAAQ,QAAQ,GAAG;AACpD,UAAM,OAAO,MAAM,OAAO;AAC1B,UAAM,MAAM,IAAI,SAAS,MAAM,SAAS;AACxC,UAAM,WAAW,KAAK,KAAK,IAAI,UAAU,GAAG,GAAG;AAC/C,UAAM,OAAO,QAAQ,KAAK,IAAI,QAAQ,IAAI,CAAC,KAAK,UAAU,KAAK,QAAQ,UAAU;AACjF,UAAM,UAAU,WAAW,kCAAkC,EAAE;AAE/D,UAAM,OAAO,MAAO,MAAM,GAAG,MAAM,iBAAiB,IAAI,KAAK,iBAAiB,EAAE,EAAE,iBAAiB,IAAI,IAAK,GAAG,aAAa,IAAI,KAAK;AACrI,UAAM,QAAQ,CAAC,MAAe,MAAM,GAAG,MAAM,YAAY,MAAM,CAAC,IAAI,GAAG,aAAa,MAAM,CAAC;AAC3F,QAAI,QAAQ;AACZ,QAAI,QAAQ;AACZ,QAAI;AACJ,WAAO,MAAM;AACX,YAAM,KAAK,OAAO,SAAS,CAAC;AAC5B,UAAI,OAAO,KAAM;AACjB,aAAO;AACP,2BAAqB,KAAK;AAC1B,UAAI,OAAO,IAAI,KAAK,CAAC;AACrB,YAAM,SAAS,IAAI,EAAE;AAErB,UAAI,QAAQ,UAAU,KAAK,SAAS,QAAQ,OAAO,SAAS,QAAQ,SAAS,WAAW,SAAS,aAAa,GAAG,eAAe;AAC9H,cAAM,OAAO,SAAS,UAAU,GAAG,cAAc,cAAc,GAAG,cAAc;AAChF,YAAI,KAAM,QAAO,EAAE,GAAI,KAAK,IAAI,OAAQ,KAAK,MAAM,IAAI;AAAA,MACzD;AACA,UAAI,SAAS,WAAW,CAAC,QAAQ,CAAC,UAAU,KAAK,SAAS,OAAO,MAAM;AACrE,gBAAQ;AACR,eAAO,MAAM,EAAE;AAAA,MACjB;AACA,YAAM,IAAI,KAAK;AACf,YAAM,IAAI,OAAO;AACjB,YAAM,QAAQ,YAAY,IAAI;AAC9B,YAAM,OAAO,CAAC,QAAgB;AAC5B,cAAM,IAAI,KAAK,IAAI,IAAI,MAAM,SAAS,QAAQ;AAC9C,cAAM,GAAG,KAAK,IAAI,KAAK,KAAK,CAAC,CAAC,GAAG,OAAO,IAAI,EAAE;AAC9C,YAAI,IAAI,EAAG,SAAQ,sBAAsB,IAAI;AAAA,MAC/C;AACA,cAAQ,sBAAsB,IAAI;AAAA,IACpC,CAAC;AACD,YAAQ,MAAM,qBAAqB,KAAK,CAAC;AAAA,EAC3C;AACF,CAAC;",
4
+ "sourcesContent": ["import { attribute, toMs } from '../../kernel/index.js';\n\nconst easings: Record<string, (t: number) => number> = {\n linear: (t) => t,\n 'ease-in': (t) => t * t,\n 'ease-out': (t) => 1 - (1 - t) * (1 - t),\n 'ease-in-out': (t) => (t < 0.5 ? 2 * t * t : 1 - (-2 * t + 2) ** 2 / 2),\n};\nconst num = (s: string): { n: number; unit: string } | undefined => {\n const m = /^\\s*(-?\\d*\\.?\\d+)([a-z%]*)\\s*$/i.exec(s);\n return m ? { n: +m[1], unit: m[2] } : undefined;\n};\n\n/**\n * `animate:opacity=\"$open ? 1 : 0\"` tweens a numeric CSS property (or attribute, for SVG) from its\n * current value to the expression's value whenever the expression changes.\n * Modifiers: `__duration.300ms`, `__easing.ease-in-out`. Non-numeric values apply immediately.\n */\nexport const animate = attribute({\n name: 'animate',\n key: 'required',\n value: 'required',\n mount({ el, mods, cased, evaluate, effect, cleanup }) {\n const prop = cased('kebab');\n const css = CSS.supports(prop, 'inherit');\n const duration = toMs(mods.get('duration'), 300);\n const ease = easings[mods.get('easing')?.[0] ?? 'ease-out'] ?? easings['ease-out'];\n const instant = matchMedia('(prefers-reduced-motion: reduce)').matches;\n // Prefer the inline value (which this directive wrote last time); computed styles report px only.\n const read = () =>\n css\n ? el.style.getPropertyValue(prop) || getComputedStyle(el).getPropertyValue(prop)\n : (el.getAttribute(prop) ?? '');\n const write = (v: string) => (css ? el.style.setProperty(prop, v) : el.setAttribute(prop, v));\n let frame = 0;\n let first = true;\n let last: string | undefined;\n effect(() => {\n const to = String(evaluate());\n if (to === last) return;\n last = to;\n cancelAnimationFrame(frame);\n let from = num(read());\n const target = num(to);\n // A px start and a % target are common for width/height: convert against the parent box.\n if (\n from &&\n target &&\n from.unit === 'px' &&\n target.unit === '%' &&\n (prop === 'width' || prop === 'height') &&\n el.parentElement\n ) {\n const size = prop === 'width' ? el.parentElement.clientWidth : el.parentElement.clientHeight;\n if (size) from = { n: (from.n / size) * 100, unit: '%' };\n }\n if (first || instant || !from || !target || from.unit !== target.unit) {\n first = false;\n return write(to);\n }\n const a = from.n;\n const b = target.n;\n const start = performance.now();\n const tick = (now: number) => {\n const p = Math.min(1, (now - start) / duration);\n write(`${a + (b - a) * ease(p)}${target.unit}`);\n if (p < 1) frame = requestAnimationFrame(tick);\n };\n frame = requestAnimationFrame(tick);\n });\n cleanup(() => cancelAnimationFrame(frame));\n },\n});\n"],
5
+ "mappings": "AAAA,SAAS,WAAW,YAAY;AAEhC,MAAM,UAAiD;AAAA,EACrD,QAAQ,CAAC,MAAM;AAAA,EACf,WAAW,CAAC,MAAM,IAAI;AAAA,EACtB,YAAY,CAAC,MAAM,KAAK,IAAI,MAAM,IAAI;AAAA,EACtC,eAAe,CAAC,MAAO,IAAI,MAAM,IAAI,IAAI,IAAI,KAAK,KAAK,IAAI,MAAM,IAAI;AACvE;AACA,MAAM,MAAM,CAAC,MAAuD;AAClE,QAAM,IAAI,kCAAkC,KAAK,CAAC;AAClD,SAAO,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,IAAI;AACxC;AAOO,MAAM,UAAU,UAAU;AAAA,EAC/B,MAAM;AAAA,EACN,KAAK;AAAA,EACL,OAAO;AAAA,EACP,MAAM,EAAE,IAAI,MAAM,OAAO,UAAU,QAAQ,QAAQ,GAAG;AACpD,UAAM,OAAO,MAAM,OAAO;AAC1B,UAAM,MAAM,IAAI,SAAS,MAAM,SAAS;AACxC,UAAM,WAAW,KAAK,KAAK,IAAI,UAAU,GAAG,GAAG;AAC/C,UAAM,OAAO,QAAQ,KAAK,IAAI,QAAQ,IAAI,CAAC,KAAK,UAAU,KAAK,QAAQ,UAAU;AACjF,UAAM,UAAU,WAAW,kCAAkC,EAAE;AAE/D,UAAM,OAAO,MACX,MACI,GAAG,MAAM,iBAAiB,IAAI,KAAK,iBAAiB,EAAE,EAAE,iBAAiB,IAAI,IAC5E,GAAG,aAAa,IAAI,KAAK;AAChC,UAAM,QAAQ,CAAC,MAAe,MAAM,GAAG,MAAM,YAAY,MAAM,CAAC,IAAI,GAAG,aAAa,MAAM,CAAC;AAC3F,QAAI,QAAQ;AACZ,QAAI,QAAQ;AACZ,QAAI;AACJ,WAAO,MAAM;AACX,YAAM,KAAK,OAAO,SAAS,CAAC;AAC5B,UAAI,OAAO,KAAM;AACjB,aAAO;AACP,2BAAqB,KAAK;AAC1B,UAAI,OAAO,IAAI,KAAK,CAAC;AACrB,YAAM,SAAS,IAAI,EAAE;AAErB,UACE,QACA,UACA,KAAK,SAAS,QACd,OAAO,SAAS,QACf,SAAS,WAAW,SAAS,aAC9B,GAAG,eACH;AACA,cAAM,OAAO,SAAS,UAAU,GAAG,cAAc,cAAc,GAAG,cAAc;AAChF,YAAI,KAAM,QAAO,EAAE,GAAI,KAAK,IAAI,OAAQ,KAAK,MAAM,IAAI;AAAA,MACzD;AACA,UAAI,SAAS,WAAW,CAAC,QAAQ,CAAC,UAAU,KAAK,SAAS,OAAO,MAAM;AACrE,gBAAQ;AACR,eAAO,MAAM,EAAE;AAAA,MACjB;AACA,YAAM,IAAI,KAAK;AACf,YAAM,IAAI,OAAO;AACjB,YAAM,QAAQ,YAAY,IAAI;AAC9B,YAAM,OAAO,CAAC,QAAgB;AAC5B,cAAM,IAAI,KAAK,IAAI,IAAI,MAAM,SAAS,QAAQ;AAC9C,cAAM,GAAG,KAAK,IAAI,KAAK,KAAK,CAAC,CAAC,GAAG,OAAO,IAAI,EAAE;AAC9C,YAAI,IAAI,EAAG,SAAQ,sBAAsB,IAAI;AAAA,MAC/C;AACA,cAAQ,sBAAsB,IAAI;AAAA,IACpC,CAAC;AACD,YAAQ,MAAM,qBAAqB,KAAK,CAAC;AAAA,EAC3C;AACF,CAAC;",
6
6
  "names": []
7
7
  }
@@ -1,5 +1,9 @@
1
1
  import { attribute } from "../../kernel/index.js";
2
- const adapter = (_read, _write, ..._events) => ({ a: _read, b: _write, c: _events });
2
+ const adapter = (_read, _write, ..._events) => ({
3
+ a: _read,
4
+ b: _write,
5
+ c: _events
6
+ });
3
7
  const readFiles = (input) => Promise.all(
4
8
  [...input.files ?? []].map(
5
9
  (f) => new Promise((resolve) => {
@@ -18,7 +22,12 @@ const bind = attribute({
18
22
  let a;
19
23
  const prop = mods.get("prop")?.[0];
20
24
  if (prop) {
21
- a = adapter(() => el[prop], (v) => el[prop] = v, "input", "change");
25
+ a = adapter(
26
+ () => el[prop],
27
+ (v) => el[prop] = v,
28
+ "input",
29
+ "change"
30
+ );
22
31
  } else if (el instanceof HTMLInputElement) {
23
32
  const t = el.type;
24
33
  if (t === "checkbox") {
@@ -40,14 +49,26 @@ const bind = attribute({
40
49
  };
41
50
  } else if (t === "radio") {
42
51
  if (!el.name) el.name = path;
43
- a = adapter(() => el.checked ? asNumber(el.value) : current(), (v) => el.checked = String(v) === el.value, "input");
52
+ a = adapter(
53
+ () => el.checked ? asNumber(el.value) : current(),
54
+ (v) => el.checked = String(v) === el.value,
55
+ "input"
56
+ );
44
57
  } else if (t === "file") {
45
58
  listen(el, "change", () => readFiles(el).then((files) => store.set(path, files)));
46
59
  return;
47
60
  } else if (t === "number" || t === "range") {
48
- a = adapter(() => el.value === "" ? "" : +el.value, (v) => el.value = String(v ?? ""), "input");
61
+ a = adapter(
62
+ () => el.value === "" ? "" : +el.value,
63
+ (v) => el.value = String(v ?? ""),
64
+ "input"
65
+ );
49
66
  } else {
50
- a = adapter(() => el.value, (v) => el.value = String(v ?? ""), "input");
67
+ a = adapter(
68
+ () => el.value,
69
+ (v) => el.value = String(v ?? ""),
70
+ "input"
71
+ );
51
72
  }
52
73
  } else if (el instanceof HTMLSelectElement) {
53
74
  a = {
@@ -59,9 +80,18 @@ const bind = attribute({
59
80
  c: ["change"]
60
81
  };
61
82
  } else if (el instanceof HTMLTextAreaElement || "value" in el) {
62
- a = adapter(() => el.value, (v) => el.value = String(v ?? ""), "input", "change");
83
+ a = adapter(
84
+ () => el.value,
85
+ (v) => el.value = String(v ?? ""),
86
+ "input",
87
+ "change"
88
+ );
63
89
  } else {
64
- a = adapter(() => el.getAttribute("value"), (v) => el.setAttribute("value", String(v ?? "")), "change");
90
+ a = adapter(
91
+ () => el.getAttribute("value"),
92
+ (v) => el.setAttribute("value", String(v ?? "")),
93
+ "change"
94
+ );
65
95
  }
66
96
  if (!store.has(path)) {
67
97
  const initial = a.a();
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/directives/two-way-bind.ts"],
4
- "sourcesContent": ["import { attribute } from '../../kernel/index.js'\n\ntype Adapter = { _read(): unknown; _write(v: unknown): void; _events: string[] }\nconst adapter = (_read: () => unknown, _write: (v: any) => void, ..._events: string[]): Adapter => ({ _read, _write, _events })\n\nconst readFiles = (input: HTMLInputElement) =>\n Promise.all(\n [...(input.files ?? [])].map(\n (f) =>\n new Promise<{ name: string; type: string; size: number; contents: string }>((resolve) => {\n const r = new FileReader()\n r.onloadend = () =>\n resolve({ name: f.name, type: f.type, size: f.size, contents: String(r.result).split(',')[1] ?? '' })\n r.readAsDataURL(f)\n }),\n ),\n )\n\n/**\n * Two-way binding: `bind:name` or `bind=\"name\"`. Creates the signal from the element when missing.\n * Checkbox groups bind to arrays, radios to the checked value, `select multiple` to arrays.\n * `__prop.value` binds a custom element property; `__event.change` picks the events to listen for.\n */\nexport const bind = attribute({\n name: 'bind',\n mount({ el, key, value, cased, mods, store, listen, effect }) {\n const path = key ? cased() : value.trim()\n const current = () => store.get(path)\n const asNumber = (s: string) => (typeof current() === 'number' ? +s : s)\n let a: Adapter\n const prop = mods.get('prop')?.[0]\n\n if (prop) {\n a = adapter(() => (el as any)[prop], (v) => ((el as any)[prop] = v), 'input', 'change')\n } else if (el instanceof HTMLInputElement) {\n const t = el.type\n if (t === 'checkbox') {\n const own = el.hasAttribute('value') && el.value !== 'on'\n a = {\n _read: () => {\n const cur = current()\n if (Array.isArray(cur)) {\n const set = new Set(cur)\n el.checked ? set.add(el.value) : set.delete(el.value)\n return [...set]\n }\n return own ? (el.checked ? el.value : '') : el.checked\n },\n _write: (v) => {\n el.checked = Array.isArray(v) ? v.includes(el.value) : own ? v === el.value : !!v\n },\n _events: ['input'],\n }\n } else if (t === 'radio') {\n if (!el.name) el.name = path\n a = adapter(() => (el.checked ? asNumber(el.value) : current()), (v) => (el.checked = String(v) === el.value), 'input')\n } else if (t === 'file') {\n listen(el, 'change', () => readFiles(el).then((files) => store.set(path, files)))\n return\n } else if (t === 'number' || t === 'range') {\n a = adapter(() => (el.value === '' ? '' : +el.value), (v) => (el.value = String(v ?? '')), 'input')\n } else {\n a = adapter(() => el.value, (v) => (el.value = String(v ?? '')), 'input')\n }\n } else if (el instanceof HTMLSelectElement) {\n a = {\n _read: () => (el.multiple ? [...el.selectedOptions].map((o) => asNumber(o.value)) : asNumber(el.value)),\n _write: (v) => {\n if (el.multiple) for (const o of el.options) o.selected = Array.isArray(v) && v.map(String).includes(o.value)\n else el.value = String(v ?? '')\n },\n _events: ['change'],\n }\n } else if (el instanceof HTMLTextAreaElement || 'value' in el) {\n a = adapter(() => (el as any).value, (v) => ((el as any).value = String(v ?? '')), 'input', 'change')\n } else {\n a = adapter(() => el.getAttribute('value'), (v) => el.setAttribute('value', String(v ?? '')), 'change')\n }\n\n if (!store.has(path)) {\n const initial = a._read()\n if (initial !== undefined && initial !== '') store.set(path, initial)\n }\n const sync = () => store.set(path, a._read())\n for (const type of mods.get('event') ?? a._events) listen(el, type, sync)\n listen(el, 'sigmx-prop-change', sync)\n effect(() => {\n const v = current()\n if (v !== undefined) a._write(v)\n })\n },\n})\n"],
5
- "mappings": "AAAA,SAAS,iBAAiB;AAG1B,MAAM,UAAU,CAAC,OAAsB,WAA6B,aAAgC,EAAEA,GAAA,OAAOC,GAAA,QAAQC,GAAA,QAAQ;AAE7H,MAAM,YAAY,CAAC,UACjB,QAAQ;AAAA,EACN,CAAC,GAAI,MAAM,SAAS,CAAC,CAAE,EAAE;AAAA,IACvB,CAAC,MACC,IAAI,QAAwE,CAAC,YAAY;AACvF,YAAM,IAAI,IAAI,WAAW;AACzB,QAAE,YAAY,MACZ,QAAQ,EAAE,MAAM,EAAE,MAAM,MAAM,EAAE,MAAM,MAAM,EAAE,MAAM,UAAU,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,EAAE,CAAC,KAAK,GAAG,CAAC;AACtG,QAAE,cAAc,CAAC;AAAA,IACnB,CAAC;AAAA,EACL;AACF;AAOK,MAAM,OAAO,UAAU;AAAA,EAC5B,MAAM;AAAA,EACN,MAAM,EAAE,IAAI,KAAK,OAAO,OAAO,MAAM,OAAO,QAAQ,OAAO,GAAG;AAC5D,UAAM,OAAO,MAAM,MAAM,IAAI,MAAM,KAAK;AACxC,UAAM,UAAU,MAAM,MAAM,IAAI,IAAI;AACpC,UAAM,WAAW,CAAC,MAAe,OAAO,QAAQ,MAAM,WAAW,CAAC,IAAI;AACtE,QAAI;AACJ,UAAM,OAAO,KAAK,IAAI,MAAM,IAAI,CAAC;AAEjC,QAAI,MAAM;AACR,UAAI,QAAQ,MAAO,GAAW,IAAI,GAAG,CAAC,MAAQ,GAAW,IAAI,IAAI,GAAI,SAAS,QAAQ;AAAA,IACxF,WAAW,cAAc,kBAAkB;AACzC,YAAM,IAAI,GAAG;AACb,UAAI,MAAM,YAAY;AACpB,cAAM,MAAM,GAAG,aAAa,OAAO,KAAK,GAAG,UAAU;AACrD,YAAI;AAAA,UACFF,GAAO,MAAM;AACX,kBAAM,MAAM,QAAQ;AACpB,gBAAI,MAAM,QAAQ,GAAG,GAAG;AACtB,oBAAM,MAAM,IAAI,IAAI,GAAG;AACvB,iBAAG,UAAU,IAAI,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK;AACpD,qBAAO,CAAC,GAAG,GAAG;AAAA,YAChB;AACA,mBAAO,MAAO,GAAG,UAAU,GAAG,QAAQ,KAAM,GAAG;AAAA,UACjD;AAAA,UACAC,GAAQ,CAAC,MAAM;AACb,eAAG,UAAU,MAAM,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,KAAK,IAAI,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC;AAAA,UAClF;AAAA,UACAC,GAAS,CAAC,OAAO;AAAA,QACnB;AAAA,MACF,WAAW,MAAM,SAAS;AACxB,YAAI,CAAC,GAAG,KAAM,IAAG,OAAO;AACxB,YAAI,QAAQ,MAAO,GAAG,UAAU,SAAS,GAAG,KAAK,IAAI,QAAQ,GAAI,CAAC,MAAO,GAAG,UAAU,OAAO,CAAC,MAAM,GAAG,OAAQ,OAAO;AAAA,MACxH,WAAW,MAAM,QAAQ;AACvB,eAAO,IAAI,UAAU,MAAM,UAAU,EAAE,EAAE,KAAK,CAAC,UAAU,MAAM,IAAI,MAAM,KAAK,CAAC,CAAC;AAChF;AAAA,MACF,WAAW,MAAM,YAAY,MAAM,SAAS;AAC1C,YAAI,QAAQ,MAAO,GAAG,UAAU,KAAK,KAAK,CAAC,GAAG,OAAQ,CAAC,MAAO,GAAG,QAAQ,OAAO,KAAK,EAAE,GAAI,OAAO;AAAA,MACpG,OAAO;AACL,YAAI,QAAQ,MAAM,GAAG,OAAO,CAAC,MAAO,GAAG,QAAQ,OAAO,KAAK,EAAE,GAAI,OAAO;AAAA,MAC1E;AAAA,IACF,WAAW,cAAc,mBAAmB;AAC1C,UAAI;AAAA,QACFF,GAAO,MAAO,GAAG,WAAW,CAAC,GAAG,GAAG,eAAe,EAAE,IAAI,CAAC,MAAM,SAAS,EAAE,KAAK,CAAC,IAAI,SAAS,GAAG,KAAK;AAAA,QACrGC,GAAQ,CAAC,MAAM;AACb,cAAI,GAAG,SAAU,YAAW,KAAK,GAAG,QAAS,GAAE,WAAW,MAAM,QAAQ,CAAC,KAAK,EAAE,IAAI,MAAM,EAAE,SAAS,EAAE,KAAK;AAAA,cACvG,IAAG,QAAQ,OAAO,KAAK,EAAE;AAAA,QAChC;AAAA,QACAC,GAAS,CAAC,QAAQ;AAAA,MACpB;AAAA,IACF,WAAW,cAAc,uBAAuB,WAAW,IAAI;AAC7D,UAAI,QAAQ,MAAO,GAAW,OAAO,CAAC,MAAQ,GAAW,QAAQ,OAAO,KAAK,EAAE,GAAI,SAAS,QAAQ;AAAA,IACtG,OAAO;AACL,UAAI,QAAQ,MAAM,GAAG,aAAa,OAAO,GAAG,CAAC,MAAM,GAAG,aAAa,SAAS,OAAO,KAAK,EAAE,CAAC,GAAG,QAAQ;AAAA,IACxG;AAEA,QAAI,CAAC,MAAM,IAAI,IAAI,GAAG;AACpB,YAAM,UAAU,EAAEF,EAAM;AACxB,UAAI,YAAY,UAAa,YAAY,GAAI,OAAM,IAAI,MAAM,OAAO;AAAA,IACtE;AACA,UAAM,OAAO,MAAM,MAAM,IAAI,MAAM,EAAEA,EAAM,CAAC;AAC5C,eAAW,QAAQ,KAAK,IAAI,OAAO,KAAK,EAAEE,EAAS,QAAO,IAAI,MAAM,IAAI;AACxE,WAAO,IAAI,qBAAqB,IAAI;AACpC,WAAO,MAAM;AACX,YAAM,IAAI,QAAQ;AAClB,UAAI,MAAM,OAAW,GAAED,EAAO,CAAC;AAAA,IACjC,CAAC;AAAA,EACH;AACF,CAAC;",
4
+ "sourcesContent": ["import { attribute } from '../../kernel/index.js';\n\ntype Adapter = { _read(): unknown; _write(v: unknown): void; _events: string[] };\nconst adapter = (_read: () => unknown, _write: (v: any) => void, ..._events: string[]): Adapter => ({\n _read,\n _write,\n _events,\n});\n\nconst readFiles = (input: HTMLInputElement) =>\n Promise.all(\n [...(input.files ?? [])].map(\n (f) =>\n new Promise<{ name: string; type: string; size: number; contents: string }>((resolve) => {\n const r = new FileReader();\n r.onloadend = () =>\n resolve({ name: f.name, type: f.type, size: f.size, contents: String(r.result).split(',')[1] ?? '' });\n r.readAsDataURL(f);\n }),\n ),\n );\n\n/**\n * Two-way binding: `bind:name` or `bind=\"name\"`. Creates the signal from the element when missing.\n * Checkbox groups bind to arrays, radios to the checked value, `select multiple` to arrays.\n * `__prop.value` binds a custom element property; `__event.change` picks the events to listen for.\n */\nexport const bind = attribute({\n name: 'bind',\n mount({ el, key, value, cased, mods, store, listen, effect }) {\n const path = key ? cased() : value.trim();\n const current = () => store.get(path);\n const asNumber = (s: string) => (typeof current() === 'number' ? +s : s);\n let a: Adapter;\n const prop = mods.get('prop')?.[0];\n\n if (prop) {\n a = adapter(\n () => (el as any)[prop],\n (v) => ((el as any)[prop] = v),\n 'input',\n 'change',\n );\n } else if (el instanceof HTMLInputElement) {\n const t = el.type;\n if (t === 'checkbox') {\n const own = el.hasAttribute('value') && el.value !== 'on';\n a = {\n _read: () => {\n const cur = current();\n if (Array.isArray(cur)) {\n const set = new Set(cur);\n el.checked ? set.add(el.value) : set.delete(el.value);\n return [...set];\n }\n return own ? (el.checked ? el.value : '') : el.checked;\n },\n _write: (v) => {\n el.checked = Array.isArray(v) ? v.includes(el.value) : own ? v === el.value : !!v;\n },\n _events: ['input'],\n };\n } else if (t === 'radio') {\n if (!el.name) el.name = path;\n a = adapter(\n () => (el.checked ? asNumber(el.value) : current()),\n (v) => (el.checked = String(v) === el.value),\n 'input',\n );\n } else if (t === 'file') {\n listen(el, 'change', () => readFiles(el).then((files) => store.set(path, files)));\n return;\n } else if (t === 'number' || t === 'range') {\n a = adapter(\n () => (el.value === '' ? '' : +el.value),\n (v) => (el.value = String(v ?? '')),\n 'input',\n );\n } else {\n a = adapter(\n () => el.value,\n (v) => (el.value = String(v ?? '')),\n 'input',\n );\n }\n } else if (el instanceof HTMLSelectElement) {\n a = {\n _read: () => (el.multiple ? [...el.selectedOptions].map((o) => asNumber(o.value)) : asNumber(el.value)),\n _write: (v) => {\n if (el.multiple) for (const o of el.options) o.selected = Array.isArray(v) && v.map(String).includes(o.value);\n else el.value = String(v ?? '');\n },\n _events: ['change'],\n };\n } else if (el instanceof HTMLTextAreaElement || 'value' in el) {\n a = adapter(\n () => (el as any).value,\n (v) => ((el as any).value = String(v ?? '')),\n 'input',\n 'change',\n );\n } else {\n a = adapter(\n () => el.getAttribute('value'),\n (v) => el.setAttribute('value', String(v ?? '')),\n 'change',\n );\n }\n\n if (!store.has(path)) {\n const initial = a._read();\n if (initial !== undefined && initial !== '') store.set(path, initial);\n }\n const sync = () => store.set(path, a._read());\n for (const type of mods.get('event') ?? a._events) listen(el, type, sync);\n listen(el, 'sigmx-prop-change', sync);\n effect(() => {\n const v = current();\n if (v !== undefined) a._write(v);\n });\n },\n});\n"],
5
+ "mappings": "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",
6
6
  "names": ["_read", "_write", "_events"]
7
7
  }
@@ -12,7 +12,8 @@ const queryString = attribute({
12
12
  mount({ key, value, mods, evaluate, cased, store, listen, effect }) {
13
13
  const history = mods.has("history");
14
14
  const push = (url) => {
15
- if (url !== location.pathname + location.search + location.hash) window.history[history ? "pushState" : "replaceState"](null, "", url);
15
+ if (url !== location.pathname + location.search + location.hash)
16
+ window.history[history ? "pushState" : "replaceState"](null, "", url);
16
17
  };
17
18
  const urlWith = (q) => `${location.pathname}${q.size ? `?${q}` : ""}${location.hash}`;
18
19
  let restoring = false;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/directives/url-params.ts"],
4
- "sourcesContent": ["import { attribute, expand, toPredicate } from '../../kernel/index.js'\n\nconst parse = (s: string): unknown => {\n try {\n return JSON.parse(s)\n } catch {\n return s\n }\n}\nconst same = (a: unknown, b: unknown) => JSON.stringify(a) === JSON.stringify(b)\n\n/**\n * Keeps signals and the URL query string in step.\n *\n * Keyed form declares one signal with a default: `query-string:page=\"1\"` creates `page`, reads\n * `?page=` on load when present (otherwise uses the default), writes it whenever it changes, and\n * drops the parameter again when the value is back at the default. The parameter name is the key\n * as written; the signal name is recased as usual.\n *\n * Bare form syncs existing signals: `query-string=\"{ include: /^(q|sort)$/ }\"` mirrors matching\n * paths both ways. `__history` pushes an entry per change and restores on back/forward;\n * `__filter` drops empty values from the URL.\n */\nexport const queryString = attribute({\n name: 'query-string',\n mount({ key, value, mods, evaluate, cased, store, listen, effect }) {\n const history = mods.has('history')\n const push = (url: string) => {\n if (url !== location.pathname + location.search + location.hash) window.history[history ? 'pushState' : 'replaceState'](null, '', url)\n }\n const urlWith = (q: URLSearchParams) => `${location.pathname}${q.size ? `?${q}` : ''}${location.hash}`\n let restoring = false\n const restore = (fn: () => void) => {\n restoring = true\n try {\n fn()\n } finally {\n restoring = false\n }\n }\n\n if (key) {\n const path = cased()\n const fallback = value ? evaluate() : ''\n const fromUrl = () => {\n const raw = new URLSearchParams(location.search).get(key)\n store.set(path, raw === null ? fallback : parse(raw))\n }\n if (!store.has(path) || new URLSearchParams(location.search).has(key)) fromUrl()\n effect(() => {\n const v = store.get(path)\n if (restoring) return\n const q = new URLSearchParams(location.search)\n if (v === undefined || same(v, fallback)) q.delete(key)\n else q.set(key, typeof v === 'string' ? v : JSON.stringify(v))\n push(urlWith(q))\n })\n if (history) listen(window, 'popstate', () => restore(fromUrl))\n return\n }\n\n const filter = value ? evaluate() : undefined\n const ok = toPredicate(filter)\n const fromUrl = () => {\n const patch = {}\n for (const [k, v] of new URLSearchParams(location.search)) if (ok(k)) expand(patch, k, parse(v))\n store.merge(patch)\n }\n fromUrl()\n effect(() => {\n const snap = store.snapshot(filter, { computed: false })\n if (restoring) return\n const q = new URLSearchParams(location.search)\n const walk = (obj: Record<string, any>, prefix: string) => {\n for (const k in obj) {\n const p = prefix ? `${prefix}.${k}` : k\n const v = obj[k]\n if (v && typeof v === 'object' && !Array.isArray(v)) walk(v, p)\n else if (mods.has('filter') && (v === '' || v == null)) q.delete(p)\n else q.set(p, typeof v === 'string' ? v : JSON.stringify(v))\n }\n }\n walk(snap, '')\n push(urlWith(q))\n })\n if (history) listen(window, 'popstate', () => restore(fromUrl))\n },\n})\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { attribute, expand, toPredicate } from '../../kernel/index.js';\n\nconst parse = (s: string): unknown => {\n try {\n return JSON.parse(s);\n } catch {\n return s;\n }\n};\nconst same = (a: unknown, b: unknown) => JSON.stringify(a) === JSON.stringify(b);\n\n/**\n * Keeps signals and the URL query string in step.\n *\n * Keyed form declares one signal with a default: `query-string:page=\"1\"` creates `page`, reads\n * `?page=` on load when present (otherwise uses the default), writes it whenever it changes, and\n * drops the parameter again when the value is back at the default. The parameter name is the key\n * as written; the signal name is recased as usual.\n *\n * Bare form syncs existing signals: `query-string=\"{ include: /^(q|sort)$/ }\"` mirrors matching\n * paths both ways. `__history` pushes an entry per change and restores on back/forward;\n * `__filter` drops empty values from the URL.\n */\nexport const queryString = attribute({\n name: 'query-string',\n mount({ key, value, mods, evaluate, cased, store, listen, effect }) {\n const history = mods.has('history');\n const push = (url: string) => {\n if (url !== location.pathname + location.search + location.hash)\n window.history[history ? 'pushState' : 'replaceState'](null, '', url);\n };\n const urlWith = (q: URLSearchParams) => `${location.pathname}${q.size ? `?${q}` : ''}${location.hash}`;\n let restoring = false;\n const restore = (fn: () => void) => {\n restoring = true;\n try {\n fn();\n } finally {\n restoring = false;\n }\n };\n\n if (key) {\n const path = cased();\n const fallback = value ? evaluate() : '';\n const fromUrl = () => {\n const raw = new URLSearchParams(location.search).get(key);\n store.set(path, raw === null ? fallback : parse(raw));\n };\n if (!store.has(path) || new URLSearchParams(location.search).has(key)) fromUrl();\n effect(() => {\n const v = store.get(path);\n if (restoring) return;\n const q = new URLSearchParams(location.search);\n if (v === undefined || same(v, fallback)) q.delete(key);\n else q.set(key, typeof v === 'string' ? v : JSON.stringify(v));\n push(urlWith(q));\n });\n if (history) listen(window, 'popstate', () => restore(fromUrl));\n return;\n }\n\n const filter = value ? evaluate() : undefined;\n const ok = toPredicate(filter);\n const fromUrl = () => {\n const patch = {};\n for (const [k, v] of new URLSearchParams(location.search)) if (ok(k)) expand(patch, k, parse(v));\n store.merge(patch);\n };\n fromUrl();\n effect(() => {\n const snap = store.snapshot(filter, { computed: false });\n if (restoring) return;\n const q = new URLSearchParams(location.search);\n const walk = (obj: Record<string, any>, prefix: string) => {\n for (const k in obj) {\n const p = prefix ? `${prefix}.${k}` : k;\n const v = obj[k];\n if (v && typeof v === 'object' && !Array.isArray(v)) walk(v, p);\n else if (mods.has('filter') && (v === '' || v == null)) q.delete(p);\n else q.set(p, typeof v === 'string' ? v : JSON.stringify(v));\n }\n };\n walk(snap, '');\n push(urlWith(q));\n });\n if (history) listen(window, 'popstate', () => restore(fromUrl));\n },\n});\n"],
5
+ "mappings": "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",
6
6
  "names": ["fromUrl"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/directives/url-replace.ts"],
4
- "sourcesContent": ["import { attribute } from '../../kernel/index.js'\n\nexport const replaceUrl = attribute({\n name: 'replace-url',\n key: 'forbidden',\n value: 'required',\n mount: ({ evaluate, effect }) =>\n effect(() => history.replaceState(history.state, '', new URL(String(evaluate()), location.href))),\n})\n"],
4
+ "sourcesContent": ["import { attribute } from '../../kernel/index.js';\n\nexport const replaceUrl = attribute({\n name: 'replace-url',\n key: 'forbidden',\n value: 'required',\n mount: ({ evaluate, effect }) =>\n effect(() => history.replaceState(history.state, '', new URL(String(evaluate()), location.href))),\n});\n"],
5
5
  "mappings": "AAAA,SAAS,iBAAiB;AAEnB,MAAM,aAAa,UAAU;AAAA,EAClC,MAAM;AAAA,EACN,KAAK;AAAA,EACL,OAAO;AAAA,EACP,OAAO,CAAC,EAAE,UAAU,OAAO,MACzB,OAAO,MAAM,QAAQ,aAAa,QAAQ,OAAO,IAAI,IAAI,IAAI,OAAO,SAAS,CAAC,GAAG,SAAS,IAAI,CAAC,CAAC;AACpG,CAAC;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/directives/validity.ts"],
4
- "sourcesContent": ["import { attribute } from '../../kernel/index.js'\n\n/** The expression's string becomes the field's validity message; '' means valid. */\nexport const customValidity = attribute({\n name: 'custom-validity',\n key: 'forbidden',\n value: 'required',\n mount({ el, evaluate, effect, error }) {\n if (!('setCustomValidity' in el)) throw error('only works on form fields')\n effect(() => (el as HTMLInputElement).setCustomValidity(String(evaluate() ?? '')))\n },\n})\n"],
4
+ "sourcesContent": ["import { attribute } from '../../kernel/index.js';\n\n/** The expression's string becomes the field's validity message; '' means valid. */\nexport const customValidity = attribute({\n name: 'custom-validity',\n key: 'forbidden',\n value: 'required',\n mount({ el, evaluate, effect, error }) {\n if (!('setCustomValidity' in el)) throw error('only works on form fields');\n effect(() => (el as HTMLInputElement).setCustomValidity(String(evaluate() ?? '')));\n },\n});\n"],
5
5
  "mappings": "AAAA,SAAS,iBAAiB;AAGnB,MAAM,iBAAiB,UAAU;AAAA,EACtC,MAAM;AAAA,EACN,KAAK;AAAA,EACL,OAAO;AAAA,EACP,MAAM,EAAE,IAAI,UAAU,QAAQ,MAAM,GAAG;AACrC,QAAI,EAAE,uBAAuB,IAAK,OAAM,MAAM,2BAA2B;AACzE,WAAO,MAAO,GAAwB,kBAAkB,OAAO,SAAS,KAAK,EAAE,CAAC,CAAC;AAAA,EACnF;AACF,CAAC;",
6
6
  "names": []
7
7
  }
@@ -7,7 +7,10 @@ const onIntersect = attribute({
7
7
  mount({ el, mods, evaluate }) {
8
8
  const t = mods.get("threshold")?.[0];
9
9
  const threshold = mods.has("full") ? 1 : mods.has("half") ? 0.5 : t ? Math.min(100, Math.max(0, +t)) / 100 : 0;
10
- const run = withTiming(withViewTransition(() => evaluate(), mods), mods);
10
+ const run = withTiming(
11
+ withViewTransition(() => evaluate(), mods),
12
+ mods
13
+ );
11
14
  const io = new IntersectionObserver(
12
15
  (entries) => {
13
16
  for (const e of entries) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/directives/viewport.ts"],
4
- "sourcesContent": ["import { attribute, withTiming, withViewTransition } from '../../kernel/index.js'\n\n/** Runs when the element enters the viewport. Modifiers: once, exit, full, half, threshold.N. */\nexport const onIntersect = attribute({\n name: 'on-intersect',\n key: 'forbidden',\n value: 'required',\n returns: false,\n mount({ el, mods, evaluate }) {\n const t = mods.get('threshold')?.[0]\n const threshold = mods.has('full') ? 1 : mods.has('half') ? 0.5 : t ? Math.min(100, Math.max(0, +t)) / 100 : 0\n const run = withTiming(withViewTransition(() => evaluate(), mods), mods)\n const io = new IntersectionObserver(\n (entries) => {\n for (const e of entries) {\n if (e.isIntersecting === mods.has('exit')) continue\n run()\n if (mods.has('once')) io.disconnect()\n }\n },\n { threshold },\n )\n io.observe(el)\n return () => io.disconnect()\n },\n})\n"],
5
- "mappings": "AAAA,SAAS,WAAW,YAAY,0BAA0B;AAGnD,MAAM,cAAc,UAAU;AAAA,EACnC,MAAM;AAAA,EACN,KAAK;AAAA,EACL,OAAO;AAAA,EACP,SAAS;AAAA,EACT,MAAM,EAAE,IAAI,MAAM,SAAS,GAAG;AAC5B,UAAM,IAAI,KAAK,IAAI,WAAW,IAAI,CAAC;AACnC,UAAM,YAAY,KAAK,IAAI,MAAM,IAAI,IAAI,KAAK,IAAI,MAAM,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,MAAM;AAC7G,UAAM,MAAM,WAAW,mBAAmB,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI;AACvE,UAAM,KAAK,IAAI;AAAA,MACb,CAAC,YAAY;AACX,mBAAW,KAAK,SAAS;AACvB,cAAI,EAAE,mBAAmB,KAAK,IAAI,MAAM,EAAG;AAC3C,cAAI;AACJ,cAAI,KAAK,IAAI,MAAM,EAAG,IAAG,WAAW;AAAA,QACtC;AAAA,MACF;AAAA,MACA,EAAE,UAAU;AAAA,IACd;AACA,OAAG,QAAQ,EAAE;AACb,WAAO,MAAM,GAAG,WAAW;AAAA,EAC7B;AACF,CAAC;",
4
+ "sourcesContent": ["import { attribute, withTiming, withViewTransition } from '../../kernel/index.js';\n\n/** Runs when the element enters the viewport. Modifiers: once, exit, full, half, threshold.N. */\nexport const onIntersect = attribute({\n name: 'on-intersect',\n key: 'forbidden',\n value: 'required',\n returns: false,\n mount({ el, mods, evaluate }) {\n const t = mods.get('threshold')?.[0];\n const threshold = mods.has('full') ? 1 : mods.has('half') ? 0.5 : t ? Math.min(100, Math.max(0, +t)) / 100 : 0;\n const run = withTiming(\n withViewTransition(() => evaluate(), mods),\n mods,\n );\n const io = new IntersectionObserver(\n (entries) => {\n for (const e of entries) {\n if (e.isIntersecting === mods.has('exit')) continue;\n run();\n if (mods.has('once')) io.disconnect();\n }\n },\n { threshold },\n );\n io.observe(el);\n return () => io.disconnect();\n },\n});\n"],
5
+ "mappings": "AAAA,SAAS,WAAW,YAAY,0BAA0B;AAGnD,MAAM,cAAc,UAAU;AAAA,EACnC,MAAM;AAAA,EACN,KAAK;AAAA,EACL,OAAO;AAAA,EACP,SAAS;AAAA,EACT,MAAM,EAAE,IAAI,MAAM,SAAS,GAAG;AAC5B,UAAM,IAAI,KAAK,IAAI,WAAW,IAAI,CAAC;AACnC,UAAM,YAAY,KAAK,IAAI,MAAM,IAAI,IAAI,KAAK,IAAI,MAAM,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,MAAM;AAC7G,UAAM,MAAM;AAAA,MACV,mBAAmB,MAAM,SAAS,GAAG,IAAI;AAAA,MACzC;AAAA,IACF;AACA,UAAM,KAAK,IAAI;AAAA,MACb,CAAC,YAAY;AACX,mBAAW,KAAK,SAAS;AACvB,cAAI,EAAE,mBAAmB,KAAK,IAAI,MAAM,EAAG;AAC3C,cAAI;AACJ,cAAI,KAAK,IAAI,MAAM,EAAG,IAAG,WAAW;AAAA,QACtC;AAAA,MACF;AAAA,MACA,EAAE,UAAU;AAAA,IACd;AACA,OAAG,QAAQ,EAAE;AACb,WAAO,MAAM,GAAG,WAAW;AAAA,EAC7B;AACF,CAAC;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/directives/visibility.ts"],
4
- "sourcesContent": ["import { attribute } from '../../kernel/index.js'\n\n/** Toggles `display: none`, restoring whatever inline display the element had. */\nexport const show = attribute({\n name: 'show',\n key: 'forbidden',\n value: 'required',\n mount({ el, evaluate, effect }) {\n const initial = el.style.display === 'none' ? '' : el.style.display\n effect(() => {\n el.style.display = evaluate() ? initial : 'none'\n })\n return () => {\n el.style.display = initial\n }\n },\n})\n"],
4
+ "sourcesContent": ["import { attribute } from '../../kernel/index.js';\n\n/** Toggles `display: none`, restoring whatever inline display the element had. */\nexport const show = attribute({\n name: 'show',\n key: 'forbidden',\n value: 'required',\n mount({ el, evaluate, effect }) {\n const initial = el.style.display === 'none' ? '' : el.style.display;\n effect(() => {\n el.style.display = evaluate() ? initial : 'none';\n });\n return () => {\n el.style.display = initial;\n };\n },\n});\n"],
5
5
  "mappings": "AAAA,SAAS,iBAAiB;AAGnB,MAAM,OAAO,UAAU;AAAA,EAC5B,MAAM;AAAA,EACN,KAAK;AAAA,EACL,OAAO;AAAA,EACP,MAAM,EAAE,IAAI,UAAU,OAAO,GAAG;AAC9B,UAAM,UAAU,GAAG,MAAM,YAAY,SAAS,KAAK,GAAG,MAAM;AAC5D,WAAO,MAAM;AACX,SAAG,MAAM,UAAU,SAAS,IAAI,UAAU;AAAA,IAC5C,CAAC;AACD,WAAO,MAAM;AACX,SAAG,MAAM,UAAU;AAAA,IACrB;AAAA,EACF;AACF,CAAC;",
6
6
  "names": []
7
7
  }
@@ -1,2 +1 @@
1
- /** Runs the expression now and whenever a signal it read changes. */
2
1
  export declare const effect: import("../../kernel/contracts.js").AttributePlugin;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/directives/watch.ts"],
4
- "sourcesContent": ["import { attribute } from '../../kernel/index.js'\n\n/** Runs the expression now and whenever a signal it read changes. */\nexport const effect = attribute({\n name: 'effect',\n key: 'forbidden',\n value: 'required',\n returns: false,\n mount: (ctx) => ctx.effect(() => ctx.evaluate()),\n})\n"],
5
- "mappings": "AAAA,SAAS,iBAAiB;AAGnB,MAAM,SAAS,UAAU;AAAA,EAC9B,MAAM;AAAA,EACN,KAAK;AAAA,EACL,OAAO;AAAA,EACP,SAAS;AAAA,EACT,OAAO,CAAC,QAAQ,IAAI,OAAO,MAAM,IAAI,SAAS,CAAC;AACjD,CAAC;",
4
+ "sourcesContent": ["import { attribute } from '../../kernel/index.js';\n\nexport const effect = attribute({\n name: 'effect',\n key: 'forbidden',\n value: 'required',\n returns: false,\n mount: (ctx) => ctx.effect(() => ctx.evaluate()),\n});\n"],
5
+ "mappings": "AAAA,SAAS,iBAAiB;AAEnB,MAAM,SAAS,UAAU;AAAA,EAC9B,MAAM;AAAA,EACN,KAAK;AAAA,EACL,OAAO;AAAA,EACP,SAAS;AAAA,EACT,OAAO,CAAC,QAAQ,IAAI,OAAO,MAAM,IAAI,SAAS,CAAC;AACjD,CAAC;",
6
6
  "names": []
7
7
  }
@@ -1,9 +1,11 @@
1
1
  import { action, batch, untracked } from "../../kernel/index.js";
2
2
  const setAll = action({
3
3
  name: "setAll",
4
- call: ({ store }, value, filter) => batch(() => untracked(() => {
5
- for (const p of store.paths(filter)) store.set(p, value);
6
- }))
4
+ call: ({ store }, value, filter) => batch(
5
+ () => untracked(() => {
6
+ for (const p of store.paths(filter)) store.set(p, value);
7
+ })
8
+ )
7
9
  });
8
10
  export {
9
11
  setAll
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/functions/bulk-set.ts"],
4
- "sourcesContent": ["import { action, batch, untracked, type Filter } from '../../kernel/index.js'\n\n/** `@setAll(value, { include: /^form\\./ })` assigns every matching signal. */\nexport const setAll = action({\n name: 'setAll',\n call: ({ store }, value: unknown, filter?: Filter) =>\n batch(() => untracked(() => { for (const p of store.paths(filter)) store.set(p, value) })),\n})\n"],
5
- "mappings": "AAAA,SAAS,QAAQ,OAAO,iBAA8B;AAG/C,MAAM,SAAS,OAAO;AAAA,EAC3B,MAAM;AAAA,EACN,MAAM,CAAC,EAAE,MAAM,GAAG,OAAgB,WAChC,MAAM,MAAM,UAAU,MAAM;AAAE,eAAW,KAAK,MAAM,MAAM,MAAM,EAAG,OAAM,IAAI,GAAG,KAAK;AAAA,EAAE,CAAC,CAAC;AAC7F,CAAC;",
4
+ "sourcesContent": ["import { action, batch, type Filter, untracked } from '../../kernel/index.js';\n\n/** `@setAll(value, { include: /^form\\./ })` assigns every matching signal. */\nexport const setAll = action({\n name: 'setAll',\n call: ({ store }, value: unknown, filter?: Filter) =>\n batch(() =>\n untracked(() => {\n for (const p of store.paths(filter)) store.set(p, value);\n }),\n ),\n});\n"],
5
+ "mappings": "AAAA,SAAS,QAAQ,OAAoB,iBAAiB;AAG/C,MAAM,SAAS,OAAO;AAAA,EAC3B,MAAM;AAAA,EACN,MAAM,CAAC,EAAE,MAAM,GAAG,OAAgB,WAChC;AAAA,IAAM,MACJ,UAAU,MAAM;AACd,iBAAW,KAAK,MAAM,MAAM,MAAM,EAAG,OAAM,IAAI,GAAG,KAAK;AAAA,IACzD,CAAC;AAAA,EACH;AACJ,CAAC;",
6
6
  "names": []
7
7
  }
@@ -1,9 +1,11 @@
1
1
  import { action, batch, untracked } from "../../kernel/index.js";
2
2
  const toggleAll = action({
3
3
  name: "toggleAll",
4
- call: ({ store }, filter) => batch(() => untracked(() => {
5
- for (const p of store.paths(filter)) store.set(p, !store.get(p));
6
- }))
4
+ call: ({ store }, filter) => batch(
5
+ () => untracked(() => {
6
+ for (const p of store.paths(filter)) store.set(p, !store.get(p));
7
+ })
8
+ )
7
9
  });
8
10
  export {
9
11
  toggleAll
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/functions/bulk-toggle.ts"],
4
- "sourcesContent": ["import { action, batch, untracked, type Filter } from '../../kernel/index.js'\n\n/** `@toggleAll({ include: /^flags\\./ })` negates every matching boolean signal. */\nexport const toggleAll = action({\n name: 'toggleAll',\n call: ({ store }, filter?: Filter) =>\n batch(() => untracked(() => { for (const p of store.paths(filter)) store.set(p, !store.get(p)) })),\n})\n"],
5
- "mappings": "AAAA,SAAS,QAAQ,OAAO,iBAA8B;AAG/C,MAAM,YAAY,OAAO;AAAA,EAC9B,MAAM;AAAA,EACN,MAAM,CAAC,EAAE,MAAM,GAAG,WAChB,MAAM,MAAM,UAAU,MAAM;AAAE,eAAW,KAAK,MAAM,MAAM,MAAM,EAAG,OAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC;AAAA,EAAE,CAAC,CAAC;AACrG,CAAC;",
4
+ "sourcesContent": ["import { action, batch, type Filter, untracked } from '../../kernel/index.js';\n\n/** `@toggleAll({ include: /^flags\\./ })` negates every matching boolean signal. */\nexport const toggleAll = action({\n name: 'toggleAll',\n call: ({ store }, filter?: Filter) =>\n batch(() =>\n untracked(() => {\n for (const p of store.paths(filter)) store.set(p, !store.get(p));\n }),\n ),\n});\n"],
5
+ "mappings": "AAAA,SAAS,QAAQ,OAAoB,iBAAiB;AAG/C,MAAM,YAAY,OAAO;AAAA,EAC9B,MAAM;AAAA,EACN,MAAM,CAAC,EAAE,MAAM,GAAG,WAChB;AAAA,IAAM,MACJ,UAAU,MAAM;AACd,iBAAW,KAAK,MAAM,MAAM,MAAM,EAAG,OAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC;AAAA,IACjE,CAAC;AAAA,EACH;AACJ,CAAC;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/functions/confirm.ts"],
4
- "sourcesContent": ["import { action } from '../../kernel/index.js'\n\n/** `@confirm('Delete?') && @delete('/x')` asks before continuing. */\nexport const confirm = action({ name: 'confirm', call: (_, message: string) => window.confirm(message) })\n"],
4
+ "sourcesContent": ["import { action } from '../../kernel/index.js';\n\n/** `@confirm('Delete?') && @delete('/x')` asks before continuing. */\nexport const confirm = action({ name: 'confirm', call: (_, message: string) => window.confirm(message) });\n"],
5
5
  "mappings": "AAAA,SAAS,cAAc;AAGhB,MAAM,UAAU,OAAO,EAAE,MAAM,WAAW,MAAM,CAAC,GAAG,YAAoB,OAAO,QAAQ,OAAO,EAAE,CAAC;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/plugins/functions/copy-text.ts"],
4
- "sourcesContent": ["import { action } from '../../kernel/index.js'\n\n/** `@clipboard(text, isBase64?)` copies text; base64 input is decoded first. */\nexport const clipboard = action({\n name: 'clipboard',\n call: (_, text: string, base64 = false) =>\n navigator.clipboard.writeText(\n base64 ? new TextDecoder().decode(Uint8Array.from(atob(text), (c) => c.charCodeAt(0))) : text,\n ),\n})\n"],
4
+ "sourcesContent": ["import { action } from '../../kernel/index.js';\n\n/** `@clipboard(text, isBase64?)` copies text; base64 input is decoded first. */\nexport const clipboard = action({\n name: 'clipboard',\n call: (_, text: string, base64 = false) =>\n navigator.clipboard.writeText(\n base64 ? new TextDecoder().decode(Uint8Array.from(atob(text), (c) => c.charCodeAt(0))) : text,\n ),\n});\n"],
5
5
  "mappings": "AAAA,SAAS,cAAc;AAGhB,MAAM,YAAY,OAAO;AAAA,EAC9B,MAAM;AAAA,EACN,MAAM,CAAC,GAAG,MAAc,SAAS,UAC/B,UAAU,UAAU;AAAA,IAClB,SAAS,IAAI,YAAY,EAAE,OAAO,WAAW,KAAK,KAAK,IAAI,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,IAAI;AAAA,EAC3F;AACJ,CAAC;",
6
6
  "names": []
7
7
  }