jssm 5.141.13 → 5.142.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 +9 -9
- package/custom-elements.json +188 -48
- package/dist/cdn/instance.js +104 -32
- package/dist/cdn/viz.js +90 -41
- package/dist/cli/fsl-render.cjs +1 -1
- package/dist/cli/fsl.cjs +1 -1
- package/dist/deno/README.md +9 -9
- 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.define.js +54 -4
- package/dist/wc/instance.js +73 -29
- package/dist/wc/viz.define.js +49 -18
- package/dist/wc/viz.js +60 -22
- package/package.json +4 -1
|
@@ -1,6 +1,56 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
1
|
+
import { FslInstance } from './instance.js';
|
|
2
|
+
export { FslInstance } from './instance.js';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Shared helpers for the dual-prefix (`fsl-` canonical, `jssm-` synonym)
|
|
6
|
+
* web-component naming convention. Centralizes the "match either prefix"
|
|
7
|
+
* rule so it lives in exactly one place.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Returns true when `tag_name` is exactly `fsl-<suffix>` or `jssm-<suffix>`
|
|
11
|
+
* (case-insensitive).
|
|
12
|
+
*
|
|
13
|
+
* @param tag_name - The element tag name to test (e.g. `"FSL-VIZ"`, `"jssm-viz"`).
|
|
14
|
+
* @param suffix - The suffix to match after the prefix (e.g. `"viz"`).
|
|
15
|
+
* @returns `true` when `tag_name` is `fsl-<suffix>` or `jssm-<suffix>`.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* wc_suffix_matches('FSL-VIZ', 'viz'); // true
|
|
19
|
+
* wc_suffix_matches('jssm-viz', 'viz'); // true
|
|
20
|
+
* wc_suffix_matches('div', 'viz'); // false
|
|
21
|
+
* wc_suffix_matches('fsl-vizard', 'viz'); // false — suffix must match exactly
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* Registers a canonical custom-element tag and its synonym tag.
|
|
25
|
+
*
|
|
26
|
+
* `customElements.define` requires a distinct constructor per tag name, so
|
|
27
|
+
* callers pass the canonical class and a thin subclass for the synonym.
|
|
28
|
+
* The function is idempotent: if either tag is already registered it skips
|
|
29
|
+
* that `define` call rather than throwing.
|
|
30
|
+
*
|
|
31
|
+
* @param canonical_tag - The primary tag name (e.g. `"fsl-instance"`).
|
|
32
|
+
* @param synonym_tag - The alias tag name (e.g. `"jssm-instance"`).
|
|
33
|
+
* @param CanonicalClass - Constructor to register under `canonical_tag`.
|
|
34
|
+
* @param SynonymClass - Constructor to register under `synonym_tag`
|
|
35
|
+
* (must be a distinct class from `CanonicalClass`).
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* class FslInstance extends HTMLElement {}
|
|
39
|
+
* class JssmInstance extends FslInstance {}
|
|
40
|
+
* define_with_synonym('fsl-instance', 'jssm-instance', FslInstance, JssmInstance);
|
|
41
|
+
*
|
|
42
|
+
* @see closest_wc
|
|
43
|
+
*/
|
|
44
|
+
function define_with_synonym(canonical_tag, synonym_tag, CanonicalClass, SynonymClass) {
|
|
45
|
+
if (!customElements.get(canonical_tag))
|
|
46
|
+
customElements.define(canonical_tag, CanonicalClass);
|
|
47
|
+
if (!customElements.get(synonym_tag))
|
|
48
|
+
customElements.define(synonym_tag, SynonymClass);
|
|
6
49
|
}
|
|
50
|
+
|
|
51
|
+
/** Thin subclass so `<jssm-instance>` registers under a distinct constructor. */
|
|
52
|
+
class JssmInstance extends FslInstance {
|
|
53
|
+
}
|
|
54
|
+
define_with_synonym('fsl-instance', 'jssm-instance', FslInstance, JssmInstance);
|
|
55
|
+
|
|
56
|
+
export { JssmInstance };
|
package/dist/wc/instance.js
CHANGED
|
@@ -1,6 +1,47 @@
|
|
|
1
1
|
import { css, LitElement, html } from 'lit';
|
|
2
2
|
import { sm } from 'jssm';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Shared helpers for the dual-prefix (`fsl-` canonical, `jssm-` synonym)
|
|
6
|
+
* web-component naming convention. Centralizes the "match either prefix"
|
|
7
|
+
* rule so it lives in exactly one place.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Returns true when `tag_name` is exactly `fsl-<suffix>` or `jssm-<suffix>`
|
|
11
|
+
* (case-insensitive).
|
|
12
|
+
*
|
|
13
|
+
* @param tag_name - The element tag name to test (e.g. `"FSL-VIZ"`, `"jssm-viz"`).
|
|
14
|
+
* @param suffix - The suffix to match after the prefix (e.g. `"viz"`).
|
|
15
|
+
* @returns `true` when `tag_name` is `fsl-<suffix>` or `jssm-<suffix>`.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* wc_suffix_matches('FSL-VIZ', 'viz'); // true
|
|
19
|
+
* wc_suffix_matches('jssm-viz', 'viz'); // true
|
|
20
|
+
* wc_suffix_matches('div', 'viz'); // false
|
|
21
|
+
* wc_suffix_matches('fsl-vizard', 'viz'); // false — suffix must match exactly
|
|
22
|
+
*/
|
|
23
|
+
function wc_suffix_matches(tag_name, suffix) {
|
|
24
|
+
const lower = tag_name.toLowerCase();
|
|
25
|
+
return lower === `fsl-${suffix}` || lower === `jssm-${suffix}`;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Returns the nearest ancestor of `el` (or `el` itself) whose tag is
|
|
29
|
+
* `fsl-<suffix>` or `jssm-<suffix>`, or `null` if none exists.
|
|
30
|
+
*
|
|
31
|
+
* @param el - The element to start the search from.
|
|
32
|
+
* @param suffix - The suffix to match (e.g. `"instance"`).
|
|
33
|
+
* @returns The closest matching ancestor element, or `null`.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* // <fsl-instance><div id="k"></div></fsl-instance>
|
|
37
|
+
* closest_wc(document.getElementById('k'), 'instance'); // <fsl-instance>
|
|
38
|
+
*
|
|
39
|
+
* @see wc_suffix_matches
|
|
40
|
+
*/
|
|
41
|
+
function closest_wc(el, suffix) {
|
|
42
|
+
return el.closest(`fsl-${suffix}, jssm-${suffix}`);
|
|
43
|
+
}
|
|
44
|
+
|
|
4
45
|
/**
|
|
5
46
|
* Walk a dotted path into a value. Used by the `data.path.to.field`
|
|
6
47
|
* variant of {@link resolve_binding}. Returns `undefined` whenever the
|
|
@@ -164,12 +205,13 @@ function install_bindings(host, machine) {
|
|
|
164
205
|
apply();
|
|
165
206
|
unsubs.push(machine.on('transition', apply));
|
|
166
207
|
}
|
|
167
|
-
// Form 2: dedicated `<jssm-bind>` configuration tags. Only
|
|
168
|
-
// children are considered configuration tags for THIS host — nested
|
|
169
|
-
// `<jssm-instance>` children would have their own
|
|
170
|
-
// their own component.
|
|
171
|
-
const
|
|
172
|
-
|
|
208
|
+
// Form 2: dedicated `<fsl-bind>` / `<jssm-bind>` configuration tags. Only
|
|
209
|
+
// direct children are considered configuration tags for THIS host — nested
|
|
210
|
+
// `<fsl-instance>` / `<jssm-instance>` children would have their own
|
|
211
|
+
// bindings handled by their own component.
|
|
212
|
+
const all_direct = host.querySelectorAll(':scope > *');
|
|
213
|
+
const config_tags = Array.from(all_direct).filter(el => wc_suffix_matches(el.tagName, 'bind'));
|
|
214
|
+
for (const tag of config_tags) {
|
|
173
215
|
const selector = tag.getAttribute('selector');
|
|
174
216
|
const expr = tag.getAttribute('source');
|
|
175
217
|
const target = (_b = tag.getAttribute('target')) !== null && _b !== void 0 ? _b : 'textContent';
|
|
@@ -191,22 +233,22 @@ function install_bindings(host, machine) {
|
|
|
191
233
|
return unsubs;
|
|
192
234
|
}
|
|
193
235
|
/**
|
|
194
|
-
* `<jssm-bind>` configuration tag. The element itself is
|
|
195
|
-
* it carries `selector`, `source`, and optional `target`
|
|
196
|
-
* that the parent `<
|
|
236
|
+
* `<fsl-bind>` / `<jssm-bind>` configuration tag. The element itself is
|
|
237
|
+
* invisible — it carries `selector`, `source`, and optional `target`
|
|
238
|
+
* attributes that the parent `<fsl-instance>` reads during its connection
|
|
197
239
|
* lifecycle to wire up a machine-to-DOM binding.
|
|
198
240
|
*
|
|
199
241
|
* Registering it as a `LitElement` (rather than leaving it as a generic
|
|
200
242
|
* unknown tag) gives it a stable upgrade timing, a `display: none`
|
|
201
243
|
* default style, and a proper place in the custom-elements registry so
|
|
202
|
-
* `customElements.get('
|
|
244
|
+
* `customElements.get('fsl-bind')` resolves.
|
|
203
245
|
*
|
|
204
|
-
* @element
|
|
246
|
+
* @element fsl-bind
|
|
205
247
|
* @attribute selector - CSS selector for the target element(s), scoped to the host.
|
|
206
248
|
* @attribute source - Binding expression (see {@link resolve_binding}).
|
|
207
249
|
* @attribute target - Target property name; defaults to `textContent`.
|
|
208
250
|
*/
|
|
209
|
-
class
|
|
251
|
+
class FslBind extends LitElement {
|
|
210
252
|
/**
|
|
211
253
|
* No-op render. The tag's purpose is purely declarative
|
|
212
254
|
* configuration; it must not contribute any DOM to the page.
|
|
@@ -215,7 +257,7 @@ class JssmBind extends LitElement {
|
|
|
215
257
|
return null;
|
|
216
258
|
}
|
|
217
259
|
}
|
|
218
|
-
|
|
260
|
+
FslBind.styles = css `:host { display: none; }`;
|
|
219
261
|
|
|
220
262
|
const VALID_KINDS = new Set([
|
|
221
263
|
'hook',
|
|
@@ -633,9 +675,10 @@ function resolve_fsl_source(host, fsl_attr) {
|
|
|
633
675
|
const clone = host.cloneNode(true);
|
|
634
676
|
// Drop every script tag (any type — we only want raw text FSL here).
|
|
635
677
|
clone.querySelectorAll('script').forEach(n => n.remove());
|
|
636
|
-
// Drop every <jssm-*> companion tag (e.g. <
|
|
678
|
+
// Drop every <fsl-*> or <jssm-*> companion tag (e.g. <fsl-hook>, <jssm-on>, etc.).
|
|
637
679
|
clone.querySelectorAll('*').forEach(n => {
|
|
638
|
-
|
|
680
|
+
const t = n.tagName.toLowerCase();
|
|
681
|
+
if (t.startsWith('fsl-') || t.startsWith('jssm-')) {
|
|
639
682
|
n.remove();
|
|
640
683
|
}
|
|
641
684
|
});
|
|
@@ -676,7 +719,7 @@ function resolve_fsl_source(host, fsl_attr) {
|
|
|
676
719
|
* and sets a `--current-state` CSS custom property so consumer CSS can
|
|
677
720
|
* style by state without subclassing.
|
|
678
721
|
*
|
|
679
|
-
* @element
|
|
722
|
+
* @element fsl-instance
|
|
680
723
|
* @cssproperty [--current-state] - The machine's current state name as a CSS string token.
|
|
681
724
|
* @slot title - Heading area for the instance.
|
|
682
725
|
* @slot viz - Visualization slot; fallback is a placeholder string.
|
|
@@ -686,7 +729,7 @@ function resolve_fsl_source(host, fsl_attr) {
|
|
|
686
729
|
* @slot info-panel - Slot for an info / status panel.
|
|
687
730
|
* @slot footer - Footer slot.
|
|
688
731
|
*/
|
|
689
|
-
class
|
|
732
|
+
class FslInstance extends LitElement {
|
|
690
733
|
constructor() {
|
|
691
734
|
super(...arguments);
|
|
692
735
|
/**
|
|
@@ -706,7 +749,7 @@ class JssmInstance extends LitElement {
|
|
|
706
749
|
*/
|
|
707
750
|
this._machine = undefined;
|
|
708
751
|
/**
|
|
709
|
-
* Live unsubscribe callbacks for #645 `<
|
|
752
|
+
* Live unsubscribe callbacks for #645 `<fsl-bind>` / `data-jssm-bind`
|
|
710
753
|
* projections. Every entry must be invoked exactly once during
|
|
711
754
|
* {@link disconnectedCallback}.
|
|
712
755
|
*/
|
|
@@ -719,7 +762,8 @@ class JssmInstance extends LitElement {
|
|
|
719
762
|
this._on_unsubscribes = [];
|
|
720
763
|
/**
|
|
721
764
|
* Per-instance registry of named hook handlers consulted before
|
|
722
|
-
* `globalThis` when resolving `<
|
|
765
|
+
* `globalThis` when resolving `<fsl-hook handler="name">` /
|
|
766
|
+
* `<jssm-hook handler="name">`.
|
|
723
767
|
*/
|
|
724
768
|
this.registry = new Map();
|
|
725
769
|
/**
|
|
@@ -742,7 +786,7 @@ class JssmInstance extends LitElement {
|
|
|
742
786
|
*/
|
|
743
787
|
get machine() {
|
|
744
788
|
if (this._machine === undefined) {
|
|
745
|
-
throw new Error('
|
|
789
|
+
throw new Error('fsl-instance: machine accessed before connection');
|
|
746
790
|
}
|
|
747
791
|
return this._machine;
|
|
748
792
|
}
|
|
@@ -785,7 +829,7 @@ class JssmInstance extends LitElement {
|
|
|
785
829
|
// Step 1: resolve FSL source.
|
|
786
830
|
const resolved = resolve_fsl_source(this, this.fsl);
|
|
787
831
|
if (resolved.error !== undefined) {
|
|
788
|
-
throw new Error(`
|
|
832
|
+
throw new Error(`fsl-instance: ${resolved.error}`);
|
|
789
833
|
}
|
|
790
834
|
// Step 2: construct the machine.
|
|
791
835
|
// (The resolver guarantees `fsl` is a non-empty string when error is undefined.)
|
|
@@ -830,7 +874,7 @@ class JssmInstance extends LitElement {
|
|
|
830
874
|
*/
|
|
831
875
|
_install_jssm_on_children() {
|
|
832
876
|
const machine = this._machine;
|
|
833
|
-
const on_nodes = this.querySelectorAll(':scope > jssm-on');
|
|
877
|
+
const on_nodes = this.querySelectorAll(':scope > fsl-on, :scope > jssm-on');
|
|
834
878
|
let index = 0;
|
|
835
879
|
for (const el of Array.from(on_nodes)) {
|
|
836
880
|
index += 1;
|
|
@@ -858,7 +902,7 @@ class JssmInstance extends LitElement {
|
|
|
858
902
|
*/
|
|
859
903
|
_install_declarative_hooks() {
|
|
860
904
|
const machine = this._machine;
|
|
861
|
-
const hook_els = this.querySelectorAll(':scope > jssm-hook');
|
|
905
|
+
const hook_els = this.querySelectorAll(':scope > fsl-hook, :scope > jssm-hook');
|
|
862
906
|
for (const el of Array.from(hook_els)) {
|
|
863
907
|
const debug_id = `${this._hook_id_prefix()}${++this._hook_debug_counter}`;
|
|
864
908
|
const spec = parse_hook_element(el, debug_id, this.registry);
|
|
@@ -919,7 +963,7 @@ class JssmInstance extends LitElement {
|
|
|
919
963
|
*/
|
|
920
964
|
_discover_jssm_actions() {
|
|
921
965
|
var _a, _b, _c, _d;
|
|
922
|
-
const inline_targets = Array.from(this.querySelectorAll('[data-jssm-action]')).filter(el => el
|
|
966
|
+
const inline_targets = Array.from(this.querySelectorAll('[data-jssm-action]')).filter(el => closest_wc(el, 'action') === null);
|
|
923
967
|
for (const el of inline_targets) {
|
|
924
968
|
this._install_action_listener({
|
|
925
969
|
source: el,
|
|
@@ -931,7 +975,7 @@ class JssmInstance extends LitElement {
|
|
|
931
975
|
stop_propagation: 'jssmStopPropagation' in el.dataset,
|
|
932
976
|
});
|
|
933
977
|
}
|
|
934
|
-
const tags = this.querySelectorAll(':scope > jssm-action');
|
|
978
|
+
const tags = this.querySelectorAll(':scope > fsl-action, :scope > jssm-action');
|
|
935
979
|
for (const tag of Array.from(tags)) {
|
|
936
980
|
const selector = tag.getAttribute('selector');
|
|
937
981
|
const action_name = tag.getAttribute('action');
|
|
@@ -1022,7 +1066,7 @@ class JssmInstance extends LitElement {
|
|
|
1022
1066
|
return html `
|
|
1023
1067
|
<div class="container">
|
|
1024
1068
|
<header>
|
|
1025
|
-
<slot name="title"><span class="placeholder">
|
|
1069
|
+
<slot name="title"><span class="placeholder">fsl-instance</span></slot>
|
|
1026
1070
|
</header>
|
|
1027
1071
|
<section class="viz">
|
|
1028
1072
|
<slot name="viz"><span class="placeholder">no viz configured</span></slot>
|
|
@@ -1049,7 +1093,7 @@ class JssmInstance extends LitElement {
|
|
|
1049
1093
|
`;
|
|
1050
1094
|
}
|
|
1051
1095
|
}
|
|
1052
|
-
|
|
1096
|
+
FslInstance.styles = css `
|
|
1053
1097
|
:host {
|
|
1054
1098
|
display: block;
|
|
1055
1099
|
}
|
|
@@ -1068,8 +1112,8 @@ JssmInstance.styles = css `
|
|
|
1068
1112
|
* survives the future companion-tag work without colliding with
|
|
1069
1113
|
* dynamically declared attributes.
|
|
1070
1114
|
*/
|
|
1071
|
-
|
|
1115
|
+
FslInstance.properties = {
|
|
1072
1116
|
fsl: { type: String, reflect: false },
|
|
1073
1117
|
};
|
|
1074
1118
|
|
|
1075
|
-
export {
|
|
1119
|
+
export { FslInstance, JSSM_ON_EVENT_NAMES, compile_inline_body, jssm_handler_registry, parse_jssm_on_element, resolve_fsl_source, resolve_named_handler };
|
package/dist/wc/viz.define.js
CHANGED
|
@@ -1,25 +1,56 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
1
|
+
import { FslViz } from './viz.js';
|
|
2
|
+
export { FslViz } from './viz.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
|
|
5
|
+
* Shared helpers for the dual-prefix (`fsl-` canonical, `jssm-` synonym)
|
|
6
|
+
* web-component naming convention. Centralizes the "match either prefix"
|
|
7
|
+
* rule so it lives in exactly one place.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Returns true when `tag_name` is exactly `fsl-<suffix>` or `jssm-<suffix>`
|
|
11
|
+
* (case-insensitive).
|
|
12
|
+
*
|
|
13
|
+
* @param tag_name - The element tag name to test (e.g. `"FSL-VIZ"`, `"jssm-viz"`).
|
|
14
|
+
* @param suffix - The suffix to match after the prefix (e.g. `"viz"`).
|
|
15
|
+
* @returns `true` when `tag_name` is `fsl-<suffix>` or `jssm-<suffix>`.
|
|
9
16
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* viz
|
|
13
|
-
*
|
|
14
|
-
*
|
|
17
|
+
* @example
|
|
18
|
+
* wc_suffix_matches('FSL-VIZ', 'viz'); // true
|
|
19
|
+
* wc_suffix_matches('jssm-viz', 'viz'); // true
|
|
20
|
+
* wc_suffix_matches('div', 'viz'); // false
|
|
21
|
+
* wc_suffix_matches('fsl-vizard', 'viz'); // false — suffix must match exactly
|
|
15
22
|
*/
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Registers a canonical custom-element tag and its synonym tag.
|
|
25
|
+
*
|
|
26
|
+
* `customElements.define` requires a distinct constructor per tag name, so
|
|
27
|
+
* callers pass the canonical class and a thin subclass for the synonym.
|
|
28
|
+
* The function is idempotent: if either tag is already registered it skips
|
|
29
|
+
* that `define` call rather than throwing.
|
|
30
|
+
*
|
|
31
|
+
* @param canonical_tag - The primary tag name (e.g. `"fsl-instance"`).
|
|
32
|
+
* @param synonym_tag - The alias tag name (e.g. `"jssm-instance"`).
|
|
33
|
+
* @param CanonicalClass - Constructor to register under `canonical_tag`.
|
|
34
|
+
* @param SynonymClass - Constructor to register under `synonym_tag`
|
|
35
|
+
* (must be a distinct class from `CanonicalClass`).
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* class FslInstance extends HTMLElement {}
|
|
39
|
+
* class JssmInstance extends FslInstance {}
|
|
40
|
+
* define_with_synonym('fsl-instance', 'jssm-instance', FslInstance, JssmInstance);
|
|
41
|
+
*
|
|
42
|
+
* @see closest_wc
|
|
43
|
+
*/
|
|
44
|
+
function define_with_synonym(canonical_tag, synonym_tag, CanonicalClass, SynonymClass) {
|
|
45
|
+
if (!customElements.get(canonical_tag))
|
|
46
|
+
customElements.define(canonical_tag, CanonicalClass);
|
|
47
|
+
if (!customElements.get(synonym_tag))
|
|
48
|
+
customElements.define(synonym_tag, SynonymClass);
|
|
20
49
|
}
|
|
21
|
-
|
|
22
|
-
|
|
50
|
+
|
|
51
|
+
/** Thin subclass so `<jssm-viz>` registers under a distinct constructor. */
|
|
52
|
+
class JssmViz extends FslViz {
|
|
23
53
|
}
|
|
54
|
+
define_with_synonym('fsl-viz', 'jssm-viz', FslViz, JssmViz);
|
|
24
55
|
|
|
25
|
-
export {
|
|
56
|
+
export { JssmViz };
|
package/dist/wc/viz.js
CHANGED
|
@@ -3,6 +3,43 @@ import { property, state } from 'lit/decorators.js';
|
|
|
3
3
|
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
|
|
4
4
|
import { machine_to_svg_string, fsl_to_svg_string } from 'jssm/viz';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Shared helpers for the dual-prefix (`fsl-` canonical, `jssm-` synonym)
|
|
8
|
+
* web-component naming convention. Centralizes the "match either prefix"
|
|
9
|
+
* rule so it lives in exactly one place.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Returns true when `tag_name` is exactly `fsl-<suffix>` or `jssm-<suffix>`
|
|
13
|
+
* (case-insensitive).
|
|
14
|
+
*
|
|
15
|
+
* @param tag_name - The element tag name to test (e.g. `"FSL-VIZ"`, `"jssm-viz"`).
|
|
16
|
+
* @param suffix - The suffix to match after the prefix (e.g. `"viz"`).
|
|
17
|
+
* @returns `true` when `tag_name` is `fsl-<suffix>` or `jssm-<suffix>`.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* wc_suffix_matches('FSL-VIZ', 'viz'); // true
|
|
21
|
+
* wc_suffix_matches('jssm-viz', 'viz'); // true
|
|
22
|
+
* wc_suffix_matches('div', 'viz'); // false
|
|
23
|
+
* wc_suffix_matches('fsl-vizard', 'viz'); // false — suffix must match exactly
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* Returns the nearest ancestor of `el` (or `el` itself) whose tag is
|
|
27
|
+
* `fsl-<suffix>` or `jssm-<suffix>`, or `null` if none exists.
|
|
28
|
+
*
|
|
29
|
+
* @param el - The element to start the search from.
|
|
30
|
+
* @param suffix - The suffix to match (e.g. `"instance"`).
|
|
31
|
+
* @returns The closest matching ancestor element, or `null`.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* // <fsl-instance><div id="k"></div></fsl-instance>
|
|
35
|
+
* closest_wc(document.getElementById('k'), 'instance'); // <fsl-instance>
|
|
36
|
+
*
|
|
37
|
+
* @see wc_suffix_matches
|
|
38
|
+
*/
|
|
39
|
+
function closest_wc(el, suffix) {
|
|
40
|
+
return el.closest(`fsl-${suffix}, jssm-${suffix}`);
|
|
41
|
+
}
|
|
42
|
+
|
|
6
43
|
var __decorate = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
|
|
7
44
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
8
45
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -45,20 +82,20 @@ function normalize_viz_error(e) {
|
|
|
45
82
|
*
|
|
46
83
|
* Two operating modes:
|
|
47
84
|
*
|
|
48
|
-
* 1. **Standalone** (no parent `<
|
|
85
|
+
* 1. **Standalone** (no parent `<fsl-instance>` ancestor): render from
|
|
49
86
|
* the element's own `fsl=""` attribute / property. Re-renders on
|
|
50
87
|
* attribute change.
|
|
51
|
-
* 2. **Nested** (inside a `<jssm-instance>` ancestor,
|
|
52
|
-
* `
|
|
53
|
-
* parent's machine and re-render on every `transition`
|
|
54
|
-
* element's own `fsl` attribute is ignored in this mode;
|
|
55
|
-
* emits a `console.warn` for developer feedback.
|
|
88
|
+
* 2. **Nested** (inside a `<fsl-instance>` or `<jssm-instance>` ancestor,
|
|
89
|
+
* found via `closest_wc(this, 'instance')` at `connectedCallback`):
|
|
90
|
+
* bind to the parent's machine and re-render on every `transition`
|
|
91
|
+
* event. The element's own `fsl` attribute is ignored in this mode;
|
|
92
|
+
* supplying it emits a `console.warn` for developer feedback.
|
|
56
93
|
*
|
|
57
|
-
* @element
|
|
94
|
+
* @element fsl-viz
|
|
58
95
|
* @cssproperty [--jssm-viz-min-height=100px] - Minimum height of the rendered SVG container.
|
|
59
96
|
* @fires {CustomEvent<{ message: string; location?: unknown }>} viz-error - Fires when the FSL source fails to parse or render.
|
|
60
97
|
*/
|
|
61
|
-
class
|
|
98
|
+
class FslViz extends LitElement {
|
|
62
99
|
constructor() {
|
|
63
100
|
super(...arguments);
|
|
64
101
|
/** FSL source to render. */
|
|
@@ -67,9 +104,10 @@ class JssmViz extends LitElement {
|
|
|
67
104
|
this.engine = undefined;
|
|
68
105
|
this._svg = '';
|
|
69
106
|
/**
|
|
70
|
-
* Parent `<jssm-instance>` host reference, set in
|
|
71
|
-
* when a parent is found. When non-null the viz is
|
|
72
|
-
* renders the parent's machine instead of its own
|
|
107
|
+
* Parent `<fsl-instance>` (or `<jssm-instance>`) host reference, set in
|
|
108
|
+
* `connectedCallback` when a parent is found. When non-null the viz is
|
|
109
|
+
* in nested mode and renders the parent's machine instead of its own
|
|
110
|
+
* `fsl` attribute.
|
|
73
111
|
*/
|
|
74
112
|
this._parent_host = null;
|
|
75
113
|
/**
|
|
@@ -102,9 +140,9 @@ class JssmViz extends LitElement {
|
|
|
102
140
|
}
|
|
103
141
|
/**
|
|
104
142
|
* Web Components lifecycle hook. Walks up to find a parent
|
|
105
|
-
* `<jssm-instance>` ancestor
|
|
106
|
-
* subscribes to the parent machine's
|
|
107
|
-
* leaves standalone behavior intact.
|
|
143
|
+
* `<fsl-instance>` or `<jssm-instance>` ancestor via `closest_wc`; if
|
|
144
|
+
* found, switches into nested mode and subscribes to the parent machine's
|
|
145
|
+
* `transition` events. Otherwise leaves standalone behavior intact.
|
|
108
146
|
*
|
|
109
147
|
* Subscription setup is deferred via `customElements.whenDefined` so the
|
|
110
148
|
* parent has had a chance to upgrade and construct its machine before
|
|
@@ -112,7 +150,7 @@ class JssmViz extends LitElement {
|
|
|
112
150
|
*/
|
|
113
151
|
connectedCallback() {
|
|
114
152
|
super.connectedCallback();
|
|
115
|
-
const host = this
|
|
153
|
+
const host = closest_wc(this, 'instance');
|
|
116
154
|
if (host === null) {
|
|
117
155
|
return; // standalone: existing behavior, willUpdate handles render
|
|
118
156
|
}
|
|
@@ -121,13 +159,13 @@ class JssmViz extends LitElement {
|
|
|
121
159
|
// owns the machine.
|
|
122
160
|
if (typeof this.fsl === 'string' && this.fsl.trim().length > 0) {
|
|
123
161
|
// eslint-disable-next-line no-console
|
|
124
|
-
console.warn('<
|
|
162
|
+
console.warn('<fsl-viz>: `fsl` ignored when nested inside <fsl-instance>; parent owns the machine');
|
|
125
163
|
}
|
|
126
164
|
this._parent_host = host;
|
|
127
165
|
// Defer to whenDefined so a not-yet-upgraded host has its machine
|
|
128
166
|
// available before we access `host.machine` (which throws when called
|
|
129
167
|
// pre-connection).
|
|
130
|
-
void customElements.whenDefined('
|
|
168
|
+
void customElements.whenDefined('fsl-instance').then(() => {
|
|
131
169
|
// Re-check the host is still attached and the viz still belongs to
|
|
132
170
|
// it — disconnection between the deferred resolution and now is
|
|
133
171
|
// legal and should not error.
|
|
@@ -242,7 +280,7 @@ class JssmViz extends LitElement {
|
|
|
242
280
|
return html `<div class="container">${unsafeHTML(this._svg)}</div>`;
|
|
243
281
|
}
|
|
244
282
|
}
|
|
245
|
-
|
|
283
|
+
FslViz.styles = css `
|
|
246
284
|
:host {
|
|
247
285
|
display: block;
|
|
248
286
|
min-height: var(--jssm-viz-min-height, 100px);
|
|
@@ -254,12 +292,12 @@ JssmViz.styles = css `
|
|
|
254
292
|
`;
|
|
255
293
|
__decorate([
|
|
256
294
|
property({ type: String })
|
|
257
|
-
],
|
|
295
|
+
], FslViz.prototype, "fsl", void 0);
|
|
258
296
|
__decorate([
|
|
259
297
|
property({ type: String })
|
|
260
|
-
],
|
|
298
|
+
], FslViz.prototype, "engine", void 0);
|
|
261
299
|
__decorate([
|
|
262
300
|
state()
|
|
263
|
-
],
|
|
301
|
+
], FslViz.prototype, "_svg", void 0);
|
|
264
302
|
|
|
265
|
-
export {
|
|
303
|
+
export { FslViz, normalize_viz_error };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jssm",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.142.0",
|
|
4
4
|
"engines": {
|
|
5
5
|
"node": ">=10.0.0"
|
|
6
6
|
},
|
|
@@ -143,7 +143,9 @@
|
|
|
143
143
|
"typescript": "tsc --build tsconfig.json",
|
|
144
144
|
"makever": "node src/buildjs/makever.cjs",
|
|
145
145
|
"make_doctests": "node src/buildjs/extract_examples.cjs",
|
|
146
|
+
"prep": "npm run makever && npm run peg",
|
|
146
147
|
"make": "npm run clean && npm run makever && npm run peg && npm run build:cem && npm run typescript && npm run make_doctests && npm run make_core && npm run make_deno && npm run make_viz && npm run make_wc_viz_es6 && npm run make_wc_viz_cdn && npm run make_wc_instance_es6 && npm run make_wc_instance_cdn && npm run typecheck_cli && npm run make_cli && npm run minify && npm run min_iife && npm run min_es6 && npm run min_cjs && npm run min_deno && npm run min_viz_iife && npm run min_viz_es6 && npm run min_viz_cjs && npm run min_cli && rm ./dist/es6/*.nonmin.js",
|
|
148
|
+
"make_ci": "npm run clean && npm run makever && npm run peg && npm run build:cem && npm run typescript && npm run make_doctests && npm run make_wc_viz_es6 && npm run make_wc_viz_cdn && npm run make_wc_instance_es6 && npm run make_wc_instance_cdn && npm run typecheck_cli && npm run make_cli",
|
|
147
149
|
"eslint": "eslint --color src/ts/jssm.ts src/ts/jssm_types.ts src/ts/tests/*.ts",
|
|
148
150
|
"audit": "text_audit -r -t major MAJOR wasteful WASTEFUL any mixed fixme FIXME checkme CHECKME testme TESTME stochable STOCHABLE todo TODO comeback COMEBACK whargarbl WHARGARBL -g ./src/ts/**/*.{js,ts}",
|
|
149
151
|
"vet": "npm run eslint && npm run audit",
|
|
@@ -156,6 +158,7 @@
|
|
|
156
158
|
"clean_bench": "npm run test && npm run benny",
|
|
157
159
|
"qbuild": "npm run test",
|
|
158
160
|
"ci_build": "npm run vet && npm run test",
|
|
161
|
+
"ci_test": "npm run vet && npm run make_ci && npm run vitest",
|
|
159
162
|
"minify": "mv dist/es6/fsl_parser.js dist/es6/fsl_parser.nonmin.js && terser dist/es6/fsl_parser.nonmin.js > dist/es6/fsl_parser.js",
|
|
160
163
|
"min_iife": "mv dist/jssm.es5.iife.js dist/jssm.es5.iife.nonmin.js && terser dist/jssm.es5.iife.nonmin.js > dist/jssm.es5.iife.js && cp dist/jssm.es5.iife.nonmin.js ./src/tools/",
|
|
161
164
|
"min_cjs": "mv dist/jssm.es5.cjs.js dist/jssm.es5.nonmin.cjs && terser dist/jssm.es5.nonmin.cjs > dist/jssm.es5.cjs",
|