@preschen/gen-vis 0.6.0 → 0.8.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 CHANGED
@@ -15,7 +15,7 @@ the styles, and provides two global functions:
15
15
  ```html
16
16
  <div class="genVis" data-def-file="/data/bev/def.json"></div>
17
17
 
18
- <script src="gen-vis-0.6.0.js"></script>
18
+ <script src="gen-vis-0.8.0.js"></script>
19
19
  <script>mountGenVisByClass('genVis')</script>
20
20
  ```
21
21
 
@@ -49,11 +49,32 @@ well.
49
49
  | `def` | `data-def` | the definition, an object or a JSON string |
50
50
  | `data` | `data-data` | the data as rows or a CSV/JSON string, if not given it is loaded from the `data` url of the definition |
51
51
  | `debug` | `data-debug` | shows the prepared definition |
52
+ | `state` | | the changes of the user, see [state](#state) |
52
53
 
53
54
  Every visualisation has its own state, several of them can be used on a page.
54
55
  If the props change, the visualisation is loaded again. Errors are shown in
55
56
  place of the visualisation.
56
57
 
58
+ ### State
59
+
60
+ The state holds what the user changed compared to the definition: the
61
+ globals of the form elements and the entries of the legends shown or hidden.
62
+
63
+ ```json
64
+ { "globals": { "column": "share" }, "visible": { "year": { "2019": true, "2022": false } } }
65
+ ```
66
+
67
+ The component emits `update:state` on every change of the user, so with
68
+ `v-model:state` the page can keep it, e.g. in the local storage. A given state
69
+ is applied when the visualisation is loaded, a new one (`null` for the
70
+ definition) is applied without loading it again. Globals, values and entries
71
+ the definition does not have (anymore) are ignored, new entries of the
72
+ definition keep their defaults.
73
+
74
+ ```html
75
+ <GenVis def-file="/data/bev/def.json" v-model:state="state"/>
76
+ ```
77
+
57
78
  ### Styles
58
79
 
59
80
  The styles of the package are in the cascade layer `gen-vis`, so every style
@@ -92,6 +113,19 @@ its `parent` (and its parent into its own parent), arrays are replaced, not
92
113
  merged. The merged definition is checked for common mistakes, e.g. unknown
93
114
  plot types, the findings are logged as warnings in the console.
94
115
 
116
+ `parent` can also be a list of definitions (mixins), merged in their order,
117
+ later ones override earlier ones, e.g. a chart type and a form element:
118
+
119
+ ```json
120
+ {
121
+ "parent": ["../shared/years.json", "../shared/scale-switch.json"],
122
+ "data": "data.csv"
123
+ }
124
+ ```
125
+
126
+ A parent shared by several mixins is merged once, before the first mixin
127
+ using it, so it does not override the mixins in between.
128
+
95
129
  The package contains a JSON Schema of the definitions, `schema.json`. With
96
130
  `"$schema"` in a definition, editors like VS Code complete and check it:
97
131
 
package/dist/gen-vis.js CHANGED
@@ -1,4 +1,4 @@
1
- (() => { const s = document.createElement("style"); s.textContent = "@layer gen-vis {\n.hover[data-v-364032d4]{font-size:13px;position:absolute;top:0}.hover .title[data-v-364032d4]{text-align:center;border-bottom:2px solid #000;padding:1px 3px;font-weight:700}.hover[data-v-364032d4]{background-color:#fffc;top:40%}.hover[data-v-364032d4] table{border-collapse:collapse}.hover[data-v-364032d4] table tr.nearest{font-weight:700}.hover[data-v-364032d4] table tr td{text-align:left;padding:1px 5px}.hover[data-v-364032d4] table tr td.value,.hover[data-v-364032d4] table tr td.y{text-align:right}.hover[data-v-364032d4] table tr td:first-child{border-left:0}.hover[data-v-364032d4] table{margin-left:auto;margin-right:auto}.hover[data-v-364032d4]{pointer-events:none}.vis-inner[data-v-1f05a06e]{display:inline-block;position:relative}.vis-inner .debug[data-v-1f05a06e]{font-size:12px}.vis-inner[data-v-1f05a06e] svg g.axis-position-top g.tick line{transform:translateY(5px)}.vis-inner[data-v-1f05a06e] svg g.axis-position-right g.tick line{transform:translate(-4px)}.vis-inner[data-v-1f05a06e] svg g.axis-position-bottom g.tick line{transform:translateY(-4px)}.vis-inner[data-v-1f05a06e] svg g.axis-position-left g.tick line{transform:translate(5px)}.vis-inner[data-v-1f05a06e] svg g.tick text,.vis-inner[data-v-1f05a06e] svg .axis-title{font-size:13px}.vis-inner[data-v-1f05a06e] svg g.group[data-visible=false],.vis-inner[data-v-1f05a06e] svg path[data-visible=false]{opacity:.01}.vis-inner[data-v-1f05a06e] svg g.grid{stroke:#ccc;stroke-width:.75px}.vis-inner[data-v-1f05a06e] svg g.hoverMarker line{stroke-width:.75px;stroke:#aaa}svg[data-v-ce0e972e]{margin-right:5px;display:inline-block}.legend .title[data-v-1bc8d55f]{margin:3px;font-size:13px;font-weight:700;position:relative}.legend .entries>div[data-v-1bc8d55f]{cursor:pointer;margin:0 5px;display:inline-block}.legend .entries>div[data-visible=false][data-v-1bc8d55f]{opacity:.3}.legend .entries>div span[data-v-1bc8d55f]{font-size:13px;display:inline-block;position:relative;top:-4px}.legend .entries>div.bold[data-v-1bc8d55f]{font-weight:700}.formElement[data-v-ec3facd5]{margin:2px 16px 2px 4px;font-size:13px;display:inline-block}.formElement .title[data-v-ec3facd5]{margin-right:5px;font-weight:700;display:inline-block}.formElement .entries[data-v-ec3facd5]{display:inline-block}.formElement .entries>div[data-v-ec3facd5]{margin-right:5px;display:inline-block}.formElement .entries>div input[data-v-ec3facd5]{display:inline-block;position:relative;top:1px}.vis[data-v-b07c17d2] text,.vis[data-v-b07c17d2] span,.vis[data-v-b07c17d2] div{font-family:var(--gen-vis-font-family,Century Gothic, sans-serif)}.vis-header .title[data-v-b07c17d2]{font-size:22px;font-weight:700}.vis-header .subtitle[data-v-b07c17d2]{margin-top:3px;font-size:13px}.vis-header[data-v-b07c17d2]{margin-bottom:10px}.vis-footer span[data-v-b07c17d2]{font-size:13px}.facet-title[data-v-b07c17d2]{margin-top:8px;font-size:13px;font-weight:700}.vis-error[data-v-a9d47434]{color:#b00;font-size:13px}\n/*$vite$:1*/\n}"; document.head.appendChild(s); })();
1
+ (() => { const s = document.createElement("style"); s.textContent = "@layer gen-vis {\n.hover[data-v-364032d4]{font-size:13px;position:absolute;top:0}.hover .title[data-v-364032d4]{text-align:center;border-bottom:2px solid #000;padding:1px 3px;font-weight:700}.hover[data-v-364032d4]{background-color:#fffc;top:40%}.hover[data-v-364032d4] table{border-collapse:collapse}.hover[data-v-364032d4] table tr.nearest{font-weight:700}.hover[data-v-364032d4] table tr td{text-align:left;padding:1px 5px}.hover[data-v-364032d4] table tr td.value,.hover[data-v-364032d4] table tr td.y{text-align:right}.hover[data-v-364032d4] table tr td:first-child{border-left:0}.hover[data-v-364032d4] table{margin-left:auto;margin-right:auto}.hover[data-v-364032d4]{pointer-events:none}.vis-inner[data-v-1f05a06e]{display:inline-block;position:relative}.vis-inner .debug[data-v-1f05a06e]{font-size:12px}.vis-inner[data-v-1f05a06e] svg g.axis-position-top g.tick line{transform:translateY(5px)}.vis-inner[data-v-1f05a06e] svg g.axis-position-right g.tick line{transform:translate(-4px)}.vis-inner[data-v-1f05a06e] svg g.axis-position-bottom g.tick line{transform:translateY(-4px)}.vis-inner[data-v-1f05a06e] svg g.axis-position-left g.tick line{transform:translate(5px)}.vis-inner[data-v-1f05a06e] svg g.tick text,.vis-inner[data-v-1f05a06e] svg .axis-title{font-size:13px}.vis-inner[data-v-1f05a06e] svg g.group[data-visible=false],.vis-inner[data-v-1f05a06e] svg path[data-visible=false]{opacity:.01}.vis-inner[data-v-1f05a06e] svg g.grid{stroke:#ccc;stroke-width:.75px}.vis-inner[data-v-1f05a06e] svg g.hoverMarker line{stroke-width:.75px;stroke:#aaa}svg[data-v-ce0e972e]{margin-right:5px;display:inline-block}.legend .title[data-v-1bc8d55f]{margin:3px;font-size:13px;font-weight:700;position:relative}.legend .entries>div[data-v-1bc8d55f]{cursor:pointer;margin:0 5px;display:inline-block}.legend .entries>div[data-visible=false][data-v-1bc8d55f]{opacity:.3}.legend .entries>div span[data-v-1bc8d55f]{font-size:13px;display:inline-block;position:relative;top:-4px}.legend .entries>div.bold[data-v-1bc8d55f]{font-weight:700}.formElement[data-v-acf88417]{margin:2px 16px 2px 4px;font-size:13px;display:inline-block}.formElement .title[data-v-acf88417]{margin-right:5px;font-weight:700;display:inline-block}.formElement .entries[data-v-acf88417]{display:inline-block}.formElement .entries>div[data-v-acf88417]{margin-right:5px;display:inline-block}.formElement .entries>div input[data-v-acf88417]{display:inline-block;position:relative;top:1px}.vis[data-v-d870f406] text,.vis[data-v-d870f406] span,.vis[data-v-d870f406] div{font-family:var(--gen-vis-font-family,Century Gothic, sans-serif)}.vis-header .title[data-v-d870f406]{font-size:22px;font-weight:700}.vis-header .subtitle[data-v-d870f406]{margin-top:3px;font-size:13px}.vis-header[data-v-d870f406]{margin-bottom:10px}.vis-footer span[data-v-d870f406]{font-size:13px}.facet-title[data-v-d870f406]{margin-top:8px;font-size:13px;font-weight:700}.vis-error[data-v-7b1c318b]{color:#b00;font-size:13px}\n/*$vite$:1*/\n}"; document.head.appendChild(s); })();
2
2
  import { Fragment as e, createApp as t, createBlock as n, createCommentVNode as r, createElementBlock as i, createElementVNode as a, markRaw as o, mergeProps as s, normalizeStyle as c, openBlock as l, reactive as u, renderList as d, resolveComponent as f, toDisplayString as p, toRaw as ee } from "vue";
3
3
  import * as m from "d3";
4
4
  import h from "deepmerge";
@@ -86,8 +86,8 @@ var g = (e) => typeof e == "string" ? (e = e.replace(/^/, ""), /^\s*\[/.test(
86
86
  }
87
87
  }
88
88
  return n ? e.value : e;
89
- }, w = (e, t) => le({ ...k(e) }, t, !0), T = (e, t, n = !0) => E(se(e, k), t, n), E = (e, t, n = !1) => se(e, (e) => le({ ...e }, t, n)), D = (e) => e.prop !== void 0, O = (e) => Object.values(e).flatMap((e) => typeof e != "object" || !e ? [] : D(e) ? typeof e.ref == "string" ? [e.ref.split(":")[0]] : [] : O(e)), k = (e) => {
90
- if (typeof e == "object" && !Array.isArray(e) && e !== null) return D(e) ? e : C(e, k);
89
+ }, w = (e, t) => le({ ...O(e) }, t, !0), T = (e, t, n = !0) => E(se(e, O), t, n), E = (e, t, n = !1) => se(e, (e) => le({ ...e }, t, n)), D = (e) => e.prop !== void 0, ue = (e) => Object.values(e).flatMap((e) => typeof e != "object" || !e ? [] : D(e) ? typeof e.ref == "string" ? [e.ref.split(":")[0]] : [] : ue(e)), O = (e) => {
90
+ if (typeof e == "object" && !Array.isArray(e) && e !== null) return D(e) ? e : C(e, O);
91
91
  if (typeof e == "string" && e.charAt() == "@") {
92
92
  let t = e.substring(1);
93
93
  return {
@@ -100,7 +100,7 @@ var g = (e) => typeof e == "string" ? (e = e.replace(/^/, ""), /^\s*\[/.test(
100
100
  prop: "fixed",
101
101
  value: e
102
102
  };
103
- }, A = (e) => {
103
+ }, k = (e) => {
104
104
  if (e.props) {
105
105
  let t = e.props;
106
106
  e.props = Object.fromEntries(Object.keys(t.manual).map((e) => {
@@ -109,21 +109,21 @@ var g = (e) => typeof e == "string" ? (e = e.replace(/^/, ""), /^\s*\[/.test(
109
109
  }));
110
110
  }
111
111
  return e.scale && (e.scale.type ??= "linear", e.scale.domain ??= [null, null], e.scale.domainAbs || (e.scale.domainRel ??= e.scale.domain.map((e, t) => e === null ? (t == 0 ? -1 : 1) * .02 : 0)), e.scale.domainAbs ??= [0, 0], Array.isArray(e.scale.range) || (e.scale.orientation == "horizontal" ? e.scale.range = [0, "@width"] : e.scale.orientation == "vertical" && (e.scale.range = ["@height", 0]))), e.axis && (e.axis.padding ??= 3), e.hover !== void 0 && e.axis !== void 0 && (e.hover.format ??= e.axis.format), e.legend && (e.legend.props === void 0 && (e.legend.props = {}), "name" in e.legend.props || (e.legend.props.name = "@name")), e.hover && (e.hover.props === void 0 && (e.hover.props = {}), "name" in e.hover.props || (e.hover.props.name = "@name")), e;
112
- }, ue = (e) => (Object.values(e.mapping).forEach(A), Array.isArray(e.plot) || (e.plot = [e.plot]), e.facets && Array.isArray(e.facets.dim) && (e.facets.dim = e.facets.dim[0]), e.plot.forEach((e, t) => {
112
+ }, de = (e) => (Object.values(e.mapping).forEach(k), Array.isArray(e.plot) || (e.plot = [e.plot]), e.facets && Array.isArray(e.facets.dim) && (e.facets.dim = e.facets.dim[0]), e.plot.forEach((e, t) => {
113
113
  e.categories ??= [], e.id ??= `plot-${t}`, e.highlightProps = Object.keys(e.props).filter((e) => e.startsWith("highlight-")).map((e) => e.substring(10));
114
114
  }), e.plot.forEach((e) => {
115
- e.props = C(e.props, k), e._fill = (t) => E(e.props, t);
116
- }), e), j = (e) => typeof e == "string" ? [...e.matchAll(/\{(\w+)\}/g)].map((e) => e[1]) : [], de = (e, t = {}) => e.replace(/\{(\w+)\}/g, (e, n) => n in t ? String(t[n]) : e), M = (e, t) => {
117
- let n = e.formElements ?? [], r = /* @__PURE__ */ new Set([...n.flatMap((e) => e.values.flatMap((e) => Object.keys(e.mapping ?? {}))), ...Object.keys(t.mapping ?? {}).filter((e) => j(t.mapping[e].column).length > 0)]);
115
+ e.props = C(e.props, O), e._fill = (t) => E(e.props, t);
116
+ }), e), A = (e) => typeof e == "string" ? [...e.matchAll(/\{(\w+)\}/g)].map((e) => e[1]) : [], fe = (e, t = {}) => e.replace(/\{(\w+)\}/g, (e, n) => n in t ? String(t[n]) : e), j = (e, t) => {
117
+ let n = e.formElements ?? [], r = /* @__PURE__ */ new Set([...n.flatMap((e) => e.values.flatMap((e) => Object.keys(e.mapping ?? {}))), ...Object.keys(t.mapping ?? {}).filter((e) => A(t.mapping[e].column).length > 0)]);
118
118
  if (r.size == 0) return !1;
119
119
  let i = n.map((t) => t.values.find((n) => S(n.value, e.globals?.[t.ref]))).filter((e) => e && e.mapping);
120
120
  return r.forEach((n) => {
121
121
  let r = i.filter((e) => e.mapping[n]).map((e) => e.mapping[n]), a = x([t.mapping[n] ?? {}, ...r]);
122
- typeof a.column == "string" && (a.column = de(a.column, e.globals));
123
- let o = A(a);
122
+ typeof a.column == "string" && (a.column = fe(a.column, e.globals));
123
+ let o = k(a);
124
124
  e.mapping[n] && "props" in e.mapping[n] && (o.props = e.mapping[n].props), e.mapping[n] = o;
125
125
  }), !0;
126
- }, N = (e) => e.charAt(0).toUpperCase() + e.slice(1), P = {
126
+ }, M = (e) => e.charAt(0).toUpperCase() + e.slice(1), N = {
127
127
  de: {
128
128
  number: {
129
129
  decimal: ",",
@@ -264,7 +264,7 @@ var g = (e) => typeof e == "string" ? (e = e.replace(/^/, ""), /^\s*\[/.test(
264
264
  year: "%Y"
265
265
  }
266
266
  }
267
- }, fe = Object.keys(P), F = {
267
+ }, pe = Object.keys(N), P = {
268
268
  time: [
269
269
  m.timeSecond,
270
270
  m.timeMinute,
@@ -283,12 +283,12 @@ var g = (e) => typeof e == "string" ? (e = e.replace(/^/, ""), /^\s*\[/.test(
283
283
  m.utcMonth,
284
284
  m.utcYear
285
285
  ]
286
- }, I = (e, t, n) => {
286
+ }, F = (e, t, n) => {
287
287
  let r = Object.fromEntries(Object.entries(t).map(([t, n]) => [t, e(n)])), [i, a, o, s, c, l, u] = n;
288
288
  return (e) => (i(e) < e ? r.millisecond : a(e) < e ? r.second : o(e) < e ? r.minute : s(e) < e ? r.hour : l(e) < e ? c(e) < e ? r.day : r.week : u(e) < e ? r.month : r.year)(e);
289
- }, pe = (e = "de") => {
290
- let t = typeof e == "string" ? { base: e } : e, n = P[t.base ?? "de"];
291
- if (!n) throw Error(`Unknown locale '${t.base}', expected one of ${fe.map((e) => `'${e}'`).join(", ")}`);
289
+ }, me = (e = "de") => {
290
+ let t = typeof e == "string" ? { base: e } : e, n = N[t.base ?? "de"];
291
+ if (!n) throw Error(`Unknown locale '${t.base}', expected one of ${pe.map((e) => `'${e}'`).join(", ")}`);
292
292
  let r = m.formatLocale({
293
293
  ...n.number,
294
294
  ...t.number
@@ -311,10 +311,10 @@ var g = (e) => typeof e == "string" ? (e = e.replace(/^/, ""), /^\s*\[/.test(
311
311
  let [t, i] = e.domain(), a = m.precisionFixed(m.tickStep(t, i, n));
312
312
  return r.format(`,.${Number.isFinite(a) ? a : 0}f`);
313
313
  }
314
- return t == "time" ? I(i.format, a, F.time) : t == "utc" ? I(i.utcFormat, a, F.utc) : null;
314
+ return t == "time" ? F(i.format, a, P.time) : t == "utc" ? F(i.utcFormat, a, P.utc) : null;
315
315
  }
316
316
  };
317
- }, L = [
317
+ }, I = [
318
318
  "svg:path",
319
319
  "svg:circle",
320
320
  "svg:line",
@@ -323,24 +323,24 @@ var g = (e) => typeof e == "string" ? (e = e.replace(/^/, ""), /^\s*\[/.test(
323
323
  "base:area",
324
324
  "bar",
325
325
  "stackedBar"
326
- ], R = [
326
+ ], L = [
327
327
  "numeric",
328
328
  "date",
329
329
  "categorical"
330
- ], z = ["horizontal", "vertical"], B = [
330
+ ], R = ["horizontal", "vertical"], z = [
331
331
  "top",
332
332
  "bottom",
333
333
  "left",
334
334
  "right"
335
- ], V = [
335
+ ], B = [
336
336
  "fixed",
337
337
  "ref",
338
338
  "relative",
339
339
  "steps"
340
- ], H = (e) => e.map((e) => `'${e}'`).join(", "), U = (e, t, n) => {
340
+ ], V = (e) => e.map((e) => `'${e}'`).join(", "), H = (e, t, n) => {
341
341
  if (typeof e != "object" || !e || Array.isArray(e)) return;
342
342
  if ("prop" in e) {
343
- V.includes(e.prop) ? e.prop != "fixed" && typeof e.ref != "string" && n(t, `a '${e.prop}' prop needs a 'ref'`) : n(t, `unknown prop '${e.prop}', expected one of ${H(V)}`);
343
+ B.includes(e.prop) ? e.prop != "fixed" && typeof e.ref != "string" && n(t, `a '${e.prop}' prop needs a 'ref'`) : n(t, `unknown prop '${e.prop}', expected one of ${V(B)}`);
344
344
  return;
345
345
  }
346
346
  let r = [
@@ -349,77 +349,104 @@ var g = (e) => typeof e == "string" ? (e = e.replace(/^/, ""), /^\s*\[/.test(
349
349
  "ref",
350
350
  "mode"
351
351
  ].filter((t) => t in e);
352
- if (r.length > 0) return n(t, `has ${H(r)} but no 'prop', so it is not evaluated`);
353
- Object.entries(e).forEach(([e, r]) => U(r, `${t}.${e}`, n));
354
- }, me = (e) => {
352
+ if (r.length > 0) return n(t, `has ${V(r)} but no 'prop', so it is not evaluated`);
353
+ Object.entries(e).forEach(([e, r]) => H(r, `${t}.${e}`, n));
354
+ }, he = (e) => {
355
355
  let t = [], n = (e, n) => t.push(`${e}: ${n}`), r = e.mapping ?? {};
356
356
  e.mapping || n("mapping", "missing"), Object.entries(r).forEach(([e, t]) => {
357
357
  let r = `mapping.${e}`;
358
- if (typeof t.column != "string" && n(r, "no 'column'"), t.type !== void 0 && !R.includes(t.type) && n(`${r}.type`, `unknown type '${t.type}', expected one of ${H(R)}`), t.props && !t.props.manual && n(`${r}.props`, "expected 'manual' (and optional 'common') entries"), t.scale) {
359
- let e = t.scale.type ?? "linear", i = m[`scale${N(e)}`];
360
- typeof i == "function" ? typeof i().ticks == "function" != ["numeric", "date"].includes(t.type) && n(`${r}.scale.type`, `a ${e} scale does not fit the type '${t.type}'`) : n(`${r}.scale.type`, `unknown d3 scale '${e}'`), t.scale.orientation !== void 0 && !z.includes(t.scale.orientation) && n(`${r}.scale.orientation`, `unknown orientation '${t.scale.orientation}', expected one of ${H(z)}`);
358
+ if (typeof t.column != "string" && n(r, "no 'column'"), t.type !== void 0 && !L.includes(t.type) && n(`${r}.type`, `unknown type '${t.type}', expected one of ${V(L)}`), t.props && !t.props.manual && n(`${r}.props`, "expected 'manual' (and optional 'common') entries"), t.scale) {
359
+ let e = t.scale.type ?? "linear", i = m[`scale${M(e)}`];
360
+ typeof i == "function" ? typeof i().ticks == "function" != ["numeric", "date"].includes(t.type) && n(`${r}.scale.type`, `a ${e} scale does not fit the type '${t.type}'`) : n(`${r}.scale.type`, `unknown d3 scale '${e}'`), t.scale.orientation !== void 0 && !R.includes(t.scale.orientation) && n(`${r}.scale.orientation`, `unknown orientation '${t.scale.orientation}', expected one of ${V(R)}`);
361
361
  }
362
- t.axis && (t.scale || n(`${r}.axis`, "an axis needs a 'scale'"), B.includes(t.axis.position) || n(`${r}.axis.position`, `unknown position '${t.axis.position}', expected one of ${H(B)}`), U(t.axis.ticks, `${r}.axis.ticks`, n));
362
+ t.axis && (t.scale || n(`${r}.axis`, "an axis needs a 'scale'"), z.includes(t.axis.position) || n(`${r}.axis.position`, `unknown position '${t.axis.position}', expected one of ${V(z)}`), H(t.axis.ticks, `${r}.axis.ticks`, n));
363
363
  });
364
364
  let i = [].concat(e.plot ?? []);
365
365
  if (i.length == 0 && n("plot", "missing"), i.forEach((e, t) => {
366
366
  let i = `plot[${t}]`;
367
- L.includes(e.type) || n(`${i}.type`, `unknown type '${e.type}', expected one of ${H(L)}`), (e.categories ?? []).filter((e) => !(e in r)).forEach((e) => n(`${i}.categories`, `unknown mapping '${e}'`)), U(e.props, `${i}.props`, n);
367
+ I.includes(e.type) || n(`${i}.type`, `unknown type '${e.type}', expected one of ${V(I)}`), (e.categories ?? []).filter((e) => !(e in r)).forEach((e) => n(`${i}.categories`, `unknown mapping '${e}'`)), H(e.props, `${i}.props`, n);
368
368
  }), e.facets) {
369
369
  let t = [].concat(e.facets.dim ?? []);
370
370
  t.length != 1 && n("facets.dim", "expected the name of one mapping"), t.filter((e) => !(e in r)).forEach((e) => n("facets.dim", `unknown mapping '${e}'`));
371
371
  }
372
- let a = (t, r) => j(t).filter((t) => !(t in (e.globals ?? {}))).forEach((e) => n(r, `unknown global '${e}' in the column template`));
373
- return Object.entries(r).forEach(([e, t]) => a(t.column, `mapping.${e}.column`)), (e.formElements ?? []).forEach((e, t) => (e.values ?? []).forEach((e, n) => Object.entries(e.mapping ?? {}).forEach(([e, r]) => a(r.column, `formElements[${t}].values[${n}].mapping.${e}.column`)))), U(e.options?.height, "options.height", n), U(e.facets?.cols, "facets.cols", n), t;
374
- }, W = (e, t = document.baseURI) => new URL(e, t).href, G = async (e) => {
372
+ let a = (t, r) => A(t).filter((t) => !(t in (e.globals ?? {}))).forEach((e) => n(r, `unknown global '${e}' in the column template`));
373
+ return Object.entries(r).forEach(([e, t]) => a(t.column, `mapping.${e}.column`)), (e.formElements ?? []).forEach((e, t) => (e.values ?? []).forEach((e, n) => Object.entries(e.mapping ?? {}).forEach(([e, r]) => a(r.column, `formElements[${t}].values[${n}].mapping.${e}.column`)))), H(e.options?.height, "options.height", n), H(e.facets?.cols, "facets.cols", n), t;
374
+ }, U = (e) => ({
375
+ globals: Object.fromEntries((e.formElements ?? []).map((t) => [t.ref, e.globals?.[t.ref]])),
376
+ visible: Object.fromEntries(Object.entries(e.mapping).filter(([e, t]) => t.legend && t.props).map(([e, t]) => [e, Object.fromEntries(Object.entries(t.props).map(([e, t]) => [e, t.visible]))]))
377
+ }), ge = (e, t) => {
378
+ let n = {}, r = Object.fromEntries(Object.entries(e.globals).filter(([e, n]) => !S(n, t.globals[e])));
379
+ Object.keys(r).length > 0 && (n.globals = r);
380
+ let i = Object.fromEntries(Object.entries(e.visible).map(([e, n]) => [e, Object.fromEntries(Object.entries(n).filter(([n, r]) => r != t.visible[e]?.[n]))]).filter(([e, t]) => Object.keys(t).length > 0));
381
+ return Object.keys(i).length > 0 && (n.visible = i), n;
382
+ }, W = (e, t) => {
383
+ Object.entries(t?.globals ?? {}).forEach(([t, n]) => {
384
+ let r = (e.formElements ?? []).filter((e) => e.ref == t).flatMap((e) => e.values).find((e) => S(e.value, n));
385
+ r && e.globals && (e.globals[t] = r.value);
386
+ }), Object.entries(t?.visible ?? {}).forEach(([t, n]) => {
387
+ let r = e.mapping[t];
388
+ r?.legend && r.props && Object.entries(n).forEach(([e, t]) => {
389
+ e in r.props && (r.props[e].visible = !!t);
390
+ });
391
+ });
392
+ }, G = (e, t = document.baseURI) => new URL(e, t).href, K = async (e) => {
375
393
  try {
376
394
  return await m.text(e);
377
395
  } catch (t) {
378
396
  throw Error(`Could not load '${e}': ${t.message}`);
379
397
  }
380
- }, K = (e, t) => {
398
+ }, q = (e, t) => {
381
399
  try {
382
400
  return JSON.parse(e);
383
401
  } catch (e) {
384
402
  throw Error(`Invalid JSON in definition ${t}: ${e.message}`);
385
403
  }
386
- }, he = async (e, t, n = G) => {
387
- let r = [e], i = /* @__PURE__ */ new Set();
388
- for (; e.parent;) {
389
- if (t = W(e.parent, t), i.has(t)) throw Error(`Cyclic parent definition '${t}'`);
390
- i.add(t), e = K(await n(t), `'${t}'`), r.unshift(e);
391
- }
392
- return x(r);
393
- }, q = (e) => o(Array.from(ee(e))), ge = async ({ def: e = null, defUrl: t = null, data: n = null }) => {
394
- let r;
395
- e === null ? (r = W(t), e = K(await G(r), `'${r}'`)) : typeof e == "string" && (e = K(e, "attribute"));
396
- let i = await he(JSON.parse(JSON.stringify(e)), r);
397
- me(i).forEach((e) => console.warn(`gen-vis ${r ?? "inline definition"}: ${e}`));
398
- let a = ue(JSON.parse(JSON.stringify(i)));
399
- if (M(a, i), n === null) {
400
- if (!i.data) throw Error("No data given, neither in the definition nor as attribute.");
401
- n = await G(W(i.data, r));
404
+ }, _e = async (e, t, n = K) => {
405
+ let r = [], i = /* @__PURE__ */ new Set(), a = async (e, t, o) => {
406
+ for (let r of [e.parent ?? []].flat()) {
407
+ let e = G(r, t);
408
+ if (o.includes(e)) throw Error(`Cyclic parent definition '${e}'`);
409
+ i.has(e) || (i.add(e), await a(q(await n(e), `'${e}'`), e, [...o, e]));
410
+ }
411
+ r.push(e);
412
+ };
413
+ return await a(e, t, []), x(r);
414
+ }, J = (e) => o(Array.from(ee(e))), ve = async ({ def: e = null, defUrl: t = null, data: n = null, state: r = null }) => {
415
+ let i;
416
+ e === null ? (i = G(t), e = q(await K(i), `'${i}'`)) : typeof e == "string" && (e = q(e, "attribute"));
417
+ let a = await _e(JSON.parse(JSON.stringify(e)), i);
418
+ he(a).forEach((e) => console.warn(`gen-vis ${i ?? "inline definition"}: ${e}`));
419
+ let s = de(JSON.parse(JSON.stringify(a))), c = U(s);
420
+ if (W(s, r), j(s, a), n === null) {
421
+ if (!a.data) throw Error("No data given, neither in the definition nor as attribute.");
422
+ n = await K(G(a.data, i));
402
423
  }
403
- let s = q(g(n));
424
+ let l = J(g(n));
404
425
  return {
405
- defUrl: r ?? null,
406
- defOrg: i,
407
- locale: o(pe(i.options?.locale)),
408
- rows: s,
409
- def: a,
410
- data: q(ne(s, a))
426
+ defUrl: i ?? null,
427
+ defOrg: a,
428
+ locale: o(me(a.options?.locale)),
429
+ rows: l,
430
+ def: s,
431
+ defaults: c,
432
+ data: J(ne(l, s))
411
433
  };
412
- }, _e = class {
434
+ }, ye = class {
413
435
  defUrl = null;
414
436
  defOrg = null;
415
437
  locale = null;
416
438
  def = null;
417
439
  rows = null;
418
440
  data = null;
441
+ defaults = null;
419
442
  runs = 0;
443
+ stateSets = 0;
420
444
  get loaded() {
421
445
  return this.def !== null && this.data !== null;
422
446
  }
447
+ get state() {
448
+ return this.loaded ? ge(U(this.def), this.defaults) : null;
449
+ }
423
450
  get axis() {
424
451
  let e = {};
425
452
  return this.mappingNamesWithKey("scale").forEach((t) => {
@@ -443,17 +470,20 @@ var g = (e) => typeof e == "string" ? (e = e.replace(/^/, ""), /^\s*\[/.test(
443
470
  let t = ++this.runs;
444
471
  this.def = this.data = null;
445
472
  try {
446
- let n = await ge(e);
473
+ let n = await ve(e);
447
474
  t == this.runs && Object.assign(this, n);
448
475
  } catch (e) {
449
476
  if (t == this.runs) throw e;
450
477
  }
451
478
  }
452
479
  applyFormElements() {
453
- M(this.def, this.defOrg) && (this.data = q(ne(this.rows, this.def)));
480
+ j(this.def, this.defOrg) && (this.data = J(ne(this.rows, this.def)));
454
481
  }
455
- }, ve = () => u(new _e()), J = (e, t) => {
456
- let n = e.mapping.scale, r = m[`scale${N(n.type)}`]();
482
+ setState(e) {
483
+ W(this.def, this.defaults), W(this.def, e), this.applyFormElements(), this.stateSets++;
484
+ }
485
+ }, be = () => u(new ye()), xe = (e, t) => {
486
+ let n = e.mapping.scale, r = m[`scale${M(n.type)}`]();
457
487
  if (r.range(T(n.range, t)), e.extent) {
458
488
  e.domain = [...n.domain], e.domainRel = [...n.domainRel ? n.domainRel : [0, 0]], e.domainAbs = n.domainAbs, e.domain[0] ??= e.extent[0], e.domain[1] ??= e.extent[1];
459
489
  let t = e.domain[1] - e.domain[0];
@@ -476,14 +506,14 @@ var g = (e) => typeof e == "string" ? (e = e.replace(/^/, ""), /^\s*\[/.test(
476
506
  }
477
507
  t.attr(e, n);
478
508
  });
479
- }, ye = function(e) {
509
+ }, X = function(e) {
480
510
  let t = m.select(this);
481
511
  e.group.forEach((e) => {
482
512
  t.attr(`data-group-${e.dim}`, e.key);
483
513
  }), e.group.forEach((e) => {
484
514
  t.attr(`data-visible-${e.dim}`, e.visible);
485
515
  }), t.attr("data-visible", e.group.reduce((e, t) => e && t.visible, !0));
486
- }, be = (e, t, n) => {
516
+ }, Se = (e, t, n) => {
487
517
  let r = t.categories.filter((e) => e in n).map((e) => ({
488
518
  attr: `data-group-${e}`,
489
519
  value: String(n[e])
@@ -491,13 +521,13 @@ var g = (e) => typeof e == "string" ? (e = e.replace(/^/, ""), /^\s*\[/.test(
491
521
  return r.length == 0 ? null : e.selectAll(`g.plotGroup.${t.id} [${r[0].attr}]`).filter(function() {
492
522
  return r.every((e) => this.getAttribute(e.attr) === e.value);
493
523
  });
494
- }, X = (e, t, n = null) => {
524
+ }, Z = (e, t, n = null) => {
495
525
  t.filter((e) => e.highlightProps.length > 0).forEach((t) => {
496
526
  e.selectAll(`g.plotGroup.${t.id} .highlight`).classed("highlight", !1).each(function() {
497
527
  let e = m.select(this);
498
528
  t.highlightProps.forEach((t) => e.attr(t, e.attr(`default-${t}`)));
499
529
  });
500
- let r = n && be(e, t, n);
530
+ let r = n && Se(e, t, n);
501
531
  r && r.classed("highlight", !0).raise().each(function() {
502
532
  let e = m.select(this);
503
533
  t.highlightProps.forEach((t) => {
@@ -505,11 +535,11 @@ var g = (e) => typeof e == "string" ? (e = e.replace(/^/, ""), /^\s*\[/.test(
505
535
  });
506
536
  });
507
537
  });
508
- }, Z = (e, t) => {
538
+ }, Q = (e, t) => {
509
539
  let n = e.__vccOpts || e;
510
540
  for (let [e, r] of t) n[e] = r;
511
541
  return n;
512
- }, xe = {
542
+ }, Ce = {
513
543
  props: [
514
544
  "title",
515
545
  "axis",
@@ -534,11 +564,11 @@ var g = (e) => typeof e == "string" ? (e = e.replace(/^/, ""), /^\s*\[/.test(
534
564
  let e = [...this.data].sort((e, t) => t.entries[this.axis.v.col].value - e.entries[this.axis.v.col].value), t = m.select(this.$refs.entries).selectAll("tr.entry").data(e).join("tr").attr("class", "entry").classed("nearest", (e) => e.nearest);
535
565
  t.selectAll("td").remove(), t.selectAll("td").data((e) => Object.entries(e.entries)).join("td").attr("class", (e) => e[0]).html((e) => typeof e[1] == "object" ? e[1].name : e[1]);
536
566
  } }
537
- }, Se = { class: "title" }, Ce = {
567
+ }, we = { class: "title" }, Te = {
538
568
  class: "entries",
539
569
  ref: "entries"
540
570
  };
541
- function we(e, t, n, o, s, u) {
571
+ function Ee(e, t, n, o, s, u) {
542
572
  return n.axis && n.axis.h ? (l(), i("div", {
543
573
  key: 0,
544
574
  class: "hover",
@@ -547,9 +577,9 @@ function we(e, t, n, o, s, u) {
547
577
  left: u.left,
548
578
  transform: u.transform
549
579
  })
550
- }, [a("div", Se, p(n.axis.h.name), 1), a("table", Ce, null, 512)], 4)) : r("", !0);
580
+ }, [a("div", we, p(n.axis.h.name), 1), a("table", Te, null, 512)], 4)) : r("", !0);
551
581
  }
552
- var Te = /*#__PURE__*/ Z(xe, [["render", we], ["__scopeId", "data-v-364032d4"]]), Ee = (...e) => e.every((e) => Number.isFinite(e)), De = {
582
+ var De = /*#__PURE__*/ Q(Ce, [["render", Ee], ["__scopeId", "data-v-364032d4"]]), Oe = (...e) => e.every((e) => Number.isFinite(e)), ke = {
553
583
  props: [
554
584
  "filter",
555
585
  "shared",
@@ -581,7 +611,7 @@ var Te = /*#__PURE__*/ Z(xe, [["render", we], ["__scopeId", "data-v-364032d4"]])
581
611
  };
582
612
  }
583
613
  },
584
- components: { Hover: Te },
614
+ components: { Hover: De },
585
615
  created() {
586
616
  this.def = this.store.def;
587
617
  },
@@ -601,16 +631,16 @@ var Te = /*#__PURE__*/ Z(xe, [["render", we], ["__scopeId", "data-v-364032d4"]])
601
631
  _groupwise: function(e, t) {
602
632
  return t.classed("paths", !0).selectAll("path").data(e).enter().append("path").each(function(e) {
603
633
  Y.call(this, e.props);
604
- }).each(ye);
634
+ }).each(X);
605
635
  },
606
636
  _pointwise(e, t, n, r = (e) => e) {
607
- return t.classed(n, !0).selectAll("g.group").data(e).enter().append("g").attr("class", "group").each(ye).selectAll(n).data((e) => {
608
- let t = O(e.props);
637
+ return t.classed(n, !0).selectAll("g.group").data(e).enter().append("g").attr("class", "group").each(X).selectAll(n).data((e) => {
638
+ let t = ue(e.props);
609
639
  return e.values.filter((e) => t.every((t) => e[t] !== null)).map((t) => r(E(e.props, t)));
610
640
  }).enter().append(n).each(Y);
611
641
  },
612
642
  "svg:path": function(e, t) {
613
- this._groupwise(e, t).attr("d", (e) => m.line().defined((e) => Ee(e.x, e.y)).x((e) => e.x).y((e) => e.y)(e.values.map((t) => E(e.props.d, t, !0))));
643
+ this._groupwise(e, t).attr("d", (e) => m.line().defined((e) => Oe(e.x, e.y)).x((e) => e.x).y((e) => e.y)(e.values.map((t) => E(e.props.d, t, !0))));
614
644
  },
615
645
  "svg:circle": function(e, t) {
616
646
  this._pointwise(e, t, "circle");
@@ -625,7 +655,7 @@ var Te = /*#__PURE__*/ Z(xe, [["render", we], ["__scopeId", "data-v-364032d4"]])
625
655
  this._pointwise(e, t, "text");
626
656
  },
627
657
  "base:area": function(e, t) {
628
- this._groupwise(e, t).attr("d", (e) => m.area().defined((e) => Ee(e.x, e.y0, e.y1)).x((e) => e.x).y1((e) => e.y1).y0((e) => e.y0)(e.values.map((t) => E(e.props.d, t, !0))));
658
+ this._groupwise(e, t).attr("d", (e) => m.area().defined((e) => Oe(e.x, e.y0, e.y1)).x((e) => e.x).y1((e) => e.y1).y0((e) => e.y0)(e.values.map((t) => E(e.props.d, t, !0))));
629
659
  },
630
660
  bar(e, t) {
631
661
  let n = this;
@@ -633,15 +663,15 @@ var Te = /*#__PURE__*/ Z(xe, [["render", we], ["__scopeId", "data-v-364032d4"]])
633
663
  let t = e.height.parts[0], r = n.info[t].scale(0);
634
664
  if (e.width === void 0) {
635
665
  let t = e.cx.parts[0];
636
- e.width = k(n.info[t].scale.step() * (1 - n.info[t].scale.padding()));
666
+ e.width = O(n.info[t].scale.step() * (1 - n.info[t].scale.padding()));
637
667
  }
638
- return e.x = k(e.cx.value - e.width.value / 2), delete e.cx, e.y = k(e.height.value), e.height = k(r - e.height.value), e;
668
+ return e.x = O(e.cx.value - e.width.value / 2), delete e.cx, e.y = O(e.height.value), e.height = O(r - e.height.value), e;
639
669
  });
640
670
  },
641
671
  stackedBar(e, t) {
642
672
  e.forEach((e) => {
643
673
  let t = e.props.x.ref, n = e.props.y.ref;
644
- e.props.x = k(`@${t}:scaled`), e.props.y = k(`@${n}:st:e:scaled`), e.props.height = k(`@${n}:st:h:scaled`), e.props.transform = k(`translate(-${e.props.width.value / 2} 0)`);
674
+ e.props.x = O(`@${t}:scaled`), e.props.y = O(`@${n}:st:e:scaled`), e.props.height = O(`@${n}:st:h:scaled`), e.props.transform = O(`translate(-${e.props.width.value / 2} 0)`);
645
675
  }), this._pointwise(e, t, "rect", (e) => (e.height.value < 0 && (e.y.value += e.height.value, e.height.value = -e.height.value), e));
646
676
  },
647
677
  scales() {
@@ -651,7 +681,7 @@ var Te = /*#__PURE__*/ Z(xe, [["render", we], ["__scopeId", "data-v-364032d4"]])
651
681
  dim: t,
652
682
  mapping: this.store.mapping(t)
653
683
  };
654
- re(n, this.data), J(n, {
684
+ re(n, this.data), xe(n, {
655
685
  width: this.innerWidth,
656
686
  height: this.innerHeight
657
687
  }), e[t] = n;
@@ -662,7 +692,7 @@ var Te = /*#__PURE__*/ Z(xe, [["render", we], ["__scopeId", "data-v-364032d4"]])
662
692
  },
663
693
  axis() {
664
694
  this.store.mappingNamesWithKey("axis").forEach((e) => {
665
- let t = this.store.mapping(e), n = t.axis, r = this.info[e].scale, i = w(n.ticks, this.relativeBases), a = m[`axis${N(n.position)}`](r).tickSizeInner(9).tickSizeOuter(0).ticks(i).tickPadding(n.padding);
695
+ let t = this.store.mapping(e), n = t.axis, r = this.info[e].scale, i = w(n.ticks, this.relativeBases), a = m[`axis${M(n.position)}`](r).tickSizeInner(9).tickSizeOuter(0).ticks(i).tickPadding(n.padding);
666
696
  if (n.format) a.tickFormat(this.store.formatter(t.scale.type)(n.format));
667
697
  else if (!n.values) {
668
698
  let e = this.store.locale.tickFormat(r, t.scale.type, i);
@@ -694,7 +724,7 @@ var Te = /*#__PURE__*/ Z(xe, [["render", we], ["__scopeId", "data-v-364032d4"]])
694
724
  formatter: this.store.formatter(n.scale.type)(r)
695
725
  }];
696
726
  })), r = this.store.mappingNamesWithKey("hover").filter((e) => e != t.h && e != t.v && this.store.mapping(e).props), i = m.select(this.$refs.hoverMarker).select("line"), a = () => {
697
- e.hover.visible = !1, X(e.inner, e.def.plot);
727
+ e.hover.visible = !1, Z(e.inner, e.def.plot);
698
728
  };
699
729
  this.hideOnPointerOutside = (t) => {
700
730
  e.hover.visible && !e.$refs.svg.contains(t.target) && a();
@@ -723,7 +753,7 @@ var Te = /*#__PURE__*/ Z(xe, [["render", we], ["__scopeId", "data-v-364032d4"]])
723
753
  f = e.store.mapping(d).stacked ? m.least(l, (e) => {
724
754
  let [t, n] = m.extent([e.data[`${d}:st:s`], e.data[`${d}:st:e`]]);
725
755
  return u < t ? t - u : u > n ? u - n : 0;
726
- }) : m.least(l, (e) => Math.abs(e.data[d] - u)), f && (f.nearest = !0), X(e.inner, e.def.plot, f?.data), e.hover.data = l, e.hover.axis = {
756
+ }) : m.least(l, (e) => Math.abs(e.data[d] - u)), f && (f.nearest = !0), Z(e.inner, e.def.plot, f?.data), e.hover.data = l, e.hover.axis = {
727
757
  h: {
728
758
  col: n.h.name,
729
759
  value: c,
@@ -739,11 +769,11 @@ var Te = /*#__PURE__*/ Z(xe, [["render", we], ["__scopeId", "data-v-364032d4"]])
739
769
  }).on("pointercancel", a);
740
770
  }
741
771
  }
742
- }, Oe = ["width", "height"], ke = ["transform"], Ae = ["visibility"], je = {
772
+ }, Ae = ["width", "height"], je = ["transform"], Me = ["visibility"], Ne = {
743
773
  key: 0,
744
774
  class: "debug"
745
775
  };
746
- function Me(e, t, o, s, u, d) {
776
+ function Pe(e, t, o, s, u, d) {
747
777
  let ee = f("hover");
748
778
  return l(), i("div", {
749
779
  style: c(`width: ${o.width}px;`),
@@ -761,7 +791,7 @@ function Me(e, t, o, s, u, d) {
761
791
  visibility: e.hover.visible ? "visible" : "hidden",
762
792
  class: "hoverMarker",
763
793
  ref: "hoverMarker"
764
- }, [...t[0] ||= [a("line", null, null, -1)]], 8, Ae)], 8, ke)], 8, Oe)),
794
+ }, [...t[0] ||= [a("line", null, null, -1)]], 8, Me)], 8, je)], 8, Ae)),
765
795
  a("div", { style: c(`transform: translate(${o.margins.left}px, ${o.margins.top + d.innerHeight / 2}px); position: absolute; top: 0; left: 0;`) }, [e.hover.visible ? (l(), n(ee, {
766
796
  key: 0,
767
797
  data: e.hover.data,
@@ -772,10 +802,10 @@ function Me(e, t, o, s, u, d) {
772
802
  "side",
773
803
  "axis"
774
804
  ])) : r("", !0)], 4),
775
- e.debug ? (l(), i("span", je, p(e.debug), 1)) : r("", !0)
805
+ e.debug ? (l(), i("span", Ne, p(e.debug), 1)) : r("", !0)
776
806
  ], 4);
777
807
  }
778
- var Ne = /*#__PURE__*/ Z(De, [["render", Me], ["__scopeId", "data-v-1f05a06e"]]), Pe = {
808
+ var Fe = /*#__PURE__*/ Q(ke, [["render", Pe], ["__scopeId", "data-v-1f05a06e"]]), Ie = {
779
809
  props: ["info", "props"],
780
810
  mounted() {
781
811
  let e = m.select(this.$refs.legendSymbol);
@@ -784,24 +814,24 @@ var Ne = /*#__PURE__*/ Z(De, [["render", Me], ["__scopeId", "data-v-1f05a06e"]])
784
814
  Y.call(n.node(), T(t.props, this.props));
785
815
  });
786
816
  }
787
- }, Fe = ["width", "height"];
788
- function Ie(e, t, n, r, a, o) {
817
+ }, Le = ["width", "height"];
818
+ function Re(e, t, n, r, a, o) {
789
819
  return l(), i("svg", {
790
820
  width: n.info.size,
791
821
  height: n.info.size,
792
822
  ref: "legendSymbol"
793
- }, null, 8, Fe);
823
+ }, null, 8, Le);
794
824
  }
795
825
  //#endregion
796
826
  //#region src/comp/Legend.vue
797
- var Le = {
827
+ var ze = {
798
828
  props: ["legend"],
799
829
  inject: ["store"],
800
830
  data: () => ({
801
831
  info: {},
802
832
  entries: []
803
833
  }),
804
- components: { LegendSymbol: /* @__PURE__ */ Z(Pe, [["render", Ie], ["__scopeId", "data-v-ce0e972e"]]) },
834
+ components: { LegendSymbol: /* @__PURE__ */ Q(Ie, [["render", Re], ["__scopeId", "data-v-ce0e972e"]]) },
805
835
  mounted() {
806
836
  this.info = this.store.mapping(this.legend), this.entries = Object.keys(this.info.props).map((e) => ({
807
837
  key: e,
@@ -816,18 +846,18 @@ var Le = {
816
846
  selected: e.props.visible
817
847
  });
818
848
  } }
819
- }, Re = ["data-dim"], ze = { class: "title" }, Be = { class: "entries" }, Ve = [
849
+ }, Be = ["data-dim"], Ve = { class: "title" }, He = { class: "entries" }, Ue = [
820
850
  "data-visible",
821
851
  "data-key",
822
852
  "onClick",
823
853
  "onMouseenter"
824
- ], He = ["innerHTML"];
825
- function Ue(t, o, c, u, ee, m) {
854
+ ], We = ["innerHTML"];
855
+ function Ge(t, o, c, u, ee, m) {
826
856
  let h = f("LegendSymbol");
827
857
  return l(), i("div", {
828
858
  class: "legend",
829
859
  "data-dim": c.legend
830
- }, [a("div", ze, p(t.info.name), 1), a("div", Be, [(l(!0), i(e, null, d(t.entries, (e) => (l(), i("div", s({
860
+ }, [a("div", Ve, p(t.info.name), 1), a("div", He, [(l(!0), i(e, null, d(t.entries, (e) => (l(), i("div", s({
831
861
  "data-visible": e.props.visible,
832
862
  "data-key": e.key
833
863
  }, { ref_for: !0 }, Object.assign({ ...e.filled }, { name: null }), {
@@ -841,10 +871,13 @@ function Ue(t, o, c, u, ee, m) {
841
871
  key: 0,
842
872
  info: t.info.legend.symbol,
843
873
  props: e.props
844
- }, null, 8, ["info", "props"])) : r("", !0), a("span", { innerHTML: e.filled.name }, null, 8, He)], 16, Ve))), 256))])], 8, Re);
874
+ }, null, 8, ["info", "props"])) : r("", !0), a("span", { innerHTML: e.filled.name }, null, 8, We)], 16, Ue))), 256))])], 8, Be);
845
875
  }
846
- var We = /*#__PURE__*/ Z(Le, [["render", Ue], ["__scopeId", "data-v-1bc8d55f"]]), Ge = {
876
+ var Ke = /*#__PURE__*/ Q(ze, [["render", Ge], ["__scopeId", "data-v-1bc8d55f"]]), qe = 0, Je = {
847
877
  props: ["element", "globals"],
878
+ created() {
879
+ this.uid = `gen-vis-form-${qe++}`;
880
+ },
848
881
  computed: { vg() {
849
882
  return this.globals[this.element.ref];
850
883
  } },
@@ -856,32 +889,33 @@ var We = /*#__PURE__*/ Z(Le, [["render", Ue], ["__scopeId", "data-v-1bc8d55f"]])
856
889
  return S(e, this.vg);
857
890
  }
858
891
  }
859
- }, Ke = ["id"], qe = { class: "title" }, Je = {
892
+ }, Ye = ["id"], Xe = { class: "title" }, Ze = {
860
893
  key: 0,
861
894
  class: "entries"
862
- }, Ye = ["id", "onClick"], Xe = [
895
+ }, Qe = ["id", "onClick"], $e = [
863
896
  "name",
864
897
  "value",
865
898
  "checked"
866
- ], Ze = ["for"];
867
- function Qe(t, n, o, s, c, u) {
899
+ ], et = ["for"];
900
+ function tt(t, n, o, s, c, u) {
868
901
  return l(), i("div", {
869
902
  class: "formElement",
870
903
  id: `container-${o.element.id}`
871
- }, [a("div", qe, p(o.element.name) + ":", 1), o.element.type == "switch" ? (l(), i("div", Je, [(l(!0), i(e, null, d(o.element.values, (e) => (l(), i("div", {
904
+ }, [a("div", Xe, p(o.element.name) + ":", 1), o.element.type == "switch" ? (l(), i("div", Ze, [(l(!0), i(e, null, d(o.element.values, (e) => (l(), i("div", {
872
905
  id: `container-${e.id}`,
873
906
  onClick: (t) => u.switched(e)
874
907
  }, [a("input", {
875
908
  type: "radio",
876
- name: o.element.id,
909
+ name: `${t.uid}-${o.element.id}`,
877
910
  value: e.id,
878
911
  checked: u.equal(e.value)
879
- }, null, 8, Xe), a("label", { for: e.id }, p(e.name), 9, Ze)], 8, Ye))), 256))])) : r("", !0)], 8, Ke);
912
+ }, null, 8, $e), a("label", { for: e.id }, p(e.name), 9, et)], 8, Qe))), 256))])) : r("", !0)], 8, Ye);
880
913
  }
881
914
  //#endregion
882
915
  //#region src/comp/Vis.vue
883
- var $e = {
916
+ var nt = {
884
917
  inject: ["store"],
918
+ emits: ["stateChanged"],
885
919
  data: () => ({
886
920
  initialized: !1,
887
921
  options: {},
@@ -912,10 +946,13 @@ var $e = {
912
946
  }
913
947
  },
914
948
  components: {
915
- Facet: Ne,
916
- LegendEntry: We,
917
- FormElement: /* @__PURE__ */ Z(Ge, [["render", Qe], ["__scopeId", "data-v-ec3facd5"]])
949
+ Facet: Fe,
950
+ LegendEntry: Ke,
951
+ FormElement: /* @__PURE__ */ Q(Je, [["render", tt], ["__scopeId", "data-v-acf88417"]])
918
952
  },
953
+ watch: { "store.stateSets"() {
954
+ this.dataInit(), this.scales();
955
+ } },
919
956
  mounted() {
920
957
  this.baseInit(), this.dataInit(), this.scales(), this.store.def.options.width || (this.resizeObserver = new ResizeObserver(() => {
921
958
  clearTimeout(this.resizeTimeout), this.resizeTimeout = setTimeout(this.resized, 100);
@@ -971,7 +1008,7 @@ var $e = {
971
1008
  dim: e,
972
1009
  mapping: this.store.mapping(e)
973
1010
  };
974
- return re(t, this.data), J(t, {
1011
+ return re(t, this.data), xe(t, {
975
1012
  width: this.facets.width - (this.facets.margins.left + this.facets.margins.right),
976
1013
  height: this.facets.height - (this.facets.margins.top + this.facets.margins.bottom)
977
1014
  }), t;
@@ -981,34 +1018,34 @@ var $e = {
981
1018
  this.initialized = !0;
982
1019
  },
983
1020
  changeSelected(e) {
984
- this.dataInit(), this.scales();
1021
+ this.dataInit(), this.scales(), this.$emit("stateChanged");
985
1022
  },
986
1023
  formChanged(e) {
987
1024
  this.store.applyFormElements(), this.changeSelected(e);
988
1025
  },
989
1026
  highlight(e) {
990
- X(m.select(this.$refs.vis), this.store.def.plot, { [e.dim]: e.key });
1027
+ Z(m.select(this.$refs.vis), this.store.def.plot, { [e.dim]: e.key });
991
1028
  }
992
1029
  }
993
- }, et = { class: "vis-header" }, tt = { class: "title" }, nt = { class: "subtitle" }, rt = {
1030
+ }, rt = { class: "vis-header" }, it = { class: "title" }, at = { class: "subtitle" }, ot = {
994
1031
  ref: "form",
995
1032
  class: "vis-form-elements"
996
- }, it = {
1033
+ }, st = {
997
1034
  ref: "legends",
998
1035
  class: "vis-legends"
999
- }, at = {
1036
+ }, ct = {
1000
1037
  key: 0,
1001
1038
  class: "vis-body"
1002
- }, ot = { class: "vis-footer" }, st = ["innerHTML"];
1003
- function ct(t, o, s, u, ee, m) {
1039
+ }, lt = { class: "vis-footer" }, ut = ["innerHTML"];
1040
+ function dt(t, o, s, u, ee, m) {
1004
1041
  let h = f("form-element"), g = f("legend-entry"), _ = f("facet");
1005
1042
  return l(), i("div", {
1006
1043
  class: "vis",
1007
1044
  ref: "vis",
1008
1045
  style: c({ "--gen-vis-font-family": t.options.fontFamily })
1009
1046
  }, [
1010
- a("div", et, [a("div", tt, p(t.options.title), 1), a("div", nt, p(t.options.subtitle), 1)]),
1011
- a("div", rt, [(l(!0), i(e, null, d(t.formElements, (e) => (l(), n(h, {
1047
+ a("div", rt, [a("div", it, p(t.options.title), 1), a("div", at, p(t.options.subtitle), 1)]),
1048
+ a("div", ot, [(l(!0), i(e, null, d(t.formElements, (e) => (l(), n(h, {
1012
1049
  element: e,
1013
1050
  globals: t.globals,
1014
1051
  onChangeSelected: m.formChanged
@@ -1017,7 +1054,7 @@ function ct(t, o, s, u, ee, m) {
1017
1054
  "globals",
1018
1055
  "onChangeSelected"
1019
1056
  ]))), 256))], 512),
1020
- a("div", it, [(l(!0), i(e, null, d(t.legends, (e) => (l(), n(g, {
1057
+ a("div", st, [(l(!0), i(e, null, d(t.legends, (e) => (l(), n(g, {
1021
1058
  legend: e,
1022
1059
  onChangeSelected: m.changeSelected,
1023
1060
  onHighlight: m.highlight
@@ -1026,7 +1063,7 @@ function ct(t, o, s, u, ee, m) {
1026
1063
  "onChangeSelected",
1027
1064
  "onHighlight"
1028
1065
  ]))), 256))], 512),
1029
- t.initialized ? (l(), i("div", at, [t.facets.entries.length > 0 ? (l(!0), i(e, { key: 0 }, d(t.facets.entries, (e) => (l(), i("div", { style: c(`width: ${t.facets.width}px; display: inline-block;`) }, [a("div", {
1066
+ t.initialized ? (l(), i("div", ct, [t.facets.entries.length > 0 ? (l(!0), i(e, { key: 0 }, d(t.facets.entries, (e) => (l(), i("div", { style: c(`width: ${t.facets.width}px; display: inline-block;`) }, [a("div", {
1030
1067
  class: "facet-title",
1031
1068
  style: c(`margin-left: ${t.facets.margins.left}px`)
1032
1069
  }, p(e.filter.name), 5), (l(), n(_, {
@@ -1055,12 +1092,12 @@ function ct(t, o, s, u, ee, m) {
1055
1092
  "width",
1056
1093
  "margins"
1057
1094
  ]))])) : r("", !0),
1058
- a("div", ot, [a("span", { innerHTML: t.options.footer }, null, 8, st)])
1095
+ a("div", lt, [a("span", { innerHTML: t.options.footer }, null, 8, ut)])
1059
1096
  ], 4);
1060
1097
  }
1061
1098
  //#endregion
1062
1099
  //#region src/comp/App.vue
1063
- var lt = {
1100
+ var ft = {
1064
1101
  name: "GenVis",
1065
1102
  props: {
1066
1103
  debug: {
@@ -1078,20 +1115,29 @@ var lt = {
1078
1115
  data: {
1079
1116
  type: [Array, String],
1080
1117
  default: null
1118
+ },
1119
+ state: {
1120
+ type: Object,
1121
+ default: null
1081
1122
  }
1082
1123
  },
1124
+ emits: ["update:state"],
1083
1125
  data: () => ({
1084
- store: ve(),
1126
+ store: be(),
1085
1127
  error: null
1086
1128
  }),
1087
1129
  provide() {
1088
1130
  return { store: this.store };
1089
1131
  },
1090
- components: { VisBase: /* @__PURE__ */ Z($e, [["render", ct], ["__scopeId", "data-v-b07c17d2"]]) },
1132
+ components: { VisBase: /* @__PURE__ */ Q(nt, [["render", dt], ["__scopeId", "data-v-d870f406"]]) },
1091
1133
  watch: {
1092
1134
  def: "init",
1093
1135
  defFile: "init",
1094
- data: "init"
1136
+ data: "init",
1137
+ state: {
1138
+ handler: "syncState",
1139
+ deep: !0
1140
+ }
1095
1141
  },
1096
1142
  mounted() {
1097
1143
  this.init();
@@ -1106,44 +1152,51 @@ var lt = {
1106
1152
  await this.store.init({
1107
1153
  def: this.def,
1108
1154
  defUrl: this.defFile,
1109
- data: this.data
1110
- });
1155
+ data: this.data,
1156
+ state: this.state
1157
+ }), this.syncState();
1111
1158
  } catch (e) {
1112
1159
  this.showError(e);
1113
1160
  }
1114
1161
  },
1162
+ syncState() {
1163
+ this.store.loaded && !S(this.state ?? {}, this.store.state) && this.store.setState(this.state);
1164
+ },
1115
1165
  showError(e) {
1116
1166
  console.error(e), this.error = e.message;
1117
1167
  }
1118
1168
  }
1119
- }, ut = { class: "vis-outer" }, dt = {
1169
+ }, pt = { class: "vis-outer" }, mt = {
1120
1170
  key: 0,
1121
1171
  class: "vis-error"
1122
- }, ft = { key: 2 }, pt = { style: {
1172
+ }, ht = { key: 2 }, gt = { style: {
1123
1173
  height: "500px",
1124
1174
  overflow: "auto",
1125
1175
  "font-size": "11px"
1126
- } }, mt = { style: {
1176
+ } }, _t = { style: {
1127
1177
  height: "500px",
1128
1178
  overflow: "auto",
1129
1179
  "font-size": "11px"
1130
1180
  } };
1131
- function ht(e, t, o, s, c, u) {
1181
+ function vt(e, t, o, s, c, u) {
1132
1182
  let d = f("vis-base");
1133
- return l(), i("div", ut, [e.error ? (l(), i("div", dt, p(e.error), 1)) : e.store.loaded ? (l(), n(d, { key: 1 })) : r("", !0), o.debug && e.store.def ? (l(), i("div", ft, [
1134
- t[0] ||= a("h3", null, "prepared:", -1),
1135
- a("pre", pt, p(JSON.stringify(e.store.def, null, 4)), 1),
1136
- t[1] ||= a("h3", null, "org:", -1),
1137
- a("pre", mt, p(JSON.stringify(e.store.defOrg, null, 4)), 1)
1183
+ return l(), i("div", pt, [e.error ? (l(), i("div", mt, p(e.error), 1)) : e.store.loaded ? (l(), n(d, {
1184
+ key: 1,
1185
+ onStateChanged: t[0] ||= (t) => e.$emit("update:state", e.store.state)
1186
+ })) : r("", !0), o.debug && e.store.def ? (l(), i("div", ht, [
1187
+ t[1] ||= a("h3", null, "prepared:", -1),
1188
+ a("pre", gt, p(JSON.stringify(e.store.def, null, 4)), 1),
1189
+ t[2] ||= a("h3", null, "org:", -1),
1190
+ a("pre", _t, p(JSON.stringify(e.store.defOrg, null, 4)), 1)
1138
1191
  ])) : r("", !0)]);
1139
1192
  }
1140
- var Q = /*#__PURE__*/ Z(lt, [["render", ht], ["__scopeId", "data-v-a9d47434"]]), gt = { install(e) {
1141
- e.component("GenVis", Q);
1142
- } }, $ = (e) => {
1193
+ var $ = /*#__PURE__*/ Q(ft, [["render", vt], ["__scopeId", "data-v-7b1c318b"]]), yt = { install(e) {
1194
+ e.component("GenVis", $);
1195
+ } }, bt = (e) => {
1143
1196
  let n = Object.fromEntries(e.getAttributeNames().filter((e) => e.startsWith("data-")).map((t) => [t.substring(5), e.getAttribute(t)]));
1144
- return t(Q, n).mount(e);
1145
- }, _t = (e) => {
1146
- for (let t of document.getElementsByClassName(e)) t.classList.contains("gen-vis-attached") || (t.classList.add("gen-vis-attached"), $(t));
1197
+ return t($, n).mount(e);
1198
+ }, xt = (e) => {
1199
+ for (let t of document.getElementsByClassName(e)) t.classList.contains("gen-vis-attached") || (t.classList.add("gen-vis-attached"), bt(t));
1147
1200
  };
1148
1201
  //#endregion
1149
- export { Q as GenVis, gt as default, _t as mountGenVisByClass, $ as mountGenVisElement };
1202
+ export { $ as GenVis, yt as default, xt as mountGenVisByClass, bt as mountGenVisElement };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@preschen/gen-vis",
3
- "version": "0.6.0",
3
+ "version": "0.8.0",
4
4
  "description": "A declarative d3 visualisation library",
5
5
  "type": "module",
6
6
  "main": "dist/gen-vis.js",
package/schema.json CHANGED
@@ -8,8 +8,11 @@
8
8
  "properties": {
9
9
  "$schema": { "type": "string" },
10
10
  "parent": {
11
- "type": "string",
12
- "description": "Url of the definition this one is deep merged into, relative to this definition. Arrays are replaced, not merged."
11
+ "oneOf": [
12
+ { "type": "string" },
13
+ { "type": "array", "items": { "type": "string" } }
14
+ ],
15
+ "description": "Url of the definition this one is deep merged into, relative to this definition, or a list of them (mixins) merged in their order, later ones override earlier ones. Arrays are replaced, not merged."
13
16
  },
14
17
  "data": {
15
18
  "type": "string",