-
Notifications
You must be signed in to change notification settings - Fork 23
Expand file tree
/
Copy pathcustom-elements.json
More file actions
1172 lines (1172 loc) · 48.6 KB
/
Copy pathcustom-elements.json
File metadata and controls
1172 lines (1172 loc) · 48.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
{
"schemaVersion": "1.0.0",
"readme": "",
"modules": [
{
"kind": "javascript-module",
"path": "src/ts/wc/fsl_bind_wc.ts",
"declarations": [
{
"kind": "function",
"name": "walk_path",
"return": {
"type": {
"text": ""
}
},
"parameters": [
{
"name": "obj",
"type": {
"text": "unknown"
},
"description": "The root value to traverse."
},
{
"name": "path",
"type": {
"text": "string"
},
"description": "Dotted path of property names, e.g. `\"a.b.c\"`."
}
],
"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```"
},
{
"kind": "function",
"name": "resolve_binding",
"return": {
"type": {
"text": ""
}
},
"parameters": [
{
"name": "m",
"type": {
"text": "Machine<unknown>"
},
"description": "The machine whose state/data is being projected."
},
{
"name": "expr",
"type": {
"text": "string"
},
"description": "The binding expression text (raw attribute value)."
}
],
"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```"
},
{
"kind": "function",
"name": "set_on_element",
"return": {
"type": {
"text": "void"
}
},
"parameters": [
{
"name": "el",
"type": {
"text": "HTMLElement"
},
"description": "The element to update."
},
{
"name": "target",
"type": {
"text": "string"
},
"description": "Target property name, possibly a `data-*` attribute."
},
{
"name": "value",
"type": {
"text": "unknown"
},
"description": "The resolved value to assign."
}
],
"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```"
},
{
"kind": "function",
"name": "install_bindings",
"return": {
"type": {
"text": ""
}
},
"parameters": [
{
"name": "host",
"type": {
"text": "HTMLElement"
},
"description": "The host element whose descendants carry the bindings."
},
{
"name": "machine",
"type": {
"text": "Machine<unknown>"
},
"description": "The machine whose state/data is being projected."
}
],
"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```"
},
{
"kind": "class",
"description": "`<fsl-bind>` / `<jssm-bind>` configuration tag. The element itself is\r\ninvisible — it carries `selector`, `source`, and optional `target`\r\nattributes that the parent `<fsl-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('fsl-bind')` resolves.",
"name": "FslBind",
"members": [],
"attributes": [
{
"description": "CSS selector for the target element(s), scoped to the host.",
"name": "selector"
},
{
"description": "Binding expression (see {@link resolve_binding}).",
"name": "source"
},
{
"description": "Target property name; defaults to `textContent`.",
"name": "target"
}
],
"superclass": {
"name": "LitElement",
"package": "lit"
},
"tagName": "fsl-bind",
"customElement": true
}
],
"exports": [
{
"kind": "js",
"name": "walk_path",
"declaration": {
"name": "walk_path",
"module": "src/ts/wc/fsl_bind_wc.ts"
}
},
{
"kind": "js",
"name": "resolve_binding",
"declaration": {
"name": "resolve_binding",
"module": "src/ts/wc/fsl_bind_wc.ts"
}
},
{
"kind": "js",
"name": "set_on_element",
"declaration": {
"name": "set_on_element",
"module": "src/ts/wc/fsl_bind_wc.ts"
}
},
{
"kind": "js",
"name": "install_bindings",
"declaration": {
"name": "install_bindings",
"module": "src/ts/wc/fsl_bind_wc.ts"
}
},
{
"kind": "js",
"name": "FslBind",
"declaration": {
"name": "FslBind",
"module": "src/ts/wc/fsl_bind_wc.ts"
}
}
]
},
{
"kind": "javascript-module",
"path": "src/ts/wc/fsl_hook_wc.ts",
"declarations": [
{
"kind": "function",
"name": "make_hook_proxy",
"return": {
"type": {
"text": ""
}
},
"parameters": [
{
"name": "ctx",
"type": {
"text": "{ data?: TData; from?: string; to?: string; action?: string }"
},
"description": "Raw hook context passed by jssm."
},
{
"name": "machine",
"type": {
"text": "{ state(): unknown }"
},
"description": "The owning machine; used for the `state()` accessor."
}
],
"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."
},
{
"kind": "function",
"name": "compile_inline_body",
"return": {
"type": {
"text": ""
}
},
"parameters": [
{
"name": "body",
"type": {
"text": "string"
},
"description": "Trimmed textContent of the `<jssm-hook>` element."
},
{
"name": "debug_id",
"type": {
"text": "string"
},
"description": "Identifier appended to the synthetic sourceURL."
}
],
"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`."
},
{
"kind": "function",
"name": "resolve_named_handler",
"return": {
"type": {
"text": ""
}
},
"parameters": [
{
"name": "name",
"type": {
"text": "string"
},
"description": "The handler name from the `handler=\"\"` attribute."
},
{
"name": "registry",
"optional": true,
"type": {
"text": "FslHookRegistry"
},
"description": "Optional in-WC registry to consult first."
}
],
"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."
},
{
"kind": "function",
"name": "normalize_hook_kind",
"return": {
"type": {
"text": ""
}
},
"parameters": [
{
"name": "raw",
"type": {
"text": "string | null | undefined"
},
"description": "The raw attribute value, or null if not present."
}
],
"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."
},
{
"kind": "function",
"name": "parse_hook_element",
"return": {
"type": {
"text": ""
}
},
"parameters": [
{
"name": "el",
"type": {
"text": "HTMLElement"
},
"description": "The `<jssm-hook>` element to parse."
},
{
"name": "debug_id",
"type": {
"text": "string"
},
"description": "Identifier used in the inline body's sourceURL."
},
{
"name": "registry",
"optional": true,
"type": {
"text": "FslHookRegistry"
},
"description": "Optional in-WC registry of named handlers."
}
],
"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."
},
{
"kind": "function",
"name": "wrap_user_handler",
"return": {
"type": {
"text": ""
}
},
"parameters": [
{
"name": "spec",
"type": {
"text": "FslHookInstallSpec"
},
"description": "The parsed install spec carrying the user handler."
},
{
"name": "machine",
"type": {
"text": "{ state(): unknown }"
},
"description": "The owning machine; used by the proxy's `state()`."
}
],
"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\"."
},
{
"kind": "function",
"name": "build_hook_descriptor",
"return": {
"type": {
"text": ""
}
},
"parameters": [
{
"name": "spec",
"type": {
"text": "FslHookInstallSpec"
},
"description": "The parsed install spec."
},
{
"name": "wrapped",
"type": {
"text": "(ctx: RawHookContext) => unknown"
},
"description": "The wrapped (friendly-proxy) handler from {@link wrap_user_handler}.\r\n * "
}
],
"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."
}
],
"exports": [
{
"kind": "js",
"name": "make_hook_proxy",
"declaration": {
"name": "make_hook_proxy",
"module": "src/ts/wc/fsl_hook_wc.ts"
}
},
{
"kind": "js",
"name": "compile_inline_body",
"declaration": {
"name": "compile_inline_body",
"module": "src/ts/wc/fsl_hook_wc.ts"
}
},
{
"kind": "js",
"name": "resolve_named_handler",
"declaration": {
"name": "resolve_named_handler",
"module": "src/ts/wc/fsl_hook_wc.ts"
}
},
{
"kind": "js",
"name": "normalize_hook_kind",
"declaration": {
"name": "normalize_hook_kind",
"module": "src/ts/wc/fsl_hook_wc.ts"
}
},
{
"kind": "js",
"name": "parse_hook_element",
"declaration": {
"name": "parse_hook_element",
"module": "src/ts/wc/fsl_hook_wc.ts"
}
},
{
"kind": "js",
"name": "wrap_user_handler",
"declaration": {
"name": "wrap_user_handler",
"module": "src/ts/wc/fsl_hook_wc.ts"
}
},
{
"kind": "js",
"name": "build_hook_descriptor",
"declaration": {
"name": "build_hook_descriptor",
"module": "src/ts/wc/fsl_hook_wc.ts"
}
}
]
},
{
"kind": "javascript-module",
"path": "src/ts/wc/fsl_instance_wc.ts",
"declarations": [
{
"kind": "variable",
"name": "JSSM_ON_EVENT_NAMES",
"default": "new Set<string>([ 'transition', 'rejection', 'action', 'entry', 'exit', 'terminal', 'complete', 'error', 'data-change', 'override', 'timeout', 'hook-registration', 'hook-removal' ])",
"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."
},
{
"kind": "function",
"name": "parse_jssm_on_element",
"return": {
"type": {
"text": ""
}
},
"parameters": [
{
"name": "el",
"type": {
"text": "HTMLElement"
},
"description": "The `<jssm-on>` element to parse."
}
],
"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```"
},
{
"kind": "variable",
"name": "jssm_handler_registry",
"type": {
"text": "Map<string, (...args: unknown[]) => unknown>"
},
"default": "new Map()",
"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."
},
{
"kind": "function",
"name": "resolve_named_handler",
"return": {
"type": {
"text": ""
}
},
"parameters": [
{
"name": "name",
"type": {
"text": "string"
},
"description": "The handler name as supplied by `handler=\"...\"`."
}
],
"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."
},
{
"kind": "function",
"name": "compile_inline_body",
"return": {
"type": {
"text": ""
}
},
"parameters": [
{
"name": "body",
"type": {
"text": "string"
},
"description": "The inline JS body (function body, not full function)."
},
{
"name": "source_id",
"type": {
"text": "string"
},
"description": "A short identifier for the sourceURL pragma."
}
],
"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."
},
{
"kind": "function",
"name": "resolve_fsl_source",
"return": {
"type": {
"text": ""
}
},
"parameters": [
{
"name": "host",
"type": {
"text": "HTMLElement"
},
"description": "The `<jssm-instance>` element being resolved."
},
{
"name": "fsl_attr",
"type": {
"text": "string"
},
"description": "The current value of the host's `fsl` attribute (or property), or empty string."
}
],
"description": "Resolve a `<jssm-instance>`'s FSL source from the three legal channels:\r\nthe `fsl=\"\"` attribute, a child `<script type=\"text/fsl\">`, and the\r\nelement's own text content (after stripping the script and any\r\n`<jssm-*>` companion tags). Exactly one channel may be used; using\r\nnone or more than one is an error.\r\n\r\nPulled out as a pure function so it's testable without spinning up a\r\nLit element.\r\n\r\n```typescript\r\nconst div = document.createElement('div');\r\ndiv.setAttribute('fsl', 'Off -> On;');\r\nresolve_fsl_source(div as HTMLElement, 'Off -> On;');\r\n// => { fsl: 'Off -> On;', provided_count: 1, error: undefined }\r\n```"
},
{
"kind": "class",
"description": "Web component that owns a single `Machine<unknown>` constructed from an\r\nFSL source supplied via one of three mutually exclusive channels:\r\n\r\n 1. The `fsl=\"\"` attribute,\r\n 2. A child `<script type=\"text/fsl\">`,\r\n 3. The element's own text content (companion `<jssm-*>` children and\r\n any `<script type=\"text/fsl\">` are excluded from this channel).\r\n\r\nSupplying zero or more than one channel is a thrown error.\r\n\r\nOn every transition the component reflects machine state to its own\r\nattributes (`current-state`, `legal-actions`, `terminal`, `complete`)\r\nand sets a `--current-state` CSS custom property so consumer CSS can\r\nstyle by state without subclassing.",
"name": "FslInstance",
"cssProperties": [
{
"description": "The machine's current state name as a CSS string token.",
"name": "--current-state"
}
],
"slots": [
{
"description": "Heading area for the instance.",
"name": "title"
},
{
"description": "Visualization slot; fallback is a placeholder string.",
"name": "viz"
},
{
"description": "Editor surface slot.",
"name": "editor"
},
{
"description": "Slot for action buttons / UI.",
"name": "actions"
},
{
"description": "Slot for toolbar UI.",
"name": "toolbar"
},
{
"description": "Slot for an info / status panel.",
"name": "info-panel"
},
{
"description": "Footer slot.",
"name": "footer"
}
],
"members": [
{
"kind": "field",
"name": "fsl",
"privacy": "public",
"type": {
"text": "string"
},
"default": "''",
"description": "FSL source attribute. When non-empty, this is the sole channel\r\nsupplying the machine's source. Setting both this and a child\r\n`<script type=\"text/fsl\">` (or non-empty text content) is an error.",
"attribute": "fsl"
},
{
"kind": "field",
"name": "_machine",
"type": {
"text": "Machine<unknown> | undefined"
},
"privacy": "private",
"default": "undefined",
"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."
},
{
"kind": "field",
"name": "_unsubs",
"type": {
"text": "FslBindUnsub[]"
},
"privacy": "private",
"default": "[]",
"description": "Live unsubscribe callbacks for #645 `<fsl-bind>` / `data-jssm-bind`\r\nprojections. Every entry must be invoked exactly once during\r\ndisconnectedCallback."
},
{
"kind": "field",
"name": "_on_unsubscribes",
"type": {
"text": "Array<() => void>"
},
"privacy": "private",
"default": "[]",
"description": "Unsubscribe callbacks for every `machine.on(...)` / `machine.once(...)`\r\nsubscription installed from a `<jssm-on>` child during\r\n`connectedCallback`. Walked in `disconnectedCallback`."
},
{
"kind": "field",
"name": "registry",
"type": {
"text": "FslHookRegistry"
},
"readonly": true,
"default": "new Map()",
"description": "Per-instance registry of named hook handlers consulted before\r\n`globalThis` when resolving `<fsl-hook handler=\"name\">` /\r\n`<jssm-hook handler=\"name\">`."
},
{
"kind": "field",
"name": "_installed_hooks",
"type": {
"text": "unknown[]"
},
"privacy": "private",
"default": "[]",
"description": "Descriptors for hooks this WC installed at connect time."
},
{
"kind": "field",
"name": "_hook_debug_counter",
"type": {
"text": "number"
},
"privacy": "private",
"default": "0",
"description": "Counter for compiled inline-body hook debug ids."
},
{
"kind": "field",
"name": "_action_listeners",
"type": {
"text": "Array<{\r\n target : EventTarget;\r\n event : string;\r\n handler : EventListener;\r\n }>"
},
"privacy": "private",
"default": "[]",
"description": "DOM listeners installed by `<jssm-action>` / `data-jssm-action` discovery."
},
{
"kind": "field",
"name": "machine",
"type": {
"text": "Machine<unknown>"
},
"description": "Raw machine accessor. Returns the owned Machine instance.",
"readonly": true
},
{
"kind": "method",
"name": "do",
"return": {
"type": {
"text": ""
}
},
"parameters": [
{
"name": "action",
"type": {
"text": "string"
},
"description": "The action name to dispatch."
},
{
"name": "data",
"optional": true,
"type": {
"text": "unknown"
},
"description": "Optional data payload to pass to the action."
}
],
"description": "Convenience wrapper for `machine.action(action, data)`.\r\nAfter the action, reflects updated state to host attributes and the\r\n`--current-state` CSS custom property, and requests a Lit update so\r\nthe state-specific `<slot name=\"state-...\">` can re-pick."
},
{
"kind": "method",
"name": "state",
"return": {
"type": {
"text": "string"
}
},
"description": "Convenience wrapper for `machine.state()`. Returns the current\r\nstate's name."
},
{
"kind": "method",
"name": "_install_jssm_on_children",
"privacy": "private",
"return": {
"type": {
"text": "void"
}
},
"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)."
},
{
"kind": "method",
"name": "_install_declarative_hooks",
"privacy": "private",
"return": {
"type": {
"text": "void"
}
},
"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."
},
{
"kind": "method",
"name": "_hook_id_prefix",
"privacy": "private",
"return": {
"type": {
"text": "string"
}
},
"description": "Prefix used in synthetic `//# sourceURL=jssm-hook:<prefix><n>` annotations\r\nfor inline-body hooks compiled by this element."
},
{
"kind": "method",
"name": "_discover_jssm_actions",
"privacy": "private",
"return": {
"type": {
"text": "void"
}
},
"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."
},
{
"kind": "method",
"name": "_install_action_listener",
"privacy": "private",
"return": {
"type": {
"text": "void"
}
},
"parameters": [
{
"name": "config",
"type": {
"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 }"
}
}
],
"description": "Attach one DOM listener that translates a DOM event into a\r\n`machine.action(...)` call, honoring the configured modifiers."
},
{
"kind": "method",
"name": "_paint_state_reflection",
"privacy": "private",
"return": {
"type": {
"text": "void"
}
},
"description": "Reflect machine state onto host attributes and CSS custom properties.\r\nCalled after every transition and once during `connectedCallback`.\r\n\r\nMechanism 1 (#639): writes to host attributes.\r\nMechanism 3 (#639): writes to host inline-style custom properties."
}
],
"attributes": [
{
"name": "fsl",
"type": {
"text": "string"
},
"default": "''",
"description": "FSL source attribute. When non-empty, this is the sole channel\r\nsupplying the machine's source. Setting both this and a child\r\n`<script type=\"text/fsl\">` (or non-empty text content) is an error.",
"fieldName": "fsl"
}
],
"superclass": {
"name": "LitElement",
"package": "lit"
},
"tagName": "fsl-instance",
"customElement": true
}
],
"exports": [
{
"kind": "js",
"name": "JSSM_ON_EVENT_NAMES",
"declaration": {
"name": "JSSM_ON_EVENT_NAMES",
"module": "src/ts/wc/fsl_instance_wc.ts"
}
},
{
"kind": "js",
"name": "parse_jssm_on_element",
"declaration": {
"name": "parse_jssm_on_element",
"module": "src/ts/wc/fsl_instance_wc.ts"
}
},
{
"kind": "js",
"name": "jssm_handler_registry",
"declaration": {
"name": "jssm_handler_registry",
"module": "src/ts/wc/fsl_instance_wc.ts"
}
},
{
"kind": "js",
"name": "resolve_named_handler",
"declaration": {
"name": "resolve_named_handler",
"module": "src/ts/wc/fsl_instance_wc.ts"
}
},
{
"kind": "js",
"name": "compile_inline_body",
"declaration": {
"name": "compile_inline_body",
"module": "src/ts/wc/fsl_instance_wc.ts"
}
},
{
"kind": "js",
"name": "resolve_fsl_source",
"declaration": {
"name": "resolve_fsl_source",
"module": "src/ts/wc/fsl_instance_wc.ts"
}
},
{
"kind": "js",
"name": "FslInstance",
"declaration": {
"name": "FslInstance",
"module": "src/ts/wc/fsl_instance_wc.ts"
}
}
]
},
{
"kind": "javascript-module",
"path": "src/ts/wc/fsl_viz_wc.ts",
"declarations": [
{
"kind": "function",
"name": "normalize_viz_error",
"return": {
"type": {
"text": ""
}
},
"parameters": [
{
"name": "e",
"type": {
"text": "unknown"
},
"description": "The thrown value to normalize."
}
],
"description": "Normalize an arbitrary thrown value into a JssmVizErrorDetail.\r\nAccepts anything (Error instances, JssmErrors with `.location`, plain\r\nstrings, etc.) and always produces a string `message`.\r\n\r\n```typescript\r\nnormalize_viz_error(new Error('boom'));\r\n// => { message: 'boom', location: undefined }\r\n\r\nnormalize_viz_error({ message: 'parse failed', location: { line: 1 } });\r\n// => { message: 'parse failed', location: { line: 1 } }\r\n\r\nnormalize_viz_error('bare string failure');\r\n// => { message: 'bare string failure', location: undefined }\r\n```"
},
{
"kind": "class",
"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 `<fsl-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 `<fsl-instance>` or `<jssm-instance>` ancestor,\r\n found via `closest_wc(this, 'instance')` at `connectedCallback`):\r\n bind to the parent's machine and re-render on every `transition`\r\n event. The element's own `fsl` attribute is ignored in this mode;\r\n supplying it emits a `console.warn` for developer feedback.",
"name": "FslViz",
"cssProperties": [
{
"description": "Minimum height of the rendered SVG container.",
"name": "--jssm-viz-min-height",
"default": "100px"
}
],
"members": [
{
"kind": "field",
"name": "fsl",
"type": {
"text": "string"
},
"default": "''",
"description": "FSL source to render.",
"attribute": "fsl"
},
{
"kind": "field",
"name": "engine",
"type": {
"text": "string | undefined"
},
"default": "undefined",
"description": "Optional Graphviz layout engine override (e.g. 'dot', 'neato').",
"attribute": "engine"
},
{
"kind": "field",
"name": "_svg",
"type": {
"text": "string"
},
"privacy": "private",
"default": "''"
},
{
"kind": "field",
"name": "_parent_host",
"type": {
"text": "JssmInstanceHost | null"
},
"privacy": "private",
"default": "null",
"description": "Parent `<fsl-instance>` (or `<jssm-instance>`) host reference, set in\r\n`connectedCallback` when a parent is found. When non-null the viz is\r\nin nested mode and renders the parent's machine instead of its own\r\n`fsl` attribute."
},
{
"kind": "field",
"name": "_parent_sub",
"type": {
"text": "(() => void) | null"
},
"privacy": "private",
"default": "null",
"description": "Unsubscribe callback returned from `host.machine.on('transition', ...)`.\r\nHeld so `disconnectedCallback` can release the subscription."
},
{
"kind": "method",
"name": "_rerenderFromHostMachine",
"privacy": "private",
"return": {
"type": {
"text": ""
}
},
"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."
},
{
"kind": "method",
"name": "_renderSvg",
"privacy": "private",
"return": {
"type": {
"text": ""
}
},
"description": "Render the current `fsl` source to an SVG string via the headless\r\n`fsl_to_svg_string` pipeline. Updates `_svg` on success; emits a\r\n`viz-error` `CustomEvent` on failure. Guards against stale results\r\nwhen `fsl` changes mid-flight."
}
],
"events": [
{
"name": "viz-error",
"type": {
"text": "CustomEvent<{ message: string; location?: unknown }>"
},
"description": "Fires when the FSL source fails to parse or render."
}
],
"attributes": [
{
"name": "fsl",
"type": {
"text": "string"
},
"default": "''",
"description": "FSL source to render.",
"fieldName": "fsl"
},
{
"name": "engine",
"type": {
"text": "string | undefined"
},
"default": "undefined",
"description": "Optional Graphviz layout engine override (e.g. 'dot', 'neato').",