@kanzo-tech/graph 0.14.0 → 0.15.1
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 +20 -16
- package/dist/core/categories.d.ts +18 -6
- package/dist/core/categories.d.ts.map +1 -1
- package/dist/core/categories.js +41 -10
- package/dist/core/categories.js.map +1 -1
- package/dist/core/channels.d.ts +10 -5
- package/dist/core/channels.d.ts.map +1 -1
- package/dist/core/channels.js +11 -13
- package/dist/core/channels.js.map +1 -1
- package/dist/core/detail.d.ts +14 -8
- package/dist/core/detail.d.ts.map +1 -1
- package/dist/core/detail.js +33 -15
- package/dist/core/detail.js.map +1 -1
- package/dist/core/filter.d.ts +3 -1
- package/dist/core/filter.d.ts.map +1 -1
- package/dist/core/filter.js +54 -50
- package/dist/core/filter.js.map +1 -1
- package/dist/core/load.d.ts +58 -0
- package/dist/core/load.d.ts.map +1 -0
- package/dist/core/load.js +115 -0
- package/dist/core/load.js.map +1 -0
- package/dist/core/state.d.ts +27 -55
- package/dist/core/state.d.ts.map +1 -1
- package/dist/core/store.d.ts +1 -3
- package/dist/core/store.d.ts.map +1 -1
- package/dist/core/store.js +159 -174
- package/dist/core/store.js.map +1 -1
- package/dist/core/types.d.ts +21 -17
- package/dist/core/types.d.ts.map +1 -1
- package/dist/index.d.ts +5 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -25
- package/dist/index.js.map +1 -1
- package/dist/parts/gesture.d.ts +1 -10
- package/dist/parts/gesture.d.ts.map +1 -1
- package/dist/parts/gesture.js +28 -28
- package/dist/parts/gesture.js.map +1 -1
- package/dist/parts/graph-canvas.d.ts.map +1 -1
- package/dist/parts/graph-canvas.js +119 -108
- package/dist/parts/graph-canvas.js.map +1 -1
- package/dist/parts/graph-inspector.d.ts +4 -4
- package/dist/parts/graph-inspector.d.ts.map +1 -1
- package/dist/parts/graph-inspector.js +55 -57
- package/dist/parts/graph-inspector.js.map +1 -1
- package/dist/parts/graph-legend.d.ts +4 -4
- package/dist/parts/graph-legend.d.ts.map +1 -1
- package/dist/parts/graph-legend.js +21 -21
- package/dist/parts/graph-legend.js.map +1 -1
- package/dist/parts/overlays.d.ts +2 -4
- package/dist/parts/overlays.d.ts.map +1 -1
- package/dist/parts/overlays.js +45 -45
- package/dist/parts/overlays.js.map +1 -1
- package/dist/react/use-graph-state.d.ts +4 -2
- package/dist/react/use-graph-state.d.ts.map +1 -1
- package/dist/react/use-graph-state.js +10 -6
- package/dist/react/use-graph-state.js.map +1 -1
- package/dist/react/use-graph.d.ts +1 -4
- package/dist/react/use-graph.d.ts.map +1 -1
- package/dist/react/use-graph.js +38 -49
- package/dist/react/use-graph.js.map +1 -1
- package/dist/render/graph-looks.d.ts.map +1 -1
- package/dist/render/graph-looks.js.map +1 -1
- package/dist/render/graph-model.d.ts +6 -8
- package/dist/render/graph-model.d.ts.map +1 -1
- package/dist/render/graph-model.js +51 -57
- package/dist/render/graph-model.js.map +1 -1
- package/dist/render/graph-sim.d.ts +2 -3
- package/dist/render/graph-sim.d.ts.map +1 -1
- package/dist/render/graph-sim.js.map +1 -1
- package/dist/render/renderer.d.ts +6 -11
- package/dist/render/renderer.d.ts.map +1 -1
- package/dist/render/renderer.js +120 -173
- package/dist/render/renderer.js.map +1 -1
- package/dist/section.d.ts.map +1 -1
- package/dist/section.js +3 -7
- package/dist/section.js.map +1 -1
- package/package.json +11 -11
- package/dist/core/refine.d.ts +0 -14
- package/dist/core/refine.d.ts.map +0 -1
- package/dist/core/refine.js +0 -20
- package/dist/core/refine.js.map +0 -1
- package/dist/core/resident.d.ts +0 -79
- package/dist/core/resident.d.ts.map +0 -1
- package/dist/core/resident.js +0 -44
- package/dist/core/resident.js.map +0 -1
- package/dist/core/scheduler.d.ts +0 -42
- package/dist/core/scheduler.d.ts.map +0 -1
- package/dist/core/scheduler.js +0 -77
- package/dist/core/scheduler.js.map +0 -1
- package/dist/core/tile-matrix.d.ts +0 -37
- package/dist/core/tile-matrix.d.ts.map +0 -1
- package/dist/core/tile-matrix.js +0 -49
- package/dist/core/tile-matrix.js.map +0 -1
- package/dist/core/tile.d.ts +0 -54
- package/dist/core/tile.d.ts.map +0 -1
- package/dist/core/tile.js +0 -76
- package/dist/core/tile.js.map +0 -1
- package/dist/core/tileset.d.ts +0 -59
- package/dist/core/tileset.d.ts.map +0 -1
- package/dist/core/tileset.js +0 -177
- package/dist/core/tileset.js.map +0 -1
- package/dist/render/adaptive.d.ts +0 -27
- package/dist/render/adaptive.d.ts.map +0 -1
- package/dist/render/adaptive.js +0 -25
- package/dist/render/adaptive.js.map +0 -1
- package/dist/render/compose.d.ts +0 -51
- package/dist/render/compose.d.ts.map +0 -1
- package/dist/render/compose.js +0 -107
- package/dist/render/compose.js.map +0 -1
- package/dist/render/encode.d.ts +0 -42
- package/dist/render/encode.d.ts.map +0 -1
- package/dist/render/encode.js +0 -68
- package/dist/render/encode.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# @kanzo-tech/graph
|
|
2
2
|
|
|
3
|
-
The graph view over a [fossil](https://github.com/
|
|
3
|
+
The graph view over a [fossil](https://github.com/Kanzo-Tech/fossil-lang) corpus, drawn with
|
|
4
4
|
[cosmos.gl](https://cosmosgl.github.io/graph). fossil is the backend and this package is the view:
|
|
5
|
-
the host opens the corpus, and `GraphRoot` draws
|
|
5
|
+
the host opens the corpus, and `GraphRoot` draws the whole of it — no SQL is written here.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -23,7 +23,7 @@ import { GraphCanvas, GraphInspector, GraphLegend, GraphRoot, GraphToolbar } fro
|
|
|
23
23
|
|
|
24
24
|
const corpus = engine().then((e) => open(url, { engine: e }));
|
|
25
25
|
|
|
26
|
-
<GraphRoot corpus={corpus}
|
|
26
|
+
<GraphRoot corpus={corpus} r="degree" filterBy={crossfilter} onFailure={setFailure}>
|
|
27
27
|
<GraphCanvas>
|
|
28
28
|
<GraphToolbar />
|
|
29
29
|
<GraphLegend />
|
|
@@ -36,20 +36,25 @@ const corpus = engine().then((e) => open(url, { engine: e }));
|
|
|
36
36
|
corpus opens as `` open(`jobs/${id}`, { engine, host }) `` — and `GraphRoot` takes what came back,
|
|
37
37
|
or the promise of it, which is what lets it say it is opening. Closing it is the host's too.
|
|
38
38
|
|
|
39
|
-
**The
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
**The whole corpus is drawn**: every vertex table with a position — fossil's layout or the
|
|
40
|
+
program's own columns — and every relation whose two ends are drawn, read once, one scan per table,
|
|
41
|
+
and uploaded once. A vertex's `dense_id` is its index in the buffers. The camera reads nothing.
|
|
42
42
|
|
|
43
|
-
**The
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
times what it selected. A far view is a coarser rung of fossil's cell pyramid; an edge is drawn when
|
|
47
|
-
both of its ends are in tiles already read.
|
|
43
|
+
**The channels are Plot's**: `fill`, `symbol`, `r`, `stroke` and `title`, where a CSS colour is a
|
|
44
|
+
constant and anything else is a column. Unbound, colour is the vertex type and a label is the table's
|
|
45
|
+
`identity`. Changing a column binding re-reads that column and nothing else.
|
|
48
46
|
|
|
49
|
-
**`filterBy` is the page's crossfilter.** Its clauses are translated into scan's filter,
|
|
50
|
-
|
|
47
|
+
**`filterBy` is the page's crossfilter.** Its clauses are translated into scan's filter, and what
|
|
48
|
+
does not survive is hidden; a clause that cannot be translated reaches `onFailure` rather than being
|
|
51
49
|
dropped. A lasso or a click publishes the reader's pick back into it, exempting the graph itself.
|
|
52
50
|
|
|
51
|
+
**The layout is off at load.** The corpus's positions are drawn as they are; `GraphToolbar` runs and
|
|
52
|
+
stops a force layout from where the points are, and dragging a node pins it either way. At 200,000
|
|
53
|
+
vertices the viewer's p95 frame interval is 9.0 ms against 9.3 ms for cosmos.gl alone.
|
|
54
|
+
|
|
55
|
+
The reference composition is the docs' workspace showcase: one `GraphRoot` around a shell with the
|
|
56
|
+
graph, a second main view and a dock of panels.
|
|
57
|
+
|
|
53
58
|
## The pieces
|
|
54
59
|
|
|
55
60
|
- `GraphRoot` — `useGraph` plus the context. `GraphRootProvider` takes an api a host built with
|
|
@@ -61,9 +66,8 @@ dropped. A lasso or a click publishes the reader's pick back into it, exempting
|
|
|
61
66
|
commands drawn, and the focused vertex's row with a render prop for a product's own fields. No
|
|
62
67
|
part takes a callback: what a click means is `onSelect`, `onFocus` and `onFailure` on the root.
|
|
63
68
|
- `lookFrom`, `simFrom`, `useGraphPrefs` — the form and the forces from a preferences panel's
|
|
64
|
-
answers; `scaleOf` — what colour and shape a category wears
|
|
65
|
-
- `
|
|
66
|
-
everything that outlives one composition is held as one.
|
|
69
|
+
answers; `scaleOf` — what colour and shape a category wears.
|
|
70
|
+
- `VertexId` — a vertex is its `dense_id`, a `number`.
|
|
67
71
|
|
|
68
72
|
## Why a package, and not part of `@kanzo-tech/ui`
|
|
69
73
|
|
|
@@ -1,12 +1,24 @@
|
|
|
1
|
-
import { Corpus } from '@fossil-lang/corpus';
|
|
2
1
|
import { Binding } from './channels';
|
|
2
|
+
import { VertexTable } from '@fossil-lang/corpus';
|
|
3
3
|
/**
|
|
4
|
-
* **The categorical domain, fixed before
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* which is what a legend whose colours moved as tiles arrived was doing for every value.
|
|
4
|
+
* **The categorical domain, fixed before the graph loads.** Colour by vertex type ranks the drawn
|
|
5
|
+
* tables in the manifest's order; a column ranks by the keys of the host's `categories`. Only a value
|
|
6
|
+
* neither names is ranked as it is seen, after them.
|
|
8
7
|
*/
|
|
9
|
-
export declare function domainOf(
|
|
8
|
+
export declare function domainOf(tables: readonly VertexTable[], binding: Binding, categories: Readonly<Record<string, string>> | undefined): readonly unknown[];
|
|
10
9
|
/** What a legend, a card or an inspector calls a category value. */
|
|
11
10
|
export declare const nameOf: (value: unknown, categories: Readonly<Record<string, string>> | undefined) => string;
|
|
11
|
+
/**
|
|
12
|
+
* Values to codes, in the order first seen. **The seed ranks first, in its own order**, so a colour
|
|
13
|
+
* is decided before a row arrives; a value outside it is ranked after the seed, numbers before
|
|
14
|
+
* strings. Values meet by their text, so a column's `0` is the host's key `"0"`.
|
|
15
|
+
*/
|
|
16
|
+
export declare class Dictionary {
|
|
17
|
+
#private;
|
|
18
|
+
readonly values: unknown[];
|
|
19
|
+
constructor(seed?: readonly unknown[]);
|
|
20
|
+
code(value: unknown): number;
|
|
21
|
+
/** Each code's rank: the seed's own order, then every other value seen. */
|
|
22
|
+
ranks(): Uint32Array;
|
|
23
|
+
}
|
|
12
24
|
//# sourceMappingURL=categories.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"categories.d.ts","sourceRoot":"","sources":["../../src/core/categories.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"categories.d.ts","sourceRoot":"","sources":["../../src/core/categories.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD;;;;GAIG;AACH,wBAAgB,QAAQ,CACtB,MAAM,EAAE,SAAS,WAAW,EAAE,EAC9B,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,GACvD,SAAS,OAAO,EAAE,CAIpB;AAED,oEAAoE;AACpE,eAAO,MAAM,MAAM,GAAI,OAAO,OAAO,EAAE,YAAY,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,KAAG,MAC7C,CAAC;AAEtD;;;;GAIG;AACH,qBAAa,UAAU;;IACrB,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,CAAM;gBAIpB,IAAI,GAAE,SAAS,OAAO,EAAO;IAKzC,IAAI,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM;IAW5B,2EAA2E;IAC3E,KAAK,IAAI,WAAW;CAUrB"}
|
package/dist/core/categories.js
CHANGED
|
@@ -1,14 +1,45 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
var m = Object.defineProperty;
|
|
2
|
+
var l = (e) => {
|
|
3
|
+
throw TypeError(e);
|
|
4
|
+
};
|
|
5
|
+
var p = (e, t, n) => t in e ? m(e, t, { enumerable: !0, configurable: !0, writable: !0, value: n }) : e[t] = n;
|
|
6
|
+
var c = (e, t, n) => p(e, typeof t != "symbol" ? t + "" : t, n), h = (e, t, n) => t.has(e) || l("Cannot " + n);
|
|
7
|
+
var o = (e, t, n) => (h(e, t, "read from private field"), n ? n.call(e) : t.get(e)), f = (e, t, n) => t.has(e) ? l("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(e) : t.set(e, n), a = (e, t, n, r) => (h(e, t, "write to private field"), r ? r.call(e, n) : t.set(e, n), n);
|
|
8
|
+
function v(e, t, n) {
|
|
9
|
+
return t.byTable ? e.map((r) => r.name) : t.category === void 0 ? [] : n ? Object.keys(n) : [];
|
|
10
|
+
}
|
|
11
|
+
const b = (e, t) => (t == null ? void 0 : t[String(e)]) ?? String(e ?? "—");
|
|
12
|
+
var u, s;
|
|
13
|
+
class g {
|
|
14
|
+
constructor(t = []) {
|
|
15
|
+
c(this, "values", []);
|
|
16
|
+
f(this, u, /* @__PURE__ */ new Map());
|
|
17
|
+
f(this, s);
|
|
18
|
+
for (const n of t) this.code(n);
|
|
19
|
+
a(this, s, this.values.length);
|
|
20
|
+
}
|
|
21
|
+
code(t) {
|
|
22
|
+
const n = t == null ? null : String(t);
|
|
23
|
+
let r = o(this, u).get(n);
|
|
24
|
+
return r === void 0 && (r = this.values.length, this.values.push(typeof t == "bigint" ? Number(t) : t ?? null), o(this, u).set(n, r)), r;
|
|
25
|
+
}
|
|
26
|
+
/** Each code's rank: the seed's own order, then every other value seen. */
|
|
27
|
+
ranks() {
|
|
28
|
+
const t = new Uint32Array(this.values.length);
|
|
29
|
+
for (let r = 0; r < o(this, s); r++) t[r] = r;
|
|
30
|
+
const n = this.values.slice(o(this, s)).map((r, i) => ({ value: r, code: o(this, s) + i }));
|
|
31
|
+
return n.sort((r, i) => d(r.value, i.value)), n.forEach(({ code: r }, i) => {
|
|
32
|
+
t[r] = o(this, s) + i;
|
|
33
|
+
}), t;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
u = new WeakMap(), s = new WeakMap();
|
|
37
|
+
function d(e, t) {
|
|
38
|
+
return typeof e == "number" && typeof t == "number" ? e - t : typeof e == "number" ? -1 : typeof t == "number" ? 1 : String(e ?? "").localeCompare(String(t ?? ""));
|
|
8
39
|
}
|
|
9
|
-
const d = (n, t) => (t == null ? void 0 : t[String(n)]) ?? String(n ?? "—");
|
|
10
40
|
export {
|
|
11
|
-
|
|
12
|
-
|
|
41
|
+
g as Dictionary,
|
|
42
|
+
v as domainOf,
|
|
43
|
+
b as nameOf
|
|
13
44
|
};
|
|
14
45
|
//# sourceMappingURL=categories.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"categories.js","sources":["../../src/core/categories.ts"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"file":"categories.js","sources":["../../src/core/categories.ts"],"sourcesContent":["import type { Binding } from \"./channels\";\nimport type { VertexTable } from \"@fossil-lang/corpus\";\n\n/**\n * **The categorical domain, fixed before the graph loads.** Colour by vertex type ranks the drawn\n * tables in the manifest's order; a column ranks by the keys of the host's `categories`. Only a value\n * neither names is ranked as it is seen, after them.\n */\nexport function domainOf(\n tables: readonly VertexTable[],\n binding: Binding,\n categories: Readonly<Record<string, string>> | undefined,\n): readonly unknown[] {\n if (binding.byTable) return tables.map((table) => table.name);\n if (binding.category === undefined) return [];\n return categories ? Object.keys(categories) : [];\n}\n\n/** What a legend, a card or an inspector calls a category value. */\nexport const nameOf = (value: unknown, categories: Readonly<Record<string, string>> | undefined): string =>\n categories?.[String(value)] ?? String(value ?? \"—\");\n\n/**\n * Values to codes, in the order first seen. **The seed ranks first, in its own order**, so a colour\n * is decided before a row arrives; a value outside it is ranked after the seed, numbers before\n * strings. Values meet by their text, so a column's `0` is the host's key `\"0\"`.\n */\nexport class Dictionary {\n readonly values: unknown[] = [];\n readonly #codes = new Map<string | null, number>();\n readonly #seeded: number;\n\n constructor(seed: readonly unknown[] = []) {\n for (const value of seed) this.code(value);\n this.#seeded = this.values.length;\n }\n\n code(value: unknown): number {\n const key = value === null || value === undefined ? null : String(value);\n let code = this.#codes.get(key);\n if (code === undefined) {\n code = this.values.length;\n this.values.push(typeof value === \"bigint\" ? Number(value) : (value ?? null));\n this.#codes.set(key, code);\n }\n return code;\n }\n\n /** Each code's rank: the seed's own order, then every other value seen. */\n ranks(): Uint32Array {\n const ranks = new Uint32Array(this.values.length);\n for (let code = 0; code < this.#seeded; code++) ranks[code] = code;\n const rest = this.values.slice(this.#seeded).map((value, i) => ({ value, code: this.#seeded + i }));\n rest.sort((a, b) => compare(a.value, b.value));\n rest.forEach(({ code }, i) => {\n ranks[code] = this.#seeded + i;\n });\n return ranks;\n }\n}\n\nfunction compare(a: unknown, b: unknown): number {\n if (typeof a === \"number\" && typeof b === \"number\") return a - b;\n if (typeof a === \"number\") return -1;\n if (typeof b === \"number\") return 1;\n return String(a ?? \"\").localeCompare(String(b ?? \"\"));\n}\n"],"names":["domainOf","tables","binding","categories","table","nameOf","value","_codes","_seeded","Dictionary","seed","__publicField","__privateAdd","__privateSet","key","code","__privateGet","ranks","rest","a","b","compare"],"mappings":";;;;;;;AAQO,SAASA,EACdC,GACAC,GACAC,GACoB;AACpB,SAAID,EAAQ,UAAgBD,EAAO,IAAI,CAACG,MAAUA,EAAM,IAAI,IACxDF,EAAQ,aAAa,SAAkB,CAAA,IACpCC,IAAa,OAAO,KAAKA,CAAU,IAAI,CAAA;AAChD;AAGO,MAAME,IAAS,CAACC,GAAgBH,OACrCA,KAAA,gBAAAA,EAAa,OAAOG,CAAK,OAAM,OAAOA,KAAS,GAAG;AAZ7C,IAAAC,GAAAC;AAmBA,MAAMC,EAAW;AAAA,EAKtB,YAAYC,IAA2B,IAAI;AAJlC,IAAAC,EAAA,gBAAoB,CAAA;AACpB,IAAAC,EAAA,MAAAL,uBAAa,IAAA;AACb,IAAAK,EAAA,MAAAJ;AAGP,eAAWF,KAASI,EAAM,MAAK,KAAKJ,CAAK;AACzC,IAAAO,EAAA,MAAKL,GAAU,KAAK,OAAO;AAAA,EAC7B;AAAA,EAEA,KAAKF,GAAwB;AAC3B,UAAMQ,IAAMR,KAAU,OAA8B,OAAO,OAAOA,CAAK;AACvE,QAAIS,IAAOC,EAAA,MAAKT,GAAO,IAAIO,CAAG;AAC9B,WAAIC,MAAS,WACXA,IAAO,KAAK,OAAO,QACnB,KAAK,OAAO,KAAK,OAAOT,KAAU,WAAW,OAAOA,CAAK,IAAKA,KAAS,IAAK,GAC5EU,EAAA,MAAKT,GAAO,IAAIO,GAAKC,CAAI,IAEpBA;AAAA,EACT;AAAA;AAAA,EAGA,QAAqB;AACnB,UAAME,IAAQ,IAAI,YAAY,KAAK,OAAO,MAAM;AAChD,aAASF,IAAO,GAAGA,IAAOC,EAAA,MAAKR,IAASO,IAAQ,CAAAE,EAAMF,CAAI,IAAIA;AAC9D,UAAMG,IAAO,KAAK,OAAO,MAAMF,EAAA,MAAKR,EAAO,EAAE,IAAI,CAACF,GAAO,OAAO,EAAE,OAAAA,GAAO,MAAMU,EAAA,MAAKR,KAAU,IAAI;AAClG,WAAAU,EAAK,KAAK,CAACC,GAAGC,MAAMC,EAAQF,EAAE,OAAOC,EAAE,KAAK,CAAC,GAC7CF,EAAK,QAAQ,CAAC,EAAE,MAAAH,EAAA,GAAQ,MAAM;AAC5B,MAAAE,EAAMF,CAAI,IAAIC,EAAA,MAAKR,KAAU;AAAA,IAC/B,CAAC,GACMS;AAAA,EACT;AACF;AA9BWV,IAAA,eACAC,IAAA;AA+BX,SAASa,EAAQF,GAAYC,GAAoB;AAC/C,SAAI,OAAOD,KAAM,YAAY,OAAOC,KAAM,WAAiBD,IAAIC,IAC3D,OAAOD,KAAM,WAAiB,KAC9B,OAAOC,KAAM,WAAiB,IAC3B,OAAOD,KAAK,EAAE,EAAE,cAAc,OAAOC,KAAK,EAAE,CAAC;AACtD;"}
|
package/dist/core/channels.d.ts
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
* paints every point one ink and leaves colour free to mean the selection.
|
|
5
5
|
*/
|
|
6
6
|
export interface Channels {
|
|
7
|
-
/** Which column colours a point, or a CSS colour every point wears. */
|
|
7
|
+
/** Which column colours a point, or a CSS colour every point wears. Absent, colour is the vertex type. */
|
|
8
8
|
fill?: string;
|
|
9
9
|
/**
|
|
10
|
-
* Which column a point's shape carries.
|
|
10
|
+
* Which column a point's shape carries. The graph holds one categorical column, so bound beside a
|
|
11
11
|
* `fill` column this reads the same one; a second would need a second array everywhere.
|
|
12
12
|
*/
|
|
13
13
|
symbol?: string;
|
|
@@ -18,8 +18,10 @@ export interface Channels {
|
|
|
18
18
|
export declare function isColour(value: string | undefined): value is string;
|
|
19
19
|
/** The columns a binding reads, which is what a scan projects. */
|
|
20
20
|
export interface Binding {
|
|
21
|
-
/** The one categorical column: `fill` when it names one, `symbol` when `fill` is a constant. */
|
|
21
|
+
/** The one categorical column: `fill` when it names one, `symbol` when `fill` is a constant or absent. */
|
|
22
22
|
readonly category: string | undefined;
|
|
23
|
+
/** No column and no constant: the category is the vertex type. */
|
|
24
|
+
readonly byTable: boolean;
|
|
23
25
|
/** What the size ramp is spent on — Plot's `r`. */
|
|
24
26
|
readonly size: string | undefined;
|
|
25
27
|
/** The text a label and the hover card show — Plot's `title`. */
|
|
@@ -29,6 +31,9 @@ export declare function bindingOf(options: Channels & {
|
|
|
29
31
|
r?: string;
|
|
30
32
|
title?: string;
|
|
31
33
|
}): Binding;
|
|
32
|
-
/**
|
|
33
|
-
|
|
34
|
+
/**
|
|
35
|
+
* A binding is a projection: `fill` and `r` as columns become the scan's `select`, where the table
|
|
36
|
+
* has them. `title` is not: a label's text is read for the few vertices that carry one.
|
|
37
|
+
*/
|
|
38
|
+
export declare function projectionOf(binding: Binding, fixed: readonly string[], has: (column: string) => boolean): string[];
|
|
34
39
|
//# sourceMappingURL=channels.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channels.d.ts","sourceRoot":"","sources":["../../src/core/channels.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACvB,
|
|
1
|
+
{"version":3,"file":"channels.d.ts","sourceRoot":"","sources":["../../src/core/channels.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACvB,0GAA0G;IAC1G,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,kGAAkG;AAClG,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,KAAK,IAAI,MAAM,CAEnE;AAED,kEAAkE;AAClE,MAAM,WAAW,OAAO;IACtB,0GAA0G;IAC1G,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,kEAAkE;IAClE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,mDAAmD;IACnD,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;CACpC;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,QAAQ,GAAG;IAAE,CAAC,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAIrF;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,GAAG,MAAM,EAAE,CAGnH"}
|
package/dist/core/channels.js
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
function
|
|
2
|
-
return
|
|
1
|
+
function c(t) {
|
|
2
|
+
return t !== void 0 && /^(var\(|#|rgb|hsl|oklch|oklab|lab|lch|color\()/i.test(t);
|
|
3
3
|
}
|
|
4
|
-
function
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
size: r.r,
|
|
8
|
-
title: r.title
|
|
9
|
-
};
|
|
4
|
+
function n(t) {
|
|
5
|
+
const l = c(t.fill), r = l ? t.symbol : t.fill ?? t.symbol;
|
|
6
|
+
return { category: r, byTable: !l && r === void 0, size: t.r, title: t.title };
|
|
10
7
|
}
|
|
11
|
-
function
|
|
12
|
-
|
|
8
|
+
function i(t, l, r) {
|
|
9
|
+
const o = [t.category, t.size].filter((e) => e !== void 0 && r(e));
|
|
10
|
+
return [.../* @__PURE__ */ new Set([...l, ...o])];
|
|
13
11
|
}
|
|
14
12
|
export {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
n as bindingOf,
|
|
14
|
+
c as isColour,
|
|
15
|
+
i as projectionOf
|
|
18
16
|
};
|
|
19
17
|
//# sourceMappingURL=channels.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channels.js","sources":["../../src/core/channels.ts"],"sourcesContent":["/**\n * What each channel is bound to — Plot's names, and Plot's rule that **a CSS colour is a constant\n * and anything else is a column.** `fill=\"kind\"` spends colour on a category; `fill=\"var(--foreground)\"`\n * paints every point one ink and leaves colour free to mean the selection.\n */\nexport interface Channels {\n /** Which column colours a point, or a CSS colour every point wears. */\n fill?: string;\n /**\n * Which column a point's shape carries.
|
|
1
|
+
{"version":3,"file":"channels.js","sources":["../../src/core/channels.ts"],"sourcesContent":["/**\n * What each channel is bound to — Plot's names, and Plot's rule that **a CSS colour is a constant\n * and anything else is a column.** `fill=\"kind\"` spends colour on a category; `fill=\"var(--foreground)\"`\n * paints every point one ink and leaves colour free to mean the selection.\n */\nexport interface Channels {\n /** Which column colours a point, or a CSS colour every point wears. Absent, colour is the vertex type. */\n fill?: string;\n /**\n * Which column a point's shape carries. The graph holds one categorical column, so bound beside a\n * `fill` column this reads the same one; a second would need a second array everywhere.\n */\n symbol?: string;\n /** What tints a link. Absent, a link takes the colour of the vertex it leaves. */\n stroke?: string;\n}\n\n/** Narrow on purpose — `var(…)`, a hex, a colour function — so a bare word is always a column. */\nexport function isColour(value: string | undefined): value is string {\n return value !== undefined && /^(var\\(|#|rgb|hsl|oklch|oklab|lab|lch|color\\()/i.test(value);\n}\n\n/** The columns a binding reads, which is what a scan projects. */\nexport interface Binding {\n /** The one categorical column: `fill` when it names one, `symbol` when `fill` is a constant or absent. */\n readonly category: string | undefined;\n /** No column and no constant: the category is the vertex type. */\n readonly byTable: boolean;\n /** What the size ramp is spent on — Plot's `r`. */\n readonly size: string | undefined;\n /** The text a label and the hover card show — Plot's `title`. */\n readonly title: string | undefined;\n}\n\nexport function bindingOf(options: Channels & { r?: string; title?: string }): Binding {\n const constant = isColour(options.fill);\n const category = constant ? options.symbol : (options.fill ?? options.symbol);\n return { category, byTable: !constant && category === undefined, size: options.r, title: options.title };\n}\n\n/**\n * A binding is a projection: `fill` and `r` as columns become the scan's `select`, where the table\n * has them. `title` is not: a label's text is read for the few vertices that carry one.\n */\nexport function projectionOf(binding: Binding, fixed: readonly string[], has: (column: string) => boolean): string[] {\n const bound = [binding.category, binding.size].filter((c): c is string => c !== undefined && has(c));\n return [...new Set([...fixed, ...bound])];\n}\n"],"names":["isColour","value","bindingOf","options","constant","category","projectionOf","binding","fixed","has","bound","c"],"mappings":"AAkBO,SAASA,EAASC,GAA4C;AACnE,SAAOA,MAAU,UAAa,kDAAkD,KAAKA,CAAK;AAC5F;AAcO,SAASC,EAAUC,GAA6D;AACrF,QAAMC,IAAWJ,EAASG,EAAQ,IAAI,GAChCE,IAAWD,IAAWD,EAAQ,SAAUA,EAAQ,QAAQA,EAAQ;AACtE,SAAO,EAAE,UAAAE,GAAU,SAAS,CAACD,KAAYC,MAAa,QAAW,MAAMF,EAAQ,GAAG,OAAOA,EAAQ,MAAA;AACnG;AAMO,SAASG,EAAaC,GAAkBC,GAA0BC,GAA4C;AACnH,QAAMC,IAAQ,CAACH,EAAQ,UAAUA,EAAQ,IAAI,EAAE,OAAO,CAACI,MAAmBA,MAAM,UAAaF,EAAIE,CAAC,CAAC;AACnG,SAAO,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAGH,GAAO,GAAGE,CAAK,CAAC,CAAC;AAC1C;"}
|
package/dist/core/detail.d.ts
CHANGED
|
@@ -1,18 +1,24 @@
|
|
|
1
|
-
import { Corpus
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import { Corpus } from '@fossil-lang/corpus';
|
|
2
|
+
import { Geometry } from './load';
|
|
3
|
+
import { VertexId } from './types';
|
|
4
|
+
/** One vertex's row, as its table's properties order it — every column but the key and the position. */
|
|
4
5
|
export interface VertexDetail {
|
|
5
6
|
readonly vertex: VertexId;
|
|
7
|
+
/** The vertex table it belongs to. */
|
|
8
|
+
readonly table: string;
|
|
6
9
|
readonly fields: readonly {
|
|
7
10
|
readonly name: string;
|
|
8
11
|
readonly value: unknown;
|
|
9
12
|
}[];
|
|
10
13
|
}
|
|
11
14
|
/**
|
|
12
|
-
* **Detail is fetched, not carried
|
|
13
|
-
* row is asked for when a reader focuses the vertex
|
|
14
|
-
* falls in, filtered to it. `corpus.node` takes an identity, and a tile carries an address, so the
|
|
15
|
-
* address is what asks.
|
|
15
|
+
* **Detail is fetched, not carried.** The loaded graph holds positions and channels; the rest of a
|
|
16
|
+
* row is asked for when a reader focuses the vertex — a scan of its table, filtered to its key.
|
|
16
17
|
*/
|
|
17
|
-
export declare function readVertex(corpus: Corpus,
|
|
18
|
+
export declare function readVertex(corpus: Corpus, geometry: Geometry, vertex: VertexId, signal?: AbortSignal): Promise<VertexDetail | null>;
|
|
19
|
+
/**
|
|
20
|
+
* **A label's text, for the few vertices that carry one** — `title` where the vertex's table has the
|
|
21
|
+
* column, and the table's declared `identity` where it does not. One scan per table they fall in.
|
|
22
|
+
*/
|
|
23
|
+
export declare function readTitles(corpus: Corpus, geometry: Geometry, vertices: readonly VertexId[], title: string | undefined, signal?: AbortSignal): Promise<Map<VertexId, string>>;
|
|
18
24
|
//# sourceMappingURL=detail.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detail.d.ts","sourceRoot":"","sources":["../../src/core/detail.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"detail.d.ts","sourceRoot":"","sources":["../../src/core/detail.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAe,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC,wGAAwG;AACxG,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC1B,sCAAsC;IACtC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,SAAS;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;CAChF;AAKD;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,QAAQ,EAChB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAa9B;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,SAAS,QAAQ,EAAE,EAC7B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAmBhC"}
|
package/dist/core/detail.js
CHANGED
|
@@ -1,20 +1,38 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
const l =
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
return { name: e, value: ((i = n.getChild(e)) == null ? void 0 : i.toArray()[0]) ?? null };
|
|
1
|
+
const y = (o, a) => a < o.size ? o.tables[o.table[a]] : void 0;
|
|
2
|
+
async function k(o, a, i, c) {
|
|
3
|
+
var u, f;
|
|
4
|
+
const e = y(a, i);
|
|
5
|
+
if (!e) return null;
|
|
6
|
+
const l = /* @__PURE__ */ new Set([e.key, (u = e.position) == null ? void 0 : u.x, (f = e.position) == null ? void 0 : f.y]), r = e.properties.map((t) => t.name).filter((t) => !l.has(t)), n = o.scan({ table: e.name, filter: { column: e.key, op: "=", value: i }, select: [e.key, ...r], limit: 1 }), s = (await n.read(n.plan(), { signal: c })).find((t) => t.numRows > 0);
|
|
7
|
+
return s ? {
|
|
8
|
+
vertex: i,
|
|
9
|
+
table: e.name,
|
|
10
|
+
fields: r.map((t) => {
|
|
11
|
+
var p;
|
|
12
|
+
return { name: t, value: ((p = s.getChild(t)) == null ? void 0 : p.toArray()[0]) ?? null };
|
|
14
13
|
})
|
|
15
|
-
};
|
|
14
|
+
} : null;
|
|
15
|
+
}
|
|
16
|
+
async function h(o, a, i, c, e) {
|
|
17
|
+
const l = /* @__PURE__ */ new Map();
|
|
18
|
+
for (const n of i) {
|
|
19
|
+
const s = y(a, n);
|
|
20
|
+
s && l.set(s, [...l.get(s) ?? [], n]);
|
|
21
|
+
}
|
|
22
|
+
const r = /* @__PURE__ */ new Map();
|
|
23
|
+
return await Promise.all(
|
|
24
|
+
[...l].map(async ([n, s]) => {
|
|
25
|
+
var t, p;
|
|
26
|
+
const u = c !== void 0 && n.properties.some((d) => d.name === c) ? c : n.identity, f = o.scan({ table: n.name, filter: { column: n.key, op: "in", values: s }, select: [n.key, u] });
|
|
27
|
+
for (const d of await f.read(f.plan(), { signal: e })) {
|
|
28
|
+
const w = ((t = d.getChild(n.key)) == null ? void 0 : t.toArray()) ?? [], b = ((p = d.getChild(u)) == null ? void 0 : p.toArray()) ?? [];
|
|
29
|
+
for (let m = 0; m < d.numRows; m++) r.set(Number(w[m]), String(b[m] ?? ""));
|
|
30
|
+
}
|
|
31
|
+
})
|
|
32
|
+
), r;
|
|
16
33
|
}
|
|
17
34
|
export {
|
|
18
|
-
|
|
35
|
+
h as readTitles,
|
|
36
|
+
k as readVertex
|
|
19
37
|
};
|
|
20
38
|
//# sourceMappingURL=detail.js.map
|
package/dist/core/detail.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detail.js","sources":["../../src/core/detail.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"detail.js","sources":["../../src/core/detail.ts"],"sourcesContent":["import type { Corpus, VertexTable } from \"@fossil-lang/corpus\";\nimport type { Geometry } from \"./load\";\nimport type { VertexId } from \"./types\";\n\n/** One vertex's row, as its table's properties order it — every column but the key and the position. */\nexport interface VertexDetail {\n readonly vertex: VertexId;\n /** The vertex table it belongs to. */\n readonly table: string;\n readonly fields: readonly { readonly name: string; readonly value: unknown }[];\n}\n\nconst tableOf = (geometry: Geometry, vertex: VertexId): VertexTable | undefined =>\n vertex < geometry.size ? geometry.tables[geometry.table[vertex] as number] : undefined;\n\n/**\n * **Detail is fetched, not carried.** The loaded graph holds positions and channels; the rest of a\n * row is asked for when a reader focuses the vertex — a scan of its table, filtered to its key.\n */\nexport async function readVertex(\n corpus: Corpus,\n geometry: Geometry,\n vertex: VertexId,\n signal?: AbortSignal,\n): Promise<VertexDetail | null> {\n const table = tableOf(geometry, vertex);\n if (!table) return null;\n const hidden = new Set([table.key, table.position?.x, table.position?.y]);\n const names = table.properties.map((p) => p.name).filter((name) => !hidden.has(name));\n const scan = corpus.scan({ table: table.name, filter: { column: table.key, op: \"=\", value: vertex }, select: [table.key, ...names], limit: 1 });\n const rows = (await scan.read(scan.plan(), { signal })).find((batch) => batch.numRows > 0);\n if (!rows) return null;\n return {\n vertex,\n table: table.name,\n fields: names.map((name) => ({ name, value: rows.getChild(name)?.toArray()[0] ?? null })),\n };\n}\n\n/**\n * **A label's text, for the few vertices that carry one** — `title` where the vertex's table has the\n * column, and the table's declared `identity` where it does not. One scan per table they fall in.\n */\nexport async function readTitles(\n corpus: Corpus,\n geometry: Geometry,\n vertices: readonly VertexId[],\n title: string | undefined,\n signal?: AbortSignal,\n): Promise<Map<VertexId, string>> {\n const byTable = new Map<VertexTable, VertexId[]>();\n for (const vertex of vertices) {\n const table = tableOf(geometry, vertex);\n if (table) byTable.set(table, [...(byTable.get(table) ?? []), vertex]);\n }\n const found = new Map<VertexId, string>();\n await Promise.all(\n [...byTable].map(async ([table, ids]) => {\n const column = title !== undefined && table.properties.some((p) => p.name === title) ? title : table.identity;\n const scan = corpus.scan({ table: table.name, filter: { column: table.key, op: \"in\", values: ids }, select: [table.key, column] });\n for (const batch of await scan.read(scan.plan(), { signal })) {\n const keys = batch.getChild(table.key)?.toArray() ?? [];\n const texts = batch.getChild(column)?.toArray() ?? [];\n for (let i = 0; i < batch.numRows; i++) found.set(Number(keys[i]), String(texts[i] ?? \"\"));\n }\n }),\n );\n return found;\n}\n"],"names":["tableOf","geometry","vertex","readVertex","corpus","signal","_a","_b","table","hidden","names","p","name","scan","rows","batch","readTitles","vertices","title","byTable","found","ids","column","keys","texts","i"],"mappings":"AAYA,MAAMA,IAAU,CAACC,GAAoBC,MACnCA,IAASD,EAAS,OAAOA,EAAS,OAAOA,EAAS,MAAMC,CAAM,CAAW,IAAI;AAM/E,eAAsBC,EACpBC,GACAH,GACAC,GACAG,GAC8B;AAZhC,MAAAC,GAAAC;AAaE,QAAMC,IAAQR,EAAQC,GAAUC,CAAM;AACtC,MAAI,CAACM,EAAO,QAAO;AACnB,QAAMC,IAAS,oBAAI,IAAI,CAACD,EAAM,MAAKF,IAAAE,EAAM,aAAN,gBAAAF,EAAgB,IAAGC,IAAAC,EAAM,aAAN,gBAAAD,EAAgB,CAAC,CAAC,GAClEG,IAAQF,EAAM,WAAW,IAAI,CAACG,MAAMA,EAAE,IAAI,EAAE,OAAO,CAACC,MAAS,CAACH,EAAO,IAAIG,CAAI,CAAC,GAC9EC,IAAOT,EAAO,KAAK,EAAE,OAAOI,EAAM,MAAM,QAAQ,EAAE,QAAQA,EAAM,KAAK,IAAI,KAAK,OAAON,EAAA,GAAU,QAAQ,CAACM,EAAM,KAAK,GAAGE,CAAK,GAAG,OAAO,EAAA,CAAG,GACxII,KAAQ,MAAMD,EAAK,KAAKA,EAAK,QAAQ,EAAE,QAAAR,EAAA,CAAQ,GAAG,KAAK,CAACU,MAAUA,EAAM,UAAU,CAAC;AACzF,SAAKD,IACE;AAAA,IACL,QAAAZ;AAAA,IACA,OAAOM,EAAM;AAAA,IACb,QAAQE,EAAM,IAAI,CAACE,MAAA;AAvBvB,UAAAN;AAuBiC,eAAE,MAAAM,GAAM,SAAON,IAAAQ,EAAK,SAASF,CAAI,MAAlB,gBAAAN,EAAqB,UAAU,OAAM;KAAO;AAAA,EAAA,IAJxE;AAMpB;AAMA,eAAsBU,EACpBZ,GACAH,GACAgB,GACAC,GACAb,GACgC;AAChC,QAAMc,wBAAc,IAAA;AACpB,aAAWjB,KAAUe,GAAU;AAC7B,UAAMT,IAAQR,EAAQC,GAAUC,CAAM;AACtC,IAAIM,KAAOW,EAAQ,IAAIX,GAAO,CAAC,GAAIW,EAAQ,IAAIX,CAAK,KAAK,CAAA,GAAKN,CAAM,CAAC;AAAA,EACvE;AACA,QAAMkB,wBAAY,IAAA;AAClB,eAAM,QAAQ;AAAA,IACZ,CAAC,GAAGD,CAAO,EAAE,IAAI,OAAO,CAACX,GAAOa,CAAG,MAAM;AA7C7C,UAAAf,GAAAC;AA8CM,YAAMe,IAASJ,MAAU,UAAaV,EAAM,WAAW,KAAK,CAACG,MAAMA,EAAE,SAASO,CAAK,IAAIA,IAAQV,EAAM,UAC/FK,IAAOT,EAAO,KAAK,EAAE,OAAOI,EAAM,MAAM,QAAQ,EAAE,QAAQA,EAAM,KAAK,IAAI,MAAM,QAAQa,EAAA,GAAO,QAAQ,CAACb,EAAM,KAAKc,CAAM,GAAG;AACjI,iBAAWP,KAAS,MAAMF,EAAK,KAAKA,EAAK,QAAQ,EAAE,QAAAR,EAAA,CAAQ,GAAG;AAC5D,cAAMkB,MAAOjB,IAAAS,EAAM,SAASP,EAAM,GAAG,MAAxB,gBAAAF,EAA2B,cAAa,CAAA,GAC/CkB,MAAQjB,IAAAQ,EAAM,SAASO,CAAM,MAArB,gBAAAf,EAAwB,cAAa,CAAA;AACnD,iBAASkB,IAAI,GAAGA,IAAIV,EAAM,SAASU,OAAW,IAAI,OAAOF,EAAKE,CAAC,CAAC,GAAG,OAAOD,EAAMC,CAAC,KAAK,EAAE,CAAC;AAAA,MAC3F;AAAA,IACF,CAAC;AAAA,EAAA,GAEIL;AACT;"}
|
package/dist/core/filter.d.ts
CHANGED
|
@@ -15,6 +15,8 @@ export declare class UntranslatableFilter extends Error {
|
|
|
15
15
|
}
|
|
16
16
|
/** One mosaic-sql expression node → one `Filter`. */
|
|
17
17
|
export declare function translate(node: unknown): Filter;
|
|
18
|
+
/** Every column a filter names, once each. */
|
|
19
|
+
export declare function columnsOf(filter: Filter): string[];
|
|
18
20
|
/**
|
|
19
21
|
* The page's filter for the graph, or `undefined` for none. `selection.predicate` skips the clause
|
|
20
22
|
* the graph published itself, which is the exemption the next function takes back.
|
|
@@ -30,5 +32,5 @@ export declare function graphClient(): MosaicClient;
|
|
|
30
32
|
* the graph and applies it to every chart. A canvas that draws only what survives would otherwise
|
|
31
33
|
* answer a lasso of thirteen by removing the other 1,530.
|
|
32
34
|
*/
|
|
33
|
-
export declare function publish(selection: Selection, self: MosaicClient, column: string,
|
|
35
|
+
export declare function publish(selection: Selection, self: MosaicClient, column: string, ids: readonly number[] | null): void;
|
|
34
36
|
//# sourceMappingURL=filter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../src/core/filter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAW,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAgB,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEhF;;;;;;;;GAQG;AAEH,+EAA+E;AAC/E,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,SAAkB,IAAI,0BAA0B;CACjD;AAoDD,qDAAqD;AACrD,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAyC/C;AAID;;;GAGG;AACH,wBAAgB,SAAS,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,GAAG,MAAM,GAAG,SAAS,CAItF;AAED;;;GAGG;AACH,wBAAgB,WAAW,IAAI,YAAY,CAE1C;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CACrB,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,YAAY,EAClB,MAAM,EAAE,MAAM,EACd,
|
|
1
|
+
{"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../src/core/filter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAW,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAgB,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEhF;;;;;;;;GAQG;AAEH,+EAA+E;AAC/E,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,SAAkB,IAAI,0BAA0B;CACjD;AAoDD,qDAAqD;AACrD,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAyC/C;AAID,8CAA8C;AAC9C,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAMlD;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,GAAG,MAAM,GAAG,SAAS,CAItF;AAED;;;GAGG;AACH,wBAAgB,WAAW,IAAI,YAAY,CAE1C;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CACrB,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,YAAY,EAClB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,GAC5B,IAAI,CAON"}
|
package/dist/core/filter.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
import { MosaicClient as
|
|
5
|
-
class
|
|
1
|
+
var m = Object.defineProperty;
|
|
2
|
+
var O = (n, t, r) => t in n ? m(n, t, { enumerable: !0, configurable: !0, writable: !0, value: r }) : n[t] = r;
|
|
3
|
+
var f = (n, t, r) => O(n, typeof t != "symbol" ? t + "" : t, r);
|
|
4
|
+
import { MosaicClient as h, clausePoints as y } from "@kanzo-tech/mosaic";
|
|
5
|
+
class A extends Error {
|
|
6
6
|
constructor() {
|
|
7
7
|
super(...arguments);
|
|
8
|
-
|
|
8
|
+
f(this, "name", "UntranslatableFilter");
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
|
-
const
|
|
11
|
+
const N = {
|
|
12
12
|
"=": "=",
|
|
13
13
|
"==": "=",
|
|
14
14
|
"IS NOT DISTINCT FROM": "=",
|
|
@@ -18,82 +18,86 @@ const A = {
|
|
|
18
18
|
"<=": "<=",
|
|
19
19
|
">": ">",
|
|
20
20
|
">=": ">="
|
|
21
|
-
},
|
|
22
|
-
throw new
|
|
23
|
-
`the graph cannot express this crossfilter clause as a filter on the corpus: ${String(
|
|
21
|
+
}, g = { "=": "=", "!=": "!=", "<": ">", "<=": ">=", ">": "<", ">=": "<=" }, o = (n) => {
|
|
22
|
+
throw new A(
|
|
23
|
+
`the graph cannot express this crossfilter clause as a filter on the corpus: ${String(n)}`
|
|
24
24
|
);
|
|
25
25
|
};
|
|
26
|
-
function
|
|
27
|
-
const t =
|
|
26
|
+
function s(n) {
|
|
27
|
+
const t = n;
|
|
28
28
|
return (t == null ? void 0 : t.type) === "COLUMN_REF" && typeof t.name == "string" ? t.name : null;
|
|
29
29
|
}
|
|
30
|
-
function
|
|
31
|
-
const t =
|
|
32
|
-
if (typeof
|
|
33
|
-
return
|
|
34
|
-
if (
|
|
35
|
-
const
|
|
36
|
-
return
|
|
30
|
+
function u(n) {
|
|
31
|
+
const t = n, r = (t == null ? void 0 : t.type) === "LITERAL" || (t == null ? void 0 : t.type) === "PARAM" ? t.value : o(n);
|
|
32
|
+
if (typeof r == "number" || typeof r == "bigint" || typeof r == "string" || typeof r == "boolean")
|
|
33
|
+
return r;
|
|
34
|
+
if (r instanceof Date) {
|
|
35
|
+
const e = r.toISOString();
|
|
36
|
+
return e.endsWith("T00:00:00.000Z") ? e.slice(0, 10) : e.replace("T", " ").replace("Z", "");
|
|
37
37
|
}
|
|
38
|
-
return
|
|
38
|
+
return o(n);
|
|
39
39
|
}
|
|
40
|
-
function
|
|
41
|
-
const t =
|
|
42
|
-
return (Array.isArray(
|
|
40
|
+
function v(n) {
|
|
41
|
+
const t = n;
|
|
42
|
+
return (Array.isArray(n) ? n : Array.isArray(t == null ? void 0 : t.values) ? t.values : o(n)).map(u);
|
|
43
43
|
}
|
|
44
|
-
function
|
|
45
|
-
const t =
|
|
46
|
-
if (Array.isArray(
|
|
44
|
+
function c(n) {
|
|
45
|
+
const t = n;
|
|
46
|
+
if (Array.isArray(n)) return i(n.map(c));
|
|
47
47
|
switch (t == null ? void 0 : t.type) {
|
|
48
48
|
case "LOGICAL_OPERATOR": {
|
|
49
|
-
const
|
|
50
|
-
return t.op === "OR" ? { or:
|
|
49
|
+
const r = (t.clauses ?? []).map(c);
|
|
50
|
+
return t.op === "OR" ? { or: r } : i(r);
|
|
51
51
|
}
|
|
52
52
|
case "UNARY":
|
|
53
|
-
return t.op === "NOT" ? { not:
|
|
53
|
+
return t.op === "NOT" ? { not: c(t.expr) } : o(n);
|
|
54
54
|
case "UNARY_POSTFIX": {
|
|
55
|
-
const
|
|
56
|
-
return t.op === "IS NULL" ? { column:
|
|
55
|
+
const r = s(t.expr) ?? o(n);
|
|
56
|
+
return t.op === "IS NULL" ? { column: r, op: "is null" } : t.op === "IS NOT NULL" ? { column: r, op: "not null" } : o(n);
|
|
57
57
|
}
|
|
58
58
|
case "BINARY": {
|
|
59
|
-
const
|
|
60
|
-
return
|
|
59
|
+
const r = N[String(t.op).toUpperCase()] ?? o(n), e = s(t.left);
|
|
60
|
+
return e !== null ? { column: e, op: r, value: u(t.right) } : { column: s(t.right) ?? o(n), op: g[r], value: u(t.left) };
|
|
61
61
|
}
|
|
62
62
|
case "BETWEEN":
|
|
63
63
|
case "NOT_BETWEEN": {
|
|
64
|
-
const
|
|
65
|
-
{ column:
|
|
66
|
-
{ column:
|
|
64
|
+
const r = s(t.expr) ?? o(n), [e, a] = t.extent ?? o(n), p = i([
|
|
65
|
+
{ column: r, op: ">=", value: u(e) },
|
|
66
|
+
{ column: r, op: "<=", value: u(a) }
|
|
67
67
|
]);
|
|
68
|
-
return t.type === "BETWEEN" ?
|
|
68
|
+
return t.type === "BETWEEN" ? p : { not: p };
|
|
69
69
|
}
|
|
70
70
|
case "IN":
|
|
71
|
-
return { column:
|
|
71
|
+
return { column: s(t.expr) ?? o(n), op: "in", values: v(t.values) };
|
|
72
72
|
default:
|
|
73
|
-
return
|
|
73
|
+
return o(n);
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
|
-
const
|
|
77
|
-
function
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
const i = (n) => n.length === 1 ? n[0] : { and: n };
|
|
77
|
+
function l(n) {
|
|
78
|
+
return "column" in n ? [n.column] : "and" in n ? [...new Set(n.and.flatMap(l))] : "or" in n ? [...new Set(n.or.flatMap(l))] : "not" in n ? l(n.not) : [];
|
|
79
|
+
}
|
|
80
|
+
function S(n, t) {
|
|
81
|
+
const r = n.predicate(t), e = (Array.isArray(r) ? r : [r]).filter((a) => a != null);
|
|
82
|
+
return e.length === 0 ? void 0 : c(e);
|
|
80
83
|
}
|
|
81
84
|
function T() {
|
|
82
|
-
return new
|
|
85
|
+
return new h();
|
|
83
86
|
}
|
|
84
|
-
function I(
|
|
85
|
-
|
|
86
|
-
|
|
87
|
+
function I(n, t, r, e) {
|
|
88
|
+
n.update(
|
|
89
|
+
y([r], e && e.length > 0 ? e.map((a) => [a]) : void 0, {
|
|
87
90
|
source: t,
|
|
88
91
|
clients: /* @__PURE__ */ new Set([t])
|
|
89
92
|
})
|
|
90
93
|
);
|
|
91
94
|
}
|
|
92
95
|
export {
|
|
93
|
-
|
|
94
|
-
|
|
96
|
+
A as UntranslatableFilter,
|
|
97
|
+
l as columnsOf,
|
|
98
|
+
S as filterFor,
|
|
95
99
|
T as graphClient,
|
|
96
100
|
I as publish,
|
|
97
|
-
|
|
101
|
+
c as translate
|
|
98
102
|
};
|
|
99
103
|
//# sourceMappingURL=filter.js.map
|