@kanzo-tech/graph 0.26.0 → 0.28.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.
Files changed (41) hide show
  1. package/README.md +7 -4
  2. package/dist/core/client.d.ts.map +1 -1
  3. package/dist/core/client.js +16 -16
  4. package/dist/core/client.js.map +1 -1
  5. package/dist/core/error.d.ts +3 -3
  6. package/dist/core/error.d.ts.map +1 -1
  7. package/dist/core/error.js.map +1 -1
  8. package/dist/core/state.d.ts +8 -3
  9. package/dist/core/state.d.ts.map +1 -1
  10. package/dist/core/store.d.ts +1 -1
  11. package/dist/core/store.d.ts.map +1 -1
  12. package/dist/core/store.js +84 -76
  13. package/dist/core/store.js.map +1 -1
  14. package/dist/core/types.d.ts +5 -3
  15. package/dist/core/types.d.ts.map +1 -1
  16. package/dist/index.d.ts +5 -3
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +28 -24
  19. package/dist/index.js.map +1 -1
  20. package/dist/parts/graph-counts.d.ts +9 -11
  21. package/dist/parts/graph-counts.d.ts.map +1 -1
  22. package/dist/parts/graph-counts.js +28 -27
  23. package/dist/parts/graph-counts.js.map +1 -1
  24. package/dist/parts/graph-select.d.ts +27 -0
  25. package/dist/parts/graph-select.d.ts.map +1 -0
  26. package/dist/parts/graph-select.js +53 -0
  27. package/dist/parts/graph-select.js.map +1 -0
  28. package/dist/parts/graph-status.d.ts +13 -0
  29. package/dist/parts/graph-status.d.ts.map +1 -0
  30. package/dist/parts/graph-status.js +28 -0
  31. package/dist/parts/graph-status.js.map +1 -0
  32. package/dist/react/use-graph-prefs.d.ts +1 -1
  33. package/dist/react/use-graph-prefs.js.map +1 -1
  34. package/dist/render/camera.d.ts +12 -1
  35. package/dist/render/camera.d.ts.map +1 -1
  36. package/dist/render/camera.js +33 -21
  37. package/dist/render/camera.js.map +1 -1
  38. package/dist/render/renderer.d.ts.map +1 -1
  39. package/dist/render/renderer.js +85 -84
  40. package/dist/render/renderer.js.map +1 -1
  41. package/package.json +8 -8
package/README.md CHANGED
@@ -19,7 +19,7 @@ DuckDB-WASM engine and its crossfilter, cosmos.gl draws, and the parts are built
19
19
  ```tsx
20
20
  import { open } from "@fossil-lang/corpus";
21
21
  import { engine } from "@kanzo-tech/mosaic";
22
- import { GraphCanvas, GraphCounts, GraphInspector, GraphLegend, GraphRoot, GraphToolbar } from "@kanzo-tech/graph";
22
+ import { GraphCanvas, GraphCounts, GraphInspector, GraphLegend, GraphRoot, GraphStatus, GraphToolbar } from "@kanzo-tech/graph";
23
23
 
24
24
  const corpus = engine().then((e) => open(url, { engine: e }));
25
25
 
@@ -28,6 +28,7 @@ const corpus = engine().then((e) => open(url, { engine: e }));
28
28
  <GraphToolbar />
29
29
  <GraphLegend />
30
30
  </GraphCanvas>
31
+ <GraphStatus />
31
32
  <GraphCounts />
32
33
  <GraphInspector />
33
34
  </GraphRoot>;
@@ -68,7 +69,9 @@ graph, a second main view and a dock of panels.
68
69
  and lasso gesture. Children are chrome positioned over it.
69
70
  - `GraphToolbar` — the selection tools, the selection, zoom and fit, and the layout's transport.
70
71
  - `GraphLegend` — one row per category: glyph, name and how many are drawn.
71
- - `GraphCounts` — what is drawn of the whole: "1.2K of 5K nodes drawn · 8K edges".
72
+ - `GraphStatus` — where the graph is, in one word: Loading, Laying out 42%, Ready or Failed.
73
+ - `GraphCounts` — the corpus and what the filter keeps of it: "5K nodes · 8K edges", or
74
+ "1.2K of 5K nodes match · 3K edges".
72
75
  - `GraphSearch` — every drawn vertex's text, read once and filtered in the browser; picking reveals.
73
76
  - `GraphInspector` — the focused vertex's row, with a render prop for a product's own fields.
74
77
  - `GraphLooks` — Nebula, Atlas and Ink as presets over `GRAPH_SECTION`'s axes, with the axes under
@@ -77,8 +80,8 @@ graph, a second main view and a dock of panels.
77
80
 
78
81
  No part takes a callback: what a click means is `onSelect`, `onFocus` and `onFailure` on the root.
79
82
  `onFailure` is required and receives every failure as thrown — fossil's coded errors, and the graph's
80
- own `GraphError` (`graph/no-webgl`, `graph/context-lost`, `graph/nothing-to-draw`,
81
- `graph/untranslatable-filter`).
83
+ own `GraphError` (`graph/no-webgl`, `graph/context-lost`, `graph/no-positions`,
84
+ `graph/nothing-to-draw`, `graph/unfilterable`).
82
85
 
83
86
  - `lookFrom`, `simFrom`, `useGraphPrefs` — the form and the forces from a preferences panel's
84
87
  answers, and the look `preset` they are; `scaleOf` — what colour and shape a category wears.
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/core/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAgC,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEjH,OAAO,EAAgC,KAAK,SAAS,EAAE,MAAM,UAAU,CAAC;AAYxE,qBAAa,WAAY,SAAQ,YAAY;;gBAMzC,QAAQ,EAAE,SAAS,GAAG,SAAS,EAC/B,SAAS,EAAE,MAAM,SAAS,GAAG,IAAI,EACjC,IAAI,EAAE,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,KAAK,IAAI,EACxC,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI;IAQhC;;;OAGG;IACH,IAAa,YAAY,IAAI,OAAO,CAEnC;IAED;;;;OAIG;IACM,KAAK,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,IAAI,GAAG,MAAM;IAwBzC,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAMhC,UAAU,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;CAIxC;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,GAAG,IAAI,CAOrG"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/core/client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EAIZ,KAAK,UAAU,EACf,KAAK,SAAS,EACf,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAgC,KAAK,SAAS,EAAE,MAAM,UAAU,CAAC;AAYxE,qBAAa,WAAY,SAAQ,YAAY;;gBAMzC,QAAQ,EAAE,SAAS,GAAG,SAAS,EAC/B,SAAS,EAAE,MAAM,SAAS,GAAG,IAAI,EACjC,IAAI,EAAE,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,KAAK,IAAI,EACxC,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI;IAQhC;;;OAGG;IACH,IAAa,YAAY,IAAI,OAAO,CAEnC;IAED;;;;OAIG;IACM,KAAK,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,IAAI,GAAG,MAAM;IAwBzC,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAMhC,UAAU,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;CAIxC;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,GAAG,IAAI,CAOrG"}
@@ -1,11 +1,11 @@
1
- var f = (t) => {
2
- throw TypeError(t);
1
+ var f = (r) => {
2
+ throw TypeError(r);
3
3
  };
4
- var L = (t, r, e) => r.has(t) || f("Cannot " + e);
5
- var u = (t, r, e) => (L(t, r, "read from private field"), e ? e.call(t) : r.get(t)), h = (t, r, e) => r.has(t) ? f("Cannot add the same private member more than once") : r instanceof WeakSet ? r.add(t) : r.set(t, e), m = (t, r, e, n) => (L(t, r, "write to private field"), n ? n.call(t, e) : r.set(t, e), e);
6
- import { MosaicClient as g, collectColumns as A, clausePoints as v } from "@kanzo-tech/mosaic";
7
- import { GraphError as C } from "./error.js";
8
- import { relation as $, ident as y } from "./source.js";
4
+ var y = (r, t, e) => t.has(r) || f("Cannot " + e);
5
+ var u = (r, t, e) => (y(r, t, "read from private field"), e ? e.call(r) : t.get(r)), h = (r, t, e) => t.has(r) ? f("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(r) : t.set(r, e), m = (r, t, e, n) => (y(r, t, "write to private field"), n ? n.call(r, e) : t.set(r, e), e);
6
+ import { MosaicClient as g, collectColumns as A, queryFailure as v, clausePoints as C } from "@kanzo-tech/mosaic";
7
+ import { GraphError as $ } from "./error.js";
8
+ import { relation as O, ident as L } from "./source.js";
9
9
  const S = "SELECT NULL::DOUBLE AS id";
10
10
  var a, c, l;
11
11
  class N extends g {
@@ -32,9 +32,9 @@ class N extends g {
32
32
  const n = (Array.isArray(e) ? e : [e]).filter((s) => s != null), i = u(this, a).call(this);
33
33
  if (!i || n.length === 0) return S;
34
34
  const d = n.map((s) => `(${String(s)})`).join(" AND "), p = [...new Set(n.flatMap((s) => A(s).map((o) => o.column)))], E = i.vertices.filter((s) => p.every((o) => s.columns.has(o)));
35
- return E.length === 0 ? (u(this, l).call(this, new C("graph/unfilterable", `no vertex type has every column this clause names: ${p.join(", ")}`)), S) : i.vertices.map((s) => {
36
- const o = $(i.from, s.name);
37
- return E.includes(s) ? `SELECT ${y("dense_id")}::DOUBLE AS id FROM ${o} WHERE ${d}` : `SELECT ${y("dense_id")}::DOUBLE AS id FROM ${o}`;
35
+ return E.length === 0 ? (u(this, l).call(this, new $("graph/unfilterable", `no vertex type has every column this clause names: ${p.join(", ")}`)), S) : i.vertices.map((s) => {
36
+ const o = O(i.from, s.name);
37
+ return E.includes(s) ? `SELECT ${L("dense_id")}::DOUBLE AS id FROM ${o} WHERE ${d}` : `SELECT ${L("dense_id")}::DOUBLE AS id FROM ${o}`;
38
38
  }).join(" UNION ALL ");
39
39
  }
40
40
  queryResult(e) {
@@ -43,15 +43,15 @@ class N extends g {
43
43
  return u(this, c).call(this, n.length === 1 && n[0] === null ? null : Float64Array.from(n)), this;
44
44
  }
45
45
  queryError(e) {
46
- return u(this, l).call(this, e), this;
46
+ return u(this, l).call(this, v(e)), this;
47
47
  }
48
48
  }
49
49
  a = new WeakMap(), c = new WeakMap(), l = new WeakMap();
50
- function R(t, r, e) {
51
- t.update(
52
- v(["dense_id"], e && e.length > 0 ? e.map((n) => [n]) : void 0, {
53
- source: r,
54
- clients: /* @__PURE__ */ new Set([r])
50
+ function R(r, t, e) {
51
+ r.update(
52
+ C(["dense_id"], e && e.length > 0 ? e.map((n) => [n]) : void 0, {
53
+ source: t,
54
+ clients: /* @__PURE__ */ new Set([t])
55
55
  })
56
56
  );
57
57
  }
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sources":["../../src/core/client.ts"],"sourcesContent":["import { MosaicClient, clausePoints, collectColumns, type FilterExpr, type Selection } from \"@kanzo-tech/mosaic\";\nimport { GraphError } from \"./error\";\nimport { ident, relation, type Answer, type Structure } from \"./source\";\n\n/**\n * **The graph as a client of the page's coordinator** — one Mosaic client, like every chart beside\n * it. The coordinator hands it the crossfilter's predicate, minus the clause the graph published\n * itself; it answers with the `dense_id`s that survive, and the canvas greys out the rest on the GPU.\n * No predicate is translated, no position is uploaded again, and the query runs on the coordinator's\n * one connection, through its cache — Cosmograph's crossfilter, on our stack.\n */\n/** The answer that clears the filter. */\nconst UNFILTERED = \"SELECT NULL::DOUBLE AS id\";\n\nexport class GraphClient extends MosaicClient {\n #structure: () => Structure | null;\n #kept: (ids: Float64Array | null) => void;\n #fail: (error: unknown) => void;\n\n constructor(\n filterBy: Selection | undefined,\n structure: () => Structure | null,\n kept: (ids: Float64Array | null) => void,\n fail: (error: unknown) => void,\n ) {\n super(filterBy);\n this.#structure = structure;\n this.#kept = kept;\n this.#fail = fail;\n }\n\n /**\n * Not stable: the answer is a set of ids, not a group-by a pre-aggregate could stand in for. And\n * Mosaic's pre-aggregator calls `query()` with no filter to analyse a client — false keeps it away.\n */\n override get filterStable(): boolean {\n return false;\n }\n\n /**\n * The surviving ids — or, with nothing to filter by, {@link UNFILTERED}: one row whose id is\n * `NULL`, which no `dense_id` is. The answer says which it is, so two statements in flight can\n * never be read as each other's.\n */\n override query(filter?: FilterExpr | null): string {\n const clauses = (Array.isArray(filter) ? filter : [filter]).filter((c) => c !== undefined && c !== null);\n const structure = this.#structure();\n if (!structure || clauses.length === 0) return UNFILTERED;\n const where = clauses.map((c) => `(${String(c)})`).join(\" AND \");\n const named = [...new Set(clauses.flatMap((c) => collectColumns(c as never).map((ref: { column: string }) => ref.column)))];\n // A table that lacks a column the predicate names is not filtered by it — what a `WHERE` over a\n // union of the tables would do. A predicate no table can answer is refused rather than ignored,\n // so the unfiltered picture is never drawn as the filtered one.\n const answering = structure.vertices.filter((t) => named.every((c) => t.columns.has(c)));\n if (answering.length === 0) {\n this.#fail(new GraphError(\"graph/unfilterable\", `no vertex type has every column this clause names: ${named.join(\", \")}`));\n return UNFILTERED;\n }\n return structure.vertices\n .map((t) => {\n const from = relation(structure.from, t.name);\n return answering.includes(t)\n ? `SELECT ${ident(\"dense_id\")}::DOUBLE AS id FROM ${from} WHERE ${where}`\n : `SELECT ${ident(\"dense_id\")}::DOUBLE AS id FROM ${from}`;\n })\n .join(\" UNION ALL \");\n }\n\n override queryResult(data: unknown): this {\n const ids = ((data as Answer).getChild(\"id\")?.toArray() ?? []) as ArrayLike<number | null>;\n this.#kept(ids.length === 1 && ids[0] === null ? null : Float64Array.from(ids as ArrayLike<number>));\n return this;\n }\n\n override queryError(error: Error): this {\n this.#fail(error);\n return this;\n }\n}\n\n/**\n * **The reader's pick, published** — from the graph, so the crossfilter applies it to every chart and\n * skips it for the graph. A canvas that greyed out everything but a lasso of thirteen would hide the\n * neighbourhood the reader was looking at.\n */\nexport function publish(selection: Selection, self: MosaicClient, ids: readonly number[] | null): void {\n selection.update(\n clausePoints([\"dense_id\"], ids && ids.length > 0 ? ids.map((d) => [d]) : undefined, {\n source: self,\n clients: new Set([self]),\n }),\n );\n}\n"],"names":["UNFILTERED","GraphClient","MosaicClient","filterBy","structure","kept","fail","__privateAdd","_structure","_kept","_fail","__privateSet","filter","clauses","c","__privateGet","where","named","collectColumns","ref","answering","t","GraphError","from","relation","ident","data","ids","_a","error","publish","selection","self","clausePoints","d"],"mappings":";;;;;;;;AAYA,MAAMA,IAAa;;AAEZ,MAAMC,UAAoBC,EAAa;AAAA,EAK5C,YACEC,GACAC,GACAC,GACAC,GACA;AACA,UAAMH,CAAQ;AAVhB,IAAAI,EAAA,MAAAC;AACA,IAAAD,EAAA,MAAAE;AACA,IAAAF,EAAA,MAAAG;AASE,IAAAC,EAAA,MAAKH,GAAaJ,IAClBO,EAAA,MAAKF,GAAQJ,IACbM,EAAA,MAAKD,GAAQJ;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAa,eAAwB;AACnC,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOS,MAAMM,GAAoC;AACjD,UAAMC,KAAW,MAAM,QAAQD,CAAM,IAAIA,IAAS,CAACA,CAAM,GAAG,OAAO,CAACE,MAAyBA,KAAM,IAAI,GACjGV,IAAYW,EAAA,MAAKP,GAAL;AAClB,QAAI,CAACJ,KAAaS,EAAQ,WAAW,EAAG,QAAOb;AAC/C,UAAMgB,IAAQH,EAAQ,IAAI,CAACC,MAAM,IAAI,OAAOA,CAAC,CAAC,GAAG,EAAE,KAAK,OAAO,GACzDG,IAAQ,CAAC,GAAG,IAAI,IAAIJ,EAAQ,QAAQ,CAACC,MAAMI,EAAeJ,CAAU,EAAE,IAAI,CAACK,MAA4BA,EAAI,MAAM,CAAC,CAAC,CAAC,GAIpHC,IAAYhB,EAAU,SAAS,OAAO,CAACiB,MAAMJ,EAAM,MAAM,CAACH,MAAMO,EAAE,QAAQ,IAAIP,CAAC,CAAC,CAAC;AACvF,WAAIM,EAAU,WAAW,KACvBL,EAAA,MAAKL,GAAL,WAAW,IAAIY,EAAW,sBAAsB,sDAAsDL,EAAM,KAAK,IAAI,CAAC,EAAE,IACjHjB,KAEFI,EAAU,SACd,IAAI,CAACiB,MAAM;AACV,YAAME,IAAOC,EAASpB,EAAU,MAAMiB,EAAE,IAAI;AAC5C,aAAOD,EAAU,SAASC,CAAC,IACvB,UAAUI,EAAM,UAAU,CAAC,uBAAuBF,CAAI,UAAUP,CAAK,KACrE,UAAUS,EAAM,UAAU,CAAC,uBAAuBF,CAAI;AAAA,IAC5D,CAAC,EACA,KAAK,aAAa;AAAA,EACvB;AAAA,EAES,YAAYG,GAAqB;;AACxC,UAAMC,MAAQC,IAAAF,EAAgB,SAAS,IAAI,MAA7B,gBAAAE,EAAgC,cAAa,CAAA;AAC3D,WAAAb,EAAA,MAAKN,GAAL,WAAWkB,EAAI,WAAW,KAAKA,EAAI,CAAC,MAAM,OAAO,OAAO,aAAa,KAAKA,CAAwB,IAC3F;AAAA,EACT;AAAA,EAES,WAAWE,GAAoB;AACtC,WAAAd,EAAA,MAAKL,GAAL,WAAWmB,IACJ;AAAA,EACT;AACF;AA/DErB,IAAA,eACAC,IAAA,eACAC,IAAA;AAoEK,SAASoB,EAAQC,GAAsBC,GAAoBL,GAAqC;AACrG,EAAAI,EAAU;AAAA,IACRE,EAAa,CAAC,UAAU,GAAGN,KAAOA,EAAI,SAAS,IAAIA,EAAI,IAAI,CAACO,MAAM,CAACA,CAAC,CAAC,IAAI,QAAW;AAAA,MAClF,QAAQF;AAAA,MACR,SAAS,oBAAI,IAAI,CAACA,CAAI,CAAC;AAAA,IAAA,CACxB;AAAA,EAAA;AAEL;"}
1
+ {"version":3,"file":"client.js","sources":["../../src/core/client.ts"],"sourcesContent":["import {\n MosaicClient,\n clausePoints,\n collectColumns,\n queryFailure,\n type FilterExpr,\n type Selection,\n} from \"@kanzo-tech/mosaic\";\nimport { GraphError } from \"./error\";\nimport { ident, relation, type Answer, type Structure } from \"./source\";\n\n/**\n * **The graph as a client of the page's coordinator** — one Mosaic client, like every chart beside\n * it. The coordinator hands it the crossfilter's predicate, minus the clause the graph published\n * itself; it answers with the `dense_id`s that survive, and the canvas greys out the rest on the GPU.\n * No predicate is translated, no position is uploaded again, and the query runs on the coordinator's\n * one connection, through its cache — Cosmograph's crossfilter, on our stack.\n */\n/** The answer that clears the filter. */\nconst UNFILTERED = \"SELECT NULL::DOUBLE AS id\";\n\nexport class GraphClient extends MosaicClient {\n #structure: () => Structure | null;\n #kept: (ids: Float64Array | null) => void;\n #fail: (error: unknown) => void;\n\n constructor(\n filterBy: Selection | undefined,\n structure: () => Structure | null,\n kept: (ids: Float64Array | null) => void,\n fail: (error: unknown) => void,\n ) {\n super(filterBy);\n this.#structure = structure;\n this.#kept = kept;\n this.#fail = fail;\n }\n\n /**\n * Not stable: the answer is a set of ids, not a group-by a pre-aggregate could stand in for. And\n * Mosaic's pre-aggregator calls `query()` with no filter to analyse a client — false keeps it away.\n */\n override get filterStable(): boolean {\n return false;\n }\n\n /**\n * The surviving ids — or, with nothing to filter by, {@link UNFILTERED}: one row whose id is\n * `NULL`, which no `dense_id` is. The answer says which it is, so two statements in flight can\n * never be read as each other's.\n */\n override query(filter?: FilterExpr | null): string {\n const clauses = (Array.isArray(filter) ? filter : [filter]).filter((c) => c !== undefined && c !== null);\n const structure = this.#structure();\n if (!structure || clauses.length === 0) return UNFILTERED;\n const where = clauses.map((c) => `(${String(c)})`).join(\" AND \");\n const named = [...new Set(clauses.flatMap((c) => collectColumns(c as never).map((ref: { column: string }) => ref.column)))];\n // A table that lacks a column the predicate names is not filtered by it — what a `WHERE` over a\n // union of the tables would do. A predicate no table can answer is refused rather than ignored,\n // so the unfiltered picture is never drawn as the filtered one.\n const answering = structure.vertices.filter((t) => named.every((c) => t.columns.has(c)));\n if (answering.length === 0) {\n this.#fail(new GraphError(\"graph/unfilterable\", `no vertex type has every column this clause names: ${named.join(\", \")}`));\n return UNFILTERED;\n }\n return structure.vertices\n .map((t) => {\n const from = relation(structure.from, t.name);\n return answering.includes(t)\n ? `SELECT ${ident(\"dense_id\")}::DOUBLE AS id FROM ${from} WHERE ${where}`\n : `SELECT ${ident(\"dense_id\")}::DOUBLE AS id FROM ${from}`;\n })\n .join(\" UNION ALL \");\n }\n\n override queryResult(data: unknown): this {\n const ids = ((data as Answer).getChild(\"id\")?.toArray() ?? []) as ArrayLike<number | null>;\n this.#kept(ids.length === 1 && ids[0] === null ? null : Float64Array.from(ids as ArrayLike<number>));\n return this;\n }\n\n override queryError(error: Error): this {\n this.#fail(queryFailure(error));\n return this;\n }\n}\n\n/**\n * **The reader's pick, published** — from the graph, so the crossfilter applies it to every chart and\n * skips it for the graph. A canvas that greyed out everything but a lasso of thirteen would hide the\n * neighbourhood the reader was looking at.\n */\nexport function publish(selection: Selection, self: MosaicClient, ids: readonly number[] | null): void {\n selection.update(\n clausePoints([\"dense_id\"], ids && ids.length > 0 ? ids.map((d) => [d]) : undefined, {\n source: self,\n clients: new Set([self]),\n }),\n );\n}\n"],"names":["UNFILTERED","GraphClient","MosaicClient","filterBy","structure","kept","fail","__privateAdd","_structure","_kept","_fail","__privateSet","filter","clauses","c","__privateGet","where","named","collectColumns","ref","answering","t","GraphError","from","relation","ident","data","ids","_a","error","queryFailure","publish","selection","self","clausePoints","d"],"mappings":";;;;;;;;AAmBA,MAAMA,IAAa;;AAEZ,MAAMC,UAAoBC,EAAa;AAAA,EAK5C,YACEC,GACAC,GACAC,GACAC,GACA;AACA,UAAMH,CAAQ;AAVhB,IAAAI,EAAA,MAAAC;AACA,IAAAD,EAAA,MAAAE;AACA,IAAAF,EAAA,MAAAG;AASE,IAAAC,EAAA,MAAKH,GAAaJ,IAClBO,EAAA,MAAKF,GAAQJ,IACbM,EAAA,MAAKD,GAAQJ;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAa,eAAwB;AACnC,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOS,MAAMM,GAAoC;AACjD,UAAMC,KAAW,MAAM,QAAQD,CAAM,IAAIA,IAAS,CAACA,CAAM,GAAG,OAAO,CAACE,MAAyBA,KAAM,IAAI,GACjGV,IAAYW,EAAA,MAAKP,GAAL;AAClB,QAAI,CAACJ,KAAaS,EAAQ,WAAW,EAAG,QAAOb;AAC/C,UAAMgB,IAAQH,EAAQ,IAAI,CAACC,MAAM,IAAI,OAAOA,CAAC,CAAC,GAAG,EAAE,KAAK,OAAO,GACzDG,IAAQ,CAAC,GAAG,IAAI,IAAIJ,EAAQ,QAAQ,CAACC,MAAMI,EAAeJ,CAAU,EAAE,IAAI,CAACK,MAA4BA,EAAI,MAAM,CAAC,CAAC,CAAC,GAIpHC,IAAYhB,EAAU,SAAS,OAAO,CAACiB,MAAMJ,EAAM,MAAM,CAACH,MAAMO,EAAE,QAAQ,IAAIP,CAAC,CAAC,CAAC;AACvF,WAAIM,EAAU,WAAW,KACvBL,EAAA,MAAKL,GAAL,WAAW,IAAIY,EAAW,sBAAsB,sDAAsDL,EAAM,KAAK,IAAI,CAAC,EAAE,IACjHjB,KAEFI,EAAU,SACd,IAAI,CAACiB,MAAM;AACV,YAAME,IAAOC,EAASpB,EAAU,MAAMiB,EAAE,IAAI;AAC5C,aAAOD,EAAU,SAASC,CAAC,IACvB,UAAUI,EAAM,UAAU,CAAC,uBAAuBF,CAAI,UAAUP,CAAK,KACrE,UAAUS,EAAM,UAAU,CAAC,uBAAuBF,CAAI;AAAA,IAC5D,CAAC,EACA,KAAK,aAAa;AAAA,EACvB;AAAA,EAES,YAAYG,GAAqB;;AACxC,UAAMC,MAAQC,IAAAF,EAAgB,SAAS,IAAI,MAA7B,gBAAAE,EAAgC,cAAa,CAAA;AAC3D,WAAAb,EAAA,MAAKN,GAAL,WAAWkB,EAAI,WAAW,KAAKA,EAAI,CAAC,MAAM,OAAO,OAAO,aAAa,KAAKA,CAAwB,IAC3F;AAAA,EACT;AAAA,EAES,WAAWE,GAAoB;AACtC,WAAAd,EAAA,MAAKL,GAAL,WAAWoB,EAAaD,CAAK,IACtB;AAAA,EACT;AACF;AA/DErB,IAAA,eACAC,IAAA,eACAC,IAAA;AAoEK,SAASqB,EAAQC,GAAsBC,GAAoBN,GAAqC;AACrG,EAAAK,EAAU;AAAA,IACRE,EAAa,CAAC,UAAU,GAAGP,KAAOA,EAAI,SAAS,IAAIA,EAAI,IAAI,CAACQ,MAAM,CAACA,CAAC,CAAC,IAAI,QAAW;AAAA,MAClF,QAAQF;AAAA,MACR,SAAS,oBAAI,IAAI,CAACA,CAAI,CAAC;AAAA,IAAA,CACxB;AAAA,EAAA;AAEL;"}
@@ -1,15 +1,15 @@
1
1
  /**
2
2
  * The failures the graph names itself: no GPU device to draw with, or the one it had was taken back;
3
- * a corpus with no vertex to draw; a crossfilter clause no vertex type can answer. A
3
+ * a device that holds no positions for the points it was given; a corpus with no vertex to draw; a crossfilter clause no vertex type can answer. A
4
4
  * corpus fossil will not read never gets here: `open` refuses it, coded. `data.after` is set when a deadline fired. Everything else reaches `onFailure` as thrown.
5
5
  */
6
6
  export declare class GraphError extends Error {
7
- readonly code: "graph/no-webgl" | "graph/context-lost" | "graph/nothing-to-draw" | "graph/unfilterable";
7
+ readonly code: "graph/no-webgl" | "graph/context-lost" | "graph/no-positions" | "graph/nothing-to-draw" | "graph/unfilterable";
8
8
  readonly data: {
9
9
  readonly after?: number;
10
10
  };
11
11
  readonly name = "GraphError";
12
- constructor(code: "graph/no-webgl" | "graph/context-lost" | "graph/nothing-to-draw" | "graph/unfilterable", message: string, data?: {
12
+ constructor(code: "graph/no-webgl" | "graph/context-lost" | "graph/no-positions" | "graph/nothing-to-draw" | "graph/unfilterable", message: string, data?: {
13
13
  readonly after?: number;
14
14
  }, options?: ErrorOptions);
15
15
  }
@@ -1 +1 @@
1
- {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../src/core/error.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,qBAAa,UAAW,SAAQ,KAAK;IAGjC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,GAAG,oBAAoB,GAAG,uBAAuB,GAAG,oBAAoB;IAEvG,QAAQ,CAAC,IAAI,EAAE;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;IAJ5C,SAAkB,IAAI,gBAAgB;gBAE3B,IAAI,EAAE,gBAAgB,GAAG,oBAAoB,GAAG,uBAAuB,GAAG,oBAAoB,EACvG,OAAO,EAAE,MAAM,EACN,IAAI,GAAE;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAO,EAC/C,OAAO,CAAC,EAAE,YAAY;CAIzB"}
1
+ {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../src/core/error.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,qBAAa,UAAW,SAAQ,KAAK;IAGjC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,GAAG,oBAAoB,GAAG,oBAAoB,GAAG,uBAAuB,GAAG,oBAAoB;IAE9H,QAAQ,CAAC,IAAI,EAAE;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;IAJ5C,SAAkB,IAAI,gBAAgB;gBAE3B,IAAI,EAAE,gBAAgB,GAAG,oBAAoB,GAAG,oBAAoB,GAAG,uBAAuB,GAAG,oBAAoB,EAC9H,OAAO,EAAE,MAAM,EACN,IAAI,GAAE;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAO,EAC/C,OAAO,CAAC,EAAE,YAAY;CAIzB"}
@@ -1 +1 @@
1
- {"version":3,"file":"error.js","sources":["../../src/core/error.ts"],"sourcesContent":["/**\n * The failures the graph names itself: no GPU device to draw with, or the one it had was taken back;\n * a corpus with no vertex to draw; a crossfilter clause no vertex type can answer. A\n * corpus fossil will not read never gets here: `open` refuses it, coded. `data.after` is set when a deadline fired. Everything else reaches `onFailure` as thrown.\n */\nexport class GraphError extends Error {\n override readonly name = \"GraphError\";\n constructor(\n readonly code: \"graph/no-webgl\" | \"graph/context-lost\" | \"graph/nothing-to-draw\" | \"graph/unfilterable\",\n message: string,\n readonly data: { readonly after?: number } = {},\n options?: ErrorOptions,\n ) {\n super(message, options);\n }\n}\n"],"names":["GraphError","code","message","data","options","__publicField"],"mappings":";;;AAKO,MAAMA,UAAmB,MAAM;AAAA,EAEpC,YACWC,GACTC,GACSC,IAAoC,CAAA,GAC7CC,GACA;AACA,UAAMF,GAASE,CAAO;AAPN,IAAAC,EAAA,cAAO;AAEd,SAAA,OAAAJ,GAEA,KAAA,OAAAE;AAAA,EAIX;AACF;"}
1
+ {"version":3,"file":"error.js","sources":["../../src/core/error.ts"],"sourcesContent":["/**\n * The failures the graph names itself: no GPU device to draw with, or the one it had was taken back;\n * a device that holds no positions for the points it was given; a corpus with no vertex to draw; a crossfilter clause no vertex type can answer. A\n * corpus fossil will not read never gets here: `open` refuses it, coded. `data.after` is set when a deadline fired. Everything else reaches `onFailure` as thrown.\n */\nexport class GraphError extends Error {\n override readonly name = \"GraphError\";\n constructor(\n readonly code: \"graph/no-webgl\" | \"graph/context-lost\" | \"graph/no-positions\" | \"graph/nothing-to-draw\" | \"graph/unfilterable\",\n message: string,\n readonly data: { readonly after?: number } = {},\n options?: ErrorOptions,\n ) {\n super(message, options);\n }\n}\n"],"names":["GraphError","code","message","data","options","__publicField"],"mappings":";;;AAKO,MAAMA,UAAmB,MAAM;AAAA,EAEpC,YACWC,GACTC,GACSC,IAAoC,CAAA,GAC7CC,GACA;AACA,UAAMF,GAASE,CAAO;AAPN,IAAAC,EAAA,cAAO;AAEd,SAAA,OAAAJ,GAEA,KAAA,OAAAE;AAAA,EAIX;AACF;"}
@@ -50,9 +50,12 @@ export interface GraphOptions extends Channels {
50
50
  * **It is the data's life, not the layout's.** A layout running over a drawn graph is `idle` here and
51
51
  * `running` in `motion`: two axes, because each can move without the other — a filter loads under a
52
52
  * paused layout, and a layout runs over a graph with nothing left to read. A host that shows one word
53
- * reads both, `motion === "running"` as "laying out" and `progress` for how far.
53
+ * reads both, and the `GraphStatus` part is that word, so a host draws the part, not the two axes.
54
+ *
55
+ * Named for its axis rather than `GraphStatus` because the part holds that name: a consumer writes
56
+ * the part in every footer, and this union only where it reads `status` itself.
54
57
  */
55
- export type GraphStatus = "none" | "loading" | "idle" | "failed";
58
+ export type DataStatus = "none" | "loading" | "idle" | "failed";
56
59
  /** What the loaded graph holds, under the page's filter. */
57
60
  export interface Drawn {
58
61
  /** Vertices in full colour: every one with a position that survives the filter. */
@@ -66,9 +69,11 @@ export interface Drawn {
66
69
  }
67
70
  /** What a host and the parts read, through `useGraphState`. */
68
71
  export interface GraphState {
69
- readonly status: GraphStatus;
72
+ readonly status: DataStatus;
70
73
  /** Every vertex of the corpus — it does not shrink with a filter. */
71
74
  readonly total: number | undefined;
75
+ /** Vertices of the corpus the page's filter keeps, or `null` when nothing is filtered. */
76
+ readonly matching: number | null;
72
77
  /** What is loaded, or `null` before the graph has loaded. */
73
78
  readonly drawn: Drawn | null;
74
79
  /** The categorical domain before anything is loaded: the drawn tables, or the host's names. */
@@ -1 +1 @@
1
- {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/core/state.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/core/state.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
  import { GraphOptions, GraphStore } from './state';
2
- export type { Drawn, GraphOptions, GraphSnapshot, GraphState, GraphStatus, GraphStore } from './state';
2
+ export type { Drawn, GraphOptions, GraphSnapshot, GraphState, DataStatus, GraphStore } from './state';
3
3
  export declare function createGraph(initial: GraphOptions): GraphStore;
4
4
  //# sourceMappingURL=store.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/core/store.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAS,YAAY,EAA8B,UAAU,EAAE,MAAM,SAAS,CAAC;AAE3F,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AA4BvG,wBAAgB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,UAAU,CA4S7D"}
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/core/store.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAS,YAAY,EAA6B,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1F,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAmCtG,wBAAgB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,UAAU,CA8S7D"}
@@ -4,38 +4,45 @@ import { GraphClient as M, publish as R } from "./client.js";
4
4
  import { GraphError as V } from "./error.js";
5
5
  import { loadGeometry as W, loadEncoding as X } from "./load.js";
6
6
  import { readStructure as Y } from "./source.js";
7
- function Z(d, o, f) {
8
- const a = o.domain.map(() => 0), y = new Uint8Array(d.size);
7
+ function Z(f, t, a) {
8
+ const d = t.domain.map(() => 0), p = new Uint8Array(f.size);
9
9
  let l = 0;
10
- for (let r = 0; r < d.size; r++) {
11
- if (f && !f[r] || Number.isNaN(d.positions[r * 2])) continue;
12
- y[r] = 1, l++;
13
- const p = o.ranks[r];
14
- a[p] = (a[p] ?? 0) + 1;
10
+ for (let r = 0; r < f.size; r++) {
11
+ if (a && !a[r] || Number.isNaN(f.positions[r * 2])) continue;
12
+ p[r] = 1, l++;
13
+ const h = t.ranks[r];
14
+ d[h] = (d[h] ?? 0) + 1;
15
15
  }
16
- let u = 0;
17
- const { links: i } = d;
16
+ let s = 0;
17
+ const { links: i } = f;
18
18
  for (let r = 0; r < i.length; r += 2)
19
- y[i[r]] && y[i[r + 1]] && u++;
20
- return { vertices: l, edges: u, domain: o.domain, tally: a };
19
+ p[i[r]] && p[i[r + 1]] && s++;
20
+ return { vertices: l, edges: s, domain: t.domain, tally: d };
21
21
  }
22
- function H(d, o) {
23
- const f = new Uint8Array(d);
24
- for (const a of o) a < d && (f[a] = 1);
25
- return f;
22
+ function _(f) {
23
+ if (f === null) return null;
24
+ let t = 0;
25
+ for (const a of f) t += a;
26
+ return t;
26
27
  }
27
- function re(d) {
28
- let o = d;
29
- const f = /* @__PURE__ */ new Set();
30
- let a = !1, y = !1, l = $(d), u = null, i = null, r = null, p = null, h = null, O = [];
28
+ function H(f, t) {
29
+ const a = new Uint8Array(f);
30
+ for (const d of t) d < f && (a[d] = 1);
31
+ return a;
32
+ }
33
+ function le(f) {
34
+ let t = f;
35
+ const a = /* @__PURE__ */ new Set();
36
+ let d = !1, p = !1, l = $(f), s = null, i = null, r = null, h = null, g = null, z = [];
31
37
  const k = { structure: 0, geometry: 0, encoding: 0 }, b = { structure: !1, geometry: !1, encoding: !1 };
32
- let m = null, B = null, z = !1, C = !0, N = null;
38
+ let m = null, B = null, O = !1, C = !0, N = null;
33
39
  const G = (e) => {
34
- C ? N = { error: e } : o.onFailure(e);
40
+ C ? N = { error: e } : t.onFailure(e);
35
41
  };
36
42
  let c = {
37
43
  status: "none",
38
44
  total: void 0,
45
+ matching: null,
39
46
  drawn: null,
40
47
  domain: [],
41
48
  selection: null,
@@ -45,7 +52,7 @@ function re(d) {
45
52
  tool: null,
46
53
  motion: "settled",
47
54
  progress: 1,
48
- options: o,
55
+ options: t,
49
56
  structure: null,
50
57
  binding: l,
51
58
  geometry: null,
@@ -53,32 +60,33 @@ function re(d) {
53
60
  mask: null
54
61
  }, T = { key: [], value: [] };
55
62
  function E() {
56
- const e = (u == null ? void 0 : u.vertices) ?? [], n = [e, l.byTable, l.category, o.categories];
57
- return n.some((t, s) => t !== T.key[s]) && (T = { key: n, value: L(e, l, o.categories) }), T.value;
63
+ const e = (s == null ? void 0 : s.vertices) ?? [], n = [e, l.byTable, l.category, t.categories];
64
+ return n.some((o, u) => o !== T.key[u]) && (T = { key: n, value: L(e, l, t.categories) }), T.value;
58
65
  }
59
66
  let F = { key: [], value: null };
60
67
  function I() {
61
- const e = [i, r, h];
62
- return e.some((n, t) => n !== F.key[t]) && (F = { key: e, value: i && r ? Z(i, r, h) : null }), F.value;
68
+ const e = [i, r, g];
69
+ return e.some((n, o) => n !== F.key[o]) && (F = { key: e, value: i && r ? Z(i, r, g) : null }), F.value;
63
70
  }
64
71
  function J() {
65
- if (a || y) return "failed";
66
- if (o.from === null || o.coordinator === null) return "none";
67
- const n = i !== null && [i, r, h].every((t, s) => t === O[s]);
72
+ if (d || p) return "failed";
73
+ if (t.from === null || t.coordinator === null) return "none";
74
+ const n = i !== null && [i, r, g].every((o, u) => o === z[u]);
68
75
  return b.structure || b.geometry || b.encoding || !n ? "loading" : "idle";
69
76
  }
70
- function g(e = {}) {
77
+ function y(e = {}) {
71
78
  c = {
72
79
  ...c,
73
- total: u == null ? void 0 : u.size,
80
+ total: s == null ? void 0 : s.size,
81
+ matching: g === c.mask ? c.matching : _(g),
74
82
  drawn: I(),
75
83
  domain: E(),
76
- options: o,
77
- structure: u,
84
+ options: t,
85
+ structure: s,
78
86
  binding: l,
79
87
  geometry: i,
80
88
  encoding: r,
81
- mask: h,
89
+ mask: g,
82
90
  ...e
83
91
  }, c = { ...c, status: J() }, P();
84
92
  }
@@ -86,58 +94,58 @@ function re(d) {
86
94
  c = { ...c, ...e }, P();
87
95
  }
88
96
  function P() {
89
- for (const e of f) e();
97
+ for (const e of a) e();
90
98
  }
91
- function S(e, n, t) {
92
- const s = ++k[e];
99
+ function S(e, n, o) {
100
+ const u = ++k[e];
93
101
  b[e] = !0, n().then(
94
102
  (w) => {
95
- k[e] === s && (b[e] = !1, t(w), g());
103
+ k[e] === u && (b[e] = !1, o(w), y());
96
104
  },
97
105
  (w) => {
98
- k[e] === s && (b[e] = !1, a = !0, G(w), g());
106
+ k[e] === u && (b[e] = !1, d = !0, G(w), y());
99
107
  }
100
108
  );
101
109
  }
102
110
  function U() {
103
- const { coordinator: e, from: n } = o;
104
- e === null || n === null || S("structure", () => Y(e, n), (t) => {
105
- if (t.size === 0) {
106
- a = !0, G(new V("graph/nothing-to-draw", `the corpus attached as ${n} has no vertex`));
111
+ const { coordinator: e, from: n } = t;
112
+ e === null || n === null || S("structure", () => Y(e, n), (o) => {
113
+ if (o.size === 0) {
114
+ d = !0, G(new V("graph/nothing-to-draw", `the corpus attached as ${n} has no vertex`));
107
115
  return;
108
116
  }
109
- u = t, j(), m == null || m.requestQuery();
117
+ s = o, j(), m == null || m.requestQuery();
110
118
  });
111
119
  }
112
120
  function j() {
113
- const { coordinator: e } = o, n = u;
114
- e === null || n === null || S("geometry", () => W(e, n, l), (t) => {
115
- i = t, h = p ? H(t.size, p) : null, q();
121
+ const { coordinator: e } = t, n = s;
122
+ e === null || n === null || S("geometry", () => W(e, n, l), (o) => {
123
+ i = o, g = h ? H(o.size, h) : null, q();
116
124
  });
117
125
  }
118
126
  function q() {
119
- const { coordinator: e } = o, n = i;
127
+ const { coordinator: e } = t, n = i;
120
128
  if (e === null || n === null) return;
121
- const t = E();
122
- S("encoding", () => X(e, n, l, t), (s) => {
123
- r = s;
129
+ const o = E();
130
+ S("encoding", () => X(e, n, l, o), (u) => {
131
+ r = u;
124
132
  });
125
133
  }
126
134
  function K() {
127
135
  for (const e of Object.keys(k))
128
136
  k[e]++, b[e] = !1;
129
- a = !1, u = i = r = null, p = h = null, O = [], g({ selection: null, focus: null, hovered: null, pinned: [] }), U();
137
+ d = !1, s = i = r = null, h = g = null, z = [], y({ selection: null, focus: null, hovered: null, pinned: [] }), U();
130
138
  }
131
139
  function A() {
132
140
  D();
133
- const { coordinator: e, filterBy: n } = o;
141
+ const { coordinator: e, filterBy: n } = t;
134
142
  e !== null && (m = new M(
135
143
  n,
136
- () => u,
137
- (t) => {
138
- p = t, h = t && i ? H(i.size, t) : null, g();
144
+ () => s,
145
+ (o) => {
146
+ h = o, g = o && i ? H(i.size, o) : null, y();
139
147
  },
140
- (t) => G(t)
148
+ (o) => G(o)
141
149
  ), e.connect(m), B = e);
142
150
  }
143
151
  function D() {
@@ -150,35 +158,35 @@ function re(d) {
150
158
  * survives StrictMode mounting everything twice.
151
159
  */
152
160
  subscribe(e) {
153
- if (f.add(e), !z && (z = !0, A(), N !== null)) {
161
+ if (a.add(e), !O && (O = !0, A(), N !== null)) {
154
162
  const { error: n } = N;
155
- N = null, o.onFailure(n);
163
+ N = null, t.onFailure(n);
156
164
  }
157
165
  return () => {
158
- f.delete(e), f.size === 0 && Q.destroy();
166
+ a.delete(e), a.size === 0 && Q.destroy();
159
167
  };
160
168
  },
161
169
  getSnapshot: () => c,
162
- getOptions: () => o,
170
+ getOptions: () => t,
163
171
  setOptions(e) {
164
- const n = o;
165
- o = e;
166
- const t = l;
172
+ const n = t;
173
+ t = e;
174
+ const o = l;
167
175
  if (l = $(e), e.from !== n.from || e.coordinator !== n.coordinator)
168
- return z && e.coordinator !== n.coordinator && A(), K();
169
- z && e.filterBy !== n.filterBy && A(), l.x !== t.x || l.y !== t.y ? j() : (l.category !== t.category || l.byTable !== t.byTable || l.size !== t.size || l.cluster !== t.cluster || e.categories !== n.categories) && q(), g();
176
+ return O && e.coordinator !== n.coordinator && A(), K();
177
+ O && e.filterBy !== n.filterBy && A(), l.x !== o.x || l.y !== o.y ? j() : (l.category !== o.category || l.byTable !== o.byTable || l.size !== o.size || l.cluster !== o.cluster || e.categories !== n.categories) && q(), y();
170
178
  },
171
179
  destroy() {
172
- z = !1, D(), f.clear();
180
+ O = !1, D(), a.clear();
173
181
  },
174
- select(e, n = "node", t = "") {
182
+ select(e, n = "external", o = "") {
175
183
  var w;
176
- const s = e && e.length > 0 ? { vertices: [...e], source: n, label: t } : null;
177
- v({ selection: s }), (w = o.onSelect) == null || w.call(o, s), o.filterBy && m && R(o.filterBy, m, s ? s.vertices : null);
184
+ const u = e && e.length > 0 ? { vertices: [...e], source: n, label: o } : null;
185
+ v({ selection: u }), (w = t.onSelect) == null || w.call(t, u), t.filterBy && m && R(t.filterBy, m, u ? u.vertices : null);
178
186
  },
179
187
  focus(e) {
180
188
  var n;
181
- e !== c.focus && (v({ focus: e }), (n = o.onFocus) == null || n.call(o, e));
189
+ e !== c.focus && (v({ focus: e }), (n = t.onFocus) == null || n.call(t, e));
182
190
  },
183
191
  hover(e) {
184
192
  e !== c.hovered && v({ hovered: e });
@@ -196,19 +204,19 @@ function re(d) {
196
204
  e !== c.progress && v({ progress: e });
197
205
  },
198
206
  renderable() {
199
- y && (y = !1, g());
207
+ p && (p = !1, y());
200
208
  },
201
209
  unrenderable(e) {
202
- y = !0, G(e), g();
210
+ p = !0, G(e), y();
203
211
  },
204
212
  reportDrawn(e) {
205
213
  const n = [e.geometry, e.encoding, e.mask];
206
- n.every((t, s) => t === O[s]) || (O = n, g());
214
+ n.every((o, u) => o === z[u]) || (z = n, y());
207
215
  }
208
216
  };
209
- return U(), g(), C = !1, Q;
217
+ return U(), y(), C = !1, Q;
210
218
  }
211
219
  export {
212
- re as createGraph
220
+ le as createGraph
213
221
  };
214
222
  //# sourceMappingURL=store.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sources":["../../src/core/store.ts"],"sourcesContent":["import type { Coordinator } from \"@kanzo-tech/mosaic\";\nimport { domainOf } from \"./categories\";\nimport { bindingOf } from \"./channels\";\nimport { GraphClient, publish } from \"./client\";\nimport { GraphError } from \"./error\";\nimport { loadEncoding, loadGeometry, type Encoding, type Geometry } from \"./load\";\nimport { readStructure, type Structure } from \"./source\";\nimport type { Drawn, GraphOptions, GraphSnapshot, GraphStatus, GraphStore } from \"./state\";\n\nexport type { Drawn, GraphOptions, GraphSnapshot, GraphState, GraphStatus, GraphStore } from \"./state\";\n\nfunction drawnOf(geometry: Geometry, encoding: Encoding, mask: Uint8Array | null): Drawn {\n const tally = encoding.domain.map(() => 0);\n const shown = new Uint8Array(geometry.size);\n let vertices = 0;\n for (let id = 0; id < geometry.size; id++) {\n if ((mask && !mask[id]) || Number.isNaN(geometry.positions[id * 2])) continue;\n shown[id] = 1;\n vertices++;\n const rank = encoding.ranks[id] as number;\n tally[rank] = (tally[rank] ?? 0) + 1;\n }\n let edges = 0;\n const { links } = geometry;\n for (let i = 0; i < links.length; i += 2) {\n if (shown[links[i] as number] && shown[links[i + 1] as number]) edges++;\n }\n return { vertices, edges, domain: encoding.domain, tally };\n}\n\n/** `1` where a vertex is among `ids`. */\nfunction maskOf(size: number, ids: Float64Array): Uint8Array {\n const mask = new Uint8Array(size);\n for (const id of ids) if (id < size) mask[id] = 1;\n return mask;\n}\n\nexport function createGraph(initial: GraphOptions): GraphStore {\n let options = initial;\n const listeners = new Set<() => void>();\n\n let failed = false;\n let unrenderable = false;\n let binding = bindingOf(initial);\n let structure: Structure | null = null;\n let geometry: Geometry | null = null;\n let encoding: Encoding | null = null;\n let kept: Float64Array | null = null;\n let mask: Uint8Array | null = null;\n let uploaded: readonly unknown[] = [];\n /** One read per kind in flight; a newer one makes an older one's answer stale. */\n const reading = { structure: 0, geometry: 0, encoding: 0 };\n const pending = { structure: false, geometry: false, encoding: false };\n let client: GraphClient | null = null;\n let connected: Coordinator | null = null;\n let active = false;\n\n // A failure found while the store is being built is found while React is still rendering —\n // `useGraph` builds it in `useState` — and a host's `onFailure` is usually a `setState`. It is held\n // and reported to the first subscriber, which arrives in the commit phase.\n let building = true;\n let held: { error: unknown } | null = null;\n const fail = (error: unknown) => {\n if (building) held = { error };\n else options.onFailure(error);\n };\n\n let snapshot: GraphSnapshot = {\n status: \"none\",\n total: undefined,\n drawn: null,\n domain: [],\n selection: null,\n focus: null,\n hovered: null,\n pinned: [],\n tool: null,\n motion: \"settled\",\n progress: 1,\n options,\n structure: null,\n binding,\n geometry: null,\n encoding: null,\n mask: null,\n };\n\n let domain: { key: unknown[]; value: readonly unknown[] } = { key: [], value: [] };\n function domainNow(): readonly unknown[] {\n const tables = structure?.vertices ?? [];\n const key = [tables, binding.byTable, binding.category, options.categories];\n if (key.some((part, i) => part !== domain.key[i])) domain = { key, value: domainOf(tables, binding, options.categories) };\n return domain.value;\n }\n\n let drawn: { key: unknown[]; value: Drawn | null } = { key: [], value: null };\n function drawnNow(): Drawn | null {\n const key = [geometry, encoding, mask];\n if (key.some((part, i) => part !== drawn.key[i])) {\n drawn = { key, value: geometry && encoding ? drawnOf(geometry, encoding, mask) : null };\n }\n return drawn.value;\n }\n\n function statusOf(): GraphStatus {\n if (failed || unrenderable) return \"failed\";\n if (options.from === null || options.coordinator === null) return \"none\";\n const current = [geometry, encoding, mask];\n const shown = geometry !== null && current.every((part, i) => part === uploaded[i]);\n return pending.structure || pending.geometry || pending.encoding || !shown ? \"loading\" : \"idle\";\n }\n\n function notify(fields: Partial<GraphSnapshot> = {}): void {\n snapshot = {\n ...snapshot,\n total: structure?.size,\n drawn: drawnNow(),\n domain: domainNow(),\n options,\n structure,\n binding,\n geometry,\n encoding,\n mask,\n ...fields,\n };\n snapshot = { ...snapshot, status: statusOf() };\n emit();\n }\n\n /** A change of state only — hover, focus, selection, tool, motion — derives nothing. */\n function patch(fields: Partial<GraphSnapshot>): void {\n snapshot = { ...snapshot, ...fields };\n emit();\n }\n\n function emit(): void {\n for (const listener of listeners) listener();\n }\n\n /**\n * Read `kind`, and keep the answer only if no newer read of the same kind started meanwhile. The\n * coordinator cannot be told to stop a statement, so a stale answer is dropped rather than aborted.\n */\n function read<T>(kind: keyof typeof reading, ask: () => Promise<T>, done: (value: T) => void): void {\n const ticket = ++reading[kind];\n pending[kind] = true;\n ask().then(\n (value) => {\n if (reading[kind] !== ticket) return;\n pending[kind] = false;\n done(value);\n notify();\n },\n (error: unknown) => {\n if (reading[kind] !== ticket) return;\n pending[kind] = false;\n failed = true;\n fail(error);\n notify();\n },\n );\n }\n\n function loadStructure(): void {\n const { coordinator, from } = options;\n if (coordinator === null || from === null) return;\n read(\"structure\", () => readStructure(coordinator, from), (next) => {\n if (next.size === 0) {\n failed = true;\n fail(new GraphError(\"graph/nothing-to-draw\", `the corpus attached as ${from} has no vertex`));\n return;\n }\n structure = next;\n loadPositions();\n client?.requestQuery();\n });\n }\n\n function loadPositions(): void {\n const { coordinator } = options;\n const given = structure;\n if (coordinator === null || given === null) return;\n read(\"geometry\", () => loadGeometry(coordinator, given, binding), (next) => {\n geometry = next;\n mask = kept ? maskOf(next.size, kept) : null;\n loadChannels();\n });\n }\n\n function loadChannels(): void {\n const { coordinator } = options;\n const given = geometry;\n if (coordinator === null || given === null) return;\n const seed = domainNow();\n read(\"encoding\", () => loadEncoding(coordinator, given, binding, seed), (next) => {\n encoding = next;\n });\n }\n\n function reset(): void {\n for (const kind of Object.keys(reading) as (keyof typeof reading)[]) {\n reading[kind]++;\n pending[kind] = false;\n }\n failed = false;\n structure = geometry = encoding = null;\n kept = mask = null;\n uploaded = [];\n notify({ selection: null, focus: null, hovered: null, pinned: [] });\n loadStructure();\n }\n\n /** The graph's Mosaic client, connected to the coordinator while anything is subscribed. */\n function connect(): void {\n disconnect();\n const { coordinator, filterBy } = options;\n if (coordinator === null) return;\n client = new GraphClient(\n filterBy,\n () => structure,\n (ids) => {\n kept = ids;\n mask = ids && geometry ? maskOf(geometry.size, ids) : null;\n notify();\n },\n (error) => fail(error),\n );\n coordinator.connect(client);\n connected = coordinator;\n }\n\n function disconnect(): void {\n if (client && connected) connected.disconnect(client);\n client = null;\n connected = null;\n }\n\n const store: GraphStore = {\n /**\n * The first subscriber connects the client to the coordinator, and the last one disconnects it\n * and lets the graph go — `QueryObserver`'s `onSubscribe`/`onUnsubscribe`, which is what\n * survives StrictMode mounting everything twice.\n */\n subscribe(listener) {\n listeners.add(listener);\n if (!active) {\n active = true;\n connect();\n if (held !== null) {\n const { error } = held;\n held = null;\n options.onFailure(error);\n }\n }\n return () => {\n listeners.delete(listener);\n if (listeners.size === 0) store.destroy();\n };\n },\n getSnapshot: () => snapshot,\n getOptions: () => options,\n setOptions(next) {\n const previous = options;\n options = next;\n const before = binding;\n binding = bindingOf(next);\n if (next.from !== previous.from || next.coordinator !== previous.coordinator) {\n if (active && next.coordinator !== previous.coordinator) connect();\n return reset();\n }\n if (active && next.filterBy !== previous.filterBy) connect();\n if (binding.x !== before.x || binding.y !== before.y) loadPositions();\n else if (\n binding.category !== before.category ||\n binding.byTable !== before.byTable ||\n binding.size !== before.size ||\n binding.cluster !== before.cluster ||\n next.categories !== previous.categories\n ) {\n loadChannels();\n }\n notify();\n },\n destroy() {\n active = false;\n disconnect();\n listeners.clear();\n },\n select(vertices, source = \"node\", label = \"\") {\n const selection = vertices && vertices.length > 0 ? { vertices: [...vertices], source, label } : null;\n patch({ selection });\n options.onSelect?.(selection);\n if (options.filterBy && client) publish(options.filterBy, client, selection ? selection.vertices : null);\n },\n focus(vertex) {\n if (vertex === snapshot.focus) return;\n patch({ focus: vertex });\n options.onFocus?.(vertex);\n },\n hover(vertex) {\n if (vertex !== snapshot.hovered) patch({ hovered: vertex });\n },\n pin(vertices) {\n patch({ pinned: [...vertices] });\n },\n setTool(tool) {\n if (tool !== snapshot.tool) patch({ tool });\n },\n report(motion) {\n if (motion !== snapshot.motion) patch({ motion });\n },\n reportProgress(value) {\n if (value !== snapshot.progress) patch({ progress: value });\n },\n renderable() {\n if (!unrenderable) return;\n unrenderable = false;\n notify();\n },\n unrenderable(error) {\n unrenderable = true;\n fail(error);\n notify();\n },\n reportDrawn(drawnSnapshot) {\n const next = [drawnSnapshot.geometry, drawnSnapshot.encoding, drawnSnapshot.mask];\n if (next.every((part, i) => part === uploaded[i])) return;\n uploaded = next;\n notify();\n },\n };\n\n loadStructure();\n notify();\n building = false;\n return store;\n}\n"],"names":["drawnOf","geometry","encoding","mask","tally","shown","vertices","id","rank","edges","links","i","maskOf","size","ids","createGraph","initial","options","listeners","failed","unrenderable","binding","bindingOf","structure","kept","uploaded","reading","pending","client","connected","active","building","held","fail","error","snapshot","domain","domainNow","tables","key","part","domainOf","drawn","drawnNow","statusOf","notify","fields","emit","patch","listener","read","kind","ask","done","ticket","value","loadStructure","coordinator","from","readStructure","next","GraphError","loadPositions","given","loadGeometry","loadChannels","seed","loadEncoding","reset","connect","disconnect","filterBy","GraphClient","store","previous","before","source","label","selection","_a","publish","vertex","tool","motion","drawnSnapshot"],"mappings":"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"}
1
+ {"version":3,"file":"store.js","sources":["../../src/core/store.ts"],"sourcesContent":["import type { Coordinator } from \"@kanzo-tech/mosaic\";\nimport { domainOf } from \"./categories\";\nimport { bindingOf } from \"./channels\";\nimport { GraphClient, publish } from \"./client\";\nimport { GraphError } from \"./error\";\nimport { loadEncoding, loadGeometry, type Encoding, type Geometry } from \"./load\";\nimport { readStructure, type Structure } from \"./source\";\nimport type { Drawn, GraphOptions, GraphSnapshot, DataStatus, GraphStore } from \"./state\";\n\nexport type { Drawn, GraphOptions, GraphSnapshot, GraphState, DataStatus, GraphStore } from \"./state\";\n\nfunction drawnOf(geometry: Geometry, encoding: Encoding, mask: Uint8Array | null): Drawn {\n const tally = encoding.domain.map(() => 0);\n const shown = new Uint8Array(geometry.size);\n let vertices = 0;\n for (let id = 0; id < geometry.size; id++) {\n if ((mask && !mask[id]) || Number.isNaN(geometry.positions[id * 2])) continue;\n shown[id] = 1;\n vertices++;\n const rank = encoding.ranks[id] as number;\n tally[rank] = (tally[rank] ?? 0) + 1;\n }\n let edges = 0;\n const { links } = geometry;\n for (let i = 0; i < links.length; i += 2) {\n if (shown[links[i] as number] && shown[links[i + 1] as number]) edges++;\n }\n return { vertices, edges, domain: encoding.domain, tally };\n}\n\nfunction matchingOf(mask: Uint8Array | null): number | null {\n if (mask === null) return null;\n let n = 0;\n for (const kept of mask) n += kept;\n return n;\n}\n\n/** `1` where a vertex is among `ids`. */\nfunction maskOf(size: number, ids: Float64Array): Uint8Array {\n const mask = new Uint8Array(size);\n for (const id of ids) if (id < size) mask[id] = 1;\n return mask;\n}\n\nexport function createGraph(initial: GraphOptions): GraphStore {\n let options = initial;\n const listeners = new Set<() => void>();\n\n let failed = false;\n let unrenderable = false;\n let binding = bindingOf(initial);\n let structure: Structure | null = null;\n let geometry: Geometry | null = null;\n let encoding: Encoding | null = null;\n let kept: Float64Array | null = null;\n let mask: Uint8Array | null = null;\n let uploaded: readonly unknown[] = [];\n /** One read per kind in flight; a newer one makes an older one's answer stale. */\n const reading = { structure: 0, geometry: 0, encoding: 0 };\n const pending = { structure: false, geometry: false, encoding: false };\n let client: GraphClient | null = null;\n let connected: Coordinator | null = null;\n let active = false;\n\n // A failure found while the store is being built is found while React is still rendering —\n // `useGraph` builds it in `useState` — and a host's `onFailure` is usually a `setState`. It is held\n // and reported to the first subscriber, which arrives in the commit phase.\n let building = true;\n let held: { error: unknown } | null = null;\n const fail = (error: unknown) => {\n if (building) held = { error };\n else options.onFailure(error);\n };\n\n let snapshot: GraphSnapshot = {\n status: \"none\",\n total: undefined,\n matching: null,\n drawn: null,\n domain: [],\n selection: null,\n focus: null,\n hovered: null,\n pinned: [],\n tool: null,\n motion: \"settled\",\n progress: 1,\n options,\n structure: null,\n binding,\n geometry: null,\n encoding: null,\n mask: null,\n };\n\n let domain: { key: unknown[]; value: readonly unknown[] } = { key: [], value: [] };\n function domainNow(): readonly unknown[] {\n const tables = structure?.vertices ?? [];\n const key = [tables, binding.byTable, binding.category, options.categories];\n if (key.some((part, i) => part !== domain.key[i])) domain = { key, value: domainOf(tables, binding, options.categories) };\n return domain.value;\n }\n\n let drawn: { key: unknown[]; value: Drawn | null } = { key: [], value: null };\n function drawnNow(): Drawn | null {\n const key = [geometry, encoding, mask];\n if (key.some((part, i) => part !== drawn.key[i])) {\n drawn = { key, value: geometry && encoding ? drawnOf(geometry, encoding, mask) : null };\n }\n return drawn.value;\n }\n\n function statusOf(): DataStatus {\n if (failed || unrenderable) return \"failed\";\n if (options.from === null || options.coordinator === null) return \"none\";\n const current = [geometry, encoding, mask];\n const shown = geometry !== null && current.every((part, i) => part === uploaded[i]);\n return pending.structure || pending.geometry || pending.encoding || !shown ? \"loading\" : \"idle\";\n }\n\n function notify(fields: Partial<GraphSnapshot> = {}): void {\n snapshot = {\n ...snapshot,\n total: structure?.size,\n matching: mask === snapshot.mask ? snapshot.matching : matchingOf(mask),\n drawn: drawnNow(),\n domain: domainNow(),\n options,\n structure,\n binding,\n geometry,\n encoding,\n mask,\n ...fields,\n };\n snapshot = { ...snapshot, status: statusOf() };\n emit();\n }\n\n /** A change of state only — hover, focus, selection, tool, motion — derives nothing. */\n function patch(fields: Partial<GraphSnapshot>): void {\n snapshot = { ...snapshot, ...fields };\n emit();\n }\n\n function emit(): void {\n for (const listener of listeners) listener();\n }\n\n /**\n * Read `kind`, and keep the answer only if no newer read of the same kind started meanwhile. The\n * coordinator cannot be told to stop a statement, so a stale answer is dropped rather than aborted.\n */\n function read<T>(kind: keyof typeof reading, ask: () => Promise<T>, done: (value: T) => void): void {\n const ticket = ++reading[kind];\n pending[kind] = true;\n ask().then(\n (value) => {\n if (reading[kind] !== ticket) return;\n pending[kind] = false;\n done(value);\n notify();\n },\n (error: unknown) => {\n if (reading[kind] !== ticket) return;\n pending[kind] = false;\n failed = true;\n fail(error);\n notify();\n },\n );\n }\n\n function loadStructure(): void {\n const { coordinator, from } = options;\n if (coordinator === null || from === null) return;\n read(\"structure\", () => readStructure(coordinator, from), (next) => {\n if (next.size === 0) {\n failed = true;\n fail(new GraphError(\"graph/nothing-to-draw\", `the corpus attached as ${from} has no vertex`));\n return;\n }\n structure = next;\n loadPositions();\n client?.requestQuery();\n });\n }\n\n function loadPositions(): void {\n const { coordinator } = options;\n const given = structure;\n if (coordinator === null || given === null) return;\n read(\"geometry\", () => loadGeometry(coordinator, given, binding), (next) => {\n geometry = next;\n mask = kept ? maskOf(next.size, kept) : null;\n loadChannels();\n });\n }\n\n function loadChannels(): void {\n const { coordinator } = options;\n const given = geometry;\n if (coordinator === null || given === null) return;\n const seed = domainNow();\n read(\"encoding\", () => loadEncoding(coordinator, given, binding, seed), (next) => {\n encoding = next;\n });\n }\n\n function reset(): void {\n for (const kind of Object.keys(reading) as (keyof typeof reading)[]) {\n reading[kind]++;\n pending[kind] = false;\n }\n failed = false;\n structure = geometry = encoding = null;\n kept = mask = null;\n uploaded = [];\n notify({ selection: null, focus: null, hovered: null, pinned: [] });\n loadStructure();\n }\n\n /** The graph's Mosaic client, connected to the coordinator while anything is subscribed. */\n function connect(): void {\n disconnect();\n const { coordinator, filterBy } = options;\n if (coordinator === null) return;\n client = new GraphClient(\n filterBy,\n () => structure,\n (ids) => {\n kept = ids;\n mask = ids && geometry ? maskOf(geometry.size, ids) : null;\n notify();\n },\n (error) => fail(error),\n );\n coordinator.connect(client);\n connected = coordinator;\n }\n\n function disconnect(): void {\n if (client && connected) connected.disconnect(client);\n client = null;\n connected = null;\n }\n\n const store: GraphStore = {\n /**\n * The first subscriber connects the client to the coordinator, and the last one disconnects it\n * and lets the graph go — `QueryObserver`'s `onSubscribe`/`onUnsubscribe`, which is what\n * survives StrictMode mounting everything twice.\n */\n subscribe(listener) {\n listeners.add(listener);\n if (!active) {\n active = true;\n connect();\n if (held !== null) {\n const { error } = held;\n held = null;\n options.onFailure(error);\n }\n }\n return () => {\n listeners.delete(listener);\n if (listeners.size === 0) store.destroy();\n };\n },\n getSnapshot: () => snapshot,\n getOptions: () => options,\n setOptions(next) {\n const previous = options;\n options = next;\n const before = binding;\n binding = bindingOf(next);\n if (next.from !== previous.from || next.coordinator !== previous.coordinator) {\n if (active && next.coordinator !== previous.coordinator) connect();\n return reset();\n }\n if (active && next.filterBy !== previous.filterBy) connect();\n if (binding.x !== before.x || binding.y !== before.y) loadPositions();\n else if (\n binding.category !== before.category ||\n binding.byTable !== before.byTable ||\n binding.size !== before.size ||\n binding.cluster !== before.cluster ||\n next.categories !== previous.categories\n ) {\n loadChannels();\n }\n notify();\n },\n destroy() {\n active = false;\n disconnect();\n listeners.clear();\n },\n select(vertices, source = \"external\", label = \"\") {\n const selection = vertices && vertices.length > 0 ? { vertices: [...vertices], source, label } : null;\n patch({ selection });\n options.onSelect?.(selection);\n if (options.filterBy && client) publish(options.filterBy, client, selection ? selection.vertices : null);\n },\n focus(vertex) {\n if (vertex === snapshot.focus) return;\n patch({ focus: vertex });\n options.onFocus?.(vertex);\n },\n hover(vertex) {\n if (vertex !== snapshot.hovered) patch({ hovered: vertex });\n },\n pin(vertices) {\n patch({ pinned: [...vertices] });\n },\n setTool(tool) {\n if (tool !== snapshot.tool) patch({ tool });\n },\n report(motion) {\n if (motion !== snapshot.motion) patch({ motion });\n },\n reportProgress(value) {\n if (value !== snapshot.progress) patch({ progress: value });\n },\n renderable() {\n if (!unrenderable) return;\n unrenderable = false;\n notify();\n },\n unrenderable(error) {\n unrenderable = true;\n fail(error);\n notify();\n },\n reportDrawn(drawnSnapshot) {\n const next = [drawnSnapshot.geometry, drawnSnapshot.encoding, drawnSnapshot.mask];\n if (next.every((part, i) => part === uploaded[i])) return;\n uploaded = next;\n notify();\n },\n };\n\n loadStructure();\n notify();\n building = false;\n return store;\n}\n"],"names":["drawnOf","geometry","encoding","mask","tally","shown","vertices","id","rank","edges","links","i","matchingOf","n","kept","maskOf","size","ids","createGraph","initial","options","listeners","failed","unrenderable","binding","bindingOf","structure","uploaded","reading","pending","client","connected","active","building","held","fail","error","snapshot","domain","domainNow","tables","key","part","domainOf","drawn","drawnNow","statusOf","notify","fields","emit","patch","listener","read","kind","ask","done","ticket","value","loadStructure","coordinator","from","readStructure","next","GraphError","loadPositions","given","loadGeometry","loadChannels","seed","loadEncoding","reset","connect","disconnect","filterBy","GraphClient","store","previous","before","source","label","selection","_a","publish","vertex","tool","motion","drawnSnapshot"],"mappings":"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"}