jssm 5.138.0 → 5.141.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/custom-elements.json +384 -47
- package/dist/cdn/instance.js +477 -101
- package/dist/cdn/viz.js +145 -5
- package/dist/cli/fsl-render.cjs +1 -1
- package/dist/cli/fsl.cjs +1 -1
- package/dist/deno/README.md +7 -7
- package/dist/deno/jssm.js +1 -1
- package/dist/jssm.es5.cjs +1 -1
- package/dist/jssm.es5.iife.js +1 -1
- package/dist/jssm.es6.mjs +1 -1
- package/dist/jssm_viz.cjs +1 -1
- package/dist/jssm_viz.iife.cjs +1 -1
- package/dist/jssm_viz.mjs +1 -1
- package/dist/wc/instance.js +477 -101
- package/dist/wc/viz.define.js +3 -3
- package/dist/wc/viz.js +132 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,10 +18,10 @@ Please edit the file it's derived from, instead: `./src/md/readme_base.md`
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
* Generated for version 5.
|
|
21
|
+
* Generated for version 5.141.0 at 5/28/2026, 8:18:17 AM
|
|
22
22
|
|
|
23
23
|
-->
|
|
24
|
-
# jssm 5.
|
|
24
|
+
# jssm 5.141.0
|
|
25
25
|
|
|
26
26
|
[**Try the live editor**](https://stonecypher.github.io/jssm-viz-demo/graph_explorer.html) ·
|
|
27
27
|
[Documentation](https://stonecypher.github.io/jssm/docs/) ·
|
|
@@ -281,7 +281,7 @@ That decision shows up everywhere downstream:
|
|
|
281
281
|
or run `npm run benny` against your own machine.
|
|
282
282
|
|
|
283
283
|
- **More thoroughly tested than any other JavaScript state-machine
|
|
284
|
-
library.** 6,
|
|
284
|
+
library.** 6,450 tests at 100.0% line coverage
|
|
285
285
|
([report](https://coveralls.io/github/StoneCypher/jssm)), plus
|
|
286
286
|
fuzz testing via `fast-check`, with parser test data across ten natural
|
|
287
287
|
languages and Emoji.
|
|
@@ -414,11 +414,11 @@ If your contribution is missing here, please open an issue.
|
|
|
414
414
|
|
|
415
415
|
<br/>
|
|
416
416
|
|
|
417
|
-
***6,
|
|
417
|
+
***6,450 tests***, run 57,237 times.
|
|
418
418
|
|
|
419
|
-
- 5,
|
|
420
|
-
- 513 fuzz tests with 3.
|
|
421
|
-
- 5,
|
|
419
|
+
- 5,937 specs with 100.0% coverage
|
|
420
|
+
- 513 fuzz tests with 3.4% coverage
|
|
421
|
+
- 5,555 TypeScript lines - 1.2 tests per line, 10.3 generated tests per line
|
|
422
422
|
|
|
423
423
|
[](https://github.com/StoneCypher/jssm/actions)
|
|
424
424
|
[](https://www.npmjs.com/package/jssm)
|
package/custom-elements.json
CHANGED
|
@@ -2,6 +2,191 @@
|
|
|
2
2
|
"schemaVersion": "1.0.0",
|
|
3
3
|
"readme": "",
|
|
4
4
|
"modules": [
|
|
5
|
+
{
|
|
6
|
+
"kind": "javascript-module",
|
|
7
|
+
"path": "src/ts/wc/jssm_bind_wc.ts",
|
|
8
|
+
"declarations": [
|
|
9
|
+
{
|
|
10
|
+
"kind": "function",
|
|
11
|
+
"name": "walk_path",
|
|
12
|
+
"return": {
|
|
13
|
+
"type": {
|
|
14
|
+
"text": ""
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"parameters": [
|
|
18
|
+
{
|
|
19
|
+
"name": "obj",
|
|
20
|
+
"type": {
|
|
21
|
+
"text": "unknown"
|
|
22
|
+
},
|
|
23
|
+
"description": "The root value to traverse."
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"name": "path",
|
|
27
|
+
"type": {
|
|
28
|
+
"text": "string"
|
|
29
|
+
},
|
|
30
|
+
"description": "Dotted path of property names, e.g. `\"a.b.c\"`."
|
|
31
|
+
}
|
|
32
|
+
],
|
|
33
|
+
"description": "Walk a dotted path into a value. Used by the `data.path.to.field`\r\nvariant of resolve_binding. Returns `undefined` whenever the\r\ntraversal would dereference a non-object, missing field, or `null` —\r\nmatching the natural \"missing data\" semantics rather than throwing.\r\n\r\n```typescript\r\nwalk_path({ a: { b: 7 } }, 'a.b'); // => 7\r\nwalk_path({ a: { b: 7 } }, 'a.c'); // => undefined\r\nwalk_path({ a: { b: 7 } }, 'a.b.c'); // => undefined (7 is not an object)\r\nwalk_path(undefined, 'a'); // => undefined\r\nwalk_path({ a: null }, 'a.b'); // => undefined (null is not an object)\r\nwalk_path({ a: 1 }, ''); // => { a: 1 } (empty path = identity)\r\n```"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"kind": "function",
|
|
37
|
+
"name": "resolve_binding",
|
|
38
|
+
"return": {
|
|
39
|
+
"type": {
|
|
40
|
+
"text": ""
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"parameters": [
|
|
44
|
+
{
|
|
45
|
+
"name": "m",
|
|
46
|
+
"type": {
|
|
47
|
+
"text": "Machine<unknown>"
|
|
48
|
+
},
|
|
49
|
+
"description": "The machine whose state/data is being projected."
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"name": "expr",
|
|
53
|
+
"type": {
|
|
54
|
+
"text": "string"
|
|
55
|
+
},
|
|
56
|
+
"description": "The binding expression text (raw attribute value)."
|
|
57
|
+
}
|
|
58
|
+
],
|
|
59
|
+
"description": "Resolve a `<jssm-bind>` / `data-jssm-bind` expression against a live\r\nmachine. Throws on any unknown expression — bindings fail fast at\r\ninstall time rather than silently producing `undefined` strings in the\r\nDOM.\r\n\r\nRecognized expressions:\r\n\r\n| Expression | Resolves to |\r\n| ---------------- | --------------------------------------------- |\r\n| `data` | `machine.data()` |\r\n| `data.a.b.c` | dotted-path traversal into `machine.data()` |\r\n| `state` | `machine.state()` |\r\n| `terminal` | `machine.is_terminal()` |\r\n| `complete` | `machine.is_complete()` |\r\n| `legal-actions` | `machine.list_exit_actions().join(' ')` |\r\n\r\n```typescript\r\nresolve_binding(m, 'state'); // current state name\r\nresolve_binding(m, 'data.username'); // typed-data subfield\r\nresolve_binding(m, 'wat'); // throws\r\n```"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"kind": "function",
|
|
63
|
+
"name": "set_on_element",
|
|
64
|
+
"return": {
|
|
65
|
+
"type": {
|
|
66
|
+
"text": "void"
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"parameters": [
|
|
70
|
+
{
|
|
71
|
+
"name": "el",
|
|
72
|
+
"type": {
|
|
73
|
+
"text": "HTMLElement"
|
|
74
|
+
},
|
|
75
|
+
"description": "The element to update."
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"name": "target",
|
|
79
|
+
"type": {
|
|
80
|
+
"text": "string"
|
|
81
|
+
},
|
|
82
|
+
"description": "Target property name, possibly a `data-*` attribute."
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"name": "value",
|
|
86
|
+
"type": {
|
|
87
|
+
"text": "unknown"
|
|
88
|
+
},
|
|
89
|
+
"description": "The resolved value to assign."
|
|
90
|
+
}
|
|
91
|
+
],
|
|
92
|
+
"description": "Apply a resolved binding value to an element's target property. The\r\n`target` selector follows the rules documented in #645:\r\n\r\n- `textContent` (or omitted) sets `el.textContent` to the value coerced\r\n with `String()`.\r\n- Any string starting with `data-` is treated as an attribute name and\r\n set via `setAttribute`, value coerced with `String()`.\r\n- Any other string is assigned directly as a property of the element\r\n (no coercion) — supports `value`, `disabled`, `hidden`, `checked`,\r\n and the documented power-user escape hatch.\r\n\r\n```typescript\r\nset_on_element(span, 'textContent', 7); // span.textContent = '7'\r\nset_on_element(input, 'value', 'hi'); // input.value = 'hi'\r\nset_on_element(button, 'disabled', true); // button.disabled = true\r\nset_on_element(div, 'data-current', 'red'); // setAttribute('data-current', 'red')\r\n```"
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"kind": "function",
|
|
96
|
+
"name": "install_bindings",
|
|
97
|
+
"return": {
|
|
98
|
+
"type": {
|
|
99
|
+
"text": ""
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
"parameters": [
|
|
103
|
+
{
|
|
104
|
+
"name": "host",
|
|
105
|
+
"type": {
|
|
106
|
+
"text": "HTMLElement"
|
|
107
|
+
},
|
|
108
|
+
"description": "The host element whose descendants carry the bindings."
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"name": "machine",
|
|
112
|
+
"type": {
|
|
113
|
+
"text": "Machine<unknown>"
|
|
114
|
+
},
|
|
115
|
+
"description": "The machine whose state/data is being projected."
|
|
116
|
+
}
|
|
117
|
+
],
|
|
118
|
+
"description": "Discover every binding declaration under `host` and install live\r\nsubscriptions that refresh them on every machine transition. Returns\r\na list of unsubscribe callbacks so the host's `disconnectedCallback`\r\ncan tear them all down.\r\n\r\nTwo surface forms are recognized:\r\n\r\n1. Inline attribute — any descendant with `data-jssm-bind=\"<expr>\"`.\r\n Optional `data-jssm-bind-to=\"<target>\"` chooses the target property\r\n (defaults to `textContent`).\r\n\r\n2. Dedicated tag — direct-child `<jssm-bind>` configuration tags with\r\n `selector=\"<css>\"` and `source=\"<expr>\"` attributes, plus an\r\n optional `target=\"<target>\"` (also defaulting to `textContent`).\r\n The `selector` is scoped to `host`'s descendants.\r\n\r\nEach binding is painted once immediately (using the machine's current\r\nstate) and then re-painted on every `transition` event.\r\n\r\n```typescript\r\n// typical install during <jssm-instance>.connectedCallback:\r\nconst unsubs = install_bindings(this, this.machine);\r\nthis._unsubs.push(...unsubs);\r\n```"
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"kind": "class",
|
|
122
|
+
"description": "`<jssm-bind>` configuration tag. The element itself is invisible —\r\nit carries `selector`, `source`, and optional `target` attributes\r\nthat the parent `<jssm-instance>` reads during its connection\r\nlifecycle to wire up a machine-to-DOM binding.\r\n\r\nRegistering it as a `LitElement` (rather than leaving it as a generic\r\nunknown tag) gives it a stable upgrade timing, a `display: none`\r\ndefault style, and a proper place in the custom-elements registry so\r\n`customElements.get('jssm-bind')` resolves.",
|
|
123
|
+
"name": "JssmBind",
|
|
124
|
+
"members": [],
|
|
125
|
+
"attributes": [
|
|
126
|
+
{
|
|
127
|
+
"description": "CSS selector for the target element(s), scoped to the host.",
|
|
128
|
+
"name": "selector"
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"description": "Binding expression (see {@link resolve_binding}).",
|
|
132
|
+
"name": "source"
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"description": "Target property name; defaults to `textContent`.",
|
|
136
|
+
"name": "target"
|
|
137
|
+
}
|
|
138
|
+
],
|
|
139
|
+
"superclass": {
|
|
140
|
+
"name": "LitElement",
|
|
141
|
+
"package": "lit"
|
|
142
|
+
},
|
|
143
|
+
"tagName": "jssm-bind",
|
|
144
|
+
"customElement": true
|
|
145
|
+
}
|
|
146
|
+
],
|
|
147
|
+
"exports": [
|
|
148
|
+
{
|
|
149
|
+
"kind": "js",
|
|
150
|
+
"name": "walk_path",
|
|
151
|
+
"declaration": {
|
|
152
|
+
"name": "walk_path",
|
|
153
|
+
"module": "src/ts/wc/jssm_bind_wc.ts"
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"kind": "js",
|
|
158
|
+
"name": "resolve_binding",
|
|
159
|
+
"declaration": {
|
|
160
|
+
"name": "resolve_binding",
|
|
161
|
+
"module": "src/ts/wc/jssm_bind_wc.ts"
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"kind": "js",
|
|
166
|
+
"name": "set_on_element",
|
|
167
|
+
"declaration": {
|
|
168
|
+
"name": "set_on_element",
|
|
169
|
+
"module": "src/ts/wc/jssm_bind_wc.ts"
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
"kind": "js",
|
|
174
|
+
"name": "install_bindings",
|
|
175
|
+
"declaration": {
|
|
176
|
+
"name": "install_bindings",
|
|
177
|
+
"module": "src/ts/wc/jssm_bind_wc.ts"
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
"kind": "js",
|
|
182
|
+
"name": "JssmBind",
|
|
183
|
+
"declaration": {
|
|
184
|
+
"name": "JssmBind",
|
|
185
|
+
"module": "src/ts/wc/jssm_bind_wc.ts"
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
]
|
|
189
|
+
},
|
|
5
190
|
{
|
|
6
191
|
"kind": "javascript-module",
|
|
7
192
|
"path": "src/ts/wc/jssm_hook_wc.ts",
|
|
@@ -30,7 +215,7 @@
|
|
|
30
215
|
"description": "The owning machine; used for the `state()` accessor."
|
|
31
216
|
}
|
|
32
217
|
],
|
|
33
|
-
"description": "Build a JssmHookProxy that wraps an arbitrary hook context object.\n\nThe context shape varies by hook kind (`from`/`to`/`action` may be absent\nfor transition-kind hooks), so this normalizes the shape via optional\nfields and exposes mutable `data` while keeping the rest read-only.\n\nThe `machine` parameter is used only for `state()`, so unit tests can\nsubstitute any object with a `state(): unknown` method."
|
|
218
|
+
"description": "Build a JssmHookProxy that wraps an arbitrary hook context object.\r\n\r\nThe context shape varies by hook kind (`from`/`to`/`action` may be absent\r\nfor transition-kind hooks), so this normalizes the shape via optional\r\nfields and exposes mutable `data` while keeping the rest read-only.\r\n\r\nThe `machine` parameter is used only for `state()`, so unit tests can\r\nsubstitute any object with a `state(): unknown` method."
|
|
34
219
|
},
|
|
35
220
|
{
|
|
36
221
|
"kind": "function",
|
|
@@ -56,7 +241,7 @@
|
|
|
56
241
|
"description": "Identifier appended to the synthetic sourceURL."
|
|
57
242
|
}
|
|
58
243
|
],
|
|
59
|
-
"description": "Compile a textContent body into a callable user handler.\n\nUses dynamic function construction — the same primitive browsers use\ninternally for `<a onclick=\"...\">` and `setTimeout(stringBody, ms)`.\nStrict CSP without `'unsafe-eval'` blocks this and the call will throw;\nconsumers should fall back to the `handler=\"name\"` form there.\n\nPrepends a `//# sourceURL=` comment so devtools surface a meaningful name\nin stack traces instead of `anonymous`."
|
|
244
|
+
"description": "Compile a textContent body into a callable user handler.\r\n\r\nUses dynamic function construction — the same primitive browsers use\r\ninternally for `<a onclick=\"...\">` and `setTimeout(stringBody, ms)`.\r\nStrict CSP without `'unsafe-eval'` blocks this and the call will throw;\r\nconsumers should fall back to the `handler=\"name\"` form there.\r\n\r\nPrepends a `//# sourceURL=` comment so devtools surface a meaningful name\r\nin stack traces instead of `anonymous`."
|
|
60
245
|
},
|
|
61
246
|
{
|
|
62
247
|
"kind": "function",
|
|
@@ -83,7 +268,7 @@
|
|
|
83
268
|
"description": "Optional in-WC registry to consult first."
|
|
84
269
|
}
|
|
85
270
|
],
|
|
86
|
-
"description": "Resolve a `handler=\"name\"` attribute to a callable by consulting first the\noptional in-WC registry, then `globalThis[name]`. Throws a clear error if\nneither resolves."
|
|
271
|
+
"description": "Resolve a `handler=\"name\"` attribute to a callable by consulting first the\r\noptional in-WC registry, then `globalThis[name]`. Throws a clear error if\r\nneither resolves."
|
|
87
272
|
},
|
|
88
273
|
{
|
|
89
274
|
"kind": "function",
|
|
@@ -102,7 +287,7 @@
|
|
|
102
287
|
"description": "The raw attribute value, or null if not present."
|
|
103
288
|
}
|
|
104
289
|
],
|
|
105
|
-
"description": "Validate and normalize a `<jssm-hook kind=\"...\">` value, defaulting to\n`\"hook\"` when the attribute is absent. Throws on unknown kinds rather\nthan silently doing nothing later."
|
|
290
|
+
"description": "Validate and normalize a `<jssm-hook kind=\"...\">` value, defaulting to\r\n`\"hook\"` when the attribute is absent. Throws on unknown kinds rather\r\nthan silently doing nothing later."
|
|
106
291
|
},
|
|
107
292
|
{
|
|
108
293
|
"kind": "function",
|
|
@@ -136,7 +321,7 @@
|
|
|
136
321
|
"description": "Optional in-WC registry of named handlers."
|
|
137
322
|
}
|
|
138
323
|
],
|
|
139
|
-
"description": "Parse a single `<jssm-hook>` element into a JssmHookInstallSpec.\n\nValidates the mutual-exclusion rule between `handler=\"name\"` and inline\nbody, defaults `kind` to `\"hook\"`, resolves named handlers against the\noptional registry then `globalThis`, and compiles inline bodies via\ndynamic function construction. Conditional-required attributes (e.g.\n`from`/`to` for `kind=\"hook\"`) are NOT validated here — `set_hook` will\nthrow with its own clear errors on missing pieces, which keeps the\nerror surface single-sourced."
|
|
324
|
+
"description": "Parse a single `<jssm-hook>` element into a JssmHookInstallSpec.\r\n\r\nValidates the mutual-exclusion rule between `handler=\"name\"` and inline\r\nbody, defaults `kind` to `\"hook\"`, resolves named handlers against the\r\noptional registry then `globalThis`, and compiles inline bodies via\r\ndynamic function construction. Conditional-required attributes (e.g.\r\n`from`/`to` for `kind=\"hook\"`) are NOT validated here — `set_hook` will\r\nthrow with its own clear errors on missing pieces, which keeps the\r\nerror surface single-sourced."
|
|
140
325
|
},
|
|
141
326
|
{
|
|
142
327
|
"kind": "function",
|
|
@@ -162,7 +347,7 @@
|
|
|
162
347
|
"description": "The owning machine; used by the proxy's `state()`."
|
|
163
348
|
}
|
|
164
349
|
],
|
|
165
|
-
"description": "Wrap a JssmHookUserHandler so that jssm's native hook contract is\nsatisfied: the user gets a friendly proxy, the proxy's mutated `data`\nbecomes the `HookComplexResult.data`, and an explicit `false` return\ncancels the transition.\n\nAny non-`false` return — including `undefined`, `true`, or an arbitrary\nobject — allows the transition. This matches the contract spelled out\nin the issue (#641): \"return false cancels; anything else allows\"."
|
|
350
|
+
"description": "Wrap a JssmHookUserHandler so that jssm's native hook contract is\r\nsatisfied: the user gets a friendly proxy, the proxy's mutated `data`\r\nbecomes the `HookComplexResult.data`, and an explicit `false` return\r\ncancels the transition.\r\n\r\nAny non-`false` return — including `undefined`, `true`, or an arbitrary\r\nobject — allows the transition. This matches the contract spelled out\r\nin the issue (#641): \"return false cancels; anything else allows\"."
|
|
166
351
|
},
|
|
167
352
|
{
|
|
168
353
|
"kind": "function",
|
|
@@ -185,10 +370,10 @@
|
|
|
185
370
|
"type": {
|
|
186
371
|
"text": "(ctx: RawHookContext) => unknown"
|
|
187
372
|
},
|
|
188
|
-
"description": "The wrapped (friendly-proxy) handler from {@link wrap_user_handler}.\n * "
|
|
373
|
+
"description": "The wrapped (friendly-proxy) handler from {@link wrap_user_handler}.\r\n * "
|
|
189
374
|
}
|
|
190
375
|
],
|
|
191
|
-
"description": "Build the typed descriptor object passed to `machine.set_hook` (and later\nto `machine.remove_hook` for cleanup) from a parsed JssmHookInstallSpec\nand the wrapped handler.\n\nFor kinds that need `from`/`to`/`action`, the descriptor includes those.\nMissing required keys produce `undefined` here; jssm's `set_hook` will\nsurface the error with its own clear message so we don't duplicate\nvalidation.\n\nReturn type is `unknown` because jssm's `HookDescription` is a\ndiscriminated union and our runtime-discriminator value can't be tracked\nby TypeScript across the build. The WC casts at the `set_hook` call site."
|
|
376
|
+
"description": "Build the typed descriptor object passed to `machine.set_hook` (and later\r\nto `machine.remove_hook` for cleanup) from a parsed JssmHookInstallSpec\r\nand the wrapped handler.\r\n\r\nFor kinds that need `from`/`to`/`action`, the descriptor includes those.\r\nMissing required keys produce `undefined` here; jssm's `set_hook` will\r\nsurface the error with its own clear message so we don't duplicate\r\nvalidation.\r\n\r\nReturn type is `unknown` because jssm's `HookDescription` is a\r\ndiscriminated union and our runtime-discriminator value can't be tracked\r\nby TypeScript across the build. The WC casts at the `set_hook` call site."
|
|
192
377
|
}
|
|
193
378
|
],
|
|
194
379
|
"exports": [
|
|
@@ -254,6 +439,85 @@
|
|
|
254
439
|
"kind": "javascript-module",
|
|
255
440
|
"path": "src/ts/wc/jssm_instance_wc.ts",
|
|
256
441
|
"declarations": [
|
|
442
|
+
{
|
|
443
|
+
"kind": "variable",
|
|
444
|
+
"name": "JSSM_ON_EVENT_NAMES",
|
|
445
|
+
"default": "new Set<string>([ 'transition', 'rejection', 'action', 'entry', 'exit', 'terminal', 'complete', 'error', 'data-change', 'override', 'timeout', 'hook-registration', 'hook-removal' ])",
|
|
446
|
+
"description": "Allow-list of event names accepted by `<jssm-on event=\"...\">`. Must stay\r\nin sync with the `JssmEventName` union in `jssm_types.ts` (the library's\r\n`machine.on(...)` event API, added in #638). Validating here gives the\r\ndeclarative wiring a clear \"unknown event name\" error at the WC layer\r\ninstead of relying on a downstream library throw whose message would\r\nmention `machine.on(...)` rather than the offending tag."
|
|
447
|
+
},
|
|
448
|
+
{
|
|
449
|
+
"kind": "function",
|
|
450
|
+
"name": "parse_jssm_on_element",
|
|
451
|
+
"return": {
|
|
452
|
+
"type": {
|
|
453
|
+
"text": ""
|
|
454
|
+
}
|
|
455
|
+
},
|
|
456
|
+
"parameters": [
|
|
457
|
+
{
|
|
458
|
+
"name": "el",
|
|
459
|
+
"type": {
|
|
460
|
+
"text": "HTMLElement"
|
|
461
|
+
},
|
|
462
|
+
"description": "The `<jssm-on>` element to parse."
|
|
463
|
+
}
|
|
464
|
+
],
|
|
465
|
+
"description": "Parse a `<jssm-on>` element into a validated ParsedJssmOn\r\nrecord. Centralized so the declarative-tag logic is testable without\r\nspinning up the full `<jssm-instance>` lifecycle.\r\n\r\nValidation rules (per #643):\r\n - `event` is required and must be in JSSM_ON_EVENT_NAMES.\r\n - Either a `handler=\"name\"` attribute or non-empty `textContent`\r\n must be supplied, but not both.\r\n - `state` is only meaningful for `event=\"entry\"` / `event=\"exit\"`;\r\n it's silently ignored on other events.\r\n - `from` / `to` are only meaningful for `event=\"transition\"`; they\r\n are silently ignored on other events. Both → AND (a specific\r\n edge). Neither → unfiltered.\r\n\r\n```typescript\r\nconst el = document.createElement('jssm-on');\r\nel.setAttribute('event', 'entry');\r\nel.setAttribute('state', 'paid');\r\nel.setAttribute('handler', 'onPaid');\r\nparse_jssm_on_element(el);\r\n// => { event: 'entry', handler_name: 'onPaid', inline_body: undefined,\r\n// once: false, name: undefined, filter: { state: 'paid' } }\r\n```"
|
|
466
|
+
},
|
|
467
|
+
{
|
|
468
|
+
"kind": "variable",
|
|
469
|
+
"name": "jssm_handler_registry",
|
|
470
|
+
"type": {
|
|
471
|
+
"text": "Map<string, (...args: unknown[]) => unknown>"
|
|
472
|
+
},
|
|
473
|
+
"default": "new Map()",
|
|
474
|
+
"description": "Optional global registry that `<jssm-on>` (and, later, `<jssm-hook>`)\r\nconsult first when resolving a `handler=\"name\"` attribute. Consumers\r\nregister named handlers here in a strict-CSP environment where a stray\r\n`globalThis[name]` isn't acceptable. Falls through to `globalThis[name]`\r\nif the registry has no entry.\r\n\r\nIntentionally a `Map<string, Function>` rather than a class with methods,\r\nso consumers can use any of `.get`, `.set`, `.delete`, `.clear` directly\r\nwithout a thin wrapper API."
|
|
475
|
+
},
|
|
476
|
+
{
|
|
477
|
+
"kind": "function",
|
|
478
|
+
"name": "resolve_named_handler",
|
|
479
|
+
"return": {
|
|
480
|
+
"type": {
|
|
481
|
+
"text": ""
|
|
482
|
+
}
|
|
483
|
+
},
|
|
484
|
+
"parameters": [
|
|
485
|
+
{
|
|
486
|
+
"name": "name",
|
|
487
|
+
"type": {
|
|
488
|
+
"text": "string"
|
|
489
|
+
},
|
|
490
|
+
"description": "The handler name as supplied by `handler=\"...\"`."
|
|
491
|
+
}
|
|
492
|
+
],
|
|
493
|
+
"description": "Resolve a named handler from the registry, then from `globalThis`.\r\nThrows if neither lookup finds a function — earlier failure here is\r\nbetter than a delayed \"is not a function\" at first event delivery."
|
|
494
|
+
},
|
|
495
|
+
{
|
|
496
|
+
"kind": "function",
|
|
497
|
+
"name": "compile_inline_body",
|
|
498
|
+
"return": {
|
|
499
|
+
"type": {
|
|
500
|
+
"text": ""
|
|
501
|
+
}
|
|
502
|
+
},
|
|
503
|
+
"parameters": [
|
|
504
|
+
{
|
|
505
|
+
"name": "body",
|
|
506
|
+
"type": {
|
|
507
|
+
"text": "string"
|
|
508
|
+
},
|
|
509
|
+
"description": "The inline JS body (function body, not full function)."
|
|
510
|
+
},
|
|
511
|
+
{
|
|
512
|
+
"name": "source_id",
|
|
513
|
+
"type": {
|
|
514
|
+
"text": "string"
|
|
515
|
+
},
|
|
516
|
+
"description": "A short identifier for the sourceURL pragma."
|
|
517
|
+
}
|
|
518
|
+
],
|
|
519
|
+
"description": "Compile an inline-body string into a handler function whose single\r\nparameter is `e` (the event detail object). Uses the same dynamic\r\n`Function(...)` constructor that browsers use internally for inline\r\nevent-handler attributes such as `<a onclick=\"...\">`; the input here\r\nis consumer-authored markup, never network data, so the surface is\r\nexactly that of an inline event-handler attribute and the same CSP\r\ncaveats apply (strict CSP without `'unsafe-eval'` blocks it). A\r\n`//# sourceURL=jssm-on:N` pragma is appended so devtools stack traces\r\npoint at a meaningful name."
|
|
520
|
+
},
|
|
257
521
|
{
|
|
258
522
|
"kind": "function",
|
|
259
523
|
"name": "resolve_fsl_source",
|
|
@@ -342,6 +606,26 @@
|
|
|
342
606
|
"default": "undefined",
|
|
343
607
|
"description": "The underlying machine instance, constructed at `connectedCallback`.\r\nExposed raw (not proxied) per the #639/#648 design decision so that\r\nconsumers can use the full Machine API directly.\r\n\r\nMarked optional because Lit will instantiate the element before\r\n`connectedCallback` runs; the instance is guaranteed present after\r\nconnection."
|
|
344
608
|
},
|
|
609
|
+
{
|
|
610
|
+
"kind": "field",
|
|
611
|
+
"name": "_unsubs",
|
|
612
|
+
"type": {
|
|
613
|
+
"text": "JssmBindUnsub[]"
|
|
614
|
+
},
|
|
615
|
+
"privacy": "private",
|
|
616
|
+
"default": "[]",
|
|
617
|
+
"description": "Live unsubscribe callbacks for #645 `<jssm-bind>` / `data-jssm-bind`\r\nprojections. Every entry must be invoked exactly once during\r\ndisconnectedCallback."
|
|
618
|
+
},
|
|
619
|
+
{
|
|
620
|
+
"kind": "field",
|
|
621
|
+
"name": "_on_unsubscribes",
|
|
622
|
+
"type": {
|
|
623
|
+
"text": "Array<() => void>"
|
|
624
|
+
},
|
|
625
|
+
"privacy": "private",
|
|
626
|
+
"default": "[]",
|
|
627
|
+
"description": "Unsubscribe callbacks for every `machine.on(...)` / `machine.once(...)`\r\nsubscription installed from a `<jssm-on>` child during\r\n`connectedCallback`. Walked in `disconnectedCallback`."
|
|
628
|
+
},
|
|
345
629
|
{
|
|
346
630
|
"kind": "field",
|
|
347
631
|
"name": "registry",
|
|
@@ -350,7 +634,7 @@
|
|
|
350
634
|
},
|
|
351
635
|
"readonly": true,
|
|
352
636
|
"default": "new Map()",
|
|
353
|
-
"description": "Per-instance registry of named hook handlers consulted before\r\n`globalThis` when resolving `<jssm-hook handler=\"name\"
|
|
637
|
+
"description": "Per-instance registry of named hook handlers consulted before\r\n`globalThis` when resolving `<jssm-hook handler=\"name\">`."
|
|
354
638
|
},
|
|
355
639
|
{
|
|
356
640
|
"kind": "field",
|
|
@@ -360,7 +644,7 @@
|
|
|
360
644
|
},
|
|
361
645
|
"privacy": "private",
|
|
362
646
|
"default": "[]",
|
|
363
|
-
"description": "Descriptors for hooks this WC installed at connect time
|
|
647
|
+
"description": "Descriptors for hooks this WC installed at connect time."
|
|
364
648
|
},
|
|
365
649
|
{
|
|
366
650
|
"kind": "field",
|
|
@@ -370,7 +654,7 @@
|
|
|
370
654
|
},
|
|
371
655
|
"privacy": "private",
|
|
372
656
|
"default": "0",
|
|
373
|
-
"description": "Counter
|
|
657
|
+
"description": "Counter for compiled inline-body hook debug ids."
|
|
374
658
|
},
|
|
375
659
|
{
|
|
376
660
|
"kind": "field",
|
|
@@ -380,7 +664,7 @@
|
|
|
380
664
|
},
|
|
381
665
|
"privacy": "private",
|
|
382
666
|
"default": "[]",
|
|
383
|
-
"description": "
|
|
667
|
+
"description": "DOM listeners installed by `<jssm-action>` / `data-jssm-action` discovery."
|
|
384
668
|
},
|
|
385
669
|
{
|
|
386
670
|
"kind": "field",
|
|
@@ -428,6 +712,17 @@
|
|
|
428
712
|
},
|
|
429
713
|
"description": "Convenience wrapper for `machine.state()`. Returns the current\r\nstate's name."
|
|
430
714
|
},
|
|
715
|
+
{
|
|
716
|
+
"kind": "method",
|
|
717
|
+
"name": "_install_jssm_on_children",
|
|
718
|
+
"privacy": "private",
|
|
719
|
+
"return": {
|
|
720
|
+
"type": {
|
|
721
|
+
"text": "void"
|
|
722
|
+
}
|
|
723
|
+
},
|
|
724
|
+
"description": "Discover direct-child `<jssm-on>` elements and install their\r\nsubscriptions on the owned machine. Per #643:\r\n\r\n- Direct children only (`:scope > jssm-on`). Deeper nesting is the\r\n responsibility of a future MutationObserver-driven v2.\r\n- Each `<jssm-on>` is parsed by parse_jssm_on_element, which\r\n enforces the form / event-name / filter rules.\r\n- Handlers come from resolve_named_handler (form A) or\r\n compile_inline_body (form B), and the result is installed\r\n via `machine.on(...)` or `machine.once(...)` depending on the\r\n element's `once` attribute.\r\n- Every returned unsubscribe is tracked in _on_unsubscribes\r\n so disconnectedCallback can release them all.\r\n\r\nCalled once from `connectedCallback` after the machine has been\r\nconstructed. Any error thrown by parsing or resolution propagates\r\nout so it surfaces via jsdom's error event (matching the rest of\r\n`<jssm-instance>`'s \"fail loud at connect\" policy)."
|
|
725
|
+
},
|
|
431
726
|
{
|
|
432
727
|
"kind": "method",
|
|
433
728
|
"name": "_install_declarative_hooks",
|
|
@@ -437,7 +732,7 @@
|
|
|
437
732
|
"text": "void"
|
|
438
733
|
}
|
|
439
734
|
},
|
|
440
|
-
"description": "Discover every direct-child `<jssm-hook>` element and install each\r\nagainst the owned machine. Handlers are wrapped with the friendly-proxy\r\nadapter that lets user code write `m.data = ...` and return `false` to\r\ncancel — see make_hook_proxy and the issue (#641) doc-comment\r\nfor the full contract
|
|
735
|
+
"description": "Discover every direct-child `<jssm-hook>` element and install each\r\nagainst the owned machine. Handlers are wrapped with the friendly-proxy\r\nadapter that lets user code write `m.data = ...` and return `false` to\r\ncancel — see make_hook_proxy and the issue (#641) doc-comment\r\nfor the full contract."
|
|
441
736
|
},
|
|
442
737
|
{
|
|
443
738
|
"kind": "method",
|
|
@@ -448,7 +743,7 @@
|
|
|
448
743
|
"text": "string"
|
|
449
744
|
}
|
|
450
745
|
},
|
|
451
|
-
"description": "Prefix used in synthetic `//# sourceURL=jssm-hook:<prefix><n>` annotations\r\nfor inline-body hooks compiled by this element.
|
|
746
|
+
"description": "Prefix used in synthetic `//# sourceURL=jssm-hook:<prefix><n>` annotations\r\nfor inline-body hooks compiled by this element."
|
|
452
747
|
},
|
|
453
748
|
{
|
|
454
749
|
"kind": "method",
|
|
@@ -459,7 +754,7 @@
|
|
|
459
754
|
"text": "void"
|
|
460
755
|
}
|
|
461
756
|
},
|
|
462
|
-
"description": "Wire DOM events to machine actions, using the two declarative forms from\r\nissue #640
|
|
757
|
+
"description": "Wire DOM events to machine actions, using the two declarative forms from\r\nissue #640. Both forms support optional `from-state` guards,\r\n`from-property` data extraction, and `prevent-default` /\r\n`stop-propagation` modifiers."
|
|
463
758
|
},
|
|
464
759
|
{
|
|
465
760
|
"kind": "method",
|
|
@@ -475,39 +770,10 @@
|
|
|
475
770
|
"name": "config",
|
|
476
771
|
"type": {
|
|
477
772
|
"text": "{\r\n source : HTMLElement;\r\n event_name : string;\r\n action_name : string;\r\n from_state : string | undefined;\r\n from_property : string | undefined;\r\n prevent_default : boolean;\r\n stop_propagation : boolean;\r\n }"
|
|
478
|
-
}
|
|
479
|
-
"description": "Listener configuration."
|
|
480
|
-
},
|
|
481
|
-
{
|
|
482
|
-
"description": "Element to attach the listener to.",
|
|
483
|
-
"name": "config.source"
|
|
484
|
-
},
|
|
485
|
-
{
|
|
486
|
-
"description": "DOM event to listen for.",
|
|
487
|
-
"name": "config.event_name"
|
|
488
|
-
},
|
|
489
|
-
{
|
|
490
|
-
"description": "Action to dispatch on the machine.",
|
|
491
|
-
"name": "config.action_name"
|
|
492
|
-
},
|
|
493
|
-
{
|
|
494
|
-
"description": "If set, only fire when `machine.state() === from_state`.",
|
|
495
|
-
"name": "config.from_state"
|
|
496
|
-
},
|
|
497
|
-
{
|
|
498
|
-
"description": "If set, pass `source[from_property]` as the action's data argument.",
|
|
499
|
-
"name": "config.from_property"
|
|
500
|
-
},
|
|
501
|
-
{
|
|
502
|
-
"description": "If true, call `e.preventDefault()` before checking the guard.",
|
|
503
|
-
"name": "config.prevent_default"
|
|
504
|
-
},
|
|
505
|
-
{
|
|
506
|
-
"description": "If true, call `e.stopPropagation()` before checking the guard.",
|
|
507
|
-
"name": "config.stop_propagation"
|
|
773
|
+
}
|
|
508
774
|
}
|
|
509
775
|
],
|
|
510
|
-
"description": "Attach one DOM listener that translates a DOM event into a\r\n`machine.action(...)` call, honoring the configured modifiers.
|
|
776
|
+
"description": "Attach one DOM listener that translates a DOM event into a\r\n`machine.action(...)` call, honoring the configured modifiers."
|
|
511
777
|
},
|
|
512
778
|
{
|
|
513
779
|
"kind": "method",
|
|
@@ -541,6 +807,46 @@
|
|
|
541
807
|
}
|
|
542
808
|
],
|
|
543
809
|
"exports": [
|
|
810
|
+
{
|
|
811
|
+
"kind": "js",
|
|
812
|
+
"name": "JSSM_ON_EVENT_NAMES",
|
|
813
|
+
"declaration": {
|
|
814
|
+
"name": "JSSM_ON_EVENT_NAMES",
|
|
815
|
+
"module": "src/ts/wc/jssm_instance_wc.ts"
|
|
816
|
+
}
|
|
817
|
+
},
|
|
818
|
+
{
|
|
819
|
+
"kind": "js",
|
|
820
|
+
"name": "parse_jssm_on_element",
|
|
821
|
+
"declaration": {
|
|
822
|
+
"name": "parse_jssm_on_element",
|
|
823
|
+
"module": "src/ts/wc/jssm_instance_wc.ts"
|
|
824
|
+
}
|
|
825
|
+
},
|
|
826
|
+
{
|
|
827
|
+
"kind": "js",
|
|
828
|
+
"name": "jssm_handler_registry",
|
|
829
|
+
"declaration": {
|
|
830
|
+
"name": "jssm_handler_registry",
|
|
831
|
+
"module": "src/ts/wc/jssm_instance_wc.ts"
|
|
832
|
+
}
|
|
833
|
+
},
|
|
834
|
+
{
|
|
835
|
+
"kind": "js",
|
|
836
|
+
"name": "resolve_named_handler",
|
|
837
|
+
"declaration": {
|
|
838
|
+
"name": "resolve_named_handler",
|
|
839
|
+
"module": "src/ts/wc/jssm_instance_wc.ts"
|
|
840
|
+
}
|
|
841
|
+
},
|
|
842
|
+
{
|
|
843
|
+
"kind": "js",
|
|
844
|
+
"name": "compile_inline_body",
|
|
845
|
+
"declaration": {
|
|
846
|
+
"name": "compile_inline_body",
|
|
847
|
+
"module": "src/ts/wc/jssm_instance_wc.ts"
|
|
848
|
+
}
|
|
849
|
+
},
|
|
544
850
|
{
|
|
545
851
|
"kind": "js",
|
|
546
852
|
"name": "resolve_fsl_source",
|
|
@@ -584,7 +890,7 @@
|
|
|
584
890
|
},
|
|
585
891
|
{
|
|
586
892
|
"kind": "class",
|
|
587
|
-
"description": "Web component that renders a jssm machine as inline SVG.",
|
|
893
|
+
"description": "Web component that renders a jssm machine as inline SVG.\r\n\r\nTwo operating modes:\r\n\r\n 1. **Standalone** (no parent `<jssm-instance>` ancestor): render from\r\n the element's own `fsl=\"\"` attribute / property. Re-renders on\r\n attribute change.\r\n 2. **Nested** (inside a `<jssm-instance>` ancestor, found via\r\n `closest('jssm-instance')` at `connectedCallback`): bind to the\r\n parent's machine and re-render on every `transition` event. The\r\n element's own `fsl` attribute is ignored in this mode; supplying it\r\n emits a `console.warn` for developer feedback.",
|
|
588
894
|
"name": "JssmViz",
|
|
589
895
|
"cssProperties": [
|
|
590
896
|
{
|
|
@@ -623,6 +929,37 @@
|
|
|
623
929
|
"privacy": "private",
|
|
624
930
|
"default": "''"
|
|
625
931
|
},
|
|
932
|
+
{
|
|
933
|
+
"kind": "field",
|
|
934
|
+
"name": "_parent_host",
|
|
935
|
+
"type": {
|
|
936
|
+
"text": "JssmInstanceHost | null"
|
|
937
|
+
},
|
|
938
|
+
"privacy": "private",
|
|
939
|
+
"default": "null",
|
|
940
|
+
"description": "Parent `<jssm-instance>` host reference, set in `connectedCallback`\r\nwhen a parent is found. When non-null the viz is in nested mode and\r\nrenders the parent's machine instead of its own `fsl` attribute."
|
|
941
|
+
},
|
|
942
|
+
{
|
|
943
|
+
"kind": "field",
|
|
944
|
+
"name": "_parent_sub",
|
|
945
|
+
"type": {
|
|
946
|
+
"text": "(() => void) | null"
|
|
947
|
+
},
|
|
948
|
+
"privacy": "private",
|
|
949
|
+
"default": "null",
|
|
950
|
+
"description": "Unsubscribe callback returned from `host.machine.on('transition', ...)`.\r\nHeld so `disconnectedCallback` can release the subscription."
|
|
951
|
+
},
|
|
952
|
+
{
|
|
953
|
+
"kind": "method",
|
|
954
|
+
"name": "_rerenderFromHostMachine",
|
|
955
|
+
"privacy": "private",
|
|
956
|
+
"return": {
|
|
957
|
+
"type": {
|
|
958
|
+
"text": ""
|
|
959
|
+
}
|
|
960
|
+
},
|
|
961
|
+
"description": "Nested-mode render path. Renders the bound parent's machine via the\r\nmachine_to_svg_string pipeline and commits the result to\r\n`_svg`. On failure emits a `viz-error` `CustomEvent` and clears the\r\nSVG."
|
|
962
|
+
},
|
|
626
963
|
{
|
|
627
964
|
"kind": "method",
|
|
628
965
|
"name": "_renderSvg",
|