@kanzo-tech/graph 0.9.0 → 0.11.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 +60 -95
- package/dist/core/categories.d.ts +12 -0
- package/dist/core/categories.d.ts.map +1 -0
- package/dist/core/categories.js +14 -0
- package/dist/core/categories.js.map +1 -0
- package/dist/core/channels.d.ts +34 -0
- package/dist/core/channels.d.ts.map +1 -0
- package/dist/core/channels.js +19 -0
- package/dist/core/channels.js.map +1 -0
- package/dist/core/detail.d.ts +18 -0
- package/dist/core/detail.d.ts.map +1 -0
- package/dist/core/detail.js +20 -0
- package/dist/core/detail.js.map +1 -0
- package/dist/core/filter.d.ts +34 -0
- package/dist/core/filter.d.ts.map +1 -0
- package/dist/core/filter.js +99 -0
- package/dist/core/filter.js.map +1 -0
- package/dist/core/refine.d.ts +14 -0
- package/dist/core/refine.d.ts.map +1 -0
- package/dist/core/refine.js +20 -0
- package/dist/core/refine.js.map +1 -0
- package/dist/{resident.d.ts → core/resident.d.ts} +8 -8
- package/dist/core/resident.d.ts.map +1 -0
- package/dist/core/resident.js +44 -0
- package/dist/core/resident.js.map +1 -0
- package/dist/core/scheduler.d.ts +42 -0
- package/dist/core/scheduler.d.ts.map +1 -0
- package/dist/core/scheduler.js +77 -0
- package/dist/core/scheduler.js.map +1 -0
- package/dist/core/state.d.ts +132 -0
- package/dist/core/state.d.ts.map +1 -0
- package/dist/core/store.d.ts +6 -0
- package/dist/core/store.d.ts.map +1 -0
- package/dist/core/store.js +235 -0
- package/dist/core/store.js.map +1 -0
- package/dist/core/tile-matrix.d.ts +37 -0
- package/dist/core/tile-matrix.d.ts.map +1 -0
- package/dist/core/tile-matrix.js +49 -0
- package/dist/core/tile-matrix.js.map +1 -0
- package/dist/core/tile.d.ts +54 -0
- package/dist/core/tile.d.ts.map +1 -0
- package/dist/core/tile.js +76 -0
- package/dist/core/tile.js.map +1 -0
- package/dist/core/tileset.d.ts +59 -0
- package/dist/core/tileset.d.ts.map +1 -0
- package/dist/core/tileset.js +177 -0
- package/dist/core/tileset.js.map +1 -0
- package/dist/{types.d.ts → core/types.d.ts} +9 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/index.d.ts +37 -70
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +32 -34
- package/dist/index.js.map +1 -1
- package/dist/{use-graph-selection.d.ts → parts/gesture.d.ts} +4 -4
- package/dist/parts/gesture.d.ts.map +1 -0
- package/dist/{use-graph-selection.js → parts/gesture.js} +17 -17
- package/dist/parts/gesture.js.map +1 -0
- package/dist/parts/graph-canvas.d.ts +17 -0
- package/dist/parts/graph-canvas.d.ts.map +1 -0
- package/dist/parts/graph-canvas.js +174 -0
- package/dist/parts/graph-canvas.js.map +1 -0
- package/dist/parts/graph-inspector.d.ts +18 -0
- package/dist/parts/graph-inspector.d.ts.map +1 -0
- package/dist/parts/graph-inspector.js +84 -0
- package/dist/parts/graph-inspector.js.map +1 -0
- package/dist/parts/graph-legend.d.ts +12 -0
- package/dist/parts/graph-legend.d.ts.map +1 -0
- package/dist/parts/graph-legend.js +61 -0
- package/dist/parts/graph-legend.js.map +1 -0
- package/dist/parts/graph-toolbar.d.ts +15 -0
- package/dist/parts/graph-toolbar.d.ts.map +1 -0
- package/dist/parts/graph-toolbar.js +94 -0
- package/dist/parts/graph-toolbar.js.map +1 -0
- package/dist/parts/overlays.d.ts +33 -0
- package/dist/parts/overlays.d.ts.map +1 -0
- package/dist/{use-graph-overlays.js → parts/overlays.js} +8 -8
- package/dist/parts/overlays.js.map +1 -0
- package/dist/{shape-glyph.d.ts → parts/shape-glyph.d.ts} +1 -1
- package/dist/parts/shape-glyph.d.ts.map +1 -0
- package/dist/{shape-glyph.js → parts/shape-glyph.js} +1 -1
- package/dist/parts/shape-glyph.js.map +1 -0
- package/dist/react/graph-root.d.ts +15 -0
- package/dist/react/graph-root.d.ts.map +1 -0
- package/dist/react/graph-root.js +23 -0
- package/dist/react/graph-root.js.map +1 -0
- package/dist/{use-graph-prefs.d.ts → react/use-graph-prefs.d.ts} +2 -2
- package/dist/react/use-graph-prefs.d.ts.map +1 -0
- package/dist/{use-graph-prefs.js → react/use-graph-prefs.js} +3 -3
- package/dist/react/use-graph-prefs.js.map +1 -0
- package/dist/react/use-graph-state.d.ts +11 -0
- package/dist/react/use-graph-state.d.ts.map +1 -0
- package/dist/react/use-graph-state.js +16 -0
- package/dist/react/use-graph-state.js.map +1 -0
- package/dist/react/use-graph.d.ts +38 -0
- package/dist/react/use-graph.d.ts.map +1 -0
- package/dist/react/use-graph.js +87 -0
- package/dist/react/use-graph.js.map +1 -0
- package/dist/{adaptive.d.ts → render/adaptive.d.ts} +1 -1
- package/dist/render/adaptive.d.ts.map +1 -0
- package/dist/render/adaptive.js.map +1 -0
- package/dist/render/compose.d.ts +51 -0
- package/dist/render/compose.d.ts.map +1 -0
- package/dist/render/compose.js +107 -0
- package/dist/render/compose.js.map +1 -0
- package/dist/render/css-color.d.ts.map +1 -0
- package/dist/render/css-color.js.map +1 -0
- package/dist/render/encode.d.ts +42 -0
- package/dist/render/encode.d.ts.map +1 -0
- package/dist/render/encode.js +68 -0
- package/dist/render/encode.js.map +1 -0
- package/dist/render/graph-looks.d.ts.map +1 -0
- package/dist/render/graph-looks.js.map +1 -0
- package/dist/render/graph-model.d.ts +44 -0
- package/dist/render/graph-model.d.ts.map +1 -0
- package/dist/render/graph-model.js +80 -0
- package/dist/render/graph-model.js.map +1 -0
- package/dist/{graph-sim.d.ts → render/graph-sim.d.ts} +2 -2
- package/dist/render/graph-sim.d.ts.map +1 -0
- package/dist/render/graph-sim.js.map +1 -0
- package/dist/{obligations.d.ts → render/obligations.d.ts} +1 -1
- package/dist/render/obligations.d.ts.map +1 -0
- package/dist/render/renderer.d.ts +38 -0
- package/dist/render/renderer.d.ts.map +1 -0
- package/dist/render/renderer.js +235 -0
- package/dist/render/renderer.js.map +1 -0
- package/dist/render/webgl.d.ts +14 -0
- package/dist/render/webgl.d.ts.map +1 -0
- package/dist/render/webgl.js +19 -0
- package/dist/render/webgl.js.map +1 -0
- package/dist/render/when-ready.d.ts.map +1 -0
- package/dist/render/when-ready.js.map +1 -0
- package/package.json +11 -21
- package/dist/adaptive.d.ts.map +0 -1
- package/dist/adaptive.js.map +0 -1
- package/dist/bounded.d.ts +0 -364
- package/dist/bounded.d.ts.map +0 -1
- package/dist/bounded.js +0 -18
- package/dist/bounded.js.map +0 -1
- package/dist/cluster-ring.d.ts +0 -25
- package/dist/cluster-ring.d.ts.map +0 -1
- package/dist/cluster-ring.js +0 -16
- package/dist/cluster-ring.js.map +0 -1
- package/dist/css-color.d.ts.map +0 -1
- package/dist/css-color.js.map +0 -1
- package/dist/duck-source.d.ts +0 -198
- package/dist/duck-source.d.ts.map +0 -1
- package/dist/duck-source.js +0 -320
- package/dist/duck-source.js.map +0 -1
- package/dist/graph-canvas.d.ts +0 -50
- package/dist/graph-canvas.d.ts.map +0 -1
- package/dist/graph-canvas.js +0 -35
- package/dist/graph-canvas.js.map +0 -1
- package/dist/graph-looks.d.ts.map +0 -1
- package/dist/graph-looks.js.map +0 -1
- package/dist/graph-model.d.ts +0 -130
- package/dist/graph-model.d.ts.map +0 -1
- package/dist/graph-model.js +0 -104
- package/dist/graph-model.js.map +0 -1
- package/dist/graph-sim.d.ts.map +0 -1
- package/dist/graph-sim.js.map +0 -1
- package/dist/obligations.d.ts.map +0 -1
- package/dist/resident.d.ts.map +0 -1
- package/dist/resident.js +0 -44
- package/dist/resident.js.map +0 -1
- package/dist/shape-glyph.d.ts.map +0 -1
- package/dist/shape-glyph.js.map +0 -1
- package/dist/slice-client.d.ts +0 -78
- package/dist/slice-client.d.ts.map +0 -1
- package/dist/slice-client.js +0 -98
- package/dist/slice-client.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/use-graph-look.d.ts +0 -28
- package/dist/use-graph-look.d.ts.map +0 -1
- package/dist/use-graph-look.js +0 -28
- package/dist/use-graph-look.js.map +0 -1
- package/dist/use-graph-overlays.d.ts +0 -44
- package/dist/use-graph-overlays.d.ts.map +0 -1
- package/dist/use-graph-overlays.js.map +0 -1
- package/dist/use-graph-prefs.d.ts.map +0 -1
- package/dist/use-graph-prefs.js.map +0 -1
- package/dist/use-graph-selection.d.ts.map +0 -1
- package/dist/use-graph-selection.js.map +0 -1
- package/dist/use-graph.d.ts +0 -203
- package/dist/use-graph.d.ts.map +0 -1
- package/dist/use-graph.js +0 -102
- package/dist/use-graph.js.map +0 -1
- package/dist/use-query-loop.d.ts +0 -88
- package/dist/use-query-loop.d.ts.map +0 -1
- package/dist/use-query-loop.js +0 -148
- package/dist/use-query-loop.js.map +0 -1
- package/dist/use-renderer.d.ts +0 -86
- package/dist/use-renderer.d.ts.map +0 -1
- package/dist/use-renderer.js +0 -188
- package/dist/use-renderer.js.map +0 -1
- package/dist/when-ready.d.ts.map +0 -1
- package/dist/when-ready.js.map +0 -1
- /package/dist/{adaptive.js → render/adaptive.js} +0 -0
- /package/dist/{css-color.d.ts → render/css-color.d.ts} +0 -0
- /package/dist/{css-color.js → render/css-color.js} +0 -0
- /package/dist/{graph-looks.d.ts → render/graph-looks.d.ts} +0 -0
- /package/dist/{graph-looks.js → render/graph-looks.js} +0 -0
- /package/dist/{graph-sim.js → render/graph-sim.js} +0 -0
- /package/dist/{when-ready.d.ts → render/when-ready.d.ts} +0 -0
- /package/dist/{when-ready.js → render/when-ready.js} +0 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const O = 32n, a = 0xffffffffn;
|
|
2
|
+
function g(t, e) {
|
|
3
|
+
return BigInt(t) << O | BigInt(e);
|
|
4
|
+
}
|
|
5
|
+
function h(t) {
|
|
6
|
+
return Number(t >> O);
|
|
7
|
+
}
|
|
8
|
+
function l(t) {
|
|
9
|
+
return Number(t & a);
|
|
10
|
+
}
|
|
11
|
+
const x = new BigUint64Array(0);
|
|
12
|
+
function p(t = x, e = (t == null ? void 0 : t.length) ?? 0) {
|
|
13
|
+
const r = t ?? x, i = Math.min(e, r.length), u = /* @__PURE__ */ new Map();
|
|
14
|
+
for (let n = 0; n < i; n++) u.set(r[n], n);
|
|
15
|
+
const c = (n) => n >= 0 && n < i ? r[n] : void 0, d = (n) => u.get(n);
|
|
16
|
+
return {
|
|
17
|
+
size: i,
|
|
18
|
+
indexOf: d,
|
|
19
|
+
at: c,
|
|
20
|
+
indicesOf(n) {
|
|
21
|
+
const o = [];
|
|
22
|
+
for (const s of n) {
|
|
23
|
+
const f = d(s);
|
|
24
|
+
f !== void 0 && o.push(f);
|
|
25
|
+
}
|
|
26
|
+
return o;
|
|
27
|
+
},
|
|
28
|
+
verticesAt(n) {
|
|
29
|
+
const o = [];
|
|
30
|
+
for (const s of n) {
|
|
31
|
+
const f = c(s);
|
|
32
|
+
f !== void 0 && o.push(f);
|
|
33
|
+
}
|
|
34
|
+
return o;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export {
|
|
39
|
+
l as denseOf,
|
|
40
|
+
p as residentOf,
|
|
41
|
+
h as typeOf,
|
|
42
|
+
g as vertexId
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=resident.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resident.js","sources":["../../src/core/resident.ts"],"sourcesContent":["\n/**\n * Who is drawn, and where the GPU is drawing them.\n *\n * **A buffer index numbers the answer, not the corpus.** cosmos.gl addresses every point by its\n * position in the arrays it was last handed, so index 7 is whatever the current answer put seventh —\n * and a resident set that comes and goes reuses every index while the vertices behind them change.\n * Anything that outlives one answer — a selection, a label, a hover, a pin — therefore has to be\n * held as an identity and re-resolved against whatever is drawn now.\n *\n * **A vertex is the pair `(type_idx, dense_id)`.** Not `dense_id` alone: it numbers\n * within one vertex type, so a union of two types repeats every value and the same number names two\n * different vertices. A `LIMIT` breaks the correspondence between an id and a position regardless of\n * how many types there are.\n */\n\n/**\n * A vertex identity — the pair, packed into one 64-bit integer so it can key a `Map` and a `Set`.\n *\n * **A `bigint`, which is strictly stronger than the brand it also wears.** A buffer index is a\n * `number`; an identity is a `bigint`. Confusing the two therefore stops being a branding\n * convention that holds while everyone remembers it and becomes a *primitive* type error — and no\n * cast quietly launders one: `7 as VertexId` was legal against `number & brand` and is a compile\n * error against `bigint & brand`. Getting one wrong now costs `as unknown as`, which is loud.\n *\n * **The evidence this is worth the friction, because it is not a precaution we invented.** Across\n * every multi-language format surveyed — Arrow, Parquet, Iceberg, Delta, MVT, PMTiles, Zarr,\n * GraphAr, H3, S2 — the failure that recurs is a 64-bit value crossing into JavaScript.\n * `mapbox/node-s2` is a **binding**, not a port: it calls the same C++ the reference implementation\n * does, and it still returned wrong cell ids — issue #92, open since 2017, `1152921504606847000`\n * where Java and Go both give `1152921504606846977`. JavaScript's `number` is 53 bits and a cell id\n * is 64, and a binding cannot protect a language boundary that cannot hold the value. H3 settled it\n * by decree before anyone could get it wrong: `h3-js` types `H3Index` as a string. This is the same\n * decree with the type JavaScript grew for it.\n *\n * **And `>>` means three different things across our three layers.** In JavaScript it converts its\n * operand to *32 bits* and takes the shift count modulo 32, so the obvious `dense | (type << 32)`\n * is not a lost high word — it is `type | dense`, silently. The packing below cannot be written on\n * `number` at all and be right.\n *\n * What goes to the GPU does not change: positions and buffer indices stay `number` and\n * `Float32Array`. The conversion happens at the edge, which is where it belongs.\n */\nexport type VertexId = bigint & { readonly vertex: unique symbol };\n\n/**\n * One type's worth of dense ids.\n *\n * `dense_id` is a `UInt32`, so the type index occupies everything above bit 32 — exactly, for all\n * 2³² of them, which is the whole point of the width. The old packing was `type * 2**32 + dense` in\n * `float64` and ran out of exactness at type index 2²¹.\n */\nconst TYPE_SHIFT = 32n;\nconst DENSE_MASK = 0xffff_ffffn;\n\nexport function vertexId(type: number, dense: number): VertexId {\n return ((BigInt(type) << TYPE_SHIFT) | BigInt(dense)) as VertexId;\n}\n\n/** Both halves come back as `number`: each is 32 bits, and a `number` holds those exactly. */\nexport function typeOf(vertex: VertexId): number {\n return Number(vertex >> TYPE_SHIFT);\n}\n\nexport function denseOf(vertex: VertexId): number {\n return Number(vertex & DENSE_MASK);\n}\n\n/**\n * The identity↔index map for whatever is drawn right now.\n *\n * Built once per residency change and never mutated, because that is what a residency change *is*: a\n * different set of vertices, in a different order. It belongs to whoever owns residency — that is\n * the renderer, which composes the buffers — and is read from there by everything else, because a\n * second copy is a second copy that can disagree with the buffers on screen.\n */\nexport interface Resident {\n /** How many points are drawn. */\n readonly size: number;\n /** Where a vertex is drawn, or `undefined` when it is not resident. */\n indexOf(vertex: VertexId): number | undefined;\n /** Which vertex is drawn at a buffer index, or `undefined` past the end of the answer. */\n at(index: number): VertexId | undefined;\n /** Where these vertices are drawn, skipping every one that is not resident. */\n indicesOf(vertices: Iterable<VertexId>): number[];\n /** Which vertices are drawn at these buffer indices, skipping any the answer does not hold. */\n verticesAt(indices: Iterable<number>): VertexId[];\n}\n\nconst NOBODY = new BigUint64Array(0);\n\n/**\n * The map a composition implies, over its first `size` slots. A composition puts its vertices\n * first — then the cells, which have no identity, then the far ends drawn only so an edge has one —\n * so nothing hovers, selects or frames a slot past them. Before the first composition nobody is\n * resident, which is not an error.\n *\n * Keyed by the identity itself. `Map` and `Set` compare keys by SameValueZero, which for a `bigint`\n * is *value* equality — asserted in `resident.test.ts`, because the whole file rests on it.\n */\nexport function residentOf(vertices: BigUint64Array | null = NOBODY, size = vertices?.length ?? 0): Resident {\n const all = vertices ?? NOBODY;\n const drawn = Math.min(size, all.length);\n const index = new Map<bigint, number>();\n for (let i = 0; i < drawn; i++) index.set(all[i] as bigint, i);\n const at = (i: number): VertexId | undefined => (i >= 0 && i < drawn ? (all[i] as VertexId) : undefined);\n const indexOf = (vertex: VertexId): number | undefined => index.get(vertex);\n\n return {\n size: drawn,\n indexOf,\n at,\n indicesOf(wanted) {\n const found: number[] = [];\n for (const vertex of wanted) {\n const i = indexOf(vertex);\n if (i !== undefined) found.push(i);\n }\n return found;\n },\n verticesAt(indices) {\n const found: VertexId[] = [];\n for (const i of indices) {\n const vertex = at(i);\n if (vertex !== undefined) found.push(vertex);\n }\n return found;\n },\n };\n}\n"],"names":["TYPE_SHIFT","DENSE_MASK","vertexId","type","dense","typeOf","vertex","denseOf","NOBODY","residentOf","vertices","size","all","drawn","index","i","at","indexOf","wanted","found","indices"],"mappings":"AAoDA,MAAMA,IAAa,KACbC,IAAa;AAEZ,SAASC,EAASC,GAAcC,GAAyB;AAC9D,SAAS,OAAOD,CAAI,KAAKH,IAAc,OAAOI,CAAK;AACrD;AAGO,SAASC,EAAOC,GAA0B;AAC/C,SAAO,OAAOA,KAAUN,CAAU;AACpC;AAEO,SAASO,EAAQD,GAA0B;AAChD,SAAO,OAAOA,IAASL,CAAU;AACnC;AAuBA,MAAMO,IAAS,IAAI,eAAe,CAAC;AAW5B,SAASC,EAAWC,IAAkCF,GAAQG,KAAOD,KAAA,gBAAAA,EAAU,WAAU,GAAa;AAC3G,QAAME,IAAMF,KAAYF,GAClBK,IAAQ,KAAK,IAAIF,GAAMC,EAAI,MAAM,GACjCE,wBAAY,IAAA;AAClB,WAASC,IAAI,GAAGA,IAAIF,GAAOE,OAAW,IAAIH,EAAIG,CAAC,GAAaA,CAAC;AAC7D,QAAMC,IAAK,CAACD,MAAqCA,KAAK,KAAKA,IAAIF,IAASD,EAAIG,CAAC,IAAiB,QACxFE,IAAU,CAACX,MAAyCQ,EAAM,IAAIR,CAAM;AAE1E,SAAO;AAAA,IACL,MAAMO;AAAA,IACN,SAAAI;AAAA,IACA,IAAAD;AAAA,IACA,UAAUE,GAAQ;AAChB,YAAMC,IAAkB,CAAA;AACxB,iBAAWb,KAAUY,GAAQ;AAC3B,cAAMH,IAAIE,EAAQX,CAAM;AACxB,QAAIS,MAAM,UAAWI,EAAM,KAAKJ,CAAC;AAAA,MACnC;AACA,aAAOI;AAAA,IACT;AAAA,IACA,WAAWC,GAAS;AAClB,YAAMD,IAAoB,CAAA;AAC1B,iBAAWJ,KAAKK,GAAS;AACvB,cAAMd,IAASU,EAAGD,CAAC;AACnB,QAAIT,MAAW,UAAWa,EAAM,KAAKb,CAAM;AAAA,MAC7C;AACA,aAAOa;AAAA,IACT;AAAA,EAAA;AAEJ;"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* loaders.gl's `RequestScheduler`, issuing a **batch** where it issues a request, with one slot:
|
|
3
|
+
* DuckDB-WASM is one worker behind one port, so a second statement queues behind the first rather
|
|
4
|
+
* than overlapping it, and fossil reads a run of consecutive tiles as one statement only when it is
|
|
5
|
+
* handed them in one call (`/docs/design/graph`, *one batch in flight*).
|
|
6
|
+
*
|
|
7
|
+
* Priorities are asked again each time a slot frees, the debounce settles or `prune` runs. A negative
|
|
8
|
+
* priority is a request nobody wants any more: queued, it resolves `null` without ever being issued;
|
|
9
|
+
* in flight, its batch is aborted only once no request in it is wanted — a batch that still answers
|
|
10
|
+
* someone finishes, and answers everyone in it.
|
|
11
|
+
*/
|
|
12
|
+
/** A request's answer, its batch's failure, or `null` when it was never issued or was aborted. */
|
|
13
|
+
export type Outcome<R> = {
|
|
14
|
+
readonly value: R;
|
|
15
|
+
} | {
|
|
16
|
+
readonly error: unknown;
|
|
17
|
+
} | null;
|
|
18
|
+
export interface SchedulerOptions<T, R> {
|
|
19
|
+
/** One call for a batch: an answer per handle, in the order given. */
|
|
20
|
+
run: (handles: readonly T[], signal: AbortSignal) => Promise<readonly R[]>;
|
|
21
|
+
/** Batches running at once. */
|
|
22
|
+
maxRequests?: number;
|
|
23
|
+
/** Quiet time, in milliseconds, before the queue is issued — a pan settles before it asks. */
|
|
24
|
+
debounceTime?: number;
|
|
25
|
+
}
|
|
26
|
+
export declare class RequestScheduler<T, R> {
|
|
27
|
+
#private;
|
|
28
|
+
constructor({ debounceTime, maxRequests, run }: SchedulerOptions<T, R>);
|
|
29
|
+
schedule(handle: T, priority: (handle: T) => number): Promise<Outcome<R>>;
|
|
30
|
+
/** How many requests are queued, and how many batches are running. */
|
|
31
|
+
get size(): {
|
|
32
|
+
queued: number;
|
|
33
|
+
active: number;
|
|
34
|
+
};
|
|
35
|
+
/** The caller no longer wants `handle`'s answer: it resolves `null` now, wherever it is. */
|
|
36
|
+
cancel(handle: T): void;
|
|
37
|
+
/** Drops queued requests nobody wants, and aborts a batch in which nobody wants anything. */
|
|
38
|
+
prune(): void;
|
|
39
|
+
/** Every queued request resolves `null`, and every running batch is aborted. */
|
|
40
|
+
clear(): void;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=scheduler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../src/core/scheduler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,kGAAkG;AAClG,MAAM,MAAM,OAAO,CAAC,CAAC,IAAI;IAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAAC;AAepF,MAAM,WAAW,gBAAgB,CAAC,CAAC,EAAE,CAAC;IACpC,sEAAsE;IACtE,GAAG,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IAC3E,+BAA+B;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8FAA8F;IAC9F,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,gBAAgB,CAAC,CAAC,EAAE,CAAC;;gBAQpB,EAAE,YAAgB,EAAE,WAAe,EAAE,GAAG,EAAE,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC;IAM9E,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAOzE,sEAAsE;IACtE,IAAI,IAAI,IAAI;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAE7C;IAED,4FAA4F;IAC5F,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI;IAgBvB,6FAA6F;IAC7F,KAAK,IAAI,IAAI;IAYb,gFAAgF;IAChF,KAAK,IAAI,IAAI;CA4Cd"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
var v = (i) => {
|
|
2
|
+
throw TypeError(i);
|
|
3
|
+
};
|
|
4
|
+
var y = (i, t, e) => t.has(i) || v("Cannot " + e);
|
|
5
|
+
var s = (i, t, e) => (y(i, t, "read from private field"), e ? e.call(i) : t.get(i)), a = (i, t, e) => t.has(i) ? v("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(i) : t.set(i, e), n = (i, t, e, r) => (y(i, t, "write to private field"), r ? r.call(i, e) : t.set(i, e), e), p = (i, t, e) => (y(i, t, "access private method"), e);
|
|
6
|
+
var g, w, m, l, o, h, u, q, b, z;
|
|
7
|
+
class x {
|
|
8
|
+
constructor({ debounceTime: t = 0, maxRequests: e = 1, run: r }) {
|
|
9
|
+
a(this, u);
|
|
10
|
+
a(this, g);
|
|
11
|
+
a(this, w);
|
|
12
|
+
a(this, m);
|
|
13
|
+
a(this, l, []);
|
|
14
|
+
a(this, o, /* @__PURE__ */ new Set());
|
|
15
|
+
a(this, h, null);
|
|
16
|
+
n(this, g, r), n(this, w, e), n(this, m, t);
|
|
17
|
+
}
|
|
18
|
+
schedule(t, e) {
|
|
19
|
+
return new Promise((r) => {
|
|
20
|
+
s(this, l).push({ handle: t, priority: e, resolve: r, settled: !1, dropped: !1 }), p(this, u, q).call(this);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
/** How many requests are queued, and how many batches are running. */
|
|
24
|
+
get size() {
|
|
25
|
+
return { queued: s(this, l).length, active: s(this, o).size };
|
|
26
|
+
}
|
|
27
|
+
/** The caller no longer wants `handle`'s answer: it resolves `null` now, wherever it is. */
|
|
28
|
+
cancel(t) {
|
|
29
|
+
n(this, l, s(this, l).filter((e) => e.handle !== t ? !0 : (f(e, null), !1)));
|
|
30
|
+
for (const e of s(this, o))
|
|
31
|
+
for (const r of e.requests)
|
|
32
|
+
r.handle === t && (r.dropped = !0, f(r, null));
|
|
33
|
+
this.prune();
|
|
34
|
+
}
|
|
35
|
+
/** Drops queued requests nobody wants, and aborts a batch in which nobody wants anything. */
|
|
36
|
+
prune() {
|
|
37
|
+
n(this, l, s(this, l).filter((t) => t.priority(t.handle) >= 0 ? !0 : (f(t, null), !1)));
|
|
38
|
+
for (const t of s(this, o))
|
|
39
|
+
t.requests.some((r) => !r.dropped && r.priority(r.handle) >= 0) || t.controller.abort();
|
|
40
|
+
}
|
|
41
|
+
/** Every queued request resolves `null`, and every running batch is aborted. */
|
|
42
|
+
clear() {
|
|
43
|
+
s(this, h) !== null && clearTimeout(s(this, h)), n(this, h, null);
|
|
44
|
+
for (const t of s(this, l)) f(t, null);
|
|
45
|
+
n(this, l, []);
|
|
46
|
+
for (const t of s(this, o)) t.controller.abort();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
g = new WeakMap(), w = new WeakMap(), m = new WeakMap(), l = new WeakMap(), o = new WeakMap(), h = new WeakMap(), u = new WeakSet(), q = function() {
|
|
50
|
+
s(this, h) !== null && clearTimeout(s(this, h)), n(this, h, setTimeout(() => {
|
|
51
|
+
n(this, h, null), p(this, u, b).call(this);
|
|
52
|
+
}, s(this, m)));
|
|
53
|
+
}, b = function() {
|
|
54
|
+
if (this.prune(), s(this, o).size >= s(this, w) || s(this, l).length === 0) return;
|
|
55
|
+
const t = s(this, l).map((e) => ({ request: e, priority: e.priority(e.handle) }));
|
|
56
|
+
t.sort((e, r) => e.priority - r.priority), n(this, l, []), p(this, u, z).call(this, { requests: t.map(({ request: e }) => e), controller: new AbortController() });
|
|
57
|
+
}, z = async function(t) {
|
|
58
|
+
s(this, o).add(t);
|
|
59
|
+
const { controller: e, requests: r } = t;
|
|
60
|
+
try {
|
|
61
|
+
const c = await s(this, g).call(this, r.map((d) => d.handle), e.signal);
|
|
62
|
+
if (c.length !== r.length)
|
|
63
|
+
throw new Error(`a batch of ${r.length} was answered with ${c.length}`);
|
|
64
|
+
r.forEach((d, T) => f(d, e.signal.aborted ? null : { value: c[T] }));
|
|
65
|
+
} catch (c) {
|
|
66
|
+
for (const d of r) f(d, e.signal.aborted ? null : { error: c });
|
|
67
|
+
} finally {
|
|
68
|
+
s(this, o).delete(t), s(this, l).length > 0 && p(this, u, b).call(this);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
function f(i, t) {
|
|
72
|
+
i.settled || (i.settled = !0, i.resolve(t));
|
|
73
|
+
}
|
|
74
|
+
export {
|
|
75
|
+
x as RequestScheduler
|
|
76
|
+
};
|
|
77
|
+
//# sourceMappingURL=scheduler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.js","sources":["../../src/core/scheduler.ts"],"sourcesContent":["/**\n * loaders.gl's `RequestScheduler`, issuing a **batch** where it issues a request, with one slot:\n * DuckDB-WASM is one worker behind one port, so a second statement queues behind the first rather\n * than overlapping it, and fossil reads a run of consecutive tiles as one statement only when it is\n * handed them in one call (`/docs/design/graph`, *one batch in flight*).\n *\n * Priorities are asked again each time a slot frees, the debounce settles or `prune` runs. A negative\n * priority is a request nobody wants any more: queued, it resolves `null` without ever being issued;\n * in flight, its batch is aborted only once no request in it is wanted — a batch that still answers\n * someone finishes, and answers everyone in it.\n */\n\n/** A request's answer, its batch's failure, or `null` when it was never issued or was aborted. */\nexport type Outcome<R> = { readonly value: R } | { readonly error: unknown } | null;\n\ninterface Request<T, R> {\n readonly handle: T;\n readonly priority: (handle: T) => number;\n readonly resolve: (outcome: Outcome<R>) => void;\n settled: boolean;\n dropped: boolean;\n}\n\ninterface Flight<T, R> {\n readonly requests: readonly Request<T, R>[];\n readonly controller: AbortController;\n}\n\nexport interface SchedulerOptions<T, R> {\n /** One call for a batch: an answer per handle, in the order given. */\n run: (handles: readonly T[], signal: AbortSignal) => Promise<readonly R[]>;\n /** Batches running at once. */\n maxRequests?: number;\n /** Quiet time, in milliseconds, before the queue is issued — a pan settles before it asks. */\n debounceTime?: number;\n}\n\nexport class RequestScheduler<T, R> {\n readonly #run: SchedulerOptions<T, R>[\"run\"];\n readonly #max: number;\n readonly #debounce: number;\n #queue: Request<T, R>[] = [];\n #flights = new Set<Flight<T, R>>();\n #timer: ReturnType<typeof setTimeout> | null = null;\n\n constructor({ debounceTime = 0, maxRequests = 1, run }: SchedulerOptions<T, R>) {\n this.#run = run;\n this.#max = maxRequests;\n this.#debounce = debounceTime;\n }\n\n schedule(handle: T, priority: (handle: T) => number): Promise<Outcome<R>> {\n return new Promise((resolve) => {\n this.#queue.push({ handle, priority, resolve, settled: false, dropped: false });\n this.#wake();\n });\n }\n\n /** How many requests are queued, and how many batches are running. */\n get size(): { queued: number; active: number } {\n return { queued: this.#queue.length, active: this.#flights.size };\n }\n\n /** The caller no longer wants `handle`'s answer: it resolves `null` now, wherever it is. */\n cancel(handle: T): void {\n this.#queue = this.#queue.filter((request) => {\n if (request.handle !== handle) return true;\n settle(request, null);\n return false;\n });\n for (const flight of this.#flights) {\n for (const request of flight.requests) {\n if (request.handle !== handle) continue;\n request.dropped = true;\n settle(request, null);\n }\n }\n this.prune();\n }\n\n /** Drops queued requests nobody wants, and aborts a batch in which nobody wants anything. */\n prune(): void {\n this.#queue = this.#queue.filter((request) => {\n if (request.priority(request.handle) >= 0) return true;\n settle(request, null);\n return false;\n });\n for (const flight of this.#flights) {\n const wanted = flight.requests.some((r) => !r.dropped && r.priority(r.handle) >= 0);\n if (!wanted) flight.controller.abort();\n }\n }\n\n /** Every queued request resolves `null`, and every running batch is aborted. */\n clear(): void {\n if (this.#timer !== null) clearTimeout(this.#timer);\n this.#timer = null;\n for (const request of this.#queue) settle(request, null);\n this.#queue = [];\n for (const flight of this.#flights) flight.controller.abort();\n }\n\n #wake(): void {\n if (this.#timer !== null) clearTimeout(this.#timer);\n this.#timer = setTimeout(() => {\n this.#timer = null;\n this.#issue();\n }, this.#debounce);\n }\n\n #issue(): void {\n this.prune();\n if (this.#flights.size >= this.#max || this.#queue.length === 0) return;\n const ranked = this.#queue.map((request) => ({ request, priority: request.priority(request.handle) }));\n ranked.sort((a, b) => a.priority - b.priority);\n this.#queue = [];\n void this.#fly({ requests: ranked.map(({ request }) => request), controller: new AbortController() });\n }\n\n async #fly(flight: Flight<T, R>): Promise<void> {\n this.#flights.add(flight);\n const { controller, requests } = flight;\n try {\n const answers = await this.#run(\n requests.map((request) => request.handle),\n controller.signal,\n );\n if (answers.length !== requests.length) {\n throw new Error(`a batch of ${requests.length} was answered with ${answers.length}`);\n }\n requests.forEach((request, i) => settle(request, controller.signal.aborted ? null : { value: answers[i] as R }));\n } catch (error) {\n for (const request of requests) settle(request, controller.signal.aborted ? null : { error });\n } finally {\n this.#flights.delete(flight);\n if (this.#queue.length > 0) this.#issue();\n }\n }\n}\n\nfunction settle<T, R>(request: Request<T, R>, outcome: Outcome<R>): void {\n if (request.settled) return;\n request.settled = true;\n request.resolve(outcome);\n}\n"],"names":["_run","_max","_debounce","_queue","_flights","_timer","_RequestScheduler_instances","wake_fn","issue_fn","fly_fn","RequestScheduler","debounceTime","maxRequests","run","__privateAdd","__privateSet","handle","priority","resolve","__privateGet","__privateMethod","request","settle","flight","ranked","a","b","controller","requests","answers","i","error","outcome"],"mappings":";;;;;AAqCO,IAAAA,GAAAC,GAAAC,GAAAC,GAAAC,GAAAC,GAAAC,GAAAC,GAAAC,GAAAC;AAAA,MAAMC,EAAuB;AAAA,EAQlC,YAAY,EAAE,cAAAC,IAAe,GAAG,aAAAC,IAAc,GAAG,KAAAC,KAA+B;AAR3E,IAAAC,EAAA,MAAAR;AACI,IAAAQ,EAAA,MAAAd;AACA,IAAAc,EAAA,MAAAb;AACA,IAAAa,EAAA,MAAAZ;AACT,IAAAY,EAAA,MAAAX,GAA0B,CAAA;AAC1B,IAAAW,EAAA,MAAAV,uBAAe,IAAA;AACf,IAAAU,EAAA,MAAAT,GAA+C;AAG7C,IAAAU,EAAA,MAAKf,GAAOa,IACZE,EAAA,MAAKd,GAAOW,IACZG,EAAA,MAAKb,GAAYS;AAAA,EACnB;AAAA,EAEA,SAASK,GAAWC,GAAsD;AACxE,WAAO,IAAI,QAAQ,CAACC,MAAY;AAC9B,MAAAC,EAAA,MAAKhB,GAAO,KAAK,EAAE,QAAAa,GAAQ,UAAAC,GAAU,SAAAC,GAAS,SAAS,IAAO,SAAS,GAAA,CAAO,GAC9EE,EAAA,MAAKd,GAAAC,GAAL;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,IAAI,OAA2C;AAC7C,WAAO,EAAE,QAAQY,EAAA,MAAKhB,GAAO,QAAQ,QAAQgB,EAAA,MAAKf,GAAS,KAAA;AAAA,EAC7D;AAAA;AAAA,EAGA,OAAOY,GAAiB;AACtB,IAAAD,EAAA,MAAKZ,GAASgB,EAAA,MAAKhB,GAAO,OAAO,CAACkB,MAC5BA,EAAQ,WAAWL,IAAe,MACtCM,EAAOD,GAAS,IAAI,GACb,GACR;AACD,eAAWE,KAAUJ,EAAA,MAAKf;AACxB,iBAAWiB,KAAWE,EAAO;AAC3B,QAAIF,EAAQ,WAAWL,MACvBK,EAAQ,UAAU,IAClBC,EAAOD,GAAS,IAAI;AAGxB,SAAK,MAAA;AAAA,EACP;AAAA;AAAA,EAGA,QAAc;AACZ,IAAAN,EAAA,MAAKZ,GAASgB,EAAA,MAAKhB,GAAO,OAAO,CAACkB,MAC5BA,EAAQ,SAASA,EAAQ,MAAM,KAAK,IAAU,MAClDC,EAAOD,GAAS,IAAI,GACb,GACR;AACD,eAAWE,KAAUJ,EAAA,MAAKf;AAExB,MADemB,EAAO,SAAS,KAAK,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC,KACrEA,EAAO,WAAW,MAAA;AAAA,EAEnC;AAAA;AAAA,EAGA,QAAc;AACZ,IAAIJ,EAAA,MAAKd,OAAW,QAAM,aAAac,EAAA,MAAKd,EAAM,GAClDU,EAAA,MAAKV,GAAS;AACd,eAAWgB,KAAWF,EAAA,MAAKhB,GAAQ,CAAAmB,EAAOD,GAAS,IAAI;AACvD,IAAAN,EAAA,MAAKZ,GAAS,CAAA;AACd,eAAWoB,KAAUJ,EAAA,MAAKf,GAAU,CAAAmB,EAAO,WAAW,MAAA;AAAA,EACxD;AAsCF;AApGWvB,IAAA,eACAC,IAAA,eACAC,IAAA,eACTC,IAAA,eACAC,IAAA,eACAC,IAAA,eANKC,IAAA,eAiELC,IAAA,WAAc;AACZ,EAAIY,EAAA,MAAKd,OAAW,QAAM,aAAac,EAAA,MAAKd,EAAM,GAClDU,EAAA,MAAKV,GAAS,WAAW,MAAM;AAC7B,IAAAU,EAAA,MAAKV,GAAS,OACde,EAAA,MAAKd,GAAAE,GAAL;AAAA,EACF,GAAGW,EAAA,MAAKjB,EAAS;AACnB,GAEAM,IAAA,WAAe;AAEb,MADA,KAAK,MAAA,GACDW,EAAA,MAAKf,GAAS,QAAQe,EAAA,MAAKlB,MAAQkB,EAAA,MAAKhB,GAAO,WAAW,EAAG;AACjE,QAAMqB,IAASL,EAAA,MAAKhB,GAAO,IAAI,CAACkB,OAAa,EAAE,SAAAA,GAAS,UAAUA,EAAQ,SAASA,EAAQ,MAAM,IAAI;AACrG,EAAAG,EAAO,KAAK,CAACC,GAAGC,MAAMD,EAAE,WAAWC,EAAE,QAAQ,GAC7CX,EAAA,MAAKZ,GAAS,CAAA,IACTiB,EAAA,MAAKd,GAAAG,GAAL,WAAU,EAAE,UAAUe,EAAO,IAAI,CAAC,EAAE,SAAAH,EAAA,MAAcA,CAAO,GAAG,YAAY,IAAI,gBAAA;AACnF,GAEMZ,mBAAKc,GAAqC;AAC9C,EAAAJ,EAAA,MAAKf,GAAS,IAAImB,CAAM;AACxB,QAAM,EAAE,YAAAI,GAAY,UAAAC,EAAA,IAAaL;AACjC,MAAI;AACF,UAAMM,IAAU,MAAMV,EAAA,MAAKnB,GAAL,WACpB4B,EAAS,IAAI,CAACP,MAAYA,EAAQ,MAAM,GACxCM,EAAW;AAEb,QAAIE,EAAQ,WAAWD,EAAS;AAC9B,YAAM,IAAI,MAAM,cAAcA,EAAS,MAAM,sBAAsBC,EAAQ,MAAM,EAAE;AAErF,IAAAD,EAAS,QAAQ,CAACP,GAASS,MAAMR,EAAOD,GAASM,EAAW,OAAO,UAAU,OAAO,EAAE,OAAOE,EAAQC,CAAC,EAAA,CAAQ,CAAC;AAAA,EACjH,SAASC,GAAO;AACd,eAAWV,KAAWO,EAAU,CAAAN,EAAOD,GAASM,EAAW,OAAO,UAAU,OAAO,EAAE,OAAAI,EAAA,CAAO;AAAA,EAC9F,UAAA;AACE,IAAAZ,EAAA,MAAKf,GAAS,OAAOmB,CAAM,GACvBJ,EAAA,MAAKhB,GAAO,SAAS,aAAQG,GAAAE;EACnC;AACF;AAGF,SAASc,EAAaD,GAAwBW,GAA2B;AACvE,EAAIX,EAAQ,YACZA,EAAQ,UAAU,IAClBA,EAAQ,QAAQW,CAAO;AACzB;"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { Corpus, Gap, TileAddress, TileMatrixSet } from '@fossil-lang/corpus';
|
|
2
|
+
import { Selection as Crossfilter } from '@kanzo-tech/mosaic';
|
|
3
|
+
import { LookPatch } from '../render/graph-looks';
|
|
4
|
+
import { Sim } from '../render/graph-sim';
|
|
5
|
+
import { Binding, Channels } from './channels';
|
|
6
|
+
import { VertexId } from './resident';
|
|
7
|
+
import { TileContent } from './tile';
|
|
8
|
+
import { Viewport } from './tile-matrix';
|
|
9
|
+
import { Motion, Selection, SelectionSource, Tool } from './types';
|
|
10
|
+
export interface GraphOptions extends Channels {
|
|
11
|
+
/**
|
|
12
|
+
* The corpus the host opened with fossil's `open`, or the promise of it. A promise is what makes
|
|
13
|
+
* *opening* a state the graph can report; `null` is no corpus at all.
|
|
14
|
+
*/
|
|
15
|
+
corpus: Corpus | PromiseLike<Corpus> | null;
|
|
16
|
+
/** The vertex type drawn. The first type with a position when absent. */
|
|
17
|
+
type?: string;
|
|
18
|
+
/** Which column the size ramp is spent on — Plot's `r`. */
|
|
19
|
+
r?: string;
|
|
20
|
+
/** Which column a label and the hover card show — Plot's `title`. */
|
|
21
|
+
title?: string;
|
|
22
|
+
/**
|
|
23
|
+
* What the categorical channel's values are called, keyed by value. For a column the manifest's
|
|
24
|
+
* `channels:` declares, the ordinals rank themselves and this only names them; for one it does not,
|
|
25
|
+
* the keys' order is also the rank, so a colour never moves because a tile arrived.
|
|
26
|
+
*/
|
|
27
|
+
categories?: Readonly<Record<string, string>>;
|
|
28
|
+
/** The page's crossfilter: its clauses filter what is read, and the reader's pick is published into it. */
|
|
29
|
+
filterBy?: Crossfilter;
|
|
30
|
+
/** The most marks drawn at once; a coarser zoom is chosen above it. */
|
|
31
|
+
limit?: number;
|
|
32
|
+
/** Form: a patch over this package's own look. Memoise it — its identity is what repaints. */
|
|
33
|
+
look?: LookPatch;
|
|
34
|
+
/** The force coefficients, as a patch over this package's own. */
|
|
35
|
+
sim?: Partial<Sim>;
|
|
36
|
+
/** A live layout. Off: a corpus's positions are the index every read is asked against. */
|
|
37
|
+
simulate?: boolean;
|
|
38
|
+
/** Required: unhandled, a browser with no WebGL context shows an empty box. */
|
|
39
|
+
onFailure: (message: string) => void;
|
|
40
|
+
onSelect?: (selection: Selection | null) => void;
|
|
41
|
+
onFocus?: (vertex: VertexId | null) => void;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Where the graph is in its life. `none` is no corpus; `opening` is a corpus promised and not yet
|
|
45
|
+
* open; `reading` is a tile in view not yet read or not yet drawn; `idle` is everything in view
|
|
46
|
+
* drawn; `failed` is a corpus that would not open, a type it cannot draw, or a canvas that could not
|
|
47
|
+
* start a renderer.
|
|
48
|
+
*/
|
|
49
|
+
export type GraphStatus = "none" | "opening" | "reading" | "idle" | "failed";
|
|
50
|
+
/** What is on the canvas, as the renderer composed it. */
|
|
51
|
+
export interface Drawn {
|
|
52
|
+
/** Points drawn — vertices and cells. */
|
|
53
|
+
readonly marks: number;
|
|
54
|
+
/** Vertices those marks stand for: a cell counts its members. */
|
|
55
|
+
readonly represented: number;
|
|
56
|
+
/** What each category rank is: the declared or named values first, then any other seen, in rank order. */
|
|
57
|
+
readonly domain: readonly unknown[];
|
|
58
|
+
/** Per rank, the vertices drawn marks stand for. */
|
|
59
|
+
readonly tally: readonly number[];
|
|
60
|
+
}
|
|
61
|
+
/** What a host and the parts read, through `useGraphState`. */
|
|
62
|
+
export interface GraphState {
|
|
63
|
+
readonly status: GraphStatus;
|
|
64
|
+
/** Vertices of the drawn type, from the manifest — it does not shrink with a filter. */
|
|
65
|
+
readonly total: number | undefined;
|
|
66
|
+
/** The zoom drawn, coarsest `0`; the payload is the last. */
|
|
67
|
+
readonly z: number | null;
|
|
68
|
+
/** Whether a tile in view is still being read. */
|
|
69
|
+
readonly pending: boolean;
|
|
70
|
+
/** What is on the canvas, or `null` before the first composition. */
|
|
71
|
+
readonly drawn: Drawn | null;
|
|
72
|
+
/** The categorical domain before anything is drawn: the manifest's ordinals, or the host's names. */
|
|
73
|
+
readonly domain: readonly unknown[];
|
|
74
|
+
readonly selection: Selection | null;
|
|
75
|
+
readonly focus: VertexId | null;
|
|
76
|
+
readonly hovered: VertexId | null;
|
|
77
|
+
readonly pinned: readonly VertexId[];
|
|
78
|
+
readonly tool: Tool;
|
|
79
|
+
readonly motion: Motion;
|
|
80
|
+
/** How far through settling a live layout is, `0`–`1`. */
|
|
81
|
+
readonly progress: number;
|
|
82
|
+
/** Relations the corpus declined to answer, with fossil's reason. */
|
|
83
|
+
readonly declined: readonly Gap[];
|
|
84
|
+
/** The options as given, with the corpus once it is open. */
|
|
85
|
+
readonly options: GraphOptions;
|
|
86
|
+
readonly corpus: Corpus | null;
|
|
87
|
+
}
|
|
88
|
+
/** One tile the picture is made of: where it is, and what it holds. */
|
|
89
|
+
export interface TileView {
|
|
90
|
+
readonly address: TileAddress;
|
|
91
|
+
readonly kind: "rows" | "cells";
|
|
92
|
+
readonly content: TileContent;
|
|
93
|
+
}
|
|
94
|
+
/** The state, plus what only the renderer reads. */
|
|
95
|
+
export interface GraphSnapshot extends GraphState {
|
|
96
|
+
readonly matrix: TileMatrixSet | null;
|
|
97
|
+
/** The drawn type's position in `corpus.types.vertices` — the type half of a `VertexId`. */
|
|
98
|
+
readonly typeIndex: number;
|
|
99
|
+
readonly binding: Binding;
|
|
100
|
+
/** The payload column a cell's `mode` is the majority of, or `null` where the tree names none. */
|
|
101
|
+
readonly modeColumn: string | null;
|
|
102
|
+
/** Tiles drawn now; the same array until the set changes. */
|
|
103
|
+
readonly visible: readonly TileView[];
|
|
104
|
+
/** Every tile holding content — where a far end is looked up. */
|
|
105
|
+
readonly cached: readonly TileView[];
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* **The graph's state, outside React** — TanStack Query's `QueryObserver` shape: `subscribe`,
|
|
109
|
+
* `getSnapshot`, `setOptions`, `destroy`. The snapshot is a new object only when something a reader
|
|
110
|
+
* can see changed, and the same object between notifications.
|
|
111
|
+
*/
|
|
112
|
+
export interface GraphStore {
|
|
113
|
+
subscribe(listener: () => void): () => void;
|
|
114
|
+
getSnapshot(): GraphSnapshot;
|
|
115
|
+
getOptions(): GraphOptions;
|
|
116
|
+
setOptions(options: GraphOptions): void;
|
|
117
|
+
destroy(): void;
|
|
118
|
+
/** The camera, from the renderer: the rectangle in view. */
|
|
119
|
+
setViewport(viewport: Viewport): void;
|
|
120
|
+
select(vertices: readonly VertexId[] | null, source?: SelectionSource, label?: string): void;
|
|
121
|
+
focus(vertex: VertexId | null): void;
|
|
122
|
+
hover(vertex: VertexId | null): void;
|
|
123
|
+
pin(vertices: readonly VertexId[]): void;
|
|
124
|
+
setTool(tool: Tool): void;
|
|
125
|
+
report(motion: Motion): void;
|
|
126
|
+
reportProgress(value: number): void;
|
|
127
|
+
/** Whether the canvas has a renderer: without one nothing in view will ever be drawn. */
|
|
128
|
+
setRenderable(renderable: boolean): void;
|
|
129
|
+
/** The renderer drew `visible`; `drawn` is what it composed, or `null` when the set was unchanged. */
|
|
130
|
+
reportDrawn(visible: readonly TileView[], drawn: Drawn | null): void;
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/core/state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { GraphOptions, GraphStore } from './state';
|
|
2
|
+
export type { Drawn, GraphOptions, GraphSnapshot, GraphState, GraphStatus, GraphStore, TileView } from './state';
|
|
3
|
+
/** Twenty thousand marks: what a canvas draws at once before a coarser zoom is chosen. */
|
|
4
|
+
export declare const DEFAULT_LIMIT = 20000;
|
|
5
|
+
export declare function createGraph(initial: GraphOptions): GraphStore;
|
|
6
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/core/store.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,YAAY,EAA8B,UAAU,EAAY,MAAM,SAAS,CAAC;AAK9F,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEjH,0FAA0F;AAC1F,eAAO,MAAM,aAAa,QAAS,CAAC;AAwBpC,wBAAgB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,UAAU,CA6T7D"}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import { PAYLOAD_ADDRESS as te, PAYLOAD_COORDINATES as ne } from "@fossil-lang/corpus";
|
|
2
|
+
import { domainOf as re } from "./categories.js";
|
|
3
|
+
import { bindingOf as Y, projectionOf as oe } from "./channels.js";
|
|
4
|
+
import { graphClient as le, publish as ie, filterFor as se } from "./filter.js";
|
|
5
|
+
import { denseOf as ce } from "./resident.js";
|
|
6
|
+
import { Tileset2D as fe } from "./tileset.js";
|
|
7
|
+
const R = 2e4, q = Y({}), H = te[0];
|
|
8
|
+
function de(i) {
|
|
9
|
+
var m;
|
|
10
|
+
let n = 0;
|
|
11
|
+
for (const s of i.edges) n += s.src.byteLength + s.dst.byteLength + (((m = s.weight) == null ? void 0 : m.byteLength) ?? 0);
|
|
12
|
+
return n + i.rows.numRows * 8 * 4;
|
|
13
|
+
}
|
|
14
|
+
const ue = (i, n) => JSON.stringify(i, (m, s) => typeof s == "bigint" ? `${s}n` : s) === JSON.stringify(n, (m, s) => typeof s == "bigint" ? `${s}n` : s), ae = (i) => typeof (i == null ? void 0 : i.then) == "function";
|
|
15
|
+
function Q(i, n) {
|
|
16
|
+
return i.length !== n.length ? n : n.every((m, s) => {
|
|
17
|
+
var o;
|
|
18
|
+
return m.content === ((o = i[s]) == null ? void 0 : o.content);
|
|
19
|
+
}) ? i : n;
|
|
20
|
+
}
|
|
21
|
+
function be(i) {
|
|
22
|
+
let n = i;
|
|
23
|
+
const m = /* @__PURE__ */ new Set(), s = le();
|
|
24
|
+
let o = null, b = null, M = !1, C = !1, u = null, T = 0, G = null, O = null, g = q, F, z = null, E = [], S = null, h = null, B = !1, J = -1;
|
|
25
|
+
const D = (e) => {
|
|
26
|
+
n.onFailure(e instanceof Error ? e.message : String(e));
|
|
27
|
+
}, a = new fe({
|
|
28
|
+
debounceTime: 60,
|
|
29
|
+
load: async (e, t) => {
|
|
30
|
+
if (!o || !O) throw new Error("the graph has no scan to read with");
|
|
31
|
+
const r = (d) => {
|
|
32
|
+
var w;
|
|
33
|
+
return ((w = u == null ? void 0 : u.tileMatrices[d.z]) == null ? void 0 : w.kind) === "cells";
|
|
34
|
+
}, l = await O.read(e, { signal: t }), y = await o.edges({ from: e, direction: "src", signal: t }), p = e.filter((d) => !r(d)), I = p.length > 0 ? await o.edges({ from: p, direction: "dst", signal: t }) : [], N = new Map(p.map((d, w) => [d, I[w]]));
|
|
35
|
+
return e.map((d, w) => {
|
|
36
|
+
const v = y[w], L = N.get(d), Z = [...(v == null ? void 0 : v.batches) ?? [], ...(L == null ? void 0 : L.batches) ?? []], K = [...(v == null ? void 0 : v.declined) ?? [], ...(L == null ? void 0 : L.declined) ?? []], x = r(d) ? K.filter((ee) => ee.direction !== "dst") : K, U = { rows: l[w], edges: Z, declined: x };
|
|
37
|
+
return { ...U, byteLength: de(U) };
|
|
38
|
+
});
|
|
39
|
+
},
|
|
40
|
+
onTileLoad: (e) => {
|
|
41
|
+
var t;
|
|
42
|
+
for (const r of ((t = e.content) == null ? void 0 : t.declined) ?? [])
|
|
43
|
+
E.some((l) => l.edgeType === r.edgeType && l.direction === r.direction) || (E = [...E, r]);
|
|
44
|
+
a.refresh(), f();
|
|
45
|
+
},
|
|
46
|
+
onTileError: (e) => {
|
|
47
|
+
a.refresh(), D(e), f();
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
let c = {
|
|
51
|
+
status: "none",
|
|
52
|
+
matrix: null,
|
|
53
|
+
typeIndex: 0,
|
|
54
|
+
modeColumn: null,
|
|
55
|
+
binding: q,
|
|
56
|
+
domain: [],
|
|
57
|
+
z: null,
|
|
58
|
+
visible: [],
|
|
59
|
+
cached: [],
|
|
60
|
+
pending: !1,
|
|
61
|
+
total: void 0,
|
|
62
|
+
declined: [],
|
|
63
|
+
selection: null,
|
|
64
|
+
focus: null,
|
|
65
|
+
hovered: null,
|
|
66
|
+
pinned: [],
|
|
67
|
+
tool: null,
|
|
68
|
+
motion: "settled",
|
|
69
|
+
progress: 1,
|
|
70
|
+
drawn: null,
|
|
71
|
+
options: n,
|
|
72
|
+
corpus: null
|
|
73
|
+
};
|
|
74
|
+
const V = (e) => {
|
|
75
|
+
var t;
|
|
76
|
+
return {
|
|
77
|
+
address: e.address,
|
|
78
|
+
kind: ((t = u == null ? void 0 : u.tileMatrices[e.address.z]) == null ? void 0 : t.kind) ?? "rows",
|
|
79
|
+
content: e.content
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
let P = { key: [], value: [] };
|
|
83
|
+
function W() {
|
|
84
|
+
const e = [o, T, g.category, n.categories];
|
|
85
|
+
return e.some((t, r) => t !== P.key[r]) && (P = { key: e, value: re(o, T, g, n.categories) }), P.value;
|
|
86
|
+
}
|
|
87
|
+
function X(e, t) {
|
|
88
|
+
return M || C ? "failed" : b ? "opening" : o ? e || S !== t || c.drawn === null ? "reading" : "idle" : "none";
|
|
89
|
+
}
|
|
90
|
+
function f(e = {}) {
|
|
91
|
+
var y;
|
|
92
|
+
J = a.frame;
|
|
93
|
+
const t = a.tiles.filter((p) => p.content !== null), r = Q(c.visible, t.filter((p) => p.isVisible).map(V)), l = a.selectedTiles.some((p) => p.isLoading);
|
|
94
|
+
c = {
|
|
95
|
+
...c,
|
|
96
|
+
matrix: u,
|
|
97
|
+
typeIndex: T,
|
|
98
|
+
modeColumn: G,
|
|
99
|
+
binding: g,
|
|
100
|
+
domain: W(),
|
|
101
|
+
z: a.z,
|
|
102
|
+
visible: r,
|
|
103
|
+
cached: Q(c.cached, t.map(V)),
|
|
104
|
+
pending: l,
|
|
105
|
+
total: u ? Number(((y = u.tileMatrices[u.tileMatrices.length - 1]) == null ? void 0 : y.count) ?? 0) : void 0,
|
|
106
|
+
declined: E,
|
|
107
|
+
options: n,
|
|
108
|
+
corpus: o,
|
|
109
|
+
...e
|
|
110
|
+
}, c = { ...c, status: X(l, c.visible) };
|
|
111
|
+
for (const p of m) p();
|
|
112
|
+
}
|
|
113
|
+
function _() {
|
|
114
|
+
if (!(!o || !u)) {
|
|
115
|
+
try {
|
|
116
|
+
const e = [H, ...ne];
|
|
117
|
+
O = o.scan({ type: u.type, filter: F, select: oe(g, e) }), a.setPlan(O.plan());
|
|
118
|
+
} catch (e) {
|
|
119
|
+
O = null, a.setPlan([]), D(e);
|
|
120
|
+
}
|
|
121
|
+
a.reloadAll(), z && a.update(z, n.limit ?? R), f();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function A() {
|
|
125
|
+
var l, y, p, I, N;
|
|
126
|
+
M = !1, u = null, O = null, E = [], S = null, a.finalize();
|
|
127
|
+
const e = { selection: null, focus: null, hovered: null, pinned: [], drawn: null };
|
|
128
|
+
if (!o) return f(e);
|
|
129
|
+
const t = o.types.vertices, r = n.type ?? ((l = t.find((d) => d.geometry)) == null ? void 0 : l.type) ?? ((y = t[0]) == null ? void 0 : y.type);
|
|
130
|
+
T = Math.max(0, t.findIndex((d) => d.type === r));
|
|
131
|
+
try {
|
|
132
|
+
if (r === void 0) throw new Error("the corpus has no vertex type to draw");
|
|
133
|
+
u = o.tileMatrix(r);
|
|
134
|
+
const d = ((p = o.addressing.vertexType(r).cells) == null ? void 0 : p.modeChannel) ?? null;
|
|
135
|
+
G = ((N = (I = t[T]) == null ? void 0 : I.channels.find((w) => w.name === d)) == null ? void 0 : N.column) ?? null, a.setMatrix(u);
|
|
136
|
+
} catch (d) {
|
|
137
|
+
M = !0, D(d);
|
|
138
|
+
}
|
|
139
|
+
c = { ...c, ...e }, _();
|
|
140
|
+
}
|
|
141
|
+
function $(e) {
|
|
142
|
+
if (o = null, b = ae(e) ? e : null, !b)
|
|
143
|
+
return o = e, A();
|
|
144
|
+
const t = b;
|
|
145
|
+
A(), t.then(
|
|
146
|
+
(r) => {
|
|
147
|
+
b === t && (b = null, o = r, A());
|
|
148
|
+
},
|
|
149
|
+
(r) => {
|
|
150
|
+
b === t && (b = null, M = !0, D(r), f());
|
|
151
|
+
}
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
function k() {
|
|
155
|
+
h == null || h(), h = null;
|
|
156
|
+
const e = n.filterBy, t = () => {
|
|
157
|
+
let r;
|
|
158
|
+
try {
|
|
159
|
+
r = e ? se(e, s) : void 0;
|
|
160
|
+
} catch (l) {
|
|
161
|
+
D(l);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
ue(r, F) || (F = r, _());
|
|
165
|
+
};
|
|
166
|
+
e && (e.addEventListener("value", t), h = () => e.removeEventListener("value", t)), t();
|
|
167
|
+
}
|
|
168
|
+
const j = {
|
|
169
|
+
/**
|
|
170
|
+
* The first subscriber starts listening to the crossfilter and the last one stops it and lets the
|
|
171
|
+
* tiles go — `QueryObserver`'s `onSubscribe`/`onUnsubscribe`, which is what survives StrictMode
|
|
172
|
+
* mounting everything twice.
|
|
173
|
+
*/
|
|
174
|
+
subscribe(e) {
|
|
175
|
+
return m.add(e), B || (B = !0, k()), () => {
|
|
176
|
+
m.delete(e), m.size === 0 && j.destroy();
|
|
177
|
+
};
|
|
178
|
+
},
|
|
179
|
+
getSnapshot: () => c,
|
|
180
|
+
getOptions: () => n,
|
|
181
|
+
setOptions(e) {
|
|
182
|
+
const t = n;
|
|
183
|
+
n = e;
|
|
184
|
+
const r = Y(e), l = r.category !== g.category || r.size !== g.size || r.title !== g.title;
|
|
185
|
+
if (g = r, e.corpus !== t.corpus || e.type !== t.type) {
|
|
186
|
+
e.corpus !== t.corpus ? $(e.corpus) : A(), B && e.filterBy !== t.filterBy && k();
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
if (B && e.filterBy !== t.filterBy && k(), l) return _();
|
|
190
|
+
e.limit !== t.limit && z && a.update(z, e.limit ?? R), f();
|
|
191
|
+
},
|
|
192
|
+
destroy() {
|
|
193
|
+
B = !1, h == null || h(), h = null, a.finalize(), m.clear();
|
|
194
|
+
},
|
|
195
|
+
setViewport(e) {
|
|
196
|
+
z = e, a.update(e, n.limit ?? R) !== J && f();
|
|
197
|
+
},
|
|
198
|
+
select(e, t = "node", r = "") {
|
|
199
|
+
var y;
|
|
200
|
+
const l = e && e.length > 0 ? { vertices: [...e], source: t, label: r } : null;
|
|
201
|
+
f({ selection: l }), (y = n.onSelect) == null || y.call(n, l), n.filterBy && ie(n.filterBy, s, H, l ? l.vertices.map(ce) : null);
|
|
202
|
+
},
|
|
203
|
+
focus(e) {
|
|
204
|
+
var t;
|
|
205
|
+
e !== c.focus && (f({ focus: e }), (t = n.onFocus) == null || t.call(n, e));
|
|
206
|
+
},
|
|
207
|
+
hover(e) {
|
|
208
|
+
e !== c.hovered && f({ hovered: e });
|
|
209
|
+
},
|
|
210
|
+
pin(e) {
|
|
211
|
+
f({ pinned: [...e] });
|
|
212
|
+
},
|
|
213
|
+
setTool(e) {
|
|
214
|
+
e !== c.tool && f({ tool: e });
|
|
215
|
+
},
|
|
216
|
+
report(e) {
|
|
217
|
+
e !== c.motion && f({ motion: e });
|
|
218
|
+
},
|
|
219
|
+
reportProgress(e) {
|
|
220
|
+
e !== c.progress && f({ progress: e });
|
|
221
|
+
},
|
|
222
|
+
setRenderable(e) {
|
|
223
|
+
C !== !e && (C = !e, f());
|
|
224
|
+
},
|
|
225
|
+
reportDrawn(e, t) {
|
|
226
|
+
S === e && t === null || (S = e, f(t ? { drawn: t } : {}));
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
return g = Y(i), $(i.corpus), j;
|
|
230
|
+
}
|
|
231
|
+
export {
|
|
232
|
+
R as DEFAULT_LIMIT,
|
|
233
|
+
be as createGraph
|
|
234
|
+
};
|
|
235
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sources":["../../src/core/store.ts"],"sourcesContent":["import {\n PAYLOAD_ADDRESS,\n PAYLOAD_COORDINATES,\n type Batch,\n type Corpus,\n type Filter,\n type Gap,\n type Scan,\n type TileAddress,\n type TileMatrixSet,\n} from \"@fossil-lang/corpus\";\nimport type { MosaicClient } from \"@kanzo-tech/mosaic\";\nimport { domainOf } from \"./categories\";\nimport { bindingOf, projectionOf, type Binding } from \"./channels\";\nimport { filterFor, graphClient, publish } from \"./filter\";\nimport { denseOf } from \"./resident\";\nimport type { GraphOptions, GraphSnapshot, GraphStatus, GraphStore, TileView } from \"./state\";\nimport type { TileContent } from \"./tile\";\nimport type { Viewport } from \"./tile-matrix\";\nimport { Tileset2D } from \"./tileset\";\n\nexport type { Drawn, GraphOptions, GraphSnapshot, GraphState, GraphStatus, GraphStore, TileView } from \"./state\";\n\n/** Twenty thousand marks: what a canvas draws at once before a coarser zoom is chosen. */\nexport const DEFAULT_LIMIT = 20_000;\n\nconst NO_BINDING: Binding = bindingOf({});\nconst KEY = PAYLOAD_ADDRESS[0] as string;\n\nfunction bytesOf(content: Omit<TileContent, \"byteLength\">): number {\n let bytes = 0;\n for (const edge of content.edges) bytes += edge.src.byteLength + edge.dst.byteLength + (edge.weight?.byteLength ?? 0);\n return bytes + content.rows.numRows * 8 * 4;\n}\n\nconst sameFilter = (a: Filter | undefined, b: Filter | undefined) =>\n JSON.stringify(a, (_, v: unknown) => (typeof v === \"bigint\" ? `${v}n` : v)) ===\n JSON.stringify(b, (_, v: unknown) => (typeof v === \"bigint\" ? `${v}n` : v));\n\nconst isPromise = (value: unknown): value is PromiseLike<Corpus> =>\n typeof (value as PromiseLike<Corpus> | null)?.then === \"function\";\n\n/** The same array while the set of tiles in it is the same, so a reader can compare by identity. */\nfunction keep(previous: readonly TileView[], next: TileView[]): readonly TileView[] {\n if (previous.length !== next.length) return next;\n return next.every((view, i) => view.content === previous[i]?.content) ? previous : next;\n}\n\nexport function createGraph(initial: GraphOptions): GraphStore {\n let options = initial;\n const listeners = new Set<() => void>();\n const self: MosaicClient = graphClient();\n\n let corpus: Corpus | null = null;\n let opening: PromiseLike<Corpus> | null = null;\n let failed = false;\n let unrenderable = false;\n let matrix: TileMatrixSet | null = null;\n let typeIndex = 0;\n let modeColumn: string | null = null;\n let scan: Scan | null = null;\n let binding = NO_BINDING;\n let filter: Filter | undefined;\n let viewport: Viewport | null = null;\n let declined: Gap[] = [];\n let composed: readonly TileView[] | null = null;\n let unlisten: (() => void) | null = null;\n let active = false;\n let lastFrame = -1;\n\n const fail = (error: unknown) => {\n options.onFailure(error instanceof Error ? error.message : String(error));\n };\n\n const tileset = new Tileset2D({\n debounceTime: 60,\n load: async (addresses, signal) => {\n if (!corpus || !scan) throw new Error(\"the graph has no scan to read with\");\n const isCells = (address: TileAddress) => matrix?.tileMatrices[address.z]?.kind === \"cells\";\n const rows = await scan.read(addresses, { signal });\n const src = await corpus.edges({ from: addresses, direction: \"src\", signal });\n const payload = addresses.filter((address) => !isCells(address));\n const dst = payload.length > 0 ? await corpus.edges({ from: payload, direction: \"dst\", signal }) : [];\n const dstOf = new Map(payload.map((address, i) => [address, dst[i]]));\n return addresses.map((address, i) => {\n const out = src[i];\n const back = dstOf.get(address);\n const edges = [...(out?.batches ?? []), ...(back?.batches ?? [])];\n const gaps = [...(out?.declined ?? []), ...(back?.declined ?? [])];\n const declined = isCells(address) ? gaps.filter((gap) => gap.direction !== \"dst\") : gaps;\n const content = { rows: rows[i] as Batch, edges, declined };\n return { ...content, byteLength: bytesOf(content) };\n });\n },\n onTileLoad: (tile) => {\n for (const gap of tile.content?.declined ?? []) {\n if (!declined.some((d) => d.edgeType === gap.edgeType && d.direction === gap.direction)) {\n declined = [...declined, gap];\n }\n }\n tileset.refresh();\n notify();\n },\n onTileError: (error) => {\n tileset.refresh();\n fail(error);\n notify();\n },\n });\n\n let snapshot: GraphSnapshot = {\n status: \"none\",\n matrix: null,\n typeIndex: 0,\n modeColumn: null,\n binding: NO_BINDING,\n domain: [],\n z: null,\n visible: [],\n cached: [],\n pending: false,\n total: undefined,\n declined: [],\n selection: null,\n focus: null,\n hovered: null,\n pinned: [],\n tool: null,\n motion: \"settled\",\n progress: 1,\n drawn: null,\n options,\n corpus: null,\n };\n\n const viewOf = (tile: { address: TileAddress; content: TileContent | null }): TileView => ({\n address: tile.address,\n kind: matrix?.tileMatrices[tile.address.z]?.kind ?? \"rows\",\n content: tile.content as TileContent,\n });\n\n let domain: { key: unknown[]; value: readonly unknown[] } = { key: [], value: [] };\n function domainNow(): readonly unknown[] {\n const key = [corpus, typeIndex, binding.category, options.categories];\n if (key.some((part, i) => part !== domain.key[i])) domain = { key, value: domainOf(corpus, typeIndex, binding, options.categories) };\n return domain.value;\n }\n\n function statusOf(pending: boolean, visible: readonly TileView[]): GraphStatus {\n if (failed || unrenderable) return \"failed\";\n if (opening) return \"opening\";\n if (!corpus) return \"none\";\n return pending || composed !== visible || snapshot.drawn === null ? \"reading\" : \"idle\";\n }\n\n function notify(patch: Partial<GraphSnapshot> = {}): void {\n lastFrame = tileset.frame;\n const tiles = tileset.tiles.filter((tile) => tile.content !== null);\n const visible = keep(snapshot.visible, tiles.filter((tile) => tile.isVisible).map(viewOf));\n const pending = tileset.selectedTiles.some((tile) => tile.isLoading);\n snapshot = {\n ...snapshot,\n matrix,\n typeIndex,\n modeColumn,\n binding,\n domain: domainNow(),\n z: tileset.z,\n visible,\n cached: keep(snapshot.cached, tiles.map(viewOf)),\n pending,\n total: matrix ? Number(matrix.tileMatrices[matrix.tileMatrices.length - 1]?.count ?? 0) : undefined,\n declined,\n options,\n corpus,\n ...patch,\n };\n snapshot = { ...snapshot, status: statusOf(pending, snapshot.visible) };\n for (const listener of listeners) listener();\n }\n\n /** A binding or a filter is a new scan, planned once and never per camera move. */\n function rescan(): void {\n if (!corpus || !matrix) return;\n try {\n const fixed = [KEY, ...PAYLOAD_COORDINATES];\n scan = corpus.scan({ type: matrix.type, filter, select: projectionOf(binding, fixed) });\n tileset.setPlan(scan.plan());\n } catch (error) {\n scan = null;\n tileset.setPlan([]);\n fail(error);\n }\n tileset.reloadAll();\n if (viewport) tileset.update(viewport, options.limit ?? DEFAULT_LIMIT);\n notify();\n }\n\n function reopen(): void {\n failed = false;\n matrix = null;\n scan = null;\n declined = [];\n composed = null;\n tileset.finalize();\n const cleared = { selection: null, focus: null, hovered: null, pinned: [], drawn: null };\n if (!corpus) return notify(cleared);\n const types = corpus.types.vertices;\n const type = options.type ?? types.find((t) => t.geometry)?.type ?? types[0]?.type;\n typeIndex = Math.max(0, types.findIndex((t) => t.type === type));\n try {\n if (type === undefined) throw new Error(\"the corpus has no vertex type to draw\");\n matrix = corpus.tileMatrix(type);\n const mode = corpus.addressing.vertexType(type).cells?.modeChannel ?? null;\n modeColumn = types[typeIndex]?.channels.find((channel) => channel.name === mode)?.column ?? null;\n tileset.setMatrix(matrix);\n } catch (error) {\n failed = true;\n fail(error);\n }\n snapshot = { ...snapshot, ...cleared };\n rescan();\n }\n\n /** A promise is adopted when it settles, and only if it is still the corpus the host means. */\n function adopt(given: GraphOptions[\"corpus\"]): void {\n corpus = null;\n opening = isPromise(given) ? given : null;\n if (!opening) {\n corpus = given as Corpus | null;\n return reopen();\n }\n const promised = opening;\n reopen();\n promised.then(\n (opened) => {\n if (opening !== promised) return;\n opening = null;\n corpus = opened;\n reopen();\n },\n (error: unknown) => {\n if (opening !== promised) return;\n opening = null;\n failed = true;\n fail(error);\n notify();\n },\n );\n }\n\n function listen(): void {\n unlisten?.();\n unlisten = null;\n const crossfilter = options.filterBy;\n const refilter = () => {\n let next: Filter | undefined;\n try {\n next = crossfilter ? filterFor(crossfilter, self) : undefined;\n } catch (error) {\n fail(error);\n return;\n }\n if (sameFilter(next, filter)) return;\n filter = next;\n rescan();\n };\n if (crossfilter) {\n crossfilter.addEventListener(\"value\", refilter);\n unlisten = () => crossfilter.removeEventListener(\"value\", refilter);\n }\n refilter();\n }\n\n const store: GraphStore = {\n /**\n * The first subscriber starts listening to the crossfilter and the last one stops it and lets the\n * tiles go — `QueryObserver`'s `onSubscribe`/`onUnsubscribe`, which is what survives StrictMode\n * mounting everything twice.\n */\n subscribe(listener) {\n listeners.add(listener);\n if (!active) {\n active = true;\n listen();\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 nextBinding = bindingOf(next);\n const rebound =\n nextBinding.category !== binding.category ||\n nextBinding.size !== binding.size ||\n nextBinding.title !== binding.title;\n binding = nextBinding;\n if (next.corpus !== previous.corpus || next.type !== previous.type) {\n if (next.corpus !== previous.corpus) adopt(next.corpus);\n else reopen();\n if (active && next.filterBy !== previous.filterBy) listen();\n return;\n }\n if (active && next.filterBy !== previous.filterBy) listen();\n if (rebound) return rescan();\n if (next.limit !== previous.limit && viewport) tileset.update(viewport, next.limit ?? DEFAULT_LIMIT);\n notify();\n },\n destroy() {\n active = false;\n unlisten?.();\n unlisten = null;\n tileset.finalize();\n listeners.clear();\n },\n setViewport(next) {\n viewport = next;\n if (tileset.update(next, options.limit ?? DEFAULT_LIMIT) !== lastFrame) notify();\n },\n select(vertices, source = \"node\", label = \"\") {\n const selection = vertices && vertices.length > 0 ? { vertices: [...vertices], source, label } : null;\n notify({ selection });\n options.onSelect?.(selection);\n if (options.filterBy) publish(options.filterBy, self, KEY, selection ? selection.vertices.map(denseOf) : null);\n },\n focus(vertex) {\n if (vertex === snapshot.focus) return;\n notify({ focus: vertex });\n options.onFocus?.(vertex);\n },\n hover(vertex) {\n if (vertex !== snapshot.hovered) notify({ hovered: vertex });\n },\n pin(vertices) {\n notify({ pinned: [...vertices] });\n },\n setTool(tool) {\n if (tool !== snapshot.tool) notify({ tool });\n },\n report(motion) {\n if (motion !== snapshot.motion) notify({ motion });\n },\n reportProgress(value) {\n if (value !== snapshot.progress) notify({ progress: value });\n },\n setRenderable(renderable) {\n if (unrenderable === !renderable) return;\n unrenderable = !renderable;\n notify();\n },\n reportDrawn(visible, drawn) {\n if (composed === visible && drawn === null) return;\n composed = visible;\n notify(drawn ? { drawn } : {});\n },\n };\n\n binding = bindingOf(initial);\n adopt(initial.corpus);\n return store;\n}\n"],"names":["DEFAULT_LIMIT","NO_BINDING","bindingOf","KEY","PAYLOAD_ADDRESS","bytesOf","content","bytes","edge","_a","sameFilter","a","b","_","v","isPromise","value","keep","previous","next","view","i","createGraph","initial","options","listeners","self","graphClient","corpus","opening","failed","unrenderable","matrix","typeIndex","modeColumn","scan","binding","filter","viewport","declined","composed","unlisten","active","lastFrame","fail","error","tileset","Tileset2D","addresses","signal","isCells","address","rows","src","payload","dst","dstOf","out","back","edges","gaps","gap","tile","d","notify","snapshot","viewOf","domain","domainNow","key","part","domainOf","statusOf","pending","visible","patch","tiles","listener","rescan","fixed","PAYLOAD_COORDINATES","projectionOf","reopen","cleared","types","type","t","_b","mode","_c","_e","_d","channel","adopt","given","promised","opened","listen","crossfilter","refilter","filterFor","store","nextBinding","rebound","vertices","source","label","selection","publish","denseOf","vertex","tool","motion","renderable","drawn"],"mappings":"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"}
|