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
package/README.md CHANGED
@@ -1,12 +1,14 @@
1
1
  # sigmx
2
2
 
3
+ [![CI](https://github.com/wrux/sigmx/actions/workflows/ci.yml/badge.svg)](https://github.com/wrux/sigmx/actions/workflows/ci.yml)
4
+
3
5
  **htmx on steroids, in a runtime smaller than htmx.**
4
6
 
5
7
  > **Status: an experiment.** sigmx is a personal exploration of what a hypermedia library looks like when it starts from a tiny, plugin-based core. It is inspired by [htmx](https://htmx.org) (the server sends HTML, the browser swaps it in), [Alpine.js](https://alpinejs.dev) (declarative `data-*` attributes with a little reactivity) and [Datastar](https://data-star.dev) (which fused the two and whose attribute syntax sigmx keeps for compatibility). The code is original, the APIs may still change, and it has not been used in production. Try it, break it, and open an issue with what you find.
6
8
 
7
9
  Your server renders HTML, as it always has. The browser asks for more of it with `@get` and `@post`, and sigmx merges the response into the page with a morph that keeps focus, typed input and scroll position. When you want live updates, the same request can return a stream of patches instead. Signals, two-way binding and reactive attributes cover the client-side state. You write `data-*` attributes and register only the plugins you use.
8
10
 
9
- - **Tiny.** 4.0 KB core, 8.9 KB with the essentials, 12.0 KB with all 52 plugins (brotli). Zero runtime dependencies.
11
+ - **Tiny.** 4.1 KB core, 8.8 KB with the essentials, 12.1 KB with all 52 plugins (brotli). Zero runtime dependencies.
10
12
  - **Server-driven.** Return plain HTML from any endpoint and it is morphed into the page by id, or targeted with a header. Return JSON to merge signals, or an event stream to push many patches over one request, with `Last-Event-ID` reconnects.
11
13
  - **Reactive where it matters.** Signals declared in markup; `bind`, `show`, `class`, computed values and effects keep the page in step. No component model, no virtual DOM.
12
14
  - **Pay for what you use.** Every directive and function is an opt-in plugin, and auto mode scans your source to bundle exactly the set it finds.
@@ -15,7 +17,7 @@ Your server renders HTML, as it always has. The browser asks for more of it with
15
17
 
16
18
  ```html
17
19
  <div data-signals="{ count: 0, name: '' }">
18
- <input data-bind:name placeholder="Your name">
20
+ <input data-bind:name placeholder="Your name" />
19
21
  <p data-show="$name">Hello, <span data-text="$name"></span>!</p>
20
22
  <button data-on:click="$count++">Clicked <b data-text="$count"></b> times</button>
21
23
  <button data-on:click="@post('/save')" data-indicator:saving data-attr:disabled="$saving">Save</button>
@@ -29,10 +31,10 @@ npm install sigmx
29
31
  ```
30
32
 
31
33
  ```ts
32
- import { createSigmx } from 'sigmx'
33
- import { essentials } from 'sigmx/presets/essentials'
34
+ import { createSigmx } from 'sigmx';
35
+ import { essentials } from 'sigmx/presets/essentials';
34
36
 
35
- createSigmx({ plugins: essentials })
37
+ createSigmx({ plugins: essentials });
36
38
  ```
37
39
 
38
40
  Or pick plugins by hand (`sigmx/plugins` is tree-shakeable), use `sigmx/presets/minimal` or `sigmx/presets/all`, let [auto mode](#auto-mode) choose, or drop in the script-tag build:
@@ -41,7 +43,7 @@ Or pick plugins by hand (`sigmx/plugins` is tree-shakeable), use `sigmx/presets/
41
43
  <script type="module" src="/sigmx.standalone.js"></script>
42
44
  ```
43
45
 
44
- Astro users: `npm install sigmx sigmx-astro` and add `sigmx()` to the integrations; see [sdks/astro](sdks/astro).
46
+ Astro users: `npm install sigmx @sigmx/astro` and add `sigmx()` to the integrations; see [sdks/astro](sdks/astro). Hono users: `npm install sigmx @sigmx/hono`, then `app.use(sigmx())` gives every handler `c.var.sigmx`; see [sdks/hono](sdks/hono). Everyone else: `sigmx/server` has the same event builders, responses, streams and signal reading as plain Fetch-API code.
45
47
 
46
48
  ## How it works
47
49
 
@@ -50,17 +52,17 @@ Attributes are `data-<plugin>[:key][__modifier.arg]="expression"`. Expressions a
50
52
  ```html
51
53
  <button data-on:click__debounce.300ms="@get('/search')">Search</button>
52
54
  <li data-class:active="$page === 3"></li>
53
- <input data-bind:user.email>
55
+ <input data-bind:user.email />
54
56
  <p data-text="`${$items.length} items, ${@intl('number', $total, { style: 'currency', currency: 'EUR' })}`"></p>
55
57
  ```
56
58
 
57
59
  State is one JSON-like store addressed by dotted paths and patched with merge-patch semantics: objects merge, `null` removes, arrays notify on `push`. Requests send the store (minus `_`-prefixed paths) and apply whatever comes back, decided by the response's content type:
58
60
 
59
- | the server returns | sigmx does |
60
- |---|---|
61
- | `text/html` | morphs it into the page: top-level elements by `id`, or a target from the `sigmx-selector` and `sigmx-mode` headers |
62
- | `application/json` | merges it into the signals |
63
- | `text/event-stream` | applies each event as it arrives: `patch-elements`, `patch-signals`, or your own handlers |
61
+ | the server returns | sigmx does |
62
+ | ------------------- | ------------------------------------------------------------------------------------------------------------------- |
63
+ | `text/html` | morphs it into the page: top-level elements by `id`, or a target from the `sigmx-selector` and `sigmx-mode` headers |
64
+ | `application/json` | merges it into the signals |
65
+ | `text/event-stream` | applies each event as it arrives: `patch-elements`, `patch-signals`, or your own handlers |
64
66
 
65
67
  The everyday case is the first row: render a partial with whatever templating you already use and return it. The morph keeps every element whose id appears on both sides, so a re-rendered form keeps what the user typed. Streams are there for progress, chat and dashboards, where one request should keep delivering:
66
68
 
@@ -76,14 +78,14 @@ data: elements <li>Validating…</li>
76
78
 
77
79
  ## Plugins
78
80
 
79
- | kind | plugins |
80
- |---|---|
81
- | state | `signals` `computed` `effect` `ref` `persist` `query-string` |
82
- | rendering | `text` `html` `show` `class` `style` `attr` `animate` `transition` `collapse` `view-transition` `cloak` |
83
- | forms | `bind` `custom-validity` `mask` |
84
- | events | `on` `init` `on-interval` `on-intersect` `on-resize` `on-raf` `on-signal-patch` `match-media` |
85
- | layout | `teleport` `trap` `scroll-into-view` `remove-me` |
86
- | server | `@get` `@post` `@put` `@patch` `@delete` `@ws` `boost` `indicator` `patch-elements` `patch-signals` |
81
+ | kind | plugins |
82
+ | --------- | -------------------------------------------------------------------------------------------------------------- |
83
+ | state | `signals` `computed` `effect` `ref` `persist` `query-string` |
84
+ | rendering | `text` `html` `show` `class` `style` `attr` `animate` `transition` `collapse` `view-transition` `cloak` |
85
+ | forms | `bind` `custom-validity` `mask` |
86
+ | events | `on` `init` `on-interval` `on-intersect` `on-resize` `on-raf` `on-signal-patch` `match-media` |
87
+ | layout | `teleport` `trap` `scroll-into-view` `remove-me` |
88
+ | server | `@get` `@post` `@put` `@patch` `@delete` `@ws` `boost` `indicator` `patch-elements` `patch-signals` |
87
89
  | utilities | `@peek` `@setAll` `@toggleAll` `@fit` `@clipboard` `@intl` `@dispatch` `@confirm` `json-signals` `replace-url` |
88
90
 
89
91
  Every plugin has a page in the docs with a live example and its measured size.
@@ -92,16 +94,16 @@ Every plugin has a page in the docs with a live example and its measured size.
92
94
 
93
95
  Brotli, measured from the real source by `npm run size` and `npm run compare` (nothing is quoted from memory):
94
96
 
95
- | | brotli |
96
- |---|---:|
97
- | sigmx core | 4.0 KB |
98
- | sigmx essentials (state, rendering, forms, requests, morph) | 8.9 KB |
99
- | sigmx everything, 52 plugins | 12.0 KB |
100
- | htmx 2.0.10 | 14.6 KB |
101
- | Datastar 1.0.3, free bundle (23 plugins) | 11.8 KB |
102
- | Alpine.js 3.17.1 | 17.6 KB |
97
+ | | brotli |
98
+ | ----------------------------------------------------------- | ------: |
99
+ | sigmx core | 4.1 KB |
100
+ | sigmx essentials (state, rendering, forms, requests, morph) | 8.8 KB |
101
+ | sigmx everything, 52 plugins | 12.1 KB |
102
+ | htmx 2.0.10 | 14.6 KB |
103
+ | Datastar 1.0.3, free bundle (23 plugins) | 11.8 KB |
104
+ | Alpine.js 3.17.1 | 17.6 KB |
103
105
 
104
- Precompiling expressions at build time removes the runtime compiler and any use of `new Function`, taking the core to 3.6 KB and making strict CSP trivial.
106
+ Precompiling expressions at build time removes the runtime compiler and any use of `new Function`, taking the core to 3.7 KB and making strict CSP trivial.
105
107
 
106
108
  ## Auto mode
107
109
 
@@ -109,14 +111,14 @@ Like a CSS framework scanning for class names, sigmx can scan your source for th
109
111
 
110
112
  ```js
111
113
  // vite.config.js
112
- import { sigmxAuto } from 'sigmx/vite'
113
- export default { plugins: [sigmxAuto({ always: ['signals'], custom: { upper: 'src/plugins/upper.ts' } })] }
114
+ import { sigmxAuto } from 'sigmx/vite';
115
+ export default { plugins: [sigmxAuto({ always: ['signals'], custom: { upper: 'src/plugins/upper.ts' } })] };
114
116
  ```
115
117
 
116
118
  ```ts
117
- import { createSigmx } from 'sigmx'
118
- import { plugins } from 'virtual:sigmx-plugins'
119
- createSigmx({ plugins })
119
+ import { createSigmx } from 'sigmx';
120
+ import { plugins } from 'virtual:sigmx-plugins';
121
+ createSigmx({ plugins });
120
122
  ```
121
123
 
122
124
  Without Vite: `npx sigmx scan src --out src/sigmx-plugins.js`. In Astro: `sigmx({ plugins: 'auto' })`.
@@ -124,15 +126,17 @@ Without Vite: `npx sigmx scan src --out src/sigmx-plugins.js`. In Astro: `sigmx(
124
126
  ## Writing a plugin
125
127
 
126
128
  ```ts
127
- import { attribute } from 'sigmx'
129
+ import { attribute } from 'sigmx';
128
130
 
129
131
  export const upper = attribute({
130
132
  name: 'upper',
131
133
  value: 'required',
132
134
  mount({ el, evaluate, effect }) {
133
- effect(() => { el.textContent = String(evaluate()).toUpperCase() })
135
+ effect(() => {
136
+ el.textContent = String(evaluate()).toUpperCase();
137
+ });
134
138
  },
135
- })
139
+ });
136
140
  ```
137
141
 
138
142
  Plugins are plain objects; nothing registers on import. The mount context gives you `evaluate`, `effect`, `listen`, `cleanup`, the store and the runtime, and everything registered through it is torn down when the attribute or element goes away. Functions (`@name()`) and server-event handlers work the same way with `action()` and `handler()`.
@@ -149,24 +153,31 @@ cd website && npm install && npm run dev
149
153
 
150
154
  ```
151
155
  src/kernel/ reactive graph, store, expression compiler, runtime (DOM-free core)
156
+ src/server.ts sigmx/server: event builders, sse/sseStream/html/json responses, readSignals
152
157
  src/plugins/ directives, functions, server-event handlers, the morph
153
158
  src/presets/ minimal, essentials, all
154
- sdks/astro/ sigmx-astro: integration, server helpers, auto mode, precompilation
159
+ sdks/astro/ @sigmx/astro: integration, server helpers, auto mode, precompilation
160
+ sdks/hono/ @sigmx/hono: middleware with signals(), html(), events(), stream(); serveClient()
161
+ examples/ standalone Vite, Express, Hono and Astro projects using the published packages
155
162
  website/ documentation site
156
163
  scripts/ build, size and comparison measurements, dev server
157
- tests/ node:test suite for the core; browser suite under tests/browser
164
+ tests/ unit (node:test), dom (happy-dom) and browser (Playwright) suites
158
165
  ```
159
166
 
160
167
  ```bash
161
168
  npm install
162
169
  npm run check # type-check
163
- npm test # build, then node:test over the DOM-free core
170
+ npm run lint # biome: formatting and lint rules
171
+ npm run format # biome: rewrite files in the house style
172
+ npm test # build, then unit tests and happy-dom tests for every plugin
173
+ npm run test:browser # Playwright: transitions, observers, WebSocket, the standalone build
174
+ npm run test:all # everything above plus the SDK suites
164
175
  npm run dev # dev server with SSE and WebSocket endpoints; open /tests/browser/index.html
165
176
  npm run size # bundle sizes for representative plugin sets
166
177
  npm run compare # sizes of htmx, Datastar and Alpine at pinned versions
167
178
  ```
168
179
 
169
- Contributions are welcome. Open an issue first for anything larger than a fix, keep plugins as small as their reference-page size table suggests, and run both test suites before a pull request.
180
+ Contributions are welcome. Open an issue first for anything larger than a fix, keep plugins as small as their reference-page size table suggests, and run `npm run lint` and both test suites before a pull request.
170
181
 
171
182
  ## Licence
172
183
 
package/dist/cli.js CHANGED
@@ -9,7 +9,9 @@ const opt = (name) => {
9
9
  return i < 0 ? void 0 : args.splice(i, 2)[1];
10
10
  };
11
11
  if (cmd !== "scan") {
12
- console.log("usage: sigmx scan [dirs...] [--out src/sigmx-plugins.js] [--always signals,httpGet] [--custom upper=src/plugins/upper.ts] [--prefix data-,hx-]");
12
+ console.log(
13
+ "usage: sigmx scan [dirs...] [--out src/sigmx-plugins.js] [--always signals,httpGet] [--custom upper=src/plugins/upper.ts] [--prefix data-,hx-]"
14
+ );
13
15
  process.exit(cmd ? 1 : 0);
14
16
  }
15
17
  const out = opt("out");
package/dist/cli.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/cli.ts"],
4
- "sourcesContent": ["#!/usr/bin/env node\n// `sigmx scan [dirs...] [--out file] [--always a,b] [--custom name=path,...] [--prefix data-,hx-]`\nimport { writeFileSync } from 'node:fs'\nimport { generatePluginsModule } from './kernel/scan.js'\nimport { scanProject } from './vite.js'\n\nconst args = process.argv.slice(2)\nconst cmd = args.shift()\nconst opt = (name: string) => {\n const i = args.indexOf(`--${name}`)\n return i < 0 ? undefined : args.splice(i, 2)[1]\n}\nif (cmd !== 'scan') {\n console.log('usage: sigmx scan [dirs...] [--out src/sigmx-plugins.js] [--always signals,httpGet] [--custom upper=src/plugins/upper.ts] [--prefix data-,hx-]')\n process.exit(cmd ? 1 : 0)\n}\nconst out = opt('out')\nconst always = opt('always')?.split(',').filter(Boolean)\nconst prefixes = opt('prefix')?.split(',').filter(Boolean)\nconst custom = Object.fromEntries((opt('custom')?.split(',') ?? []).map((pair) => pair.split('=') as [string, string]))\nconst sel = scanProject({ include: args.length ? args : undefined, always, prefixes, custom })\nconst code = generatePluginsModule(sel)\nif (out) {\n writeFileSync(out, code)\n console.log(`wrote ${out}: ${sel.plugins.length} plugins, ${sel.unused.length} unused`)\n} else process.stdout.write(code)\nfor (const [exp, why] of Object.entries(sel.reasons)) console.error(` ${exp.padEnd(16)} ${why}`)\n"],
5
- "mappings": ";AAEA,SAAS,qBAAqB;AAC9B,SAAS,6BAA6B;AACtC,SAAS,mBAAmB;AAE5B,MAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AACjC,MAAM,MAAM,KAAK,MAAM;AACvB,MAAM,MAAM,CAAC,SAAiB;AAC5B,QAAM,IAAI,KAAK,QAAQ,KAAK,IAAI,EAAE;AAClC,SAAO,IAAI,IAAI,SAAY,KAAK,OAAO,GAAG,CAAC,EAAE,CAAC;AAChD;AACA,IAAI,QAAQ,QAAQ;AAClB,UAAQ,IAAI,gJAAgJ;AAC5J,UAAQ,KAAK,MAAM,IAAI,CAAC;AAC1B;AACA,MAAM,MAAM,IAAI,KAAK;AACrB,MAAM,SAAS,IAAI,QAAQ,GAAG,MAAM,GAAG,EAAE,OAAO,OAAO;AACvD,MAAM,WAAW,IAAI,QAAQ,GAAG,MAAM,GAAG,EAAE,OAAO,OAAO;AACzD,MAAM,SAAS,OAAO,aAAa,IAAI,QAAQ,GAAG,MAAM,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,KAAK,MAAM,GAAG,CAAqB,CAAC;AACtH,MAAM,MAAM,YAAY,EAAE,SAAS,KAAK,SAAS,OAAO,QAAW,QAAQ,UAAU,OAAO,CAAC;AAC7F,MAAM,OAAO,sBAAsB,GAAG;AACtC,IAAI,KAAK;AACP,gBAAc,KAAK,IAAI;AACvB,UAAQ,IAAI,SAAS,GAAG,KAAK,IAAI,QAAQ,MAAM,aAAa,IAAI,OAAO,MAAM,SAAS;AACxF,MAAO,SAAQ,OAAO,MAAM,IAAI;AAChC,WAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,IAAI,OAAO,EAAG,SAAQ,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC,IAAI,GAAG,EAAE;",
4
+ "sourcesContent": ["#!/usr/bin/env node\n// `sigmx scan [dirs...] [--out file] [--always a,b] [--custom name=path,...] [--prefix data-,hx-]`\nimport { writeFileSync } from 'node:fs';\nimport { generatePluginsModule } from './kernel/scan.js';\nimport { scanProject } from './vite.js';\n\nconst args = process.argv.slice(2);\nconst cmd = args.shift();\nconst opt = (name: string) => {\n const i = args.indexOf(`--${name}`);\n return i < 0 ? undefined : args.splice(i, 2)[1];\n};\nif (cmd !== 'scan') {\n console.log(\n 'usage: sigmx scan [dirs...] [--out src/sigmx-plugins.js] [--always signals,httpGet] [--custom upper=src/plugins/upper.ts] [--prefix data-,hx-]',\n );\n process.exit(cmd ? 1 : 0);\n}\nconst out = opt('out');\nconst always = opt('always')?.split(',').filter(Boolean);\nconst prefixes = opt('prefix')?.split(',').filter(Boolean);\nconst custom = Object.fromEntries((opt('custom')?.split(',') ?? []).map((pair) => pair.split('=') as [string, string]));\nconst sel = scanProject({ include: args.length ? args : undefined, always, prefixes, custom });\nconst code = generatePluginsModule(sel);\nif (out) {\n writeFileSync(out, code);\n console.log(`wrote ${out}: ${sel.plugins.length} plugins, ${sel.unused.length} unused`);\n} else process.stdout.write(code);\nfor (const [exp, why] of Object.entries(sel.reasons)) console.error(` ${exp.padEnd(16)} ${why}`);\n"],
5
+ "mappings": ";AAEA,SAAS,qBAAqB;AAC9B,SAAS,6BAA6B;AACtC,SAAS,mBAAmB;AAE5B,MAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AACjC,MAAM,MAAM,KAAK,MAAM;AACvB,MAAM,MAAM,CAAC,SAAiB;AAC5B,QAAM,IAAI,KAAK,QAAQ,KAAK,IAAI,EAAE;AAClC,SAAO,IAAI,IAAI,SAAY,KAAK,OAAO,GAAG,CAAC,EAAE,CAAC;AAChD;AACA,IAAI,QAAQ,QAAQ;AAClB,UAAQ;AAAA,IACN;AAAA,EACF;AACA,UAAQ,KAAK,MAAM,IAAI,CAAC;AAC1B;AACA,MAAM,MAAM,IAAI,KAAK;AACrB,MAAM,SAAS,IAAI,QAAQ,GAAG,MAAM,GAAG,EAAE,OAAO,OAAO;AACvD,MAAM,WAAW,IAAI,QAAQ,GAAG,MAAM,GAAG,EAAE,OAAO,OAAO;AACzD,MAAM,SAAS,OAAO,aAAa,IAAI,QAAQ,GAAG,MAAM,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,KAAK,MAAM,GAAG,CAAqB,CAAC;AACtH,MAAM,MAAM,YAAY,EAAE,SAAS,KAAK,SAAS,OAAO,QAAW,QAAQ,UAAU,OAAO,CAAC;AAC7F,MAAM,OAAO,sBAAsB,GAAG;AACtC,IAAI,KAAK;AACP,gBAAc,KAAK,IAAI;AACvB,UAAQ,IAAI,SAAS,GAAG,KAAK,IAAI,QAAQ,MAAM,aAAa,IAAI,OAAO,MAAM,SAAS;AACxF,MAAO,SAAQ,OAAO,MAAM,IAAI;AAChC,WAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,IAAI,OAAO,EAAG,SAAQ,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC,IAAI,GAAG,EAAE;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/kernel/compile.ts"],
4
- "sourcesContent": ["// Expression compiler. Signals need no rewriting: the body runs inside `with (scope)`, where\n// `$count`, `$user.name` and `$` resolve through the store's scope proxy. Only `@action(` is\n// rewritten, into a call on the per-evaluation actions object.\n\nimport type { ExpressionCompiler } from './contracts.js'\n\nexport type Compiler = (params: string[], body: string) => (...args: any[]) => any\n\n/** Default compiler: `new Function`. Not usable under a strict CSP; see `cspCompiler`. */\nexport const functionCompiler: Compiler = (params, body) => Function(...params, body) as (...args: any[]) => any\n\nconst cache = new Map<string, (...args: any[]) => any>()\n\nconst isIdent = (c: string): boolean => /[A-Za-z0-9_$]/.test(c)\n\n/** Walk source text, skipping string, template and comment contents; `emit` receives code chars. */\nconst scan = (src: string, onCode: (c: string, i: number) => number | void): void => {\n let i = 0\n const n = src.length\n while (i < n) {\n const c = src[i]\n const next = src[i + 1]\n if (c === '\"' || c === \"'\" || c === '`') {\n let j = i + 1\n while (j < n && src[j] !== c) j += src[j] === '\\\\' ? 2 : 1\n onCode(src.slice(i, j + 1), i)\n i = j + 1\n } else if (c === '/' && next === '/') {\n const j = src.indexOf('\\n', i)\n i = j < 0 ? n : j\n } else if (c === '/' && next === '*') {\n const j = src.indexOf('*/', i + 2)\n i = j < 0 ? n : j + 2\n } else {\n const skip = onCode(c, i)\n i += skip || 1\n }\n }\n}\n\n/** Replace `@name(` with `__a.name(` outside strings and comments. */\nexport const rewriteActions = (src: string): string => {\n let out = ''\n scan(src, (c, i) => {\n if (c === '@') {\n let j = i + 1\n while (j < src.length && isIdent(src[j])) j++\n let k = j\n while (k < src.length && /\\s/.test(src[k])) k++\n if (j > i + 1 && src[k] === '(') {\n out += `__a.${src.slice(i + 1, j)}(`\n return k + 1 - i\n }\n }\n out += c\n })\n return out\n}\n\n/** Split on top-level semicolons. */\nexport const splitStatements = (src: string): string[] => {\n const parts: string[] = []\n let depth = 0\n let start = 0\n scan(src, (c, i) => {\n if (c.length > 1) return\n if ('([{'.includes(c)) depth++\n else if (')]}'.includes(c)) depth--\n else if (c === ';' && !depth) {\n parts.push(src.slice(start, i))\n start = i + 1\n }\n })\n parts.push(src.slice(start))\n return parts.filter((p) => p.trim())\n}\n\n/**\n * Compile an expression to `(store, actions, ...params) => any`: the body runs inside\n * `with (store.scope)`, so `$name` resolves through the store. With `returns`, the value of the\n * last statement is returned, so `$a = 1; $a * 2` works. Compiled functions are cached by source.\n */\nexport const compile = (\n compiler: Compiler,\n src: string,\n params: string[],\n returns: boolean,\n): ((...args: any[]) => any) => {\n const key = `${+returns}|${params.join()}|${src}`\n const hit = cache.get(key)\n if (hit) return hit\n const code = rewriteActions(src.trim())\n const make = (body: string) => compiler(['$', '__a', ...params], `with($.scope){${body}\\n}`)\n let fn: (...args: any[]) => any\n if (!returns) {\n fn = make(code)\n } else {\n try {\n fn = make(`return(${code}\\n)`)\n } catch {\n const parts = splitStatements(code)\n const last = parts.pop() ?? ''\n try {\n fn = make(`${parts.join(';')};return(${last}\\n)`)\n } catch {\n fn = make(code)\n }\n }\n }\n cache.set(key, fn)\n return fn\n}\n\n/** The default pipeline: compile at runtime inside `with (scope)` using `compiler` (`new Function` or CSP). */\nexport const runtimeExpressions =\n (compiler: Compiler): ExpressionCompiler =>\n (src, params, returns) =>\n compile(compiler, src, params, returns)\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["// Expression compiler. Signals need no rewriting: the body runs inside `with (scope)`, where\n// `$count`, `$user.name` and `$` resolve through the store's scope proxy. Only `@action(` is\n// rewritten, into a call on the per-evaluation actions object.\n\nimport type { ExpressionCompiler } from './contracts.js';\n\nexport type Compiler = (params: string[], body: string) => (...args: any[]) => any;\n\n/** Default compiler: `new Function`. Not usable under a strict CSP; see `cspCompiler`. */\nexport const functionCompiler: Compiler = (params, body) => Function(...params, body) as (...args: any[]) => any;\n\nconst cache = new Map<string, (...args: any[]) => any>();\n\nconst isIdent = (c: string): boolean => /[A-Za-z0-9_$]/.test(c);\n\n/** Walk source text, skipping string, template and comment contents; `emit` receives code chars. */\n// biome-ignore lint/suspicious/noConfusingVoidType: callers may return nothing to keep scanning\nconst scan = (src: string, onCode: (c: string, i: number) => number | void): void => {\n let i = 0;\n const n = src.length;\n while (i < n) {\n const c = src[i];\n const next = src[i + 1];\n if (c === '\"' || c === \"'\" || c === '`') {\n let j = i + 1;\n while (j < n && src[j] !== c) j += src[j] === '\\\\' ? 2 : 1;\n onCode(src.slice(i, j + 1), i);\n i = j + 1;\n } else if (c === '/' && next === '/') {\n const j = src.indexOf('\\n', i);\n i = j < 0 ? n : j;\n } else if (c === '/' && next === '*') {\n const j = src.indexOf('*/', i + 2);\n i = j < 0 ? n : j + 2;\n } else {\n const skip = onCode(c, i);\n i += skip || 1;\n }\n }\n};\n\n/** Replace `@name(` with `__a.name(` outside strings and comments. */\nexport const rewriteActions = (src: string): string => {\n let out = '';\n scan(src, (c, i) => {\n if (c === '@') {\n let j = i + 1;\n while (j < src.length && isIdent(src[j])) j++;\n let k = j;\n while (k < src.length && /\\s/.test(src[k])) k++;\n if (j > i + 1 && src[k] === '(') {\n out += `__a.${src.slice(i + 1, j)}(`;\n return k + 1 - i;\n }\n }\n out += c;\n });\n return out;\n};\n\n/** Split on top-level semicolons. */\nexport const splitStatements = (src: string): string[] => {\n const parts: string[] = [];\n let depth = 0;\n let start = 0;\n scan(src, (c, i) => {\n if (c.length > 1) return;\n if ('([{'.includes(c)) depth++;\n else if (')]}'.includes(c)) depth--;\n else if (c === ';' && !depth) {\n parts.push(src.slice(start, i));\n start = i + 1;\n }\n });\n parts.push(src.slice(start));\n return parts.filter((p) => p.trim());\n};\n\n/**\n * Compile an expression to `(store, actions, ...params) => any`: the body runs inside\n * `with (store.scope)`, so `$name` resolves through the store. With `returns`, the value of the\n * last statement is returned, so `$a = 1; $a * 2` works. Compiled functions are cached by source.\n */\nexport const compile = (\n compiler: Compiler,\n src: string,\n params: string[],\n returns: boolean,\n): ((...args: any[]) => any) => {\n const key = `${+returns}|${params.join()}|${src}`;\n const hit = cache.get(key);\n if (hit) return hit;\n const code = rewriteActions(src.trim());\n const make = (body: string) => compiler(['$', '__a', ...params], `with($.scope){${body}\\n}`);\n let fn: (...args: any[]) => any;\n if (!returns) {\n fn = make(code);\n } else {\n try {\n fn = make(`return(${code}\\n)`);\n } catch {\n const parts = splitStatements(code);\n const last = parts.pop() ?? '';\n try {\n fn = make(`${parts.join(';')};return(${last}\\n)`);\n } catch {\n fn = make(code);\n }\n }\n }\n cache.set(key, fn);\n return fn;\n};\n\n/** The default pipeline: compile at runtime inside `with (scope)` using `compiler` (`new Function` or CSP). */\nexport const runtimeExpressions =\n (compiler: Compiler): ExpressionCompiler =>\n (src, params, returns) =>\n compile(compiler, src, params, returns);\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,6 +1,6 @@
1
+ import type { CaseStyle } from '../lib/casing.js';
1
2
  import type { Compiler } from './compile.js';
2
3
  import type { Store } from './state.js';
3
- import type { CaseStyle } from '../lib/casing.js';
4
4
  export type El = HTMLElement | SVGElement | MathMLElement;
5
5
  export type Mods = Map<string, string[]>;
6
6
  /** A compiled attribute expression. `store` is the instance store; `actions` resolves `@name(...)`. */
@@ -17,7 +17,6 @@ export interface Runtime {
17
17
  readonly compiler: Compiler;
18
18
  /** Dispatch a `sigmx-<type>` CustomEvent on `document`. */
19
19
  emit(type: string, detail?: unknown): void;
20
- /** Call a registered action by name. */
21
20
  call(name: string, ctx: ActionCtx, args: any[]): any;
22
21
  /** Event-name prefixes accepted from servers; the first is what sigmx itself uses. */
23
22
  readonly eventPrefixes: readonly string[];
@@ -29,13 +28,10 @@ export interface Runtime {
29
28
  }
30
29
  export interface Ctx {
31
30
  el: El;
32
- /** Plugin name, e.g. 'on'. */
33
31
  plugin: string;
34
32
  /** Full attribute name as written, e.g. 'data-on:click__debounce.300ms'. */
35
33
  attr: string;
36
- /** The `:key` part, if any. */
37
34
  key: string | undefined;
38
- /** Attribute value (the expression source). */
39
35
  value: string;
40
36
  mods: Mods;
41
37
  /** The key recased per `__case.<style>`, defaulting to `style`. */
@@ -76,7 +72,6 @@ export interface ActionPlugin {
76
72
  name: string;
77
73
  call(ctx: ActionCtx, ...args: any[]): any;
78
74
  }
79
- /** Handles a named server event (for example a streamed patch). */
80
75
  export interface HandlerPlugin {
81
76
  type: 'handler';
82
77
  name: string;
@@ -93,7 +88,6 @@ export interface RuntimeOptions {
93
88
  prefix?: string | string[];
94
89
  /** Server event-name prefixes to accept, add a second prefix while migrating from another library. Default 'sigmx-'. */
95
90
  eventPrefix?: string | string[];
96
- /** Share a store between instances. */
97
91
  store?: Store;
98
92
  /** Called for any plugin or expression error. Default: console.error. */
99
93
  onError?: (error: unknown, info: {
@@ -113,7 +107,6 @@ export interface Sigmx {
113
107
  store: Store;
114
108
  /** Root namespace proxy for use from JavaScript: `sigmx.$.count++`. */
115
109
  $: any;
116
- /** Mount plugins under `root` and observe it for changes. */
117
110
  apply(root?: El | ShadowRoot, observe?: boolean): void;
118
111
  /** Register more plugins; attribute plugins are applied to observed roots immediately. */
119
112
  use(...plugins: Plugin[]): void;
@@ -1,20 +1,19 @@
1
- export { createRuntime, parseAttr } from './runtime.js';
1
+ export { camel, kebab, pascal, recase, snake } from '../lib/casing.js';
2
+ export type { Filter } from '../lib/objects.js';
3
+ export { expand, isPlain, toPredicate } from '../lib/objects.js';
4
+ export { debounce, delay, throttle, toMs, withTiming, withViewTransition } from '../lib/schedule.js';
5
+ export type { Compiler } from './compile.js';
2
6
  export { compile, functionCompiler, rewriteActions, runtimeExpressions, splitStatements } from './compile.js';
3
- export { expressionKey, precompiled } from './precompiled.js';
7
+ export type * from './contracts.js';
4
8
  export type { ExpressionTable } from './precompiled.js';
5
- export type { Compiler } from './compile.js';
6
- export { Computed, Signal, batch, computed, effect, flush, onSettled, signal, untracked } from './reactive.js';
7
- export { createStore } from './state.js';
9
+ export { expressionKey, precompiled } from './precompiled.js';
10
+ export { batch, Computed, computed, effect, flush, onSettled, Signal, signal, untracked } from './reactive.js';
11
+ export { createRuntime, parseAttr } from './runtime.js';
8
12
  export type { Patch, Store } from './state.js';
9
- export type * from './contracts.js';
10
- export { expand, isPlain, toPredicate } from '../lib/objects.js';
11
- export type { Filter } from '../lib/objects.js';
12
- export { camel, kebab, pascal, recase, snake } from '../lib/casing.js';
13
- export { debounce, delay, throttle, toMs, withTiming, withViewTransition } from '../lib/schedule.js';
13
+ export { createStore } from './state.js';
14
14
  import type { ActionPlugin, AttributePlugin, HandlerPlugin, Sigmx, SigmxOptions } from './contracts.js';
15
15
  /** Create an instance. Expressions compile at runtime unless you pass `expressions` (see `precompiled`). */
16
16
  export declare const createSigmx: (options?: SigmxOptions) => Sigmx;
17
- /** Type a plugin definition. Pure: registration is `createSigmx({ plugins })` or `sigmx.use()`. */
18
17
  export declare const attribute: (p: Omit<AttributePlugin, "type">) => AttributePlugin;
19
18
  export declare const action: (p: Omit<ActionPlugin, "type">) => ActionPlugin;
20
19
  export declare const handler: (p: Omit<HandlerPlugin, "type">) => HandlerPlugin;
@@ -1,14 +1,17 @@
1
- import { createRuntime, parseAttr } from "./runtime.js";
1
+ import { camel, kebab, pascal, recase, snake } from "../lib/casing.js";
2
+ import { expand, isPlain, toPredicate } from "../lib/objects.js";
3
+ import { debounce, delay, throttle, toMs, withTiming, withViewTransition } from "../lib/schedule.js";
2
4
  import { compile, functionCompiler, rewriteActions, runtimeExpressions, splitStatements } from "./compile.js";
3
5
  import { expressionKey, precompiled } from "./precompiled.js";
4
- import { Computed, Signal, batch, computed, effect, flush, onSettled, signal, untracked } from "./reactive.js";
6
+ import { batch, Computed, computed, effect, flush, onSettled, Signal, signal, untracked } from "./reactive.js";
7
+ import { createRuntime, parseAttr } from "./runtime.js";
5
8
  import { createStore } from "./state.js";
6
- import { expand, isPlain, toPredicate } from "../lib/objects.js";
7
- import { camel, kebab, pascal, recase, snake } from "../lib/casing.js";
8
- import { debounce, delay, throttle, toMs, withTiming, withViewTransition } from "../lib/schedule.js";
9
- import { createRuntime as createRuntime2 } from "./runtime.js";
10
9
  import { functionCompiler as functionCompiler2, runtimeExpressions as runtimeExpressions2 } from "./compile.js";
11
- const createSigmx = (options = {}) => createRuntime2({ ...options, expressions: options.expressions ?? runtimeExpressions2(options.compile ?? functionCompiler2) });
10
+ import { createRuntime as createRuntime2 } from "./runtime.js";
11
+ const createSigmx = (options = {}) => createRuntime2({
12
+ ...options,
13
+ expressions: options.expressions ?? runtimeExpressions2(options.compile ?? functionCompiler2)
14
+ });
12
15
  const attribute = (p) => ({ type: "attribute", ...p });
13
16
  const action = (p) => ({ type: "action", ...p });
14
17
  const handler = (p) => ({ type: "handler", ...p });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/kernel/index.ts"],
4
- "sourcesContent": ["export { createRuntime, parseAttr } from './runtime.js'\nexport { compile, functionCompiler, rewriteActions, runtimeExpressions, splitStatements } from './compile.js'\nexport { expressionKey, precompiled } from './precompiled.js'\nexport type { ExpressionTable } from './precompiled.js'\nexport type { Compiler } from './compile.js'\nexport { Computed, Signal, batch, computed, effect, flush, onSettled, signal, untracked } from './reactive.js'\nexport { createStore } from './state.js'\nexport type { Patch, Store } from './state.js'\nexport type * from './contracts.js'\nexport { expand, isPlain, toPredicate } from '../lib/objects.js'\nexport type { Filter } from '../lib/objects.js'\nexport { camel, kebab, pascal, recase, snake } from '../lib/casing.js'\nexport { debounce, delay, throttle, toMs, withTiming, withViewTransition } from '../lib/schedule.js'\n\nimport type { ActionPlugin, AttributePlugin, HandlerPlugin, Sigmx, SigmxOptions } from './contracts.js'\nimport { createRuntime } from './runtime.js'\nimport { functionCompiler, runtimeExpressions } from './compile.js'\n\n/** Create an instance. Expressions compile at runtime unless you pass `expressions` (see `precompiled`). */\nexport const createSigmx = (options: SigmxOptions = {}): Sigmx =>\n createRuntime({ ...options, expressions: options.expressions ?? runtimeExpressions(options.compile ?? functionCompiler) })\n\n/** Type a plugin definition. Pure: registration is `createSigmx({ plugins })` or `sigmx.use()`. */\nexport const attribute = (p: Omit<AttributePlugin, 'type'>): AttributePlugin => ({ type: 'attribute', ...p })\nexport const action = (p: Omit<ActionPlugin, 'type'>): ActionPlugin => ({ type: 'action', ...p })\nexport const handler = (p: Omit<HandlerPlugin, 'type'>): HandlerPlugin => ({ type: 'handler', ...p })\n"],
5
- "mappings": "AAAA,SAAS,eAAe,iBAAiB;AACzC,SAAS,SAAS,kBAAkB,gBAAgB,oBAAoB,uBAAuB;AAC/F,SAAS,eAAe,mBAAmB;AAG3C,SAAS,UAAU,QAAQ,OAAO,UAAU,QAAQ,OAAO,WAAW,QAAQ,iBAAiB;AAC/F,SAAS,mBAAmB;AAG5B,SAAS,QAAQ,SAAS,mBAAmB;AAE7C,SAAS,OAAO,OAAO,QAAQ,QAAQ,aAAa;AACpD,SAAS,UAAU,OAAO,UAAU,MAAM,YAAY,0BAA0B;AAGhF,SAAS,iBAAAA,sBAAqB;AAC9B,SAAS,oBAAAC,mBAAkB,sBAAAC,2BAA0B;AAG9C,MAAM,cAAc,CAAC,UAAwB,CAAC,MACnDF,eAAc,EAAE,GAAG,SAAS,aAAa,QAAQ,eAAeE,oBAAmB,QAAQ,WAAWD,iBAAgB,EAAE,CAAC;AAGpH,MAAM,YAAY,CAAC,OAAuD,EAAE,MAAM,aAAa,GAAG,EAAE;AACpG,MAAM,SAAS,CAAC,OAAiD,EAAE,MAAM,UAAU,GAAG,EAAE;AACxF,MAAM,UAAU,CAAC,OAAmD,EAAE,MAAM,WAAW,GAAG,EAAE;",
6
- "names": ["createRuntime", "functionCompiler", "runtimeExpressions"]
4
+ "sourcesContent": ["export { camel, kebab, pascal, recase, snake } from '../lib/casing.js';\nexport type { Filter } from '../lib/objects.js';\nexport { expand, isPlain, toPredicate } from '../lib/objects.js';\nexport { debounce, delay, throttle, toMs, withTiming, withViewTransition } from '../lib/schedule.js';\nexport type { Compiler } from './compile.js';\nexport { compile, functionCompiler, rewriteActions, runtimeExpressions, splitStatements } from './compile.js';\nexport type * from './contracts.js';\nexport type { ExpressionTable } from './precompiled.js';\nexport { expressionKey, precompiled } from './precompiled.js';\nexport { batch, Computed, computed, effect, flush, onSettled, Signal, signal, untracked } from './reactive.js';\nexport { createRuntime, parseAttr } from './runtime.js';\nexport type { Patch, Store } from './state.js';\nexport { createStore } from './state.js';\n\nimport { functionCompiler, runtimeExpressions } from './compile.js';\nimport type { ActionPlugin, AttributePlugin, HandlerPlugin, Sigmx, SigmxOptions } from './contracts.js';\nimport { createRuntime } from './runtime.js';\n\n/** Create an instance. Expressions compile at runtime unless you pass `expressions` (see `precompiled`). */\nexport const createSigmx = (options: SigmxOptions = {}): Sigmx =>\n createRuntime({\n ...options,\n expressions: options.expressions ?? runtimeExpressions(options.compile ?? functionCompiler),\n });\n\nexport const attribute = (p: Omit<AttributePlugin, 'type'>): AttributePlugin => ({ type: 'attribute', ...p });\nexport const action = (p: Omit<ActionPlugin, 'type'>): ActionPlugin => ({ type: 'action', ...p });\nexport const handler = (p: Omit<HandlerPlugin, 'type'>): HandlerPlugin => ({ type: 'handler', ...p });\n"],
5
+ "mappings": "AAAA,SAAS,OAAO,OAAO,QAAQ,QAAQ,aAAa;AAEpD,SAAS,QAAQ,SAAS,mBAAmB;AAC7C,SAAS,UAAU,OAAO,UAAU,MAAM,YAAY,0BAA0B;AAEhF,SAAS,SAAS,kBAAkB,gBAAgB,oBAAoB,uBAAuB;AAG/F,SAAS,eAAe,mBAAmB;AAC3C,SAAS,OAAO,UAAU,UAAU,QAAQ,OAAO,WAAW,QAAQ,QAAQ,iBAAiB;AAC/F,SAAS,eAAe,iBAAiB;AAEzC,SAAS,mBAAmB;AAE5B,SAAS,oBAAAA,mBAAkB,sBAAAC,2BAA0B;AAErD,SAAS,iBAAAC,sBAAqB;AAGvB,MAAM,cAAc,CAAC,UAAwB,CAAC,MACnDA,eAAc;AAAA,EACZ,GAAG;AAAA,EACH,aAAa,QAAQ,eAAeD,oBAAmB,QAAQ,WAAWD,iBAAgB;AAC5F,CAAC;AAEI,MAAM,YAAY,CAAC,OAAuD,EAAE,MAAM,aAAa,GAAG,EAAE;AACpG,MAAM,SAAS,CAAC,OAAiD,EAAE,MAAM,UAAU,GAAG,EAAE;AACxF,MAAM,UAAU,CAAC,OAAmD,EAAE,MAAM,WAAW,GAAG,EAAE;",
6
+ "names": ["functionCompiler", "runtimeExpressions", "createRuntime"]
7
7
  }
@@ -4,14 +4,12 @@
4
4
  * `$` alone, `$[...]` alone, and `obj.$prop` alone.
5
5
  */
6
6
  export declare const rewriteSignals: (src: string) => string;
7
- /** The strict-mode function body for one expression: same semantics as the runtime compiler. */
8
7
  export declare const compileBody: (src: string, returns: boolean) => string;
9
8
  export type Extracted = {
10
9
  src: string;
11
10
  params: string[];
12
11
  returns: boolean;
13
12
  };
14
- /** JavaScript source for a module exporting `table`, from a list of extracted expressions. */
15
13
  export declare const generateTable: (items: Extracted[]) => string;
16
14
  export type PluginMeta = {
17
15
  name: string;
@@ -32,7 +32,7 @@ const rewriteSignals = (src) => {
32
32
  else if (src[j] === "}") depth--;
33
33
  if (depth) j++;
34
34
  }
35
- out += "${" + rewriteSignals(src.slice(i + 2, j)) + "}";
35
+ out += `\${${rewriteSignals(src.slice(i + 2, j))}}`;
36
36
  i = j + 1;
37
37
  } else out += src[i++];
38
38
  }
@@ -47,7 +47,7 @@ const rewriteSignals = (src) => {
47
47
  } else if (c === "$" && next !== void 0 && ident.test(next) && next !== "$" && prevCode() !== "." && !ident.test(out[out.length - 1] ?? "")) {
48
48
  let j = i + 1;
49
49
  while (j < n && ident.test(src[j])) j++;
50
- out += "$." + src.slice(i + 1, j);
50
+ out += `$.${src.slice(i + 1, j)}`;
51
51
  i = j;
52
52
  } else {
53
53
  out += c;
@@ -61,7 +61,7 @@ const compileBody = (src, returns) => {
61
61
  if (!returns) return code;
62
62
  const parts = splitStatements(code);
63
63
  const last = parts.pop() ?? "";
64
- return `${parts.length ? parts.join(";") + ";" : ""}return (${last}
64
+ return `${parts.length ? `${parts.join(";")};` : ""}return (${last}
65
65
  )`;
66
66
  };
67
67
  const generateTable = (items) => {
@@ -85,7 +85,14 @@ ${lines.join("\n")}
85
85
  }
86
86
  `;
87
87
  };
88
- const entities = { "&quot;": '"', "&#39;": "'", "&apos;": "'", "&lt;": "<", "&gt;": ">", "&amp;": "&" };
88
+ const entities = {
89
+ "&quot;": '"',
90
+ "&#39;": "'",
91
+ "&apos;": "'",
92
+ "&lt;": "<",
93
+ "&gt;": ">",
94
+ "&amp;": "&"
95
+ };
89
96
  const decode = (s) => s.replace(/&(quot|#39|apos|lt|gt|amp);/g, (m) => entities[m]);
90
97
  const extractExpressions = (source, plugins, prefixes = ["data-"]) => {
91
98
  const byName = new Map(plugins.map((p) => [p.name, p]));
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/kernel/precompile.ts"],
4
- "sourcesContent": ["// Build-time expression compiler. Not for the browser: import it from a Vite/Astro plugin.\nimport { rewriteActions, splitStatements } from './compile.js'\nimport { expressionKey } from './precompiled.js'\n\nconst ident = /[A-Za-z0-9_$]/\n\n/**\n * Rewrite `$name` and `$a.b` into `$.name` / `$.a.b` so the expression runs in strict mode without\n * `with`. Skips strings and comments, recurses into template-literal interpolations, and leaves\n * `$` alone, `$[...]` alone, and `obj.$prop` alone.\n */\nexport const rewriteSignals = (src: string): string => {\n let out = ''\n let i = 0\n const n = src.length\n const prevCode = () => {\n for (let j = out.length - 1; j >= 0; j--) if (!/\\s/.test(out[j])) return out[j]\n return ''\n }\n while (i < n) {\n const c = src[i]\n const next = src[i + 1]\n if (c === '\"' || c === \"'\") {\n let j = i + 1\n while (j < n && src[j] !== c) j += src[j] === '\\\\' ? 2 : 1\n out += src.slice(i, j + 1)\n i = j + 1\n } else if (c === '`') {\n out += c\n i++\n while (i < n && src[i] !== '`') {\n if (src[i] === '\\\\') {\n out += src.slice(i, i + 2)\n i += 2\n } else if (src[i] === '$' && src[i + 1] === '{') {\n let depth = 1\n let j = i + 2\n while (j < n && depth) {\n if (src[j] === '{') depth++\n else if (src[j] === '}') depth--\n if (depth) j++\n }\n out += '${' + rewriteSignals(src.slice(i + 2, j)) + '}'\n i = j + 1\n } else out += src[i++]\n }\n out += '`'\n i++\n } else if (c === '/' && next === '/') {\n const j = src.indexOf('\\n', i)\n i = j < 0 ? n : j\n } else if (c === '/' && next === '*') {\n const j = src.indexOf('*/', i + 2)\n i = j < 0 ? n : j + 2\n } else if (c === '$' && next !== undefined && ident.test(next) && next !== '$' && prevCode() !== '.' && !ident.test(out[out.length - 1] ?? '')) {\n let j = i + 1\n while (j < n && ident.test(src[j])) j++\n out += '$.' + src.slice(i + 1, j)\n i = j\n } else {\n out += c\n i++\n }\n }\n return out\n}\n\n/** The strict-mode function body for one expression: same semantics as the runtime compiler. */\nexport const compileBody = (src: string, returns: boolean): string => {\n const code = rewriteSignals(rewriteActions(src.trim()))\n if (!returns) return code\n const parts = splitStatements(code)\n const last = parts.pop() ?? ''\n return `${parts.length ? parts.join(';') + ';' : ''}return (${last}\\n)`\n}\n\nexport type Extracted = { src: string; params: string[]; returns: boolean }\n\n/** JavaScript source for a module exporting `table`, from a list of extracted expressions. */\nexport const generateTable = (items: Extracted[]): string => {\n const seen = new Set<string>()\n const lines: string[] = []\n for (const { src, params, returns } of items) {\n const key = expressionKey(src, params, returns)\n if (seen.has(key)) continue\n seen.add(key)\n let body: string\n try {\n body = compileBody(src, returns)\n Function('$', '__a', ...params, body) // syntax check at build time\n } catch {\n continue // leave it to the runtime fallback (or fail there)\n }\n lines.push(` ${JSON.stringify(key)}: function($, __a, ${params.join(', ')}) { ${body} },`)\n }\n return `export const table = {\\n${lines.join('\\n')}\\n}\\n`\n}\n\nconst entities: Record<string, string> = { '&quot;': '\"', '&#39;': \"'\", '&apos;': \"'\", '&lt;': '<', '&gt;': '>', '&amp;': '&' }\nconst decode = (s: string) => s.replace(/&(quot|#39|apos|lt|gt|amp);/g, (m) => entities[m])\n\nexport type PluginMeta = { name: string; returns?: boolean; args?: string[] }\n\n/**\n * Find directive attributes with literal values in template source. Values must be plain quoted\n * strings; anything interpolated at render time is left to the runtime fallback.\n */\nexport const extractExpressions = (source: string, plugins: PluginMeta[], prefixes: string[] = ['data-']): Extracted[] => {\n const byName = new Map(plugins.map((p) => [p.name, p]))\n const out: Extracted[] = []\n const re = /([a-z][\\w-]*(?::[^\\s=\"'<>]+)?(?:__[^\\s=\"'<>]+)*)=(?:\"([^\"]*)\"|'([^']*)')/g\n for (const m of source.matchAll(re)) {\n const attr = m[1]\n const value = decode(m[2] ?? m[3] ?? '')\n const prefix = prefixes.find((p) => attr.startsWith(p))\n if (!prefix || !value.trim()) continue\n const plugin = byName.get(attr.slice(prefix.length).split('__')[0].split(':')[0])\n if (!plugin) continue\n out.push({ src: value, params: ['el', 'evt', ...(plugin.args ?? [])], returns: plugin.returns ?? true })\n }\n return out\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["// Build-time expression compiler. Not for the browser: import it from a Vite/Astro plugin.\nimport { rewriteActions, splitStatements } from './compile.js';\nimport { expressionKey } from './precompiled.js';\n\nconst ident = /[A-Za-z0-9_$]/;\n\n/**\n * Rewrite `$name` and `$a.b` into `$.name` / `$.a.b` so the expression runs in strict mode without\n * `with`. Skips strings and comments, recurses into template-literal interpolations, and leaves\n * `$` alone, `$[...]` alone, and `obj.$prop` alone.\n */\nexport const rewriteSignals = (src: string): string => {\n let out = '';\n let i = 0;\n const n = src.length;\n const prevCode = () => {\n for (let j = out.length - 1; j >= 0; j--) if (!/\\s/.test(out[j])) return out[j];\n return '';\n };\n while (i < n) {\n const c = src[i];\n const next = src[i + 1];\n if (c === '\"' || c === \"'\") {\n let j = i + 1;\n while (j < n && src[j] !== c) j += src[j] === '\\\\' ? 2 : 1;\n out += src.slice(i, j + 1);\n i = j + 1;\n } else if (c === '`') {\n out += c;\n i++;\n while (i < n && src[i] !== '`') {\n if (src[i] === '\\\\') {\n out += src.slice(i, i + 2);\n i += 2;\n } else if (src[i] === '$' && src[i + 1] === '{') {\n let depth = 1;\n let j = i + 2;\n while (j < n && depth) {\n if (src[j] === '{') depth++;\n else if (src[j] === '}') depth--;\n if (depth) j++;\n }\n out += `\\${${rewriteSignals(src.slice(i + 2, j))}}`;\n i = j + 1;\n } else out += src[i++];\n }\n out += '`';\n i++;\n } else if (c === '/' && next === '/') {\n const j = src.indexOf('\\n', i);\n i = j < 0 ? n : j;\n } else if (c === '/' && next === '*') {\n const j = src.indexOf('*/', i + 2);\n i = j < 0 ? n : j + 2;\n } else if (\n c === '$' &&\n next !== undefined &&\n ident.test(next) &&\n next !== '$' &&\n prevCode() !== '.' &&\n !ident.test(out[out.length - 1] ?? '')\n ) {\n let j = i + 1;\n while (j < n && ident.test(src[j])) j++;\n out += `$.${src.slice(i + 1, j)}`;\n i = j;\n } else {\n out += c;\n i++;\n }\n }\n return out;\n};\n\nexport const compileBody = (src: string, returns: boolean): string => {\n const code = rewriteSignals(rewriteActions(src.trim()));\n if (!returns) return code;\n const parts = splitStatements(code);\n const last = parts.pop() ?? '';\n return `${parts.length ? `${parts.join(';')};` : ''}return (${last}\\n)`;\n};\n\nexport type Extracted = { src: string; params: string[]; returns: boolean };\n\nexport const generateTable = (items: Extracted[]): string => {\n const seen = new Set<string>();\n const lines: string[] = [];\n for (const { src, params, returns } of items) {\n const key = expressionKey(src, params, returns);\n if (seen.has(key)) continue;\n seen.add(key);\n let body: string;\n try {\n body = compileBody(src, returns);\n Function('$', '__a', ...params, body); // syntax check at build time\n } catch {\n continue; // leave it to the runtime fallback (or fail there)\n }\n lines.push(` ${JSON.stringify(key)}: function($, __a, ${params.join(', ')}) { ${body} },`);\n }\n return `export const table = {\\n${lines.join('\\n')}\\n}\\n`;\n};\n\nconst entities: Record<string, string> = {\n '&quot;': '\"',\n '&#39;': \"'\",\n '&apos;': \"'\",\n '&lt;': '<',\n '&gt;': '>',\n '&amp;': '&',\n};\nconst decode = (s: string) => s.replace(/&(quot|#39|apos|lt|gt|amp);/g, (m) => entities[m]);\n\nexport type PluginMeta = { name: string; returns?: boolean; args?: string[] };\n\n/**\n * Find directive attributes with literal values in template source. Values must be plain quoted\n * strings; anything interpolated at render time is left to the runtime fallback.\n */\nexport const extractExpressions = (\n source: string,\n plugins: PluginMeta[],\n prefixes: string[] = ['data-'],\n): Extracted[] => {\n const byName = new Map(plugins.map((p) => [p.name, p]));\n const out: Extracted[] = [];\n const re = /([a-z][\\w-]*(?::[^\\s=\"'<>]+)?(?:__[^\\s=\"'<>]+)*)=(?:\"([^\"]*)\"|'([^']*)')/g;\n for (const m of source.matchAll(re)) {\n const attr = m[1];\n const value = decode(m[2] ?? m[3] ?? '');\n const prefix = prefixes.find((p) => attr.startsWith(p));\n if (!prefix || !value.trim()) continue;\n const plugin = byName.get(attr.slice(prefix.length).split('__')[0].split(':')[0]);\n if (!plugin) continue;\n out.push({ src: value, params: ['el', 'evt', ...(plugin.args ?? [])], returns: plugin.returns ?? true });\n }\n return out;\n};\n"],
5
+ "mappings": "AACA,SAAS,gBAAgB,uBAAuB;AAChD,SAAS,qBAAqB;AAE9B,MAAM,QAAQ;AAOP,MAAM,iBAAiB,CAAC,QAAwB;AACrD,MAAI,MAAM;AACV,MAAI,IAAI;AACR,QAAM,IAAI,IAAI;AACd,QAAM,WAAW,MAAM;AACrB,aAAS,IAAI,IAAI,SAAS,GAAG,KAAK,GAAG,IAAK,KAAI,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,EAAG,QAAO,IAAI,CAAC;AAC9E,WAAO;AAAA,EACT;AACA,SAAO,IAAI,GAAG;AACZ,UAAM,IAAI,IAAI,CAAC;AACf,UAAM,OAAO,IAAI,IAAI,CAAC;AACtB,QAAI,MAAM,OAAO,MAAM,KAAK;AAC1B,UAAI,IAAI,IAAI;AACZ,aAAO,IAAI,KAAK,IAAI,CAAC,MAAM,EAAG,MAAK,IAAI,CAAC,MAAM,OAAO,IAAI;AACzD,aAAO,IAAI,MAAM,GAAG,IAAI,CAAC;AACzB,UAAI,IAAI;AAAA,IACV,WAAW,MAAM,KAAK;AACpB,aAAO;AACP;AACA,aAAO,IAAI,KAAK,IAAI,CAAC,MAAM,KAAK;AAC9B,YAAI,IAAI,CAAC,MAAM,MAAM;AACnB,iBAAO,IAAI,MAAM,GAAG,IAAI,CAAC;AACzB,eAAK;AAAA,QACP,WAAW,IAAI,CAAC,MAAM,OAAO,IAAI,IAAI,CAAC,MAAM,KAAK;AAC/C,cAAI,QAAQ;AACZ,cAAI,IAAI,IAAI;AACZ,iBAAO,IAAI,KAAK,OAAO;AACrB,gBAAI,IAAI,CAAC,MAAM,IAAK;AAAA,qBACX,IAAI,CAAC,MAAM,IAAK;AACzB,gBAAI,MAAO;AAAA,UACb;AACA,iBAAO,MAAM,eAAe,IAAI,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC;AAChD,cAAI,IAAI;AAAA,QACV,MAAO,QAAO,IAAI,GAAG;AAAA,MACvB;AACA,aAAO;AACP;AAAA,IACF,WAAW,MAAM,OAAO,SAAS,KAAK;AACpC,YAAM,IAAI,IAAI,QAAQ,MAAM,CAAC;AAC7B,UAAI,IAAI,IAAI,IAAI;AAAA,IAClB,WAAW,MAAM,OAAO,SAAS,KAAK;AACpC,YAAM,IAAI,IAAI,QAAQ,MAAM,IAAI,CAAC;AACjC,UAAI,IAAI,IAAI,IAAI,IAAI;AAAA,IACtB,WACE,MAAM,OACN,SAAS,UACT,MAAM,KAAK,IAAI,KACf,SAAS,OACT,SAAS,MAAM,OACf,CAAC,MAAM,KAAK,IAAI,IAAI,SAAS,CAAC,KAAK,EAAE,GACrC;AACA,UAAI,IAAI,IAAI;AACZ,aAAO,IAAI,KAAK,MAAM,KAAK,IAAI,CAAC,CAAC,EAAG;AACpC,aAAO,KAAK,IAAI,MAAM,IAAI,GAAG,CAAC,CAAC;AAC/B,UAAI;AAAA,IACN,OAAO;AACL,aAAO;AACP;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEO,MAAM,cAAc,CAAC,KAAa,YAA6B;AACpE,QAAM,OAAO,eAAe,eAAe,IAAI,KAAK,CAAC,CAAC;AACtD,MAAI,CAAC,QAAS,QAAO;AACrB,QAAM,QAAQ,gBAAgB,IAAI;AAClC,QAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,SAAO,GAAG,MAAM,SAAS,GAAG,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,WAAW,IAAI;AAAA;AACpE;AAIO,MAAM,gBAAgB,CAAC,UAA+B;AAC3D,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,QAAkB,CAAC;AACzB,aAAW,EAAE,KAAK,QAAQ,QAAQ,KAAK,OAAO;AAC5C,UAAM,MAAM,cAAc,KAAK,QAAQ,OAAO;AAC9C,QAAI,KAAK,IAAI,GAAG,EAAG;AACnB,SAAK,IAAI,GAAG;AACZ,QAAI;AACJ,QAAI;AACF,aAAO,YAAY,KAAK,OAAO;AAC/B,eAAS,KAAK,OAAO,GAAG,QAAQ,IAAI;AAAA,IACtC,QAAQ;AACN;AAAA,IACF;AACA,UAAM,KAAK,KAAK,KAAK,UAAU,GAAG,CAAC,sBAAsB,OAAO,KAAK,IAAI,CAAC,OAAO,IAAI,KAAK;AAAA,EAC5F;AACA,SAAO;AAAA,EAA2B,MAAM,KAAK,IAAI,CAAC;AAAA;AAAA;AACpD;AAEA,MAAM,WAAmC;AAAA,EACvC,UAAU;AAAA,EACV,SAAS;AAAA,EACT,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AACX;AACA,MAAM,SAAS,CAAC,MAAc,EAAE,QAAQ,gCAAgC,CAAC,MAAM,SAAS,CAAC,CAAC;AAQnF,MAAM,qBAAqB,CAChC,QACA,SACA,WAAqB,CAAC,OAAO,MACb;AAChB,QAAM,SAAS,IAAI,IAAI,QAAQ,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AACtD,QAAM,MAAmB,CAAC;AAC1B,QAAM,KAAK;AACX,aAAW,KAAK,OAAO,SAAS,EAAE,GAAG;AACnC,UAAM,OAAO,EAAE,CAAC;AAChB,UAAM,QAAQ,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE;AACvC,UAAM,SAAS,SAAS,KAAK,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC;AACtD,QAAI,CAAC,UAAU,CAAC,MAAM,KAAK,EAAG;AAC9B,UAAM,SAAS,OAAO,IAAI,KAAK,MAAM,OAAO,MAAM,EAAE,MAAM,IAAI,EAAE,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC,CAAC;AAChF,QAAI,CAAC,OAAQ;AACb,QAAI,KAAK,EAAE,KAAK,OAAO,QAAQ,CAAC,MAAM,OAAO,GAAI,OAAO,QAAQ,CAAC,CAAE,GAAG,SAAS,OAAO,WAAW,KAAK,CAAC;AAAA,EACzG;AACA,SAAO;AACT;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/kernel/precompiled.ts"],
4
- "sourcesContent": ["import type { Evaluator, ExpressionCompiler } from './contracts.js'\n\nexport type ExpressionTable = Record<string, (root: any, actions: any, el: any, evt: any, ...args: any[]) => any>\n\n/** Key used by the build plugin and the lookup: returns flag, parameter names, trimmed source. */\nexport const expressionKey = (src: string, params: string[], returns: boolean): string => `${+returns}|${params.join()}|${src.trim()}`\n\n/**\n * Look expressions up in a table generated at build time (see `sigmx/precompile`). Precompiled functions\n * receive the root store proxy as `$` instead of a `with` scope. Pass a `fallback` (for example\n * `runtimeExpressions(functionCompiler)`) for markup assembled at runtime; omit it and the runtime\n * compiler is not bundled at all.\n */\nexport const precompiled =\n (table: ExpressionTable, fallback?: ExpressionCompiler, onMiss?: (src: string) => void): ExpressionCompiler =>\n (src, params, returns) => {\n const fn = table[expressionKey(src, params, returns)]\n if (fn) return ((store, actions, el, evt, ...args) => fn(store.$, actions, el, evt, ...args)) as Evaluator\n onMiss?.(src)\n if (!fallback) throw new Error(`expression not precompiled: ${src}`)\n return fallback(src, params, returns)\n }\n"],
5
- "mappings": "AAKO,MAAM,gBAAgB,CAAC,KAAa,QAAkB,YAA6B,GAAG,CAAC,OAAO,IAAI,OAAO,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC;AAQ7H,MAAM,cACX,CAAC,OAAwB,UAA+B,WACxD,CAAC,KAAK,QAAQ,YAAY;AACxB,QAAM,KAAK,MAAM,cAAc,KAAK,QAAQ,OAAO,CAAC;AACpD,MAAI,GAAI,SAAQ,CAAC,OAAO,SAAS,IAAI,QAAQ,SAAS,GAAG,MAAM,GAAG,SAAS,IAAI,KAAK,GAAG,IAAI;AAC3F,WAAS,GAAG;AACZ,MAAI,CAAC,SAAU,OAAM,IAAI,MAAM,+BAA+B,GAAG,EAAE;AACnE,SAAO,SAAS,KAAK,QAAQ,OAAO;AACtC;",
4
+ "sourcesContent": ["import type { Evaluator, ExpressionCompiler } from './contracts.js';\n\nexport type ExpressionTable = Record<string, (root: any, actions: any, el: any, evt: any, ...args: any[]) => any>;\n\n/** Key used by the build plugin and the lookup: returns flag, parameter names, trimmed source. */\nexport const expressionKey = (src: string, params: string[], returns: boolean): string =>\n `${+returns}|${params.join()}|${src.trim()}`;\n\n/**\n * Look expressions up in a table generated at build time (see `sigmx/precompile`). Precompiled functions\n * receive the root store proxy as `$` instead of a `with` scope. Pass a `fallback` (for example\n * `runtimeExpressions(functionCompiler)`) for markup assembled at runtime; omit it and the runtime\n * compiler is not bundled at all.\n */\nexport const precompiled =\n (table: ExpressionTable, fallback?: ExpressionCompiler, onMiss?: (src: string) => void): ExpressionCompiler =>\n (src, params, returns) => {\n const fn = table[expressionKey(src, params, returns)];\n if (fn) return ((store, actions, el, evt, ...args) => fn(store.$, actions, el, evt, ...args)) as Evaluator;\n onMiss?.(src);\n if (!fallback) throw new Error(`expression not precompiled: ${src}`);\n return fallback(src, params, returns);\n };\n"],
5
+ "mappings": "AAKO,MAAM,gBAAgB,CAAC,KAAa,QAAkB,YAC3D,GAAG,CAAC,OAAO,IAAI,OAAO,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC;AAQrC,MAAM,cACX,CAAC,OAAwB,UAA+B,WACxD,CAAC,KAAK,QAAQ,YAAY;AACxB,QAAM,KAAK,MAAM,cAAc,KAAK,QAAQ,OAAO,CAAC;AACpD,MAAI,GAAI,SAAQ,CAAC,OAAO,SAAS,IAAI,QAAQ,SAAS,GAAG,MAAM,GAAG,SAAS,IAAI,KAAK,GAAG,IAAI;AAC3F,WAAS,GAAG;AACZ,MAAI,CAAC,SAAU,OAAM,IAAI,MAAM,+BAA+B,GAAG,EAAE;AACnE,SAAO,SAAS,KAAK,QAAQ,OAAO;AACtC;",
6
6
  "names": []
7
7
  }
@@ -3,23 +3,22 @@ interface Tracker {
3
3
  _invalidate(): void;
4
4
  }
5
5
  export declare class Signal<T> {
6
- /** @internal */ _v: T;
7
- /** @internal */ _ver: number;
8
- /** @internal */ _subs: Set<Tracker>;
6
+ _v: T;
7
+ _ver: number;
8
+ _subs: Set<Tracker>;
9
9
  constructor(v: T);
10
10
  get value(): T;
11
11
  set value(x: T);
12
- /** Read without subscribing. */
13
12
  peek(): T;
14
13
  /** Notify subscribers without replacing the value (after mutating an array or object in place). */
15
14
  bump(): void;
16
15
  }
17
16
  export declare class Computed<T> extends Signal<T> implements Tracker {
18
17
  _deps: Map<Signal<any>, number>;
19
- /** @internal */ _dirty: boolean;
20
- /** @internal */ _fn: () => T;
18
+ _dirty: boolean;
19
+ _fn: () => T;
21
20
  constructor(fn: () => T);
22
- /** @internal */ _refresh(): void;
21
+ _refresh(): void;
23
22
  get value(): T;
24
23
  set value(_: T);
25
24
  peek(): T;
@@ -32,11 +31,8 @@ export declare const computed: <T>(fn: () => T) => Computed<T>;
32
31
  * effect are disposed when the parent re-runs. Returns a disposer.
33
32
  */
34
33
  export declare const effect: (fn: () => void, onError?: (e: unknown) => void) => (() => void);
35
- /** Coalesce many writes into one round of effect runs. */
36
34
  export declare const batch: <R>(fn: () => R) => R;
37
- /** Read signals inside `fn` without subscribing the current effect to them. */
38
35
  export declare const untracked: <R>(fn: () => R) => R;
39
- /** Called after each flush once every queued effect has run. */
40
36
  export declare const onSettled: (fn: () => void) => (() => void);
41
37
  export declare const flush: () => void;
42
38
  export {};