@kanzo-tech/graph 0.13.1 → 0.15.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 +12 -15
- 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 +31 -56
- 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 +162 -172
- 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 +26 -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 +128 -106
- 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/graph-toolbar.d.ts +1 -1
- package/dist/parts/graph-toolbar.d.ts.map +1 -1
- package/dist/parts/graph-toolbar.js +40 -40
- package/dist/parts/graph-toolbar.js.map +1 -1
- package/dist/parts/overlays.d.ts +6 -5
- package/dist/parts/overlays.d.ts.map +1 -1
- package/dist/parts/overlays.js +70 -68
- 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 +10 -10
- package/dist/render/renderer.d.ts.map +1 -1
- package/dist/render/renderer.js +121 -177
- 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 +29 -10
- 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/dist/render/when-ready.d.ts +0 -35
- package/dist/render/when-ready.d.ts.map +0 -1
- package/dist/render/when-ready.js +0 -17
- package/dist/render/when-ready.js.map +0 -1
package/dist/core/filter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter.js","sources":["../../src/core/filter.ts"],"sourcesContent":["import type { Filter, Literal } from \"@fossil-lang/corpus\";\nimport { MosaicClient, clausePoints, type Selection } from \"@kanzo-tech/mosaic\";\n\n/**\n * **The page's crossfilter, as scan's typed filter.** The graph listens to the `Selection` rather\n * than being a client of the coordinator: a client hands the coordinator SQL to run, and the graph\n * has none — it hands fossil a `Filter` and fossil binds it. So this takes the half of Mosaic's\n * protocol that is about filtering: the `value` event, and `selection.predicate(client)`.\n *\n * The nodes are read by their `type`, never by importing mosaic-sql's classes: what arrives is\n * whatever the page's copy of mosaic-sql built.\n */\n\n/** A predicate this cannot express as a `Filter` — reported, never dropped. */\nexport class UntranslatableFilter extends Error {\n override readonly name = \"UntranslatableFilter\";\n}\n\ninterface Node {\n readonly type?: string;\n readonly op?: string;\n readonly [field: string]: unknown;\n}\n\nconst COMPARISONS: Record<string, \"=\" | \"!=\" | \"<\" | \"<=\" | \">\" | \">=\"> = {\n \"=\": \"=\",\n \"==\": \"=\",\n \"IS NOT DISTINCT FROM\": \"=\",\n \"<>\": \"!=\",\n \"!=\": \"!=\",\n \"<\": \"<\",\n \"<=\": \"<=\",\n \">\": \">\",\n \">=\": \">=\",\n};\nconst MIRRORED = { \"=\": \"=\", \"!=\": \"!=\", \"<\": \">\", \"<=\": \">=\", \">\": \"<\", \">=\": \"<=\" } as const;\n\nconst fail = (what: unknown): never => {\n throw new UntranslatableFilter(\n `the graph cannot express this crossfilter clause as a filter on the corpus: ${String(what)}`,\n );\n};\n\nfunction columnOf(node: unknown): string | null {\n const n = node as Node | null;\n if (n?.type === \"COLUMN_REF\" && typeof n.name === \"string\") return n.name;\n return null;\n}\n\nfunction literalOf(node: unknown): Literal {\n const n = node as Node | null;\n const value = n?.type === \"LITERAL\" || n?.type === \"PARAM\" ? n.value : fail(node);\n if (typeof value === \"number\" || typeof value === \"bigint\" || typeof value === \"string\" || typeof value === \"boolean\") {\n return value;\n }\n if (value instanceof Date) {\n const iso = value.toISOString();\n return iso.endsWith(\"T00:00:00.000Z\") ? iso.slice(0, 10) : iso.replace(\"T\", \" \").replace(\"Z\", \"\");\n }\n return fail(node);\n}\n\nfunction valuesOf(node: unknown): Literal[] {\n const n = node as Node | null;\n const list = Array.isArray(node) ? node : Array.isArray(n?.values) ? n.values : fail(node);\n return (list as unknown[]).map(literalOf);\n}\n\n/** One mosaic-sql expression node → one `Filter`. */\nexport function translate(node: unknown): Filter {\n const n = node as Node | null;\n if (Array.isArray(node)) return and(node.map(translate));\n switch (n?.type) {\n case \"LOGICAL_OPERATOR\": {\n const clauses = ((n.clauses as unknown[] | undefined) ?? []).map(translate);\n return n.op === \"OR\" ? { or: clauses } : and(clauses);\n }\n case \"UNARY\":\n if (n.op === \"NOT\") return { not: translate(n.expr) };\n return fail(node);\n case \"UNARY_POSTFIX\": {\n const column = columnOf(n.expr) ?? fail(node);\n if (n.op === \"IS NULL\") return { column, op: \"is null\" };\n if (n.op === \"IS NOT NULL\") return { column, op: \"not null\" };\n return fail(node);\n }\n case \"BINARY\": {\n const op = COMPARISONS[String(n.op).toUpperCase()] ?? fail(node);\n const left = columnOf(n.left);\n if (left !== null) return { column: left, op, value: literalOf(n.right) };\n const right = columnOf(n.right) ?? fail(node);\n return { column: right, op: MIRRORED[op], value: literalOf(n.left) };\n }\n case \"BETWEEN\":\n case \"NOT_BETWEEN\": {\n const column = columnOf(n.expr) ?? fail(node);\n const [lo, hi] = (n.extent as unknown[] | undefined) ?? fail(node);\n const within: Filter = and([\n { column, op: \">=\", value: literalOf(lo) },\n { column, op: \"<=\", value: literalOf(hi) },\n ]);\n return n.type === \"BETWEEN\" ? within : { not: within };\n }\n case \"IN\": {\n const column = columnOf(n.expr) ?? fail(node);\n return { column, op: \"in\", values: valuesOf(n.values) };\n }\n default:\n return fail(node);\n }\n}\n\nconst and = (clauses: Filter[]): Filter => (clauses.length === 1 ? (clauses[0] as Filter) : { and: clauses });\n\n/**\n * The page's filter for the graph, or `undefined` for none. `selection.predicate` skips the clause\n * the graph published itself, which is the exemption the next function takes back.\n */\nexport function filterFor(selection: Selection, self: MosaicClient): Filter | undefined {\n const predicate = selection.predicate(self) as unknown;\n const clauses = (Array.isArray(predicate) ? predicate : [predicate]).filter((p) => p !== undefined && p !== null);\n return clauses.length === 0 ? undefined : translate(clauses);\n}\n\n/**\n * An identity for `clients`, and nothing more: it is never connected, so the coordinator never\n * queries on its behalf.\n */\nexport function graphClient(): MosaicClient {\n return new MosaicClient();\n}\n\n/**\n * **The reader's pick, published** — naming the graph in `clients`, so the crossfilter skips it for\n * the graph and applies it to every chart. A canvas that draws only what survives would otherwise\n * answer a lasso of thirteen by removing the other 1,530.\n */\nexport function publish(\n selection: Selection,\n self: MosaicClient,\n column: string,\n
|
|
1
|
+
{"version":3,"file":"filter.js","sources":["../../src/core/filter.ts"],"sourcesContent":["import type { Filter, Literal } from \"@fossil-lang/corpus\";\nimport { MosaicClient, clausePoints, type Selection } from \"@kanzo-tech/mosaic\";\n\n/**\n * **The page's crossfilter, as scan's typed filter.** The graph listens to the `Selection` rather\n * than being a client of the coordinator: a client hands the coordinator SQL to run, and the graph\n * has none — it hands fossil a `Filter` and fossil binds it. So this takes the half of Mosaic's\n * protocol that is about filtering: the `value` event, and `selection.predicate(client)`.\n *\n * The nodes are read by their `type`, never by importing mosaic-sql's classes: what arrives is\n * whatever the page's copy of mosaic-sql built.\n */\n\n/** A predicate this cannot express as a `Filter` — reported, never dropped. */\nexport class UntranslatableFilter extends Error {\n override readonly name = \"UntranslatableFilter\";\n}\n\ninterface Node {\n readonly type?: string;\n readonly op?: string;\n readonly [field: string]: unknown;\n}\n\nconst COMPARISONS: Record<string, \"=\" | \"!=\" | \"<\" | \"<=\" | \">\" | \">=\"> = {\n \"=\": \"=\",\n \"==\": \"=\",\n \"IS NOT DISTINCT FROM\": \"=\",\n \"<>\": \"!=\",\n \"!=\": \"!=\",\n \"<\": \"<\",\n \"<=\": \"<=\",\n \">\": \">\",\n \">=\": \">=\",\n};\nconst MIRRORED = { \"=\": \"=\", \"!=\": \"!=\", \"<\": \">\", \"<=\": \">=\", \">\": \"<\", \">=\": \"<=\" } as const;\n\nconst fail = (what: unknown): never => {\n throw new UntranslatableFilter(\n `the graph cannot express this crossfilter clause as a filter on the corpus: ${String(what)}`,\n );\n};\n\nfunction columnOf(node: unknown): string | null {\n const n = node as Node | null;\n if (n?.type === \"COLUMN_REF\" && typeof n.name === \"string\") return n.name;\n return null;\n}\n\nfunction literalOf(node: unknown): Literal {\n const n = node as Node | null;\n const value = n?.type === \"LITERAL\" || n?.type === \"PARAM\" ? n.value : fail(node);\n if (typeof value === \"number\" || typeof value === \"bigint\" || typeof value === \"string\" || typeof value === \"boolean\") {\n return value;\n }\n if (value instanceof Date) {\n const iso = value.toISOString();\n return iso.endsWith(\"T00:00:00.000Z\") ? iso.slice(0, 10) : iso.replace(\"T\", \" \").replace(\"Z\", \"\");\n }\n return fail(node);\n}\n\nfunction valuesOf(node: unknown): Literal[] {\n const n = node as Node | null;\n const list = Array.isArray(node) ? node : Array.isArray(n?.values) ? n.values : fail(node);\n return (list as unknown[]).map(literalOf);\n}\n\n/** One mosaic-sql expression node → one `Filter`. */\nexport function translate(node: unknown): Filter {\n const n = node as Node | null;\n if (Array.isArray(node)) return and(node.map(translate));\n switch (n?.type) {\n case \"LOGICAL_OPERATOR\": {\n const clauses = ((n.clauses as unknown[] | undefined) ?? []).map(translate);\n return n.op === \"OR\" ? { or: clauses } : and(clauses);\n }\n case \"UNARY\":\n if (n.op === \"NOT\") return { not: translate(n.expr) };\n return fail(node);\n case \"UNARY_POSTFIX\": {\n const column = columnOf(n.expr) ?? fail(node);\n if (n.op === \"IS NULL\") return { column, op: \"is null\" };\n if (n.op === \"IS NOT NULL\") return { column, op: \"not null\" };\n return fail(node);\n }\n case \"BINARY\": {\n const op = COMPARISONS[String(n.op).toUpperCase()] ?? fail(node);\n const left = columnOf(n.left);\n if (left !== null) return { column: left, op, value: literalOf(n.right) };\n const right = columnOf(n.right) ?? fail(node);\n return { column: right, op: MIRRORED[op], value: literalOf(n.left) };\n }\n case \"BETWEEN\":\n case \"NOT_BETWEEN\": {\n const column = columnOf(n.expr) ?? fail(node);\n const [lo, hi] = (n.extent as unknown[] | undefined) ?? fail(node);\n const within: Filter = and([\n { column, op: \">=\", value: literalOf(lo) },\n { column, op: \"<=\", value: literalOf(hi) },\n ]);\n return n.type === \"BETWEEN\" ? within : { not: within };\n }\n case \"IN\": {\n const column = columnOf(n.expr) ?? fail(node);\n return { column, op: \"in\", values: valuesOf(n.values) };\n }\n default:\n return fail(node);\n }\n}\n\nconst and = (clauses: Filter[]): Filter => (clauses.length === 1 ? (clauses[0] as Filter) : { and: clauses });\n\n/** Every column a filter names, once each. */\nexport function columnsOf(filter: Filter): string[] {\n if (\"column\" in filter) return [filter.column];\n if (\"and\" in filter) return [...new Set(filter.and.flatMap(columnsOf))];\n if (\"or\" in filter) return [...new Set(filter.or.flatMap(columnsOf))];\n if (\"not\" in filter) return columnsOf(filter.not);\n return [];\n}\n\n/**\n * The page's filter for the graph, or `undefined` for none. `selection.predicate` skips the clause\n * the graph published itself, which is the exemption the next function takes back.\n */\nexport function filterFor(selection: Selection, self: MosaicClient): Filter | undefined {\n const predicate = selection.predicate(self) as unknown;\n const clauses = (Array.isArray(predicate) ? predicate : [predicate]).filter((p) => p !== undefined && p !== null);\n return clauses.length === 0 ? undefined : translate(clauses);\n}\n\n/**\n * An identity for `clients`, and nothing more: it is never connected, so the coordinator never\n * queries on its behalf.\n */\nexport function graphClient(): MosaicClient {\n return new MosaicClient();\n}\n\n/**\n * **The reader's pick, published** — naming the graph in `clients`, so the crossfilter skips it for\n * the graph and applies it to every chart. A canvas that draws only what survives would otherwise\n * answer a lasso of thirteen by removing the other 1,530.\n */\nexport function publish(\n selection: Selection,\n self: MosaicClient,\n column: string,\n ids: readonly number[] | null,\n): void {\n selection.update(\n clausePoints([column], ids && ids.length > 0 ? ids.map((d) => [d]) : undefined, {\n source: self,\n clients: new Set([self]),\n }),\n );\n}\n"],"names":["UntranslatableFilter","__publicField","COMPARISONS","MIRRORED","fail","what","columnOf","node","n","literalOf","value","iso","valuesOf","translate","and","clauses","column","op","left","lo","hi","within","columnsOf","filter","filterFor","selection","self","predicate","p","graphClient","MosaicClient","publish","ids","clausePoints","d"],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Binding } from './channels';
|
|
2
|
+
import { Corpus, Filter, VertexTable } from '@fossil-lang/corpus';
|
|
3
|
+
/**
|
|
4
|
+
* **The whole graph, read once and laid out as cosmos.gl's buffers.** A drawn vertex's `dense_id` is
|
|
5
|
+
* its index, so every array is sized from the manifest's `record_count`s before a row arrives, and a
|
|
6
|
+
* row is written where its id says. The camera never reaches here: nothing is read because it moved.
|
|
7
|
+
*/
|
|
8
|
+
/** Where the drawn vertices are and how they connect — read once per corpus. */
|
|
9
|
+
export interface Geometry {
|
|
10
|
+
/** The vertex tables with a position, in the manifest's order. */
|
|
11
|
+
readonly tables: readonly VertexTable[];
|
|
12
|
+
/** Drawn vertices: ids `0 … size − 1`. */
|
|
13
|
+
readonly size: number;
|
|
14
|
+
/** `[x, y, …]` by id; `NaN` where no row has a position. */
|
|
15
|
+
readonly positions: Float32Array;
|
|
16
|
+
/** By id, the vertex's index in `tables`. */
|
|
17
|
+
readonly table: Uint16Array;
|
|
18
|
+
/** `[src, dst, …]` by id, every relation whose two ends are drawn. */
|
|
19
|
+
readonly links: Float32Array;
|
|
20
|
+
readonly extent: {
|
|
21
|
+
readonly x: number;
|
|
22
|
+
readonly y: number;
|
|
23
|
+
readonly w: number;
|
|
24
|
+
readonly h: number;
|
|
25
|
+
} | null;
|
|
26
|
+
}
|
|
27
|
+
/** What the bound channels say about each vertex — read again when a binding changes. */
|
|
28
|
+
export interface Encoding {
|
|
29
|
+
/** By id, the category's rank. */
|
|
30
|
+
readonly ranks: Uint32Array;
|
|
31
|
+
/** By id, the ramp's raw value, or `null` when `r` is unbound. */
|
|
32
|
+
readonly sizes: Float32Array | null;
|
|
33
|
+
/** What each rank is: the seed, then the other values seen, in rank order. */
|
|
34
|
+
readonly domain: readonly unknown[];
|
|
35
|
+
}
|
|
36
|
+
/** The vertex tables fossil lays out or the program places; a table without a position is not drawn. */
|
|
37
|
+
export declare const drawnTables: (corpus: Corpus) => VertexTable[];
|
|
38
|
+
/** One scan per drawn table and one per relation between them, read whole, in parallel. */
|
|
39
|
+
export declare function loadGraph(corpus: Corpus, binding: Binding, seed: readonly unknown[], signal: AbortSignal): Promise<{
|
|
40
|
+
geometry: Geometry;
|
|
41
|
+
encoding: Encoding;
|
|
42
|
+
}>;
|
|
43
|
+
/** A new binding re-reads the channels and nothing else: the positions and the links stay uploaded. */
|
|
44
|
+
export declare function loadEncoding(corpus: Corpus, geometry: Geometry, binding: Binding, seed: readonly unknown[], signal: AbortSignal): Promise<Encoding>;
|
|
45
|
+
/** What a filter kept: per table that holds every column it names, the surviving ids. */
|
|
46
|
+
export interface Kept {
|
|
47
|
+
readonly filtered: ReadonlySet<number>;
|
|
48
|
+
readonly ids: readonly number[];
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* **A predicate, applied as a mask.** A table that lacks a column the filter names is not filtered,
|
|
52
|
+
* which is what a `WHERE` over a union of the tables would do; a filter no drawn table can answer at
|
|
53
|
+
* all is refused, so the unfiltered picture is never drawn as the filtered one.
|
|
54
|
+
*/
|
|
55
|
+
export declare function readKept(corpus: Corpus, tables: readonly VertexTable[], filter: Filter, signal: AbortSignal): Promise<Kept>;
|
|
56
|
+
/** `1` where a vertex survives the page's filter. */
|
|
57
|
+
export declare function maskOf(geometry: Geometry, kept: Kept): Uint8Array;
|
|
58
|
+
//# sourceMappingURL=load.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../../src/core/load.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,OAAO,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,KAAK,EAAS,MAAM,EAAa,MAAM,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGzF;;;;GAIG;AAEH,gFAAgF;AAChF,MAAM,WAAW,QAAQ;IACvB,kEAAkE;IAClE,QAAQ,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,CAAC;IACxC,0CAA0C;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,4DAA4D;IAC5D,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC;IACjC,6CAA6C;IAC7C,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,sEAAsE;IACtE,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAC5G;AAED,yFAAyF;AACzF,MAAM,WAAW,QAAQ;IACvB,kCAAkC;IAClC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;IACpC,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE,CAAC;CACrC;AAED,wGAAwG;AACxG,eAAO,MAAM,WAAW,GAAI,QAAQ,MAAM,KAAG,WAAW,EAAqE,CAAC;AAgF9H,2FAA2F;AAC3F,wBAAsB,SAAS,CAC7B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,SAAS,OAAO,EAAE,EACxB,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,CAAC,CAgCrD;AAED,uGAAuG;AACvG,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,SAAS,OAAO,EAAE,EACxB,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,QAAQ,CAAC,CAUnB;AAED,yFAAyF;AACzF,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACvC,QAAQ,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,CAAC;CACjC;AAED;;;;GAIG;AACH,wBAAsB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,WAAW,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBjI;AAED,qDAAqD;AACrD,wBAAgB,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,GAAG,UAAU,CAKjE"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { Dictionary as P } from "./categories.js";
|
|
2
|
+
import { projectionOf as C } from "./channels.js";
|
|
3
|
+
import { columnsOf as I } from "./filter.js";
|
|
4
|
+
const O = (o) => o.manifest.vertex_tables.filter((n) => n.position), v = (o) => (n) => o.properties.some((e) => e.name === n);
|
|
5
|
+
async function x(o, n, e) {
|
|
6
|
+
const r = o.scan(n);
|
|
7
|
+
return r.read(r.plan(), { signal: e });
|
|
8
|
+
}
|
|
9
|
+
function E(o, n, e, r) {
|
|
10
|
+
const c = new P(r), s = new Uint32Array(n), f = e.size === void 0 ? null : new Float32Array(n).fill(Number.NaN);
|
|
11
|
+
return {
|
|
12
|
+
add(a, i) {
|
|
13
|
+
var m, w, b;
|
|
14
|
+
const t = o[a], d = ((m = i.getChild(t.key)) == null ? void 0 : m.toArray()) ?? [], l = e.category === void 0 || (w = i.getChild(e.category)) == null ? void 0 : w.toArray(), u = e.size === void 0 || (b = i.getChild(e.size)) == null ? void 0 : b.toArray(), N = e.byTable ? c.code(t.name) : 0;
|
|
15
|
+
for (let y = 0; y < i.numRows; y++) {
|
|
16
|
+
const h = Number(d[y]);
|
|
17
|
+
h < n && (s[h] = e.byTable || e.category === void 0 ? N : c.code((l == null ? void 0 : l[y]) ?? null), f && (f[h] = Number((u == null ? void 0 : u[y]) ?? Number.NaN)));
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
finish() {
|
|
21
|
+
const a = c.ranks(), i = s.map((d) => a[d] ?? 0), t = [];
|
|
22
|
+
return a.forEach((d, l) => {
|
|
23
|
+
t[d] = c.values[l];
|
|
24
|
+
}), { ranks: i, sizes: f, domain: t };
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function R(o) {
|
|
29
|
+
let [n, e, r, c] = [1 / 0, 1 / 0, -1 / 0, -1 / 0];
|
|
30
|
+
for (let s = 0; s < o.length; s += 2) {
|
|
31
|
+
const f = o[s], a = o[s + 1];
|
|
32
|
+
Number.isNaN(f) || Number.isNaN(a) || (f < n && (n = f), f > r && (r = f), a < e && (e = a), a > c && (c = a));
|
|
33
|
+
}
|
|
34
|
+
return n > r ? null : { x: n, y: e, w: r - n, h: c - e };
|
|
35
|
+
}
|
|
36
|
+
async function _(o, n, e, r) {
|
|
37
|
+
const c = new Set(n.map((t) => t.name)), s = o.manifest.edge_tables.filter(
|
|
38
|
+
(t) => c.has(t.source.references) && c.has(t.destination.references)
|
|
39
|
+
), f = await Promise.all(
|
|
40
|
+
s.map((t) => x(o, { table: t.name, select: [t.source.key, t.destination.key] }, r))
|
|
41
|
+
), a = new Float32Array(2 * s.reduce((t, d) => t + d.record_count, 0));
|
|
42
|
+
let i = 0;
|
|
43
|
+
return f.forEach((t, d) => {
|
|
44
|
+
var u, N;
|
|
45
|
+
const l = s[d];
|
|
46
|
+
for (const m of t) {
|
|
47
|
+
const w = ((u = m.getChild(l.source.key)) == null ? void 0 : u.toArray()) ?? [], b = ((N = m.getChild(l.destination.key)) == null ? void 0 : N.toArray()) ?? [];
|
|
48
|
+
for (let y = 0; y < m.numRows && i < a.length; y++) {
|
|
49
|
+
const h = Number(w[y]), A = Number(b[y]);
|
|
50
|
+
h < e && A < e && (a[i++] = h, a[i++] = A);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}), i === a.length ? a : a.slice(0, i);
|
|
54
|
+
}
|
|
55
|
+
async function j(o, n, e, r) {
|
|
56
|
+
const c = O(o), s = c.reduce((l, u) => l + u.record_count, 0), f = new Float32Array(2 * s).fill(Number.NaN), a = new Uint16Array(s), i = E(c, s, n, e), [t, d] = await Promise.all([
|
|
57
|
+
Promise.all(
|
|
58
|
+
c.map((l) => {
|
|
59
|
+
const { x: u, y: N } = l.position;
|
|
60
|
+
return x(o, { table: l.name, select: C(n, [l.key, u, N], v(l)) }, r);
|
|
61
|
+
})
|
|
62
|
+
),
|
|
63
|
+
_(o, c, s, r)
|
|
64
|
+
]);
|
|
65
|
+
return t.forEach((l, u) => {
|
|
66
|
+
var w, b, y;
|
|
67
|
+
const { key: N, position: m } = c[u];
|
|
68
|
+
for (const h of l) {
|
|
69
|
+
const A = ((w = h.getChild(N)) == null ? void 0 : w.toArray()) ?? [], z = ((b = h.getChild((m == null ? void 0 : m.x) ?? "")) == null ? void 0 : b.toArray()) ?? [], g = ((y = h.getChild((m == null ? void 0 : m.y) ?? "")) == null ? void 0 : y.toArray()) ?? [];
|
|
70
|
+
for (let k = 0; k < h.numRows; k++) {
|
|
71
|
+
const p = Number(A[k]);
|
|
72
|
+
p < s && (f[p * 2] = Number(z[k] ?? Number.NaN), f[p * 2 + 1] = Number(g[k] ?? Number.NaN), a[p] = u);
|
|
73
|
+
}
|
|
74
|
+
i.add(u, h);
|
|
75
|
+
}
|
|
76
|
+
}), { geometry: { tables: c, size: s, positions: f, table: a, links: d, extent: R(f) }, encoding: i.finish() };
|
|
77
|
+
}
|
|
78
|
+
async function S(o, n, e, r, c) {
|
|
79
|
+
const { tables: s, size: f } = n, a = E(s, f, e, r);
|
|
80
|
+
return (await Promise.all(
|
|
81
|
+
s.map((t) => x(o, { table: t.name, select: C(e, [t.key], v(t)) }, c))
|
|
82
|
+
)).forEach((t, d) => {
|
|
83
|
+
for (const l of t) a.add(d, l);
|
|
84
|
+
}), a.finish();
|
|
85
|
+
}
|
|
86
|
+
async function D(o, n, e, r) {
|
|
87
|
+
const c = I(e), s = n.flatMap((i, t) => c.every(v(i)) ? [t] : []);
|
|
88
|
+
if (s.length === 0)
|
|
89
|
+
throw new Error(`no drawn vertex type has every column this filter names: ${c.join(", ")}`);
|
|
90
|
+
const f = await Promise.all(
|
|
91
|
+
s.map((i) => x(o, { table: n[i].name, filter: e, select: [n[i].key] }, r))
|
|
92
|
+
), a = [];
|
|
93
|
+
return f.forEach((i, t) => {
|
|
94
|
+
var l;
|
|
95
|
+
const { key: d } = n[s[t]];
|
|
96
|
+
for (const u of i) {
|
|
97
|
+
const N = ((l = u.getChild(d)) == null ? void 0 : l.toArray()) ?? [];
|
|
98
|
+
for (let m = 0; m < u.numRows; m++) a.push(Number(N[m]));
|
|
99
|
+
}
|
|
100
|
+
}), { filtered: new Set(s), ids: a };
|
|
101
|
+
}
|
|
102
|
+
function G(o, n) {
|
|
103
|
+
const e = new Uint8Array(o.size);
|
|
104
|
+
for (let r = 0; r < o.size; r++) e[r] = n.filtered.has(o.table[r]) ? 0 : 1;
|
|
105
|
+
for (const r of n.ids) r < o.size && (e[r] = 1);
|
|
106
|
+
return e;
|
|
107
|
+
}
|
|
108
|
+
export {
|
|
109
|
+
O as drawnTables,
|
|
110
|
+
S as loadEncoding,
|
|
111
|
+
j as loadGraph,
|
|
112
|
+
G as maskOf,
|
|
113
|
+
D as readKept
|
|
114
|
+
};
|
|
115
|
+
//# sourceMappingURL=load.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load.js","sources":["../../src/core/load.ts"],"sourcesContent":["import { Dictionary } from \"./categories\";\nimport { projectionOf, type Binding } from \"./channels\";\nimport type { Batch, Corpus, EdgeTable, Filter, VertexTable } from \"@fossil-lang/corpus\";\nimport { columnsOf } from \"./filter\";\n\n/**\n * **The whole graph, read once and laid out as cosmos.gl's buffers.** A drawn vertex's `dense_id` is\n * its index, so every array is sized from the manifest's `record_count`s before a row arrives, and a\n * row is written where its id says. The camera never reaches here: nothing is read because it moved.\n */\n\n/** Where the drawn vertices are and how they connect — read once per corpus. */\nexport interface Geometry {\n /** The vertex tables with a position, in the manifest's order. */\n readonly tables: readonly VertexTable[];\n /** Drawn vertices: ids `0 … size − 1`. */\n readonly size: number;\n /** `[x, y, …]` by id; `NaN` where no row has a position. */\n readonly positions: Float32Array;\n /** By id, the vertex's index in `tables`. */\n readonly table: Uint16Array;\n /** `[src, dst, …]` by id, every relation whose two ends are drawn. */\n readonly links: Float32Array;\n readonly extent: { readonly x: number; readonly y: number; readonly w: number; readonly h: number } | null;\n}\n\n/** What the bound channels say about each vertex — read again when a binding changes. */\nexport interface Encoding {\n /** By id, the category's rank. */\n readonly ranks: Uint32Array;\n /** By id, the ramp's raw value, or `null` when `r` is unbound. */\n readonly sizes: Float32Array | null;\n /** What each rank is: the seed, then the other values seen, in rank order. */\n readonly domain: readonly unknown[];\n}\n\n/** The vertex tables fossil lays out or the program places; a table without a position is not drawn. */\nexport const drawnTables = (corpus: Corpus): VertexTable[] => corpus.manifest.vertex_tables.filter((table) => table.position);\n\nconst has = (table: VertexTable) => (column: string) => table.properties.some((p) => p.name === column);\n\nasync function readAll(corpus: Corpus, params: Parameters<Corpus[\"scan\"]>[0], signal: AbortSignal): Promise<readonly Batch[]> {\n const scan = corpus.scan(params);\n return scan.read(scan.plan(), { signal });\n}\n\nfunction encoder(tables: readonly VertexTable[], size: number, binding: Binding, seed: readonly unknown[]) {\n const dictionary = new Dictionary(seed);\n const codes = new Uint32Array(size);\n const sizes = binding.size === undefined ? null : new Float32Array(size).fill(Number.NaN);\n return {\n add(t: number, batch: Batch) {\n const table = tables[t] as VertexTable;\n const ids = batch.getChild(table.key)?.toArray() ?? [];\n const values = binding.category === undefined ? undefined : batch.getChild(binding.category)?.toArray();\n const ramp = binding.size === undefined ? undefined : batch.getChild(binding.size)?.toArray();\n const own = binding.byTable ? dictionary.code(table.name) : 0;\n for (let i = 0; i < batch.numRows; i++) {\n const id = Number(ids[i]);\n if (!(id < size)) continue;\n codes[id] = binding.byTable || binding.category === undefined ? own : dictionary.code(values?.[i] ?? null);\n if (sizes) sizes[id] = Number(ramp?.[i] ?? Number.NaN);\n }\n },\n finish(): Encoding {\n const order = dictionary.ranks();\n const ranks = codes.map((code) => order[code] ?? 0);\n const domain: unknown[] = [];\n order.forEach((rank, code) => {\n domain[rank] = dictionary.values[code];\n });\n return { ranks, sizes, domain };\n },\n };\n}\n\nfunction extentOf(positions: Float32Array): Geometry[\"extent\"] {\n let [x0, y0, x1, y1] = [Infinity, Infinity, -Infinity, -Infinity];\n for (let i = 0; i < positions.length; i += 2) {\n const x = positions[i] as number;\n const y = positions[i + 1] as number;\n if (Number.isNaN(x) || Number.isNaN(y)) continue;\n if (x < x0) x0 = x;\n if (x > x1) x1 = x;\n if (y < y0) y0 = y;\n if (y > y1) y1 = y;\n }\n return x0 > x1 ? null : { x: x0, y: y0, w: x1 - x0, h: y1 - y0 };\n}\n\nasync function readLinks(corpus: Corpus, tables: readonly VertexTable[], size: number, signal: AbortSignal): Promise<Float32Array> {\n const drawn = new Set(tables.map((table) => table.name));\n const relations = corpus.manifest.edge_tables.filter(\n (edge: EdgeTable) => drawn.has(edge.source.references) && drawn.has(edge.destination.references),\n );\n const answers = await Promise.all(\n relations.map((edge) => readAll(corpus, { table: edge.name, select: [edge.source.key, edge.destination.key] }, signal)),\n );\n const links = new Float32Array(2 * relations.reduce((sum, edge) => sum + edge.record_count, 0));\n let at = 0;\n answers.forEach((batches, r) => {\n const edge = relations[r] as EdgeTable;\n for (const batch of batches) {\n const src = batch.getChild(edge.source.key)?.toArray() ?? [];\n const dst = batch.getChild(edge.destination.key)?.toArray() ?? [];\n for (let e = 0; e < batch.numRows && at < links.length; e++) {\n const a = Number(src[e]);\n const b = Number(dst[e]);\n if (!(a < size && b < size)) continue;\n links[at++] = a;\n links[at++] = b;\n }\n }\n });\n return at === links.length ? links : links.slice(0, at);\n}\n\n/** One scan per drawn table and one per relation between them, read whole, in parallel. */\nexport async function loadGraph(\n corpus: Corpus,\n binding: Binding,\n seed: readonly unknown[],\n signal: AbortSignal,\n): Promise<{ geometry: Geometry; encoding: Encoding }> {\n const tables = drawnTables(corpus);\n const size = tables.reduce((sum, table) => sum + table.record_count, 0);\n const positions = new Float32Array(2 * size).fill(Number.NaN);\n const table = new Uint16Array(size);\n const encode = encoder(tables, size, binding, seed);\n const [vertices, links] = await Promise.all([\n Promise.all(\n tables.map((t) => {\n const { x, y } = t.position as NonNullable<VertexTable[\"position\"]>;\n return readAll(corpus, { table: t.name, select: projectionOf(binding, [t.key, x, y], has(t)) }, signal);\n }),\n ),\n readLinks(corpus, tables, size, signal),\n ]);\n vertices.forEach((batches, t) => {\n const { key, position } = tables[t] as VertexTable;\n for (const batch of batches) {\n const ids = batch.getChild(key)?.toArray() ?? [];\n const xs = batch.getChild(position?.x ?? \"\")?.toArray() ?? [];\n const ys = batch.getChild(position?.y ?? \"\")?.toArray() ?? [];\n for (let i = 0; i < batch.numRows; i++) {\n const id = Number(ids[i]);\n if (!(id < size)) continue;\n positions[id * 2] = Number(xs[i] ?? Number.NaN);\n positions[id * 2 + 1] = Number(ys[i] ?? Number.NaN);\n table[id] = t;\n }\n encode.add(t, batch);\n }\n });\n return { geometry: { tables, size, positions, table, links, extent: extentOf(positions) }, encoding: encode.finish() };\n}\n\n/** A new binding re-reads the channels and nothing else: the positions and the links stay uploaded. */\nexport async function loadEncoding(\n corpus: Corpus,\n geometry: Geometry,\n binding: Binding,\n seed: readonly unknown[],\n signal: AbortSignal,\n): Promise<Encoding> {\n const { tables, size } = geometry;\n const encode = encoder(tables, size, binding, seed);\n const answers = await Promise.all(\n tables.map((t) => readAll(corpus, { table: t.name, select: projectionOf(binding, [t.key], has(t)) }, signal)),\n );\n answers.forEach((batches, t) => {\n for (const batch of batches) encode.add(t, batch);\n });\n return encode.finish();\n}\n\n/** What a filter kept: per table that holds every column it names, the surviving ids. */\nexport interface Kept {\n readonly filtered: ReadonlySet<number>;\n readonly ids: readonly number[];\n}\n\n/**\n * **A predicate, applied as a mask.** A table that lacks a column the filter names is not filtered,\n * which is what a `WHERE` over a union of the tables would do; a filter no drawn table can answer at\n * all is refused, so the unfiltered picture is never drawn as the filtered one.\n */\nexport async function readKept(corpus: Corpus, tables: readonly VertexTable[], filter: Filter, signal: AbortSignal): Promise<Kept> {\n const columns = columnsOf(filter);\n const filtered = tables.flatMap((table, t) => (columns.every(has(table)) ? [t] : []));\n if (filtered.length === 0) {\n throw new Error(`no drawn vertex type has every column this filter names: ${columns.join(\", \")}`);\n }\n const answers = await Promise.all(\n filtered.map((t) => readAll(corpus, { table: (tables[t] as VertexTable).name, filter, select: [(tables[t] as VertexTable).key] }, signal)),\n );\n const ids: number[] = [];\n answers.forEach((batches, i) => {\n const { key } = tables[filtered[i] as number] as VertexTable;\n for (const batch of batches) {\n const column = batch.getChild(key)?.toArray() ?? [];\n for (let r = 0; r < batch.numRows; r++) ids.push(Number(column[r]));\n }\n });\n return { filtered: new Set(filtered), ids };\n}\n\n/** `1` where a vertex survives the page's filter. */\nexport function maskOf(geometry: Geometry, kept: Kept): Uint8Array {\n const mask = new Uint8Array(geometry.size);\n for (let id = 0; id < geometry.size; id++) mask[id] = kept.filtered.has(geometry.table[id] as number) ? 0 : 1;\n for (const id of kept.ids) if (id < geometry.size) mask[id] = 1;\n return mask;\n}\n"],"names":["drawnTables","corpus","table","has","column","p","readAll","params","signal","scan","encoder","tables","size","binding","seed","dictionary","Dictionary","codes","sizes","t","batch","ids","_a","values","_b","ramp","_c","own","i","id","order","ranks","code","domain","rank","extentOf","positions","x0","y0","x1","y1","x","y","readLinks","drawn","relations","edge","answers","links","sum","at","batches","r","src","dst","e","a","b","loadGraph","encode","vertices","projectionOf","key","position","xs","ys","loadEncoding","geometry","readKept","filter","columns","columnsOf","filtered","maskOf","kept","mask"],"mappings":"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"}
|
package/dist/core/state.d.ts
CHANGED
|
@@ -1,39 +1,35 @@
|
|
|
1
|
-
import { Corpus, Gap, TileAddress, TileMatrixSet } from '@fossil-lang/corpus';
|
|
2
1
|
import { Selection as Crossfilter } from '@kanzo-tech/mosaic';
|
|
3
2
|
import { LookPatch } from '../render/graph-looks';
|
|
4
3
|
import { Sim } from '../render/graph-sim';
|
|
5
4
|
import { Binding, Channels } from './channels';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { Motion, Selection, SelectionSource, Tool } from './types';
|
|
5
|
+
import { Corpus } from '@fossil-lang/corpus';
|
|
6
|
+
import { Encoding, Geometry } from './load';
|
|
7
|
+
import { Motion, Selection, SelectionSource, Tool, VertexId } from './types';
|
|
10
8
|
export interface GraphOptions extends Channels {
|
|
11
9
|
/**
|
|
12
10
|
* The corpus the host opened with fossil's `open`, or the promise of it. A promise is what makes
|
|
13
11
|
* *opening* a state the graph can report; `null` is no corpus at all.
|
|
14
12
|
*/
|
|
15
13
|
corpus: Corpus | PromiseLike<Corpus> | null;
|
|
16
|
-
/** The vertex type drawn. The first type with a position when absent. */
|
|
17
|
-
type?: string;
|
|
18
14
|
/** Which column the size ramp is spent on — Plot's `r`. */
|
|
19
15
|
r?: string;
|
|
20
|
-
/** Which column a label and the hover card show — Plot's `title`. */
|
|
16
|
+
/** Which column a label and the hover card show — Plot's `title`. Absent, each table's `identity`. */
|
|
21
17
|
title?: string;
|
|
22
18
|
/**
|
|
23
|
-
* What the categorical channel's values are called, keyed by value
|
|
24
|
-
*
|
|
25
|
-
* the keys' order is also the rank, so a colour never moves because a tile arrived.
|
|
19
|
+
* What the categorical channel's values are called, keyed by value; the keys' order is also the
|
|
20
|
+
* rank, so a colour never moves because a row arrived. With colour by type, the keys are table names.
|
|
26
21
|
*/
|
|
27
22
|
categories?: Readonly<Record<string, string>>;
|
|
28
|
-
/** The page's crossfilter: its clauses filter what is
|
|
23
|
+
/** The page's crossfilter: its clauses filter what is drawn, and the reader's pick is published into it. */
|
|
29
24
|
filterBy?: Crossfilter;
|
|
30
|
-
/** The most marks drawn at once; a coarser zoom is chosen above it. */
|
|
31
|
-
limit?: number;
|
|
32
25
|
/** Form: a patch over this package's own look. Memoise it — its identity is what repaints. */
|
|
33
26
|
look?: LookPatch;
|
|
34
27
|
/** The force coefficients, as a patch over this package's own. */
|
|
35
28
|
sim?: Partial<Sim>;
|
|
36
|
-
/**
|
|
29
|
+
/**
|
|
30
|
+
* Runs the live layout while true, from the points' current positions. Off by default: the corpus's
|
|
31
|
+
* positions are drawn as they are. `GraphToolbar` starts and stops the layout whatever this says.
|
|
32
|
+
*/
|
|
37
33
|
simulate?: boolean;
|
|
38
34
|
/** Required: unhandled, a browser with no WebGL context shows an empty box. */
|
|
39
35
|
onFailure: (message: string) => void;
|
|
@@ -42,34 +38,28 @@ export interface GraphOptions extends Channels {
|
|
|
42
38
|
}
|
|
43
39
|
/**
|
|
44
40
|
* Where the graph is in its life. `none` is no corpus; `opening` is a corpus promised and not yet
|
|
45
|
-
* open; `
|
|
46
|
-
* drawn; `failed` is a corpus that would not open
|
|
47
|
-
*
|
|
41
|
+
* open; `loading` is the graph, a binding or a filter not yet read or not yet drawn; `idle` is all of
|
|
42
|
+
* it drawn; `failed` is a corpus that would not open or read, or a canvas that could not start a
|
|
43
|
+
* renderer.
|
|
48
44
|
*/
|
|
49
|
-
export type GraphStatus = "none" | "opening" | "
|
|
50
|
-
/** What
|
|
45
|
+
export type GraphStatus = "none" | "opening" | "loading" | "idle" | "failed";
|
|
46
|
+
/** What the loaded graph holds, under the page's filter. */
|
|
51
47
|
export interface Drawn {
|
|
52
|
-
/**
|
|
53
|
-
readonly
|
|
54
|
-
/**
|
|
55
|
-
readonly represented: number;
|
|
56
|
-
/** What each category rank is: the declared or named values first, then any other seen, in rank order. */
|
|
48
|
+
/** Vertices drawn: every one with a position that survives the filter. */
|
|
49
|
+
readonly vertices: number;
|
|
50
|
+
/** What each category rank is: the seed first, then any other value seen, in rank order. */
|
|
57
51
|
readonly domain: readonly unknown[];
|
|
58
|
-
/** Per rank, the vertices drawn
|
|
52
|
+
/** Per rank, the vertices drawn. */
|
|
59
53
|
readonly tally: readonly number[];
|
|
60
54
|
}
|
|
61
55
|
/** What a host and the parts read, through `useGraphState`. */
|
|
62
56
|
export interface GraphState {
|
|
63
57
|
readonly status: GraphStatus;
|
|
64
|
-
/** Vertices of the drawn
|
|
58
|
+
/** Vertices of the drawn types, from the manifest — it does not shrink with a filter. */
|
|
65
59
|
readonly total: number | undefined;
|
|
66
|
-
/**
|
|
67
|
-
readonly z: number | null;
|
|
68
|
-
/** Whether a tile in view is still being read. */
|
|
69
|
-
readonly pending: boolean;
|
|
70
|
-
/** What is on the canvas, or `null` before the first composition. */
|
|
60
|
+
/** What is loaded, or `null` before the graph has loaded. */
|
|
71
61
|
readonly drawn: Drawn | null;
|
|
72
|
-
/** The categorical domain before anything is
|
|
62
|
+
/** The categorical domain before anything is loaded: the drawn tables, or the host's names. */
|
|
73
63
|
readonly domain: readonly unknown[];
|
|
74
64
|
readonly selection: Selection | null;
|
|
75
65
|
readonly focus: VertexId | null;
|
|
@@ -79,30 +69,17 @@ export interface GraphState {
|
|
|
79
69
|
readonly motion: Motion;
|
|
80
70
|
/** How far through settling a live layout is, `0`–`1`. */
|
|
81
71
|
readonly progress: number;
|
|
82
|
-
/** Relations the corpus declined to answer, with fossil's reason. */
|
|
83
|
-
readonly declined: readonly Gap[];
|
|
84
72
|
/** The options as given, with the corpus once it is open. */
|
|
85
73
|
readonly options: GraphOptions;
|
|
86
74
|
readonly corpus: Corpus | null;
|
|
87
75
|
}
|
|
88
|
-
/**
|
|
89
|
-
export interface TileView {
|
|
90
|
-
readonly address: TileAddress;
|
|
91
|
-
readonly kind: "rows" | "cells";
|
|
92
|
-
readonly content: TileContent;
|
|
93
|
-
}
|
|
94
|
-
/** The state, plus what only the renderer reads. */
|
|
76
|
+
/** The state, plus what only the renderer and the parts read. */
|
|
95
77
|
export interface GraphSnapshot extends GraphState {
|
|
96
|
-
readonly matrix: TileMatrixSet | null;
|
|
97
|
-
/** The drawn type's position in `corpus.types.vertices` — the type half of a `VertexId`. */
|
|
98
|
-
readonly typeIndex: number;
|
|
99
78
|
readonly binding: Binding;
|
|
100
|
-
|
|
101
|
-
readonly
|
|
102
|
-
/**
|
|
103
|
-
readonly
|
|
104
|
-
/** Every tile holding content — where a far end is looked up. */
|
|
105
|
-
readonly cached: readonly TileView[];
|
|
79
|
+
readonly geometry: Geometry | null;
|
|
80
|
+
readonly encoding: Encoding | null;
|
|
81
|
+
/** `1` where a vertex survives the page's filter; `null` when nothing is filtered. */
|
|
82
|
+
readonly mask: Uint8Array | null;
|
|
106
83
|
}
|
|
107
84
|
/**
|
|
108
85
|
* **The graph's state, outside React** — TanStack Query's `QueryObserver` shape: `subscribe`,
|
|
@@ -115,8 +92,6 @@ export interface GraphStore {
|
|
|
115
92
|
getOptions(): GraphOptions;
|
|
116
93
|
setOptions(options: GraphOptions): void;
|
|
117
94
|
destroy(): void;
|
|
118
|
-
/** The camera, from the renderer: the rectangle in view. */
|
|
119
|
-
setViewport(viewport: Viewport): void;
|
|
120
95
|
select(vertices: readonly VertexId[] | null, source?: SelectionSource, label?: string): void;
|
|
121
96
|
focus(vertex: VertexId | null): void;
|
|
122
97
|
hover(vertex: VertexId | null): void;
|
|
@@ -124,9 +99,9 @@ export interface GraphStore {
|
|
|
124
99
|
setTool(tool: Tool): void;
|
|
125
100
|
report(motion: Motion): void;
|
|
126
101
|
reportProgress(value: number): void;
|
|
127
|
-
/** Whether the canvas has a renderer: without one nothing
|
|
102
|
+
/** Whether the canvas has a renderer: without one nothing will ever be drawn. */
|
|
128
103
|
setRenderable(renderable: boolean): void;
|
|
129
|
-
/** The renderer
|
|
130
|
-
reportDrawn(
|
|
104
|
+
/** The renderer uploaded this snapshot's geometry, encoding and mask. */
|
|
105
|
+
reportDrawn(snapshot: GraphSnapshot): void;
|
|
131
106
|
}
|
|
132
107
|
//# sourceMappingURL=state.d.ts.map
|
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,
|
|
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,6 +1,4 @@
|
|
|
1
1
|
import { GraphOptions, GraphStore } from './state';
|
|
2
|
-
export type { Drawn, GraphOptions, GraphSnapshot, GraphState, GraphStatus, GraphStore
|
|
3
|
-
/** Twenty thousand marks: what a canvas draws at once before a coarser zoom is chosen. */
|
|
4
|
-
export declare const DEFAULT_LIMIT = 20000;
|
|
2
|
+
export type { Drawn, GraphOptions, GraphSnapshot, GraphState, GraphStatus, GraphStore } from './state';
|
|
5
3
|
export declare function createGraph(initial: GraphOptions): GraphStore;
|
|
6
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":"
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/core/store.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAS,YAAY,EAA8B,UAAU,EAAE,MAAM,SAAS,CAAC;AAE3F,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAqBvG,wBAAgB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,UAAU,CAuV7D"}
|