@kanzo-tech/graph 0.27.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.
- package/README.md +5 -2
- package/dist/core/state.d.ts +8 -3
- package/dist/core/state.d.ts.map +1 -1
- package/dist/core/store.d.ts +1 -1
- package/dist/core/store.d.ts.map +1 -1
- package/dist/core/store.js +80 -72
- package/dist/core/store.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +28 -26
- package/dist/index.js.map +1 -1
- package/dist/parts/graph-counts.d.ts +9 -11
- package/dist/parts/graph-counts.d.ts.map +1 -1
- package/dist/parts/graph-counts.js +28 -27
- package/dist/parts/graph-counts.js.map +1 -1
- package/dist/parts/graph-status.d.ts +13 -0
- package/dist/parts/graph-status.d.ts.map +1 -0
- package/dist/parts/graph-status.js +28 -0
- package/dist/parts/graph-status.js.map +1 -0
- package/dist/react/use-graph-prefs.d.ts +1 -1
- package/dist/react/use-graph-prefs.js.map +1 -1
- package/package.json +5 -5
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
|
-
- `
|
|
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
|
package/dist/core/state.d.ts
CHANGED
|
@@ -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,
|
|
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
|
|
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:
|
|
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. */
|
package/dist/core/state.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/core/state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,IAAI,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAChF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAElF,MAAM,WAAW,YAAa,SAAQ,QAAQ;IAC5C;;;OAGG;IACH,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,gGAAgG;IAChG,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,2DAA2D;IAC3D,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,sGAAsG;IACtG,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC9C,4GAA4G;IAC5G,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,8FAA8F;IAC9F,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,kEAAkE;IAClE,GAAG,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IACnB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,SAAS,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACpC,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,KAAK,IAAI,CAAC;IACjD,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,KAAK,IAAI,CAAC;CAC7C;AAED
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/core/state.ts"],"names":[],"mappings":"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"}
|
package/dist/core/store.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { GraphOptions, GraphStore } from './state';
|
|
2
|
-
export type { Drawn, GraphOptions, GraphSnapshot, GraphState,
|
|
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
|
package/dist/core/store.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/core/store.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAS,YAAY,
|
|
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"}
|
package/dist/core/store.js
CHANGED
|
@@ -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(
|
|
8
|
-
const
|
|
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 <
|
|
11
|
-
if (a && !a[r] || Number.isNaN(
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
|
|
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
|
|
17
|
-
const { links: i } =
|
|
16
|
+
let s = 0;
|
|
17
|
+
const { links: i } = f;
|
|
18
18
|
for (let r = 0; r < i.length; r += 2)
|
|
19
|
-
|
|
20
|
-
return { vertices: l, edges:
|
|
19
|
+
p[i[r]] && p[i[r + 1]] && s++;
|
|
20
|
+
return { vertices: l, edges: s, domain: t.domain, tally: d };
|
|
21
21
|
}
|
|
22
|
-
function
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
function _(f) {
|
|
23
|
+
if (f === null) return null;
|
|
24
|
+
let t = 0;
|
|
25
|
+
for (const a of f) t += a;
|
|
26
|
+
return t;
|
|
27
|
+
}
|
|
28
|
+
function H(f, t) {
|
|
29
|
+
const a = new Uint8Array(f);
|
|
30
|
+
for (const d of t) d < f && (a[d] = 1);
|
|
25
31
|
return a;
|
|
26
32
|
}
|
|
27
|
-
function
|
|
28
|
-
let
|
|
33
|
+
function le(f) {
|
|
34
|
+
let t = f;
|
|
29
35
|
const a = /* @__PURE__ */ new Set();
|
|
30
|
-
let
|
|
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,
|
|
38
|
+
let m = null, B = null, O = !1, C = !0, N = null;
|
|
33
39
|
const G = (e) => {
|
|
34
|
-
C ? N = { error: 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:
|
|
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 = (
|
|
57
|
-
return n.some((
|
|
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,
|
|
62
|
-
return e.some((n,
|
|
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 (
|
|
66
|
-
if (
|
|
67
|
-
const n = i !== null && [i, r,
|
|
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
|
|
77
|
+
function y(e = {}) {
|
|
71
78
|
c = {
|
|
72
79
|
...c,
|
|
73
|
-
total:
|
|
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:
|
|
77
|
-
structure:
|
|
84
|
+
options: t,
|
|
85
|
+
structure: s,
|
|
78
86
|
binding: l,
|
|
79
87
|
geometry: i,
|
|
80
88
|
encoding: r,
|
|
81
|
-
mask:
|
|
89
|
+
mask: g,
|
|
82
90
|
...e
|
|
83
91
|
}, c = { ...c, status: J() }, P();
|
|
84
92
|
}
|
|
@@ -88,56 +96,56 @@ function re(d) {
|
|
|
88
96
|
function P() {
|
|
89
97
|
for (const e of a) e();
|
|
90
98
|
}
|
|
91
|
-
function S(e, n,
|
|
92
|
-
const
|
|
99
|
+
function S(e, n, o) {
|
|
100
|
+
const u = ++k[e];
|
|
93
101
|
b[e] = !0, n().then(
|
|
94
102
|
(w) => {
|
|
95
|
-
k[e] ===
|
|
103
|
+
k[e] === u && (b[e] = !1, o(w), y());
|
|
96
104
|
},
|
|
97
105
|
(w) => {
|
|
98
|
-
k[e] ===
|
|
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 } =
|
|
104
|
-
e === null || n === null || S("structure", () => Y(e, n), (
|
|
105
|
-
if (
|
|
106
|
-
|
|
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
|
-
|
|
117
|
+
s = o, j(), m == null || m.requestQuery();
|
|
110
118
|
});
|
|
111
119
|
}
|
|
112
120
|
function j() {
|
|
113
|
-
const { coordinator: e } =
|
|
114
|
-
e === null || n === null || S("geometry", () => W(e, n, l), (
|
|
115
|
-
i =
|
|
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 } =
|
|
127
|
+
const { coordinator: e } = t, n = i;
|
|
120
128
|
if (e === null || n === null) return;
|
|
121
|
-
const
|
|
122
|
-
S("encoding", () => X(e, n, l,
|
|
123
|
-
r =
|
|
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
|
-
|
|
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 } =
|
|
141
|
+
const { coordinator: e, filterBy: n } = t;
|
|
134
142
|
e !== null && (m = new M(
|
|
135
143
|
n,
|
|
136
|
-
() =>
|
|
137
|
-
(
|
|
138
|
-
|
|
144
|
+
() => s,
|
|
145
|
+
(o) => {
|
|
146
|
+
h = o, g = o && i ? H(i.size, o) : null, y();
|
|
139
147
|
},
|
|
140
|
-
(
|
|
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 (a.add(e), !
|
|
161
|
+
if (a.add(e), !O && (O = !0, A(), N !== null)) {
|
|
154
162
|
const { error: n } = N;
|
|
155
|
-
N = null,
|
|
163
|
+
N = null, t.onFailure(n);
|
|
156
164
|
}
|
|
157
165
|
return () => {
|
|
158
166
|
a.delete(e), a.size === 0 && Q.destroy();
|
|
159
167
|
};
|
|
160
168
|
},
|
|
161
169
|
getSnapshot: () => c,
|
|
162
|
-
getOptions: () =>
|
|
170
|
+
getOptions: () => t,
|
|
163
171
|
setOptions(e) {
|
|
164
|
-
const n =
|
|
165
|
-
|
|
166
|
-
const
|
|
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
|
|
169
|
-
|
|
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
|
-
|
|
180
|
+
O = !1, D(), a.clear();
|
|
173
181
|
},
|
|
174
|
-
select(e, n = "external",
|
|
182
|
+
select(e, n = "external", o = "") {
|
|
175
183
|
var w;
|
|
176
|
-
const
|
|
177
|
-
v({ selection:
|
|
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 =
|
|
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
|
-
|
|
207
|
+
p && (p = !1, y());
|
|
200
208
|
},
|
|
201
209
|
unrenderable(e) {
|
|
202
|
-
|
|
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((
|
|
214
|
+
n.every((o, u) => o === z[u]) || (z = n, y());
|
|
207
215
|
}
|
|
208
216
|
};
|
|
209
|
-
return U(),
|
|
217
|
+
return U(), y(), C = !1, Q;
|
|
210
218
|
}
|
|
211
219
|
export {
|
|
212
|
-
|
|
220
|
+
le as createGraph
|
|
213
221
|
};
|
|
214
222
|
//# sourceMappingURL=store.js.map
|
package/dist/core/store.js.map
CHANGED
|
@@ -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 = \"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","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":";;;;;;AAWA,SAASA,EAAQC,GAAoBC,GAAoBC,GAAgC;AACvF,QAAMC,IAAQF,EAAS,OAAO,IAAI,MAAM,CAAC,GACnCG,IAAQ,IAAI,WAAWJ,EAAS,IAAI;AAC1C,MAAIK,IAAW;AACf,WAASC,IAAK,GAAGA,IAAKN,EAAS,MAAMM,KAAM;AACzC,QAAKJ,KAAQ,CAACA,EAAKI,CAAE,KAAM,OAAO,MAAMN,EAAS,UAAUM,IAAK,CAAC,CAAC,EAAG;AACrE,IAAAF,EAAME,CAAE,IAAI,GACZD;AACA,UAAME,IAAON,EAAS,MAAMK,CAAE;AAC9B,IAAAH,EAAMI,CAAI,KAAKJ,EAAMI,CAAI,KAAK,KAAK;AAAA,EACrC;AACA,MAAIC,IAAQ;AACZ,QAAM,EAAE,OAAAC,MAAUT;AAClB,WAASU,IAAI,GAAGA,IAAID,EAAM,QAAQC,KAAK;AACrC,IAAIN,EAAMK,EAAMC,CAAC,CAAW,KAAKN,EAAMK,EAAMC,IAAI,CAAC,CAAW,KAAGF;AAElE,SAAO,EAAE,UAAAH,GAAU,OAAAG,GAAO,QAAQP,EAAS,QAAQ,OAAAE,EAAA;AACrD;AAEA,SAASQ,EAAWT,GAAwC;AAC1D,MAAIA,MAAS,KAAM,QAAO;AAC1B,MAAIU,IAAI;AACR,aAAWC,KAAQX,EAAM,CAAAU,KAAKC;AAC9B,SAAOD;AACT;AAGA,SAASE,EAAOC,GAAcC,GAA+B;AAC3D,QAAMd,IAAO,IAAI,WAAWa,CAAI;AAChC,aAAWT,KAAMU,EAAK,CAAIV,IAAKS,MAAMb,EAAKI,CAAE,IAAI;AAChD,SAAOJ;AACT;AAEO,SAASe,GAAYC,GAAmC;AAC7D,MAAIC,IAAUD;AACd,QAAME,wBAAgB,IAAA;AAEtB,MAAIC,IAAS,IACTC,IAAe,IACfC,IAAUC,EAAUN,CAAO,GAC3BO,IAA8B,MAC9BzB,IAA4B,MAC5BC,IAA4B,MAC5BY,IAA4B,MAC5BX,IAA0B,MAC1BwB,IAA+B,CAAA;AAEnC,QAAMC,IAAU,EAAE,WAAW,GAAG,UAAU,GAAG,UAAU,EAAA,GACjDC,IAAU,EAAE,WAAW,IAAO,UAAU,IAAO,UAAU,GAAA;AAC/D,MAAIC,IAA6B,MAC7BC,IAAgC,MAChCC,IAAS,IAKTC,IAAW,IACXC,IAAkC;AACtC,QAAMC,IAAO,CAACC,MAAmB;AAC/B,IAAIH,IAAUC,IAAO,EAAE,OAAAE,EAAA,IAClBhB,EAAQ,UAAUgB,CAAK;AAAA,EAC9B;AAEA,MAAIC,IAA0B;AAAA,IAC5B,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO;AAAA,IACP,QAAQ,CAAA;AAAA,IACR,WAAW;AAAA,IACX,OAAO;AAAA,IACP,SAAS;AAAA,IACT,QAAQ,CAAA;AAAA,IACR,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,SAAAjB;AAAA,IACA,WAAW;AAAA,IACX,SAAAI;AAAA,IACA,UAAU;AAAA,IACV,UAAU;AAAA,IACV,MAAM;AAAA,EAAA,GAGJc,IAAwD,EAAE,KAAK,CAAA,GAAI,OAAO,CAAA,EAAC;AAC/E,WAASC,IAAgC;AACvC,UAAMC,KAASd,KAAA,gBAAAA,EAAW,aAAY,CAAA,GAChCe,IAAM,CAACD,GAAQhB,EAAQ,SAASA,EAAQ,UAAUJ,EAAQ,UAAU;AAC1E,WAAIqB,EAAI,KAAK,CAACC,GAAM/B,MAAM+B,MAASJ,EAAO,IAAI3B,CAAC,CAAC,MAAG2B,IAAS,EAAE,KAAAG,GAAK,OAAOE,EAASH,GAAQhB,GAASJ,EAAQ,UAAU,EAAA,IAC/GkB,EAAO;AAAA,EAChB;AAEA,MAAIM,IAAiD,EAAE,KAAK,CAAA,GAAI,OAAO,KAAA;AACvE,WAASC,IAAyB;AAChC,UAAMJ,IAAM,CAACxC,GAAUC,GAAUC,CAAI;AACrC,WAAIsC,EAAI,KAAK,CAACC,GAAM/B,MAAM+B,MAASE,EAAM,IAAIjC,CAAC,CAAC,MAC7CiC,IAAQ,EAAE,KAAAH,GAAK,OAAOxC,KAAYC,IAAWF,EAAQC,GAAUC,GAAUC,CAAI,IAAI,KAAA,IAE5EyC,EAAM;AAAA,EACf;AAEA,WAASE,IAAuB;AAC9B,QAAIxB,KAAUC,EAAc,QAAO;AACnC,QAAIH,EAAQ,SAAS,QAAQA,EAAQ,gBAAgB,KAAM,QAAO;AAElE,UAAMf,IAAQJ,MAAa,QADX,CAACA,GAAUC,GAAUC,CAAI,EACE,MAAM,CAACuC,GAAM/B,MAAM+B,MAASf,EAAShB,CAAC,CAAC;AAClF,WAAOkB,EAAQ,aAAaA,EAAQ,YAAYA,EAAQ,YAAY,CAACxB,IAAQ,YAAY;AAAA,EAC3F;AAEA,WAAS0C,EAAOC,IAAiC,IAAU;AACzD,IAAAX,IAAW;AAAA,MACT,GAAGA;AAAA,MACH,OAAOX,KAAA,gBAAAA,EAAW;AAAA,MAClB,UAAUvB,MAASkC,EAAS,OAAOA,EAAS,WAAWzB,EAAWT,CAAI;AAAA,MACtE,OAAO0C,EAAA;AAAA,MACP,QAAQN,EAAA;AAAA,MACR,SAAAnB;AAAA,MACA,WAAAM;AAAA,MACA,SAAAF;AAAA,MACA,UAAAvB;AAAA,MACA,UAAAC;AAAA,MACA,MAAAC;AAAA,MACA,GAAG6C;AAAA,IAAA,GAELX,IAAW,EAAE,GAAGA,GAAU,QAAQS,IAAS,GAC3CG,EAAA;AAAA,EACF;AAGA,WAASC,EAAMF,GAAsC;AACnD,IAAAX,IAAW,EAAE,GAAGA,GAAU,GAAGW,EAAA,GAC7BC,EAAA;AAAA,EACF;AAEA,WAASA,IAAa;AACpB,eAAWE,KAAY9B,EAAW,CAAA8B,EAAA;AAAA,EACpC;AAMA,WAASC,EAAQC,GAA4BC,GAAuBC,GAAgC;AAClG,UAAMC,IAAS,EAAE5B,EAAQyB,CAAI;AAC7B,IAAAxB,EAAQwB,CAAI,IAAI,IAChBC,EAAA,EAAM;AAAA,MACJ,CAACG,MAAU;AACT,QAAI7B,EAAQyB,CAAI,MAAMG,MACtB3B,EAAQwB,CAAI,IAAI,IAChBE,EAAKE,CAAK,GACVV,EAAA;AAAA,MACF;AAAA,MACA,CAACX,MAAmB;AAClB,QAAIR,EAAQyB,CAAI,MAAMG,MACtB3B,EAAQwB,CAAI,IAAI,IAChB/B,IAAS,IACTa,EAAKC,CAAK,GACVW,EAAA;AAAA,MACF;AAAA,IAAA;AAAA,EAEJ;AAEA,WAASW,IAAsB;AAC7B,UAAM,EAAE,aAAAC,GAAa,MAAAC,EAAA,IAASxC;AAC9B,IAAIuC,MAAgB,QAAQC,MAAS,QACrCR,EAAK,aAAa,MAAMS,EAAcF,GAAaC,CAAI,GAAG,CAACE,MAAS;AAClE,UAAIA,EAAK,SAAS,GAAG;AACnB,QAAAxC,IAAS,IACTa,EAAK,IAAI4B,EAAW,yBAAyB,0BAA0BH,CAAI,gBAAgB,CAAC;AAC5F;AAAA,MACF;AACA,MAAAlC,IAAYoC,GACZE,EAAA,GACAlC,KAAA,QAAAA,EAAQ;AAAA,IACV,CAAC;AAAA,EACH;AAEA,WAASkC,IAAsB;AAC7B,UAAM,EAAE,aAAAL,MAAgBvC,GAClB6C,IAAQvC;AACd,IAAIiC,MAAgB,QAAQM,MAAU,QACtCb,EAAK,YAAY,MAAMc,EAAaP,GAAaM,GAAOzC,CAAO,GAAG,CAACsC,MAAS;AAC1E,MAAA7D,IAAW6D,GACX3D,IAAOW,IAAOC,EAAO+C,EAAK,MAAMhD,CAAI,IAAI,MACxCqD,EAAA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,WAASA,IAAqB;AAC5B,UAAM,EAAE,aAAAR,MAAgBvC,GAClB6C,IAAQhE;AACd,QAAI0D,MAAgB,QAAQM,MAAU,KAAM;AAC5C,UAAMG,IAAO7B,EAAA;AACb,IAAAa,EAAK,YAAY,MAAMiB,EAAaV,GAAaM,GAAOzC,GAAS4C,CAAI,GAAG,CAACN,MAAS;AAChF,MAAA5D,IAAW4D;AAAA,IACb,CAAC;AAAA,EACH;AAEA,WAASQ,IAAc;AACrB,eAAWjB,KAAQ,OAAO,KAAKzB,CAAO;AACpC,MAAAA,EAAQyB,CAAI,KACZxB,EAAQwB,CAAI,IAAI;AAElB,IAAA/B,IAAS,IACTI,IAAYzB,IAAWC,IAAW,MAClCY,IAAOX,IAAO,MACdwB,IAAW,CAAA,GACXoB,EAAO,EAAE,WAAW,MAAM,OAAO,MAAM,SAAS,MAAM,QAAQ,CAAA,GAAI,GAClEW,EAAA;AAAA,EACF;AAGA,WAASa,IAAgB;AACvB,IAAAC,EAAA;AACA,UAAM,EAAE,aAAAb,GAAa,UAAAc,EAAA,IAAarD;AAClC,IAAIuC,MAAgB,SACpB7B,IAAS,IAAI4C;AAAA,MACXD;AAAA,MACA,MAAM/C;AAAA,MACN,CAACT,MAAQ;AACP,QAAAH,IAAOG,GACPd,IAAOc,KAAOhB,IAAWc,EAAOd,EAAS,MAAMgB,CAAG,IAAI,MACtD8B,EAAA;AAAA,MACF;AAAA,MACA,CAACX,MAAUD,EAAKC,CAAK;AAAA,IAAA,GAEvBuB,EAAY,QAAQ7B,CAAM,GAC1BC,IAAY4B;AAAA,EACd;AAEA,WAASa,IAAmB;AAC1B,IAAI1C,KAAUC,KAAWA,EAAU,WAAWD,CAAM,GACpDA,IAAS,MACTC,IAAY;AAAA,EACd;AAEA,QAAM4C,IAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMxB,UAAUxB,GAAU;AAElB,UADA9B,EAAU,IAAI8B,CAAQ,GAClB,CAACnB,MACHA,IAAS,IACTuC,EAAA,GACIrC,MAAS,OAAM;AACjB,cAAM,EAAE,OAAAE,MAAUF;AAClB,QAAAA,IAAO,MACPd,EAAQ,UAAUgB,CAAK;AAAA,MACzB;AAEF,aAAO,MAAM;AACX,QAAAf,EAAU,OAAO8B,CAAQ,GACrB9B,EAAU,SAAS,KAAGsD,EAAM,QAAA;AAAA,MAClC;AAAA,IACF;AAAA,IACA,aAAa,MAAMtC;AAAA,IACnB,YAAY,MAAMjB;AAAA,IAClB,WAAW0C,GAAM;AACf,YAAMc,IAAWxD;AACjB,MAAAA,IAAU0C;AACV,YAAMe,IAASrD;AAEf,UADAA,IAAUC,EAAUqC,CAAI,GACpBA,EAAK,SAASc,EAAS,QAAQd,EAAK,gBAAgBc,EAAS;AAC/D,eAAI5C,KAAU8B,EAAK,gBAAgBc,EAAS,eAAaL,EAAA,GAClDD,EAAA;AAET,MAAItC,KAAU8B,EAAK,aAAac,EAAS,YAAUL,EAAA,GAC/C/C,EAAQ,MAAMqD,EAAO,KAAKrD,EAAQ,MAAMqD,EAAO,IAAGb,EAAA,KAEpDxC,EAAQ,aAAaqD,EAAO,YAC5BrD,EAAQ,YAAYqD,EAAO,WAC3BrD,EAAQ,SAASqD,EAAO,QACxBrD,EAAQ,YAAYqD,EAAO,WAC3Bf,EAAK,eAAec,EAAS,eAE7BT,EAAA,GAEFpB,EAAA;AAAA,IACF;AAAA,IACA,UAAU;AACR,MAAAf,IAAS,IACTwC,EAAA,GACAnD,EAAU,MAAA;AAAA,IACZ;AAAA,IACA,OAAOf,GAAUwE,IAAS,YAAYC,IAAQ,IAAI;;AAChD,YAAMC,IAAY1E,KAAYA,EAAS,SAAS,IAAI,EAAE,UAAU,CAAC,GAAGA,CAAQ,GAAG,QAAAwE,GAAQ,OAAAC,MAAU;AACjG,MAAA7B,EAAM,EAAE,WAAA8B,GAAW,IACnBC,IAAA7D,EAAQ,aAAR,QAAA6D,EAAA,KAAA7D,GAAmB4D,IACf5D,EAAQ,YAAYU,KAAQoD,EAAQ9D,EAAQ,UAAUU,GAAQkD,IAAYA,EAAU,WAAW,IAAI;AAAA,IACzG;AAAA,IACA,MAAMG,GAAQ;;AACZ,MAAIA,MAAW9C,EAAS,UACxBa,EAAM,EAAE,OAAOiC,GAAQ,IACvBF,IAAA7D,EAAQ,YAAR,QAAA6D,EAAA,KAAA7D,GAAkB+D;AAAA,IACpB;AAAA,IACA,MAAMA,GAAQ;AACZ,MAAIA,MAAW9C,EAAS,aAAe,EAAE,SAAS8C,GAAQ;AAAA,IAC5D;AAAA,IACA,IAAI7E,GAAU;AACZ,MAAA4C,EAAM,EAAE,QAAQ,CAAC,GAAG5C,CAAQ,GAAG;AAAA,IACjC;AAAA,IACA,QAAQ8E,GAAM;AACZ,MAAIA,MAAS/C,EAAS,QAAMa,EAAM,EAAE,MAAAkC,GAAM;AAAA,IAC5C;AAAA,IACA,OAAOC,GAAQ;AACb,MAAIA,MAAWhD,EAAS,UAAQa,EAAM,EAAE,QAAAmC,GAAQ;AAAA,IAClD;AAAA,IACA,eAAe5B,GAAO;AACpB,MAAIA,MAAUpB,EAAS,cAAgB,EAAE,UAAUoB,GAAO;AAAA,IAC5D;AAAA,IACA,aAAa;AACX,MAAKlC,MACLA,IAAe,IACfwB,EAAA;AAAA,IACF;AAAA,IACA,aAAaX,GAAO;AAClB,MAAAb,IAAe,IACfY,EAAKC,CAAK,GACVW,EAAA;AAAA,IACF;AAAA,IACA,YAAYuC,GAAe;AACzB,YAAMxB,IAAO,CAACwB,EAAc,UAAUA,EAAc,UAAUA,EAAc,IAAI;AAChF,MAAIxB,EAAK,MAAM,CAACpB,GAAM/B,MAAM+B,MAASf,EAAShB,CAAC,CAAC,MAChDgB,IAAWmC,GACXf,EAAA;AAAA,IACF;AAAA,EAAA;AAGF,SAAAW,EAAA,GACAX,EAAA,GACAd,IAAW,IACJ0C;AACT;"}
|
package/dist/index.d.ts
CHANGED
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
* - `react/` — `useGraph`, `GraphRoot`, `GraphRootProvider`, `useGraphContext`: Ark's four; and
|
|
13
13
|
* `useGraphState`, TanStack Store's selector, because the api is commands and the state moves at
|
|
14
14
|
* frame rate.
|
|
15
|
-
* - `parts/` — `GraphCanvas`, `GraphLegend`, `GraphCounts`, `
|
|
16
|
-
* `GraphSearch`, `GraphSelect`: flat parts over the one context; and `GraphLooks`, the picture's preferences,
|
|
15
|
+
* - `parts/` — `GraphCanvas`, `GraphLegend`, `GraphCounts`, `GraphStatus`, `GraphToolbar`,
|
|
16
|
+
* `GraphInspector`, `GraphSearch`, `GraphSelect`: flat parts over the one context; and `GraphLooks`, the picture's preferences,
|
|
17
17
|
* which needs only the theme provider. They own the vocabulary; the root's callbacks are the host's policy.
|
|
18
18
|
*
|
|
19
19
|
* **Why a package and not `@kanzo-tech/ui`.** The first admission rule is *domain-free — nothing
|
|
@@ -27,6 +27,7 @@ export { useGraphPrefs } from './react/use-graph-prefs';
|
|
|
27
27
|
export { GraphCanvas, type GraphCanvasProps } from './parts/graph-canvas';
|
|
28
28
|
export { GraphLegend, type GraphLegendProps } from './parts/graph-legend';
|
|
29
29
|
export { GraphCounts, type GraphCountsProps } from './parts/graph-counts';
|
|
30
|
+
export { GraphStatus, type GraphStatusProps } from './parts/graph-status';
|
|
30
31
|
export { GraphToolbar, type GraphToolbarProps } from './parts/graph-toolbar';
|
|
31
32
|
export { GraphInspector, type GraphInspectorProps } from './parts/graph-inspector';
|
|
32
33
|
export { GraphSearch, type GraphSearchProps } from './parts/graph-search';
|
|
@@ -38,7 +39,7 @@ export { simFrom, type Sim } from './render/graph-sim';
|
|
|
38
39
|
export { scaleOf } from './render/graph-model';
|
|
39
40
|
export type { Channels } from './core/channels';
|
|
40
41
|
export type { GraphCommands, Motion, Selection, SelectionSource, Tool, VertexId } from './core/types';
|
|
41
|
-
export type { Drawn, GraphState
|
|
42
|
+
export type { DataStatus, Drawn, GraphState } from './core/state';
|
|
42
43
|
export type { VertexDetail } from './core/source';
|
|
43
44
|
export { GraphError } from './core/error';
|
|
44
45
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EACL,SAAS,EACT,iBAAiB,EACjB,eAAe,EACf,KAAK,cAAc,EACnB,KAAK,sBAAsB,GAC5B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,QAAQ,EAAE,KAAK,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAExD,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,KAAK,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnF,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAIvE,OAAO,EAAE,QAAQ,EAAE,KAAK,IAAI,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,EAAE,KAAK,KAAK,EAAE,MAAM,sBAAsB,CAAC;AACxG,OAAO,EAAE,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,YAAY,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEhD,YAAY,EAAE,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACtG,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EACL,SAAS,EACT,iBAAiB,EACjB,eAAe,EACf,KAAK,cAAc,EACnB,KAAK,sBAAsB,GAC5B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,QAAQ,EAAE,KAAK,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAExD,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,KAAK,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnF,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAIvE,OAAO,EAAE,QAAQ,EAAE,KAAK,IAAI,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,EAAE,KAAK,KAAK,EAAE,MAAM,sBAAsB,CAAC;AACxG,OAAO,EAAE,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,YAAY,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEhD,YAAY,EAAE,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACtG,YAAY,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAClE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -2,35 +2,37 @@ import { GraphRoot as p, GraphRootProvider as e, useGraphContext as t } from "./
|
|
|
2
2
|
import { useGraph as m } from "./react/use-graph.js";
|
|
3
3
|
import { useGraphState as h } from "./react/use-graph-state.js";
|
|
4
4
|
import { useGraphPrefs as G } from "./react/use-graph-prefs.js";
|
|
5
|
-
import { GraphCanvas as
|
|
6
|
-
import { GraphLegend as
|
|
7
|
-
import { GraphCounts as
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
5
|
+
import { GraphCanvas as u } from "./parts/graph-canvas.js";
|
|
6
|
+
import { GraphLegend as n } from "./parts/graph-legend.js";
|
|
7
|
+
import { GraphCounts as c } from "./parts/graph-counts.js";
|
|
8
|
+
import { GraphStatus as d } from "./parts/graph-status.js";
|
|
9
|
+
import { GraphToolbar as k } from "./parts/graph-toolbar.js";
|
|
10
|
+
import { GraphInspector as F } from "./parts/graph-inspector.js";
|
|
11
|
+
import { GraphSearch as P } from "./parts/graph-search.js";
|
|
12
|
+
import { GraphSelect as b } from "./parts/graph-select.js";
|
|
13
|
+
import { GraphLooks as y } from "./parts/graph-looks.js";
|
|
14
|
+
import { ShapeGlyph as I } from "./parts/shape-glyph.js";
|
|
15
|
+
import { lookFrom as T } from "./render/graph-looks.js";
|
|
16
|
+
import { simFrom as q } from "./render/graph-sim.js";
|
|
17
|
+
import { scaleOf as z } from "./render/graph-model.js";
|
|
18
|
+
import { GraphError as B } from "./core/error.js";
|
|
18
19
|
export {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
u as GraphCanvas,
|
|
21
|
+
c as GraphCounts,
|
|
22
|
+
B as GraphError,
|
|
23
|
+
F as GraphInspector,
|
|
24
|
+
n as GraphLegend,
|
|
25
|
+
y as GraphLooks,
|
|
25
26
|
p as GraphRoot,
|
|
26
27
|
e as GraphRootProvider,
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
d as
|
|
30
|
-
|
|
31
|
-
I as
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
P as GraphSearch,
|
|
29
|
+
b as GraphSelect,
|
|
30
|
+
d as GraphStatus,
|
|
31
|
+
k as GraphToolbar,
|
|
32
|
+
I as ShapeGlyph,
|
|
33
|
+
T as lookFrom,
|
|
34
|
+
z as scaleOf,
|
|
35
|
+
q as simFrom,
|
|
34
36
|
m as useGraph,
|
|
35
37
|
t as useGraphContext,
|
|
36
38
|
G as useGraphPrefs,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;"}
|
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
export
|
|
2
|
-
/** Draws a spinner while the corpus opens, the graph loads or a layout runs — for a host with no status of its own beside it. */
|
|
3
|
-
spinner?: boolean;
|
|
4
|
-
}
|
|
1
|
+
export type GraphCountsProps = React.ComponentProps<"p">;
|
|
5
2
|
/**
|
|
6
|
-
* **
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
3
|
+
* **The corpus in one sentence** — "5K nodes · 8K edges", and under the page's filter "1.2K of 5K
|
|
4
|
+
* nodes match · 3K edges". Nodes are the corpus's, so a filter's effect is `matching` of `total`; a
|
|
5
|
+
* vertex the filter drops is greyed on the canvas, not hidden, which is why the verb is "match" and
|
|
6
|
+
* not "drawn". Edges are those whose two ends are drawn, so they shrink with the filter. A figure
|
|
7
|
+
* not yet known is "—", and the numbers are compact in the nearest `LocaleProvider`'s locale.
|
|
10
8
|
*
|
|
11
|
-
* `aria-busy` follows `status`, because only a load changes these figures; a
|
|
12
|
-
*
|
|
9
|
+
* `aria-busy` follows `status`, because only a load changes these figures; whether a layout runs is
|
|
10
|
+
* `GraphStatus`'s word.
|
|
13
11
|
*/
|
|
14
|
-
export declare function GraphCounts({ className, slot,
|
|
12
|
+
export declare function GraphCounts({ className, slot, ...rest }: GraphCountsProps): import("react").JSX.Element;
|
|
15
13
|
//# sourceMappingURL=graph-counts.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph-counts.d.ts","sourceRoot":"","sources":["../../src/parts/graph-counts.tsx"],"names":[],"mappings":"AAKA,MAAM,
|
|
1
|
+
{"version":3,"file":"graph-counts.d.ts","sourceRoot":"","sources":["../../src/parts/graph-counts.tsx"],"names":[],"mappings":"AAKA,MAAM,MAAM,gBAAgB,GAAG,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;AAQzD;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,EAAE,gBAAgB,+BAyBzE"}
|
|
@@ -1,41 +1,42 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsxs as i, jsx as n } from "react/jsx-runtime";
|
|
3
|
-
import {
|
|
4
|
-
import { useGraphState as
|
|
5
|
-
const
|
|
2
|
+
import { jsxs as s, Fragment as i, jsx as n } from "react/jsx-runtime";
|
|
3
|
+
import { cn as h, FormatNumber as p } from "@kanzo-tech/ui";
|
|
4
|
+
import { useGraphState as a } from "../react/use-graph-state.js";
|
|
5
|
+
const f = { notation: "compact", maximumFractionDigits: 1 };
|
|
6
6
|
function r({ value: o }) {
|
|
7
|
-
return o == null ? "—" : /* @__PURE__ */ n(
|
|
7
|
+
return o == null ? "—" : /* @__PURE__ */ n(p, { value: o, ...f });
|
|
8
8
|
}
|
|
9
|
-
function
|
|
10
|
-
const
|
|
11
|
-
var
|
|
12
|
-
return (
|
|
13
|
-
}),
|
|
14
|
-
|
|
15
|
-
return (a = t.drawn) == null ? void 0 : a.edges;
|
|
16
|
-
}), g = e((t) => t.total), s = e((t) => t.status === "loading"), p = e((t) => t.motion === "running");
|
|
17
|
-
return /* @__PURE__ */ i(
|
|
9
|
+
function C({ className: o, slot: m, ...d }) {
|
|
10
|
+
const e = a((t) => t.total), u = a((t) => t.matching), l = a((t) => {
|
|
11
|
+
var c;
|
|
12
|
+
return (c = t.drawn) == null ? void 0 : c.edges;
|
|
13
|
+
}), g = a((t) => t.status === "loading");
|
|
14
|
+
return /* @__PURE__ */ s(
|
|
18
15
|
"p",
|
|
19
16
|
{
|
|
20
|
-
"aria-busy":
|
|
21
|
-
...
|
|
22
|
-
className:
|
|
23
|
-
"data-slot":
|
|
17
|
+
"aria-busy": g || void 0,
|
|
18
|
+
...d,
|
|
19
|
+
className: h("text-muted-foreground text-xs tabular-nums", o),
|
|
20
|
+
"data-slot": m ?? "graph-counts",
|
|
24
21
|
children: [
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
u === null ? /* @__PURE__ */ s(i, { children: [
|
|
23
|
+
/* @__PURE__ */ n(r, { value: e }),
|
|
24
|
+
" nodes"
|
|
25
|
+
] }) : /* @__PURE__ */ s(i, { children: [
|
|
26
|
+
/* @__PURE__ */ n(r, { value: u }),
|
|
28
27
|
" of ",
|
|
29
|
-
/* @__PURE__ */ n(r, { value:
|
|
30
|
-
" nodes
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
/* @__PURE__ */ n(r, { value: e }),
|
|
29
|
+
" nodes match"
|
|
30
|
+
] }),
|
|
31
|
+
" ",
|
|
32
|
+
"· ",
|
|
33
|
+
/* @__PURE__ */ n(r, { value: l }),
|
|
34
|
+
" edges"
|
|
34
35
|
]
|
|
35
36
|
}
|
|
36
37
|
);
|
|
37
38
|
}
|
|
38
39
|
export {
|
|
39
|
-
|
|
40
|
+
C as GraphCounts
|
|
40
41
|
};
|
|
41
42
|
//# sourceMappingURL=graph-counts.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph-counts.js","sources":["../../src/parts/graph-counts.tsx"],"sourcesContent":["\"use client\";\n\nimport { cn, FormatNumber
|
|
1
|
+
{"version":3,"file":"graph-counts.js","sources":["../../src/parts/graph-counts.tsx"],"sourcesContent":["\"use client\";\n\nimport { cn, FormatNumber } from \"@kanzo-tech/ui\";\nimport { useGraphState } from \"../react/use-graph-state\";\n\nexport type GraphCountsProps = React.ComponentProps<\"p\">;\n\nconst COMPACT = { notation: \"compact\", maximumFractionDigits: 1 } as const;\n\nfunction Count({ value }: { value: number | null | undefined }) {\n return value === null || value === undefined ? \"—\" : <FormatNumber value={value} {...COMPACT} />;\n}\n\n/**\n * **The corpus in one sentence** — \"5K nodes · 8K edges\", and under the page's filter \"1.2K of 5K\n * nodes match · 3K edges\". Nodes are the corpus's, so a filter's effect is `matching` of `total`; a\n * vertex the filter drops is greyed on the canvas, not hidden, which is why the verb is \"match\" and\n * not \"drawn\". Edges are those whose two ends are drawn, so they shrink with the filter. A figure\n * not yet known is \"—\", and the numbers are compact in the nearest `LocaleProvider`'s locale.\n *\n * `aria-busy` follows `status`, because only a load changes these figures; whether a layout runs is\n * `GraphStatus`'s word.\n */\nexport function GraphCounts({ className, slot, ...rest }: GraphCountsProps) {\n const total = useGraphState((s) => s.total);\n const matching = useGraphState((s) => s.matching);\n const edges = useGraphState((s) => s.drawn?.edges);\n const busy = useGraphState((s) => s.status === \"loading\");\n\n return (\n <p\n aria-busy={busy || undefined}\n {...rest}\n className={cn(\"text-muted-foreground text-xs tabular-nums\", className)}\n data-slot={slot ?? \"graph-counts\"}\n >\n {matching === null ? (\n <>\n <Count value={total} /> nodes\n </>\n ) : (\n <>\n <Count value={matching} /> of <Count value={total} /> nodes match\n </>\n )}{\" \"}\n · <Count value={edges} /> edges\n </p>\n );\n}\n"],"names":[],"mappings":";;;;AAOA;AAEA;AACE;AACF;AAYO;AACL;;AAEmC;AAAS;AAG5C;AACE;AAAC;AAAA;AACoB;AACf;AACiE;AAClD;AAElB;AAEG;AAAqB;AAAE;AAIvB;AAAwB;AAAE;AAAyB;AAAE;AACvD;AACC;AAAI;AACgB;AAAE;AAAA;AAAA;AAG/B;;;;"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type GraphStatusProps = React.ComponentProps<"span">;
|
|
2
|
+
/**
|
|
3
|
+
* **Where the graph is, in one word** — Loading, Laying out 42%, Ready or Failed. It reads both axes
|
|
4
|
+
* of the state: `status` for the data and `motion` with `progress` for the layout, so a running
|
|
5
|
+
* layout over a drawn graph is "Laying out", never the data's `idle`. A load wins over a layout,
|
|
6
|
+
* and a root with no corpus yet reads as Loading: the host is still opening one.
|
|
7
|
+
*
|
|
8
|
+
* ARIA: the word is a polite live region, so a change of word is announced once; the percentage
|
|
9
|
+
* sits outside it, because it moves at frame rate and would be read out on every frame. The badge
|
|
10
|
+
* is `aria-busy` while loading or laying out. The dot is decoration, hidden from the tree.
|
|
11
|
+
*/
|
|
12
|
+
export declare function GraphStatus({ className, slot, ...rest }: GraphStatusProps): import("react").JSX.Element;
|
|
13
|
+
//# sourceMappingURL=graph-status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-status.d.ts","sourceRoot":"","sources":["../../src/parts/graph-status.tsx"],"names":[],"mappings":"AAKA,MAAM,MAAM,gBAAgB,GAAG,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;AAM5D;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,EAAE,gBAAgB,+BA0BzE"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs as u, jsx as i } from "react/jsx-runtime";
|
|
3
|
+
import { Badge as d, Status as c, Show as l, FormatNumber as m, cn as g } from "@kanzo-tech/ui";
|
|
4
|
+
import { useGraphState as r } from "../react/use-graph-state.js";
|
|
5
|
+
const p = { Loading: "info", "Laying out": "info", Ready: "success", Failed: "destructive" };
|
|
6
|
+
function v({ className: s, slot: n, ...e }) {
|
|
7
|
+
const t = r((a) => a.status === "failed" ? "Failed" : a.status !== "idle" ? "Loading" : a.motion === "running" ? "Laying out" : "Ready"), o = r((a) => Math.round(a.progress * 100) / 100);
|
|
8
|
+
return /* @__PURE__ */ u(
|
|
9
|
+
d,
|
|
10
|
+
{
|
|
11
|
+
"aria-busy": t === "Loading" || t === "Laying out" || void 0,
|
|
12
|
+
size: "xs",
|
|
13
|
+
variant: "outline",
|
|
14
|
+
...e,
|
|
15
|
+
className: g("gap-1.5 tabular-nums", s),
|
|
16
|
+
slot: n ?? "graph-status",
|
|
17
|
+
children: [
|
|
18
|
+
/* @__PURE__ */ i(c, { className: "ring-0", size: "sm", variant: p[t] }),
|
|
19
|
+
/* @__PURE__ */ i("span", { "aria-live": "polite", children: t }),
|
|
20
|
+
/* @__PURE__ */ i(l, { when: t === "Laying out", children: /* @__PURE__ */ i(m, { maximumFractionDigits: 0, style: "percent", value: o }) })
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
export {
|
|
26
|
+
v as GraphStatus
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=graph-status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-status.js","sources":["../../src/parts/graph-status.tsx"],"sourcesContent":["\"use client\";\n\nimport { Badge, cn, FormatNumber, Show, Status } from \"@kanzo-tech/ui\";\nimport { useGraphState } from \"../react/use-graph-state\";\n\nexport type GraphStatusProps = React.ComponentProps<\"span\">;\n\ntype Word = \"Loading\" | \"Laying out\" | \"Ready\" | \"Failed\";\n\nconst TONE = { Loading: \"info\", \"Laying out\": \"info\", Ready: \"success\", Failed: \"destructive\" } as const;\n\n/**\n * **Where the graph is, in one word** — Loading, Laying out 42%, Ready or Failed. It reads both axes\n * of the state: `status` for the data and `motion` with `progress` for the layout, so a running\n * layout over a drawn graph is \"Laying out\", never the data's `idle`. A load wins over a layout,\n * and a root with no corpus yet reads as Loading: the host is still opening one.\n *\n * ARIA: the word is a polite live region, so a change of word is announced once; the percentage\n * sits outside it, because it moves at frame rate and would be read out on every frame. The badge\n * is `aria-busy` while loading or laying out. The dot is decoration, hidden from the tree.\n */\nexport function GraphStatus({ className, slot, ...rest }: GraphStatusProps) {\n const word = useGraphState((s): Word => {\n if (s.status === \"failed\") return \"Failed\";\n if (s.status !== \"idle\") return \"Loading\";\n return s.motion === \"running\" ? \"Laying out\" : \"Ready\";\n });\n // Rounded in the selector, so the part re-renders once a percent rather than once a frame.\n const progress = useGraphState((s) => Math.round(s.progress * 100) / 100);\n const busy = word === \"Loading\" || word === \"Laying out\";\n\n return (\n <Badge\n aria-busy={busy || undefined}\n size=\"xs\"\n variant=\"outline\"\n {...rest}\n className={cn(\"gap-1.5 tabular-nums\", className)}\n slot={slot ?? \"graph-status\"}\n >\n <Status className=\"ring-0\" size=\"sm\" variant={TONE[word]} />\n <span aria-live=\"polite\">{word}</span>\n <Show when={word === \"Laying out\"}>\n <FormatNumber maximumFractionDigits={0} style=\"percent\" value={progress} />\n </Show>\n </Badge>\n );\n}\n"],"names":[],"mappings":";;;;AASA;AAYO;AACL;AASA;AACE;AAAC;AAAA;AACoB;AACd;AACG;AACJ;AAC2C;AACjC;AAEd;AAA0D;AAC3B;AAG/B;AAAA;AAAA;AAGN;;;;"}
|
|
@@ -4,7 +4,7 @@ import { Sim } from '../render/graph-sim';
|
|
|
4
4
|
* The graph section's resolved preferences, as the two objects `useGraph` takes.
|
|
5
5
|
*
|
|
6
6
|
* The join between the provider's `sectionPrefs` and the two readers of this package's manifest.
|
|
7
|
-
* Every host that drew a graph under a preferences panel wrote it — the docs' workspace and
|
|
7
|
+
* Every host that drew a graph under a preferences panel wrote it — the docs' workspace and a host's
|
|
8
8
|
* discover page, the same eight lines each — and it knows nothing a host decides: the namespace,
|
|
9
9
|
* the keys, the defaults and the bounds are all `GRAPH_SECTION`'s, and the resolution chain is the
|
|
10
10
|
* provider's. What reaches `lookFrom`/`simFrom` is the resolved value, never the stored one.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-graph-prefs.js","sources":["../../src/react/use-graph-prefs.ts"],"sourcesContent":["\"use client\";\n\nimport { useMemo } from \"react\";\nimport { useKanzoTheme } from \"@kanzo-tech/ui\";\nimport { lookFrom, presetOf, type Look, type LookPreset } from \"../render/graph-looks\";\nimport { simFrom, type Sim } from \"../render/graph-sim\";\nimport { GRAPH_SECTION } from \"../section\";\n\n/**\n * The graph section's resolved preferences, as the two objects `useGraph` takes.\n *\n * The join between the provider's `sectionPrefs` and the two readers of this package's manifest.\n * Every host that drew a graph under a preferences panel wrote it — the docs' workspace and
|
|
1
|
+
{"version":3,"file":"use-graph-prefs.js","sources":["../../src/react/use-graph-prefs.ts"],"sourcesContent":["\"use client\";\n\nimport { useMemo } from \"react\";\nimport { useKanzoTheme } from \"@kanzo-tech/ui\";\nimport { lookFrom, presetOf, type Look, type LookPreset } from \"../render/graph-looks\";\nimport { simFrom, type Sim } from \"../render/graph-sim\";\nimport { GRAPH_SECTION } from \"../section\";\n\n/**\n * The graph section's resolved preferences, as the two objects `useGraph` takes.\n *\n * The join between the provider's `sectionPrefs` and the two readers of this package's manifest.\n * Every host that drew a graph under a preferences panel wrote it — the docs' workspace and a host's\n * discover page, the same eight lines each — and it knows nothing a host decides: the namespace,\n * the keys, the defaults and the bounds are all `GRAPH_SECTION`'s, and the resolution chain is the\n * provider's. What reaches `lookFrom`/`simFrom` is the resolved value, never the stored one.\n *\n * `preset` is the named look the axes are, for a host that pairs channels with it — Ink spends\n * identity on shape — and `null` once a reader has customised past all three.\n *\n * Needs `KanzoThemeProvider` with `GRAPH_SECTION` among its `sections`. Without it the namespace\n * resolves to nothing, both objects are the manifest's defaults and the preset is Atlas.\n */\nexport function useGraphPrefs(): { look: Look; sim: Sim; preset: LookPreset | null } {\n const resolved = useKanzoTheme().sectionPrefs[GRAPH_SECTION.namespace];\n\n return useMemo(() => {\n const values = Object.fromEntries(\n Object.entries(resolved ?? {}).map(([key, pref]) => [key, pref.value]),\n );\n return { look: lookFrom(values), sim: simFrom(values), preset: presetOf(values) };\n }, [resolved]);\n}\n"],"names":[],"mappings":";;;;;;AAuBO;AACL;AAEA;AACE;AAAsB;AACiD;AAEvE;AAA8E;AAElF;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kanzo-tech/graph",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.0",
|
|
4
4
|
"description": "Kanzo graph view — a fossil corpus attached to the page's DuckDB, read through the page's Mosaic coordinator as one more client, laid out and drawn with cosmos.gl on the GPU. Sibling of @kanzo-tech/ui, not part of it: the admission rules exclude graphs from the generic vocabulary by name.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
"@cosmos.gl/graph": "^3.4.0",
|
|
29
29
|
"lucide-react": ">=1",
|
|
30
30
|
"react": "^19.0.0",
|
|
31
|
-
"@kanzo-tech/mosaic": "0.
|
|
32
|
-
"@kanzo-tech/ui": "0.
|
|
31
|
+
"@kanzo-tech/mosaic": "0.28.0",
|
|
32
|
+
"@kanzo-tech/ui": "0.28.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@cosmos.gl/graph": "^3.4.0",
|
|
@@ -46,9 +46,9 @@
|
|
|
46
46
|
"react": "^19.0.0",
|
|
47
47
|
"react-dom": "^19.0.0",
|
|
48
48
|
"rollup-plugin-preserve-directives": "^0.4.0",
|
|
49
|
-
"@kanzo-tech/mosaic": "0.
|
|
49
|
+
"@kanzo-tech/mosaic": "0.28.0"
|
|
50
50
|
},
|
|
51
|
-
"//size-limit": "Budgets our code only: `ignore` mirrors the peers the build externalises in vite.config.ts, cosmos.gl included (about 190 kB gzipped on its own, and the consumer pays it once whatever this package does). First measured 2026-09-30 at 19.07 kB, before the lag work of `perf/phase1-lag`; 19.13 kB before the whole-corpus store deleted the tileset, 15.29 kB after it, and the budget follows it down so real growth trips the gate. Raised to 18 kB on 2026-10-01 as a decision: 17.71 kB after GraphCounts, GraphSearch and GraphLooks moved in from the workspace showcase (their code left the host, it did not appear from nowhere) and the drag-to-fix release. Raised to 18.5 kB on 2026-10-02 as a decision (Ángel): 18.01 kB once the layout's square placement and the camera that follows a running layout landed. Raised to 19 kB on 2026-10-03 as a decision (Ángel): 18.58 kB once GraphSelect moved in from the
|
|
51
|
+
"//size-limit": "Budgets our code only: `ignore` mirrors the peers the build externalises in vite.config.ts, cosmos.gl included (about 190 kB gzipped on its own, and the consumer pays it once whatever this package does). First measured 2026-09-30 at 19.07 kB, before the lag work of `perf/phase1-lag`; 19.13 kB before the whole-corpus store deleted the tileset, 15.29 kB after it, and the budget follows it down so real growth trips the gate. Raised to 18 kB on 2026-10-01 as a decision: 17.71 kB after GraphCounts, GraphSearch and GraphLooks moved in from the workspace showcase (their code left the host, it did not appear from nowhere) and the drag-to-fix release. Raised to 18.5 kB on 2026-10-02 as a decision (Ángel): 18.01 kB once the layout's square placement and the camera that follows a running layout landed. Raised to 19 kB on 2026-10-03 as a decision (Ángel): 18.58 kB once GraphSelect moved in from the hosts (which drop their copies) and the camera stopped reading positions cosmos.gl had not uploaded.",
|
|
52
52
|
"size-limit": [
|
|
53
53
|
{
|
|
54
54
|
"name": "root barrel (JS)",
|