@kanzo-tech/graph 0.10.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -95
- package/dist/core/categories.d.ts +12 -0
- package/dist/core/categories.d.ts.map +1 -0
- package/dist/core/categories.js +14 -0
- package/dist/core/categories.js.map +1 -0
- package/dist/core/channels.d.ts +34 -0
- package/dist/core/channels.d.ts.map +1 -0
- package/dist/core/channels.js +19 -0
- package/dist/core/channels.js.map +1 -0
- package/dist/core/detail.d.ts +18 -0
- package/dist/core/detail.d.ts.map +1 -0
- package/dist/core/detail.js +20 -0
- package/dist/core/detail.js.map +1 -0
- package/dist/core/filter.d.ts +34 -0
- package/dist/core/filter.d.ts.map +1 -0
- package/dist/core/filter.js +99 -0
- package/dist/core/filter.js.map +1 -0
- package/dist/core/refine.d.ts +14 -0
- package/dist/core/refine.d.ts.map +1 -0
- package/dist/core/refine.js +20 -0
- package/dist/core/refine.js.map +1 -0
- package/dist/{resident.d.ts → core/resident.d.ts} +7 -7
- package/dist/core/resident.d.ts.map +1 -0
- package/dist/core/resident.js +44 -0
- package/dist/core/resident.js.map +1 -0
- package/dist/core/scheduler.d.ts +42 -0
- package/dist/core/scheduler.d.ts.map +1 -0
- package/dist/core/scheduler.js +77 -0
- package/dist/core/scheduler.js.map +1 -0
- package/dist/core/state.d.ts +132 -0
- package/dist/core/state.d.ts.map +1 -0
- package/dist/core/store.d.ts +6 -0
- package/dist/core/store.d.ts.map +1 -0
- package/dist/core/store.js +235 -0
- package/dist/core/store.js.map +1 -0
- package/dist/core/tile-matrix.d.ts +37 -0
- package/dist/core/tile-matrix.d.ts.map +1 -0
- package/dist/core/tile-matrix.js +49 -0
- package/dist/core/tile-matrix.js.map +1 -0
- package/dist/core/tile.d.ts +54 -0
- package/dist/core/tile.d.ts.map +1 -0
- package/dist/core/tile.js +76 -0
- package/dist/core/tile.js.map +1 -0
- package/dist/core/tileset.d.ts +59 -0
- package/dist/core/tileset.d.ts.map +1 -0
- package/dist/core/tileset.js +177 -0
- package/dist/core/tileset.js.map +1 -0
- package/dist/{types.d.ts → core/types.d.ts} +9 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/index.d.ts +37 -70
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +32 -34
- package/dist/index.js.map +1 -1
- package/dist/{use-graph-selection.d.ts → parts/gesture.d.ts} +4 -4
- package/dist/parts/gesture.d.ts.map +1 -0
- package/dist/{use-graph-selection.js → parts/gesture.js} +17 -17
- package/dist/parts/gesture.js.map +1 -0
- package/dist/parts/graph-canvas.d.ts +17 -0
- package/dist/parts/graph-canvas.d.ts.map +1 -0
- package/dist/parts/graph-canvas.js +174 -0
- package/dist/parts/graph-canvas.js.map +1 -0
- package/dist/parts/graph-inspector.d.ts +18 -0
- package/dist/parts/graph-inspector.d.ts.map +1 -0
- package/dist/parts/graph-inspector.js +84 -0
- package/dist/parts/graph-inspector.js.map +1 -0
- package/dist/parts/graph-legend.d.ts +12 -0
- package/dist/parts/graph-legend.d.ts.map +1 -0
- package/dist/parts/graph-legend.js +61 -0
- package/dist/parts/graph-legend.js.map +1 -0
- package/dist/parts/graph-toolbar.d.ts +15 -0
- package/dist/parts/graph-toolbar.d.ts.map +1 -0
- package/dist/parts/graph-toolbar.js +94 -0
- package/dist/parts/graph-toolbar.js.map +1 -0
- package/dist/parts/overlays.d.ts +33 -0
- package/dist/parts/overlays.d.ts.map +1 -0
- package/dist/{use-graph-overlays.js → parts/overlays.js} +8 -8
- package/dist/parts/overlays.js.map +1 -0
- package/dist/{shape-glyph.d.ts → parts/shape-glyph.d.ts} +1 -1
- package/dist/parts/shape-glyph.d.ts.map +1 -0
- package/dist/{shape-glyph.js → parts/shape-glyph.js} +1 -1
- package/dist/parts/shape-glyph.js.map +1 -0
- package/dist/react/graph-root.d.ts +15 -0
- package/dist/react/graph-root.d.ts.map +1 -0
- package/dist/react/graph-root.js +23 -0
- package/dist/react/graph-root.js.map +1 -0
- package/dist/{use-graph-prefs.d.ts → react/use-graph-prefs.d.ts} +2 -2
- package/dist/react/use-graph-prefs.d.ts.map +1 -0
- package/dist/{use-graph-prefs.js → react/use-graph-prefs.js} +3 -3
- package/dist/react/use-graph-prefs.js.map +1 -0
- package/dist/react/use-graph-state.d.ts +11 -0
- package/dist/react/use-graph-state.d.ts.map +1 -0
- package/dist/react/use-graph-state.js +16 -0
- package/dist/react/use-graph-state.js.map +1 -0
- package/dist/react/use-graph.d.ts +38 -0
- package/dist/react/use-graph.d.ts.map +1 -0
- package/dist/react/use-graph.js +87 -0
- package/dist/react/use-graph.js.map +1 -0
- package/dist/{adaptive.d.ts → render/adaptive.d.ts} +1 -1
- package/dist/render/adaptive.d.ts.map +1 -0
- package/dist/render/adaptive.js.map +1 -0
- package/dist/render/compose.d.ts +51 -0
- package/dist/render/compose.d.ts.map +1 -0
- package/dist/render/compose.js +107 -0
- package/dist/render/compose.js.map +1 -0
- package/dist/render/css-color.d.ts.map +1 -0
- package/dist/render/css-color.js.map +1 -0
- package/dist/render/encode.d.ts +42 -0
- package/dist/render/encode.d.ts.map +1 -0
- package/dist/render/encode.js +68 -0
- package/dist/render/encode.js.map +1 -0
- package/dist/render/graph-looks.d.ts.map +1 -0
- package/dist/render/graph-looks.js.map +1 -0
- package/dist/render/graph-model.d.ts +44 -0
- package/dist/render/graph-model.d.ts.map +1 -0
- package/dist/render/graph-model.js +80 -0
- package/dist/render/graph-model.js.map +1 -0
- package/dist/{graph-sim.d.ts → render/graph-sim.d.ts} +1 -1
- package/dist/render/graph-sim.d.ts.map +1 -0
- package/dist/render/graph-sim.js.map +1 -0
- package/dist/{obligations.d.ts → render/obligations.d.ts} +1 -1
- package/dist/render/obligations.d.ts.map +1 -0
- package/dist/render/renderer.d.ts +38 -0
- package/dist/render/renderer.d.ts.map +1 -0
- package/dist/render/renderer.js +235 -0
- package/dist/render/renderer.js.map +1 -0
- package/dist/render/webgl.d.ts +14 -0
- package/dist/render/webgl.d.ts.map +1 -0
- package/dist/render/webgl.js +19 -0
- package/dist/render/webgl.js.map +1 -0
- package/dist/render/when-ready.d.ts.map +1 -0
- package/dist/render/when-ready.js.map +1 -0
- package/package.json +11 -21
- package/dist/adaptive.d.ts.map +0 -1
- package/dist/adaptive.js.map +0 -1
- package/dist/bounded.d.ts +0 -364
- package/dist/bounded.d.ts.map +0 -1
- package/dist/bounded.js +0 -18
- package/dist/bounded.js.map +0 -1
- package/dist/cluster-ring.d.ts +0 -25
- package/dist/cluster-ring.d.ts.map +0 -1
- package/dist/cluster-ring.js +0 -16
- package/dist/cluster-ring.js.map +0 -1
- package/dist/css-color.d.ts.map +0 -1
- package/dist/css-color.js.map +0 -1
- package/dist/duck-source.d.ts +0 -198
- package/dist/duck-source.d.ts.map +0 -1
- package/dist/duck-source.js +0 -320
- package/dist/duck-source.js.map +0 -1
- package/dist/graph-canvas.d.ts +0 -50
- package/dist/graph-canvas.d.ts.map +0 -1
- package/dist/graph-canvas.js +0 -35
- package/dist/graph-canvas.js.map +0 -1
- package/dist/graph-looks.d.ts.map +0 -1
- package/dist/graph-looks.js.map +0 -1
- package/dist/graph-model.d.ts +0 -130
- package/dist/graph-model.d.ts.map +0 -1
- package/dist/graph-model.js +0 -104
- package/dist/graph-model.js.map +0 -1
- package/dist/graph-sim.d.ts.map +0 -1
- package/dist/graph-sim.js.map +0 -1
- package/dist/obligations.d.ts.map +0 -1
- package/dist/resident.d.ts.map +0 -1
- package/dist/resident.js +0 -44
- package/dist/resident.js.map +0 -1
- package/dist/shape-glyph.d.ts.map +0 -1
- package/dist/shape-glyph.js.map +0 -1
- package/dist/slice-client.d.ts +0 -78
- package/dist/slice-client.d.ts.map +0 -1
- package/dist/slice-client.js +0 -98
- package/dist/slice-client.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/use-graph-look.d.ts +0 -28
- package/dist/use-graph-look.d.ts.map +0 -1
- package/dist/use-graph-look.js +0 -28
- package/dist/use-graph-look.js.map +0 -1
- package/dist/use-graph-overlays.d.ts +0 -44
- package/dist/use-graph-overlays.d.ts.map +0 -1
- package/dist/use-graph-overlays.js.map +0 -1
- package/dist/use-graph-prefs.d.ts.map +0 -1
- package/dist/use-graph-prefs.js.map +0 -1
- package/dist/use-graph-selection.d.ts.map +0 -1
- package/dist/use-graph-selection.js.map +0 -1
- package/dist/use-graph.d.ts +0 -203
- package/dist/use-graph.d.ts.map +0 -1
- package/dist/use-graph.js +0 -102
- package/dist/use-graph.js.map +0 -1
- package/dist/use-query-loop.d.ts +0 -88
- package/dist/use-query-loop.d.ts.map +0 -1
- package/dist/use-query-loop.js +0 -148
- package/dist/use-query-loop.js.map +0 -1
- package/dist/use-renderer.d.ts +0 -86
- package/dist/use-renderer.d.ts.map +0 -1
- package/dist/use-renderer.js +0 -188
- package/dist/use-renderer.js.map +0 -1
- package/dist/when-ready.d.ts.map +0 -1
- package/dist/when-ready.js.map +0 -1
- /package/dist/{adaptive.js → render/adaptive.js} +0 -0
- /package/dist/{css-color.d.ts → render/css-color.d.ts} +0 -0
- /package/dist/{css-color.js → render/css-color.js} +0 -0
- /package/dist/{graph-looks.d.ts → render/graph-looks.d.ts} +0 -0
- /package/dist/{graph-looks.js → render/graph-looks.js} +0 -0
- /package/dist/{graph-sim.js → render/graph-sim.js} +0 -0
- /package/dist/{when-ready.d.ts → render/when-ready.d.ts} +0 -0
- /package/dist/{when-ready.js → render/when-ready.js} +0 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,73 +1,40 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*/
|
|
22
|
-
export { scaleOf, neighboursOf, type Channels } from './graph-model';
|
|
23
|
-
export { lookFrom, type Look, type LookPatch, type Shape, } from './graph-looks';
|
|
24
|
-
export { ShapeGlyph, type ShapeGlyphProps } from './shape-glyph';
|
|
25
|
-
/**
|
|
26
|
-
* The graph, in Ark's four pieces.
|
|
27
|
-
*
|
|
28
|
-
* `useGraph(props)` **creates** the api and `useGraphContext()` **reads** it, which is Ark's
|
|
29
|
-
* convention and was inverted here: the reader was `useGraphCanvas` and there was no creator.
|
|
30
|
-
* `GraphCanvas` is the shortcut that does both, and `GraphRootProvider` is what a host reaches for
|
|
31
|
-
* when it has to call a hook *beside* the canvas — `useGraphOverlays` takes the api and the `events`
|
|
32
|
-
* block reads `getGraph`/`getResident` off it, both from above the element where no context is
|
|
33
|
-
* readable.
|
|
34
|
-
*
|
|
35
|
-
* That was not a symmetry we wanted for its own sake: it is what the workspace could not adopt
|
|
36
|
-
* `GraphCanvas` without, and the `graphRef`/`residentRef` props that stood in for it are gone.
|
|
37
|
-
*/
|
|
38
|
-
export { GraphCanvas, GraphRootProvider, useGraphContext, type GraphCanvasProps, type GraphRootProviderProps, } from './graph-canvas';
|
|
39
|
-
export { useGraph, type GraphApi, type GraphEvents, type UseGraphProps } from './use-graph';
|
|
40
|
-
export { useGraphOverlays, type GraphOverlays } from './use-graph-overlays';
|
|
41
|
-
export { useGraphSelection, cursorChip } from './use-graph-selection';
|
|
42
|
-
/**
|
|
43
|
-
* Identity, and the map from it to the buffer index cosmos.gl draws at.
|
|
44
|
-
*
|
|
45
|
-
* The renderer addresses points by position in the arrays it was handed, and a resident set that
|
|
46
|
-
* comes and goes reuses every position. So a vertex is the pair `(type_idx, dense_id)`, and
|
|
47
|
-
* everything that outlives one answer is held as one and re-resolved through the `Resident` that
|
|
48
|
-
* `useQueryLoop` rebuilds per answer. A host never builds its own: two maps of the same thing is
|
|
49
|
-
* how one of them ends up describing buffers that are no longer on screen.
|
|
50
|
-
*/
|
|
51
|
-
export { residentOf, vertexId, typeOf, denseOf, type Resident, type VertexId, } from './resident';
|
|
52
|
-
/**
|
|
53
|
-
* The bounded render path — a graph you never hold all of.
|
|
54
|
-
*
|
|
55
|
-
* A contract, not a format: anything that can answer "what is in this rectangle, at this zoom, in
|
|
56
|
-
* at most this many marks" is a source. A tile fetched by a computed address is one; a relation
|
|
57
|
-
* with `x`/`y` and a spatial predicate is another. This package renders and does not learn a storage layout,
|
|
58
|
-
* which is what removed the ceiling rather than raising it.
|
|
59
|
-
*
|
|
60
|
-
* `useQueryLoop` is the loop that asks — it observes the camera, debounces, cancels what the
|
|
61
|
-
* camera has already superseded, and pushes each answer into the renderer. **The source itself is
|
|
62
|
-
* not here and there is one of it**: `openCorpus`, on `@kanzo-tech/graph/duckdb`, because a corpus
|
|
63
|
-
* is read through a database and a database is an optional peer. What is left on this barrel is the
|
|
64
|
-
* rendering surface — the hooks, the look, identity and the buffers a slice implies — and it draws
|
|
65
|
-
* nothing on its own.
|
|
2
|
+
* The graph view over a fossil corpus. fossil reads and this package draws, and nothing crosses
|
|
3
|
+
* between them but the corpus contract: the host opens the corpus with fossil's `open` on the page's
|
|
4
|
+
* `engine()`, and `GraphRoot` draws it.
|
|
5
|
+
*
|
|
6
|
+
* Four layers, each the shape of a named reference — `/docs/design/graph`:
|
|
7
|
+
*
|
|
8
|
+
* - `core/` — a headless tileset in deck.gl's `Tileset2D` shape over `tileMatrix` and `scan`, and a
|
|
9
|
+
* store in TanStack Query's observer shape. No React, no cosmos.gl, no SQL.
|
|
10
|
+
* - `render/` — tiles to cosmos.gl buffers: encoded once per tile, uploaded by kind, rendered once a
|
|
11
|
+
* frame.
|
|
12
|
+
* - `react/` — `useGraph`, `GraphRoot`, `GraphRootProvider`, `useGraphContext`: Ark's four; and
|
|
13
|
+
* `useGraphState`, TanStack Store's selector, because the api is commands and the state moves at
|
|
14
|
+
* frame rate.
|
|
15
|
+
* - `parts/` — `GraphCanvas`, `GraphLegend`, `GraphToolbar`, `GraphInspector`: flat parts over the
|
|
16
|
+
* one context. They own the vocabulary; the root's callbacks are the host's policy.
|
|
17
|
+
*
|
|
18
|
+
* **Why a package and not `@kanzo-tech/ui`.** The first admission rule is *domain-free — nothing
|
|
19
|
+
* about RDF / SHACL / fossil / graphs / auth*. Graphs are excluded by name, and a sibling package is
|
|
20
|
+
* the only place a required WebGL peer belongs.
|
|
66
21
|
*/
|
|
67
|
-
export {
|
|
68
|
-
export {
|
|
69
|
-
export {
|
|
70
|
-
export {
|
|
71
|
-
export {
|
|
72
|
-
export {
|
|
22
|
+
export { GraphRoot, GraphRootProvider, useGraphContext, type GraphRootProps, type GraphRootProviderProps, } from './react/graph-root';
|
|
23
|
+
export { useGraph, type GraphApi, type UseGraphProps } from './react/use-graph';
|
|
24
|
+
export { useGraphState } from './react/use-graph-state';
|
|
25
|
+
export { useGraphPrefs } from './react/use-graph-prefs';
|
|
26
|
+
export { GraphCanvas, type GraphCanvasProps } from './parts/graph-canvas';
|
|
27
|
+
export { GraphLegend, type GraphLegendProps } from './parts/graph-legend';
|
|
28
|
+
export { GraphToolbar, type GraphToolbarProps } from './parts/graph-toolbar';
|
|
29
|
+
export { GraphInspector, type GraphInspectorProps } from './parts/graph-inspector';
|
|
30
|
+
export { ShapeGlyph, type ShapeGlyphProps } from './parts/shape-glyph';
|
|
31
|
+
export { lookFrom, type Look, type LookPatch, type Shape } from './render/graph-looks';
|
|
32
|
+
export { simFrom, type Sim } from './render/graph-sim';
|
|
33
|
+
export { adaptive } from './render/adaptive';
|
|
34
|
+
export { scaleOf } from './render/graph-model';
|
|
35
|
+
export type { Channels } from './core/channels';
|
|
36
|
+
export { vertexId, typeOf, denseOf, type Resident, type VertexId } from './core/resident';
|
|
37
|
+
export type { GraphCommands, Motion, Selection, SelectionSource, Tool } from './core/types';
|
|
38
|
+
export type { Drawn, GraphState, GraphStatus } from './core/state';
|
|
39
|
+
export type { VertexDetail } from './core/detail';
|
|
73
40
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EACL,SAAS,EACT,iBAAiB,EACjB,eAAe,EACf,KAAK,cAAc,EACnB,KAAK,sBAAsB,GAC5B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,QAAQ,EAAE,KAAK,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAExD,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,KAAK,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnF,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAIvE,OAAO,EAAE,QAAQ,EAAE,KAAK,IAAI,EAAE,KAAK,SAAS,EAAE,KAAK,KAAK,EAAE,MAAM,sBAAsB,CAAC;AACvF,OAAO,EAAE,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,YAAY,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAIhD,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE1F,YAAY,EAAE,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAC5F,YAAY,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACnE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,37 +1,35 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
1
|
+
import { GraphRoot as e, GraphRootProvider as p, useGraphContext as t } from "./react/graph-root.js";
|
|
2
|
+
import { useGraph as f } from "./react/use-graph.js";
|
|
3
|
+
import { useGraphState as x } from "./react/use-graph-state.js";
|
|
4
|
+
import { useGraphPrefs as G } from "./react/use-graph-prefs.js";
|
|
5
|
+
import { GraphCanvas as d } from "./parts/graph-canvas.js";
|
|
6
|
+
import { GraphLegend as l } from "./parts/graph-legend.js";
|
|
7
|
+
import { GraphToolbar as v } from "./parts/graph-toolbar.js";
|
|
8
|
+
import { GraphInspector as O } from "./parts/graph-inspector.js";
|
|
9
|
+
import { ShapeGlyph as y } from "./parts/shape-glyph.js";
|
|
10
|
+
import { lookFrom as F } from "./render/graph-looks.js";
|
|
11
|
+
import { simFrom as P } from "./render/graph-sim.js";
|
|
12
|
+
import { adaptive as S } from "./render/adaptive.js";
|
|
13
|
+
import { scaleOf as g } from "./render/graph-model.js";
|
|
14
|
+
import { denseOf as L, typeOf as T, vertexId as j } from "./core/resident.js";
|
|
14
15
|
export {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
P as
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
w as useGraphPrefs,
|
|
34
|
-
O as useGraphSelection,
|
|
35
|
-
k as vertexId
|
|
16
|
+
d as GraphCanvas,
|
|
17
|
+
O as GraphInspector,
|
|
18
|
+
l as GraphLegend,
|
|
19
|
+
e as GraphRoot,
|
|
20
|
+
p as GraphRootProvider,
|
|
21
|
+
v as GraphToolbar,
|
|
22
|
+
y as ShapeGlyph,
|
|
23
|
+
S as adaptive,
|
|
24
|
+
L as denseOf,
|
|
25
|
+
F as lookFrom,
|
|
26
|
+
g as scaleOf,
|
|
27
|
+
P as simFrom,
|
|
28
|
+
T as typeOf,
|
|
29
|
+
f as useGraph,
|
|
30
|
+
t as useGraphContext,
|
|
31
|
+
G as useGraphPrefs,
|
|
32
|
+
x as useGraphState,
|
|
33
|
+
j as vertexId
|
|
36
34
|
};
|
|
37
35
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
import { Graph } from '@cosmos.gl/graph';
|
|
3
|
-
import { Resident, VertexId } from '
|
|
4
|
-
import { Selection, SelectionSource, Tool } from '
|
|
3
|
+
import { Resident, VertexId } from '../core/resident';
|
|
4
|
+
import { Selection, SelectionSource, Tool } from '../core/types';
|
|
5
5
|
/**
|
|
6
6
|
* Drawing a selection on the canvas: the marquee, the lasso, and the keys that modify them.
|
|
7
7
|
*
|
|
@@ -55,5 +55,5 @@ export interface GraphSelectionOptions {
|
|
|
55
55
|
tool: Tool;
|
|
56
56
|
setTool: (tool: Tool) => void;
|
|
57
57
|
}
|
|
58
|
-
export declare function
|
|
59
|
-
//# sourceMappingURL=
|
|
58
|
+
export declare function useGesture(options: GraphSelectionOptions): GraphSelectionGesture;
|
|
59
|
+
//# sourceMappingURL=gesture.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gesture.d.ts","sourceRoot":"","sources":["../../src/parts/gesture.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAGtE;;;;;;;;;;GAUG;AACH,MAAM,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAErC,wFAAwF;AACxF,MAAM,MAAM,IAAI,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,KAAK,CAAC;IAAC,EAAE,EAAE,KAAK,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,KAAK,EAAE,CAAA;CAAE,CAAC;AAS/F,4FAA4F;AAC5F,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,KAAK,CAAC,aAAa,CAIjE;AAED,MAAM,WAAW,qBAAqB;IACpC,0DAA0D;IAC1D,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,oFAAoF;IACpF,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,mFAAmF;IACnF,MAAM,EAAE,IAAI,CAAC;IACb,QAAQ,EAAE;QACR,aAAa,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,YAAY,KAAK,IAAI,CAAC;QACnD,aAAa,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,YAAY,KAAK,IAAI,CAAC;QACnD,WAAW,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,YAAY,KAAK,IAAI,CAAC;QACjD,eAAe,EAAE,MAAM,IAAI,CAAC;KAC7B,CAAC;CACH;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,KAAK,GAAG,IAAI,CAAC;IAC7B;;;;;;OAMG;IACH,WAAW,EAAE,MAAM,QAAQ,CAAC;IAC5B,wEAAwE;IACxE,YAAY,EAAE,MAAM,SAAS,GAAG,IAAI,CAAC;IACrC,MAAM,EAAE,CAAC,QAAQ,EAAE,GAAG,CAAC,QAAQ,CAAC,GAAG,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzF,IAAI,EAAE,IAAI,CAAC;IACX,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;CAC/B;AAOD,wBAAgB,UAAU,CAAC,OAAO,EAAE,qBAAqB,GAAG,qBAAqB,CA6IhF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { useState as m, useRef as C, useCallback as
|
|
3
|
-
import { isReady as K } from "
|
|
2
|
+
import { useState as m, useRef as C, useCallback as S, useEffect as I } from "react";
|
|
3
|
+
import { isReady as K } from "../render/when-ready.js";
|
|
4
4
|
const x = 3, _ = 4, q = 60;
|
|
5
5
|
function N(l) {
|
|
6
6
|
if (!l) return { display: "none" };
|
|
@@ -12,7 +12,7 @@ const z = {
|
|
|
12
12
|
lasso: { source: "lasso", label: "Lasso" }
|
|
13
13
|
};
|
|
14
14
|
function U(l) {
|
|
15
|
-
const { commit: i, getGraph: a, getResident: k, getSelection: v, setTool: y, tool: h } = l, [s, c] = m(null), [L, f] = m(null), [R,
|
|
15
|
+
const { commit: i, getGraph: a, getResident: k, getSelection: v, setTool: y, tool: h } = l, [s, c] = m(null), [L, f] = m(null), [R, d] = m(!1), b = C(0), p = S(
|
|
16
16
|
(t) => {
|
|
17
17
|
const e = a();
|
|
18
18
|
if (!e) return [];
|
|
@@ -29,19 +29,19 @@ function U(l) {
|
|
|
29
29
|
return t.path.length < 3 ? [] : Array.from(e.findPointsInPolygon(t.path));
|
|
30
30
|
},
|
|
31
31
|
[a]
|
|
32
|
-
), E =
|
|
32
|
+
), E = S(
|
|
33
33
|
(t) => {
|
|
34
34
|
const e = performance.now();
|
|
35
|
-
e - b.current < q || (b.current = e, f(
|
|
35
|
+
e - b.current < q || (b.current = e, f(p(t).length));
|
|
36
36
|
},
|
|
37
|
-
[
|
|
37
|
+
[p]
|
|
38
38
|
);
|
|
39
39
|
I(() => {
|
|
40
40
|
const t = (n) => {
|
|
41
|
-
n.key === "Shift" &&
|
|
41
|
+
n.key === "Shift" && d(!0), n.key === "Escape" && (c((r) => (r || (h ? y(null) : i(null, "node", "")), null)), f(null));
|
|
42
42
|
}, e = (n) => {
|
|
43
|
-
n.key === "Shift" &&
|
|
44
|
-
}, o = () =>
|
|
43
|
+
n.key === "Shift" && d(!1);
|
|
44
|
+
}, o = () => d(!1);
|
|
45
45
|
return window.addEventListener("keydown", t), window.addEventListener("keyup", e), window.addEventListener("blur", o), () => {
|
|
46
46
|
window.removeEventListener("keydown", t), window.removeEventListener("keyup", e), window.removeEventListener("blur", o);
|
|
47
47
|
};
|
|
@@ -50,28 +50,28 @@ function U(l) {
|
|
|
50
50
|
const e = t.currentTarget.getBoundingClientRect();
|
|
51
51
|
return [t.clientX - e.left, t.clientY - e.top];
|
|
52
52
|
}, T = (t, e) => {
|
|
53
|
-
var
|
|
53
|
+
var P;
|
|
54
54
|
if (c(null), f(null), !t) return;
|
|
55
|
-
const o = new Set(k().verticesAt(
|
|
55
|
+
const o = new Set(k().verticesAt(p(t)));
|
|
56
56
|
if (o.size === 0 && !e.altKey) return;
|
|
57
|
-
const { label: n, source: r } = z[t.tool], u = ((
|
|
57
|
+
const { label: n, source: r } = z[t.tool], u = ((P = v()) == null ? void 0 : P.vertices) ?? [];
|
|
58
58
|
if (e.altKey) {
|
|
59
59
|
const w = new Set(u);
|
|
60
60
|
for (const A of o) w.delete(A);
|
|
61
61
|
i(w.size > 0 ? w : null, r, n);
|
|
62
62
|
} else e.metaKey || e.ctrlKey ? i(/* @__PURE__ */ new Set([...u, ...o]), r, n) : i(o, r, n);
|
|
63
|
-
},
|
|
63
|
+
}, g = h ?? (R ? "rect" : null);
|
|
64
64
|
return {
|
|
65
65
|
drag: s,
|
|
66
66
|
preview: L,
|
|
67
|
-
active:
|
|
67
|
+
active: g,
|
|
68
68
|
handlers: {
|
|
69
69
|
onPointerDown: (t) => {
|
|
70
70
|
if (t.button !== 0) return;
|
|
71
71
|
t.currentTarget.setPointerCapture(t.pointerId);
|
|
72
72
|
const e = M(t);
|
|
73
73
|
c(
|
|
74
|
-
|
|
74
|
+
g === "rect" ? { tool: "rect", from: e, to: e } : { tool: "lasso", path: [e] }
|
|
75
75
|
);
|
|
76
76
|
},
|
|
77
77
|
onPointerMove: (t) => {
|
|
@@ -96,6 +96,6 @@ function U(l) {
|
|
|
96
96
|
}
|
|
97
97
|
export {
|
|
98
98
|
N as cursorChip,
|
|
99
|
-
U as
|
|
99
|
+
U as useGesture
|
|
100
100
|
};
|
|
101
|
-
//# sourceMappingURL=
|
|
101
|
+
//# sourceMappingURL=gesture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gesture.js","sources":["../../src/parts/gesture.ts"],"sourcesContent":["\"use client\";\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport type React from \"react\";\nimport type { Graph } from \"@cosmos.gl/graph\";\nimport type { Resident, VertexId } from \"../core/resident\";\nimport type { Selection, SelectionSource, Tool } from \"../core/types\";\nimport { isReady } from \"../render/when-ready\";\n\n/**\n * Drawing a selection on the canvas: the marquee, the lasso, and the keys that modify them.\n *\n * The whole gesture lives here — what is being drawn, how many nodes it currently holds, and what\n * happens when the pointer comes up. The component gets handlers to spread onto an overlay and the\n * state to draw it with; it does not need to know that Shift borrows the marquee or that a hit test\n * costs a GPU readback.\n *\n * Modifiers are read at *release*, not at press, because that is when the reader has decided:\n * `Alt` removes what was drawn from the selection, `⌘`/`Ctrl` adds it, and neither replaces.\n */\nexport type Point = [number, number];\n\n/** A selection gesture in flight. The two tools differ only in what they accumulate. */\nexport type Drag = { tool: \"rect\"; from: Point; to: Point } | { tool: \"lasso\"; path: Point[] };\n\n/** Below this the hit test would be answering about a click, not a box. */\nconst MIN_RECT = 3;\n/** A raw pointer stream makes a polygon of near-duplicate vertices; the hit test walks every one. */\nconst PATH_STEP = 4;\n/** Slower than the hand, faster than the eye — and one GPU readback per gesture frame is plenty. */\nconst MEASURE_MS = 60;\n\n/** The running count rides just off the cursor, at the edge the gesture is growing from. */\nexport function cursorChip(drag: Drag | null): React.CSSProperties {\n if (!drag) return { display: \"none\" };\n const [x = 0, y = 0] = drag.tool === \"rect\" ? drag.to : (drag.path[drag.path.length - 1] ?? []);\n return { left: x + 14, top: y + 14 };\n}\n\nexport interface GraphSelectionGesture {\n /** The gesture being drawn, for the overlay to render. */\n drag: Drag | null;\n /** How many nodes it holds right now, so the number lands before the mouse does. */\n preview: number | null;\n /** The tool actually in force: the chosen one, or the marquee Shift is lending. */\n active: Tool;\n handlers: {\n onPointerDown: (event: React.PointerEvent) => void;\n onPointerMove: (event: React.PointerEvent) => void;\n onPointerUp: (event: React.PointerEvent) => void;\n onPointerCancel: () => void;\n };\n}\n\nexport interface GraphSelectionOptions {\n getGraph: () => Graph | null;\n /**\n * Who is drawn right now — the only thing that can turn a hit-test index into an identity.\n *\n * A gesture selects positions on screen, and a position is a buffer index, which the next\n * residency reuses for a different vertex. So the gesture resolves to identities here and now,\n * while the answer that produced them is still the one on screen.\n */\n getResident: () => Resident;\n /** The live selection, for the modifiers to add to or subtract from. */\n getSelection: () => Selection | null;\n commit: (vertices: Set<VertexId> | null, source: SelectionSource, label: string) => void;\n tool: Tool;\n setTool: (tool: Tool) => void;\n}\n\nconst NAME: Record<\"rect\" | \"lasso\", { source: SelectionSource; label: string }> = {\n rect: { source: \"marquee\", label: \"Marquee\" },\n lasso: { source: \"lasso\", label: \"Lasso\" },\n};\n\nexport function useGesture(options: GraphSelectionOptions): GraphSelectionGesture {\n const { commit, getGraph, getResident, getSelection, setTool, tool } = options;\n const [drag, setDrag] = useState<Drag | null>(null);\n const [preview, setPreview] = useState<number | null>(null);\n const [shift, setShift] = useState(false);\n const measured = useRef(0);\n\n const hitTest = useCallback(\n (shape: Drag): number[] => {\n const graph = getGraph();\n if (!graph) return [];\n // **Upstream's own words, on these two and on nothing else in its `.d.ts`:** *this method is\n // synchronous and must only be called when the graph is ready*. There is nothing to await in\n // a pointer handler, so the answer for a device that is not there is the honest one — a\n // gesture over a graph that has not drawn selects nothing, which is what it looks like.\n if (!isReady(graph)) return [];\n if (shape.tool === \"rect\") {\n const [[ax, ay], [bx, by]] = [shape.from, shape.to];\n if (Math.abs(bx - ax) < MIN_RECT || Math.abs(by - ay) < MIN_RECT) return [];\n return Array.from(\n graph.findPointsInRect([\n [Math.min(ax, bx), Math.min(ay, by)],\n [Math.max(ax, bx), Math.max(ay, by)],\n ]),\n );\n }\n if (shape.path.length < 3) return [];\n return Array.from(graph.findPointsInPolygon(shape.path));\n },\n [getGraph],\n );\n\n // Both hit tests are a GPU pass followed by a synchronous `readPixels`, so running one per\n // pointer event would stall the frame the gesture is being drawn into.\n const measure = useCallback(\n (shape: Drag) => {\n const now = performance.now();\n if (now - measured.current < MEASURE_MS) return;\n measured.current = now;\n setPreview(hitTest(shape).length);\n },\n [hitTest],\n );\n\n // Escape is the way out of everything, in layers: it abandons a drag in progress, then drops the\n // tool, then clears what is held. And a window that loses focus never delivers the Shift keyup,\n // which would leave the canvas unable to pan.\n useEffect(() => {\n const down = (event: KeyboardEvent) => {\n if (event.key === \"Shift\") setShift(true);\n if (event.key !== \"Escape\") return;\n setDrag((current) => {\n if (current) return null;\n if (tool) setTool(null);\n else commit(null, \"node\", \"\");\n return null;\n });\n setPreview(null);\n };\n const up = (event: KeyboardEvent) => {\n if (event.key === \"Shift\") setShift(false);\n };\n const blur = () => setShift(false);\n window.addEventListener(\"keydown\", down);\n window.addEventListener(\"keyup\", up);\n window.addEventListener(\"blur\", blur);\n return () => {\n window.removeEventListener(\"keydown\", down);\n window.removeEventListener(\"keyup\", up);\n window.removeEventListener(\"blur\", blur);\n };\n }, [commit, setTool, tool]);\n\n /** Screen coordinates inside the canvas — the space every cosmos.gl hit test speaks. */\n const at = (event: React.PointerEvent): Point => {\n const box = event.currentTarget.getBoundingClientRect();\n return [event.clientX - box.left, event.clientY - box.top];\n };\n\n const finish = (shape: Drag | null, event: React.PointerEvent) => {\n setDrag(null);\n setPreview(null);\n if (!shape) return;\n // The one line the whole gesture turns on: the hit test answers in buffer indices, and they stop\n // meaning anything the moment the resident set changes.\n const vertices = new Set(getResident().verticesAt(hitTest(shape)));\n // A gesture that caught nothing and asked for nothing is a misfire, not a request to clear —\n // clearing is what the corner's own button and Escape are for.\n if (vertices.size === 0 && !event.altKey) return;\n const { label, source } = NAME[shape.tool];\n const held = getSelection()?.vertices ?? [];\n if (event.altKey) {\n const next = new Set(held);\n for (const vertex of vertices) next.delete(vertex);\n commit(next.size > 0 ? next : null, source, label);\n } else if (event.metaKey || event.ctrlKey) {\n commit(new Set([...held, ...vertices]), source, label);\n } else {\n commit(vertices, source, label);\n }\n };\n\n const active: Tool = tool ?? (shift ? \"rect\" : null);\n\n return {\n drag,\n preview,\n active,\n handlers: {\n onPointerDown: (event) => {\n if (event.button !== 0) return;\n event.currentTarget.setPointerCapture(event.pointerId);\n const start = at(event);\n setDrag(\n active === \"rect\"\n ? { tool: \"rect\", from: start, to: start }\n : { tool: \"lasso\", path: [start] },\n );\n },\n onPointerMove: (event) => {\n if (!drag) return;\n const next = at(event);\n if (drag.tool === \"rect\") {\n const shape: Drag = { ...drag, to: next };\n setDrag(shape);\n measure(shape);\n return;\n }\n const last = drag.path[drag.path.length - 1] as Point;\n if (Math.hypot(next[0] - last[0], next[1] - last[1]) < PATH_STEP) return;\n const shape: Drag = { tool: \"lasso\", path: [...drag.path, next] };\n setDrag(shape);\n measure(shape);\n },\n onPointerUp: (event) => finish(drag, event),\n onPointerCancel: () => {\n setDrag(null);\n setPreview(null);\n },\n },\n };\n}\n"],"names":[],"mappings":";;;AA0BA;AAOO;AACL;AACA;AACA;AACF;AAkCA;AAAmF;AAC/C;AAEpC;AAEO;AACL;AAMgB;AAEZ;AACA;AAKA;AACA;AACE;AACA;AACa;AACY;AACc;AACA;AACpC;AAAA;AAGL;AACuD;AACzD;AACS;AAKK;AAEZ;AACA;AAEgC;AAClC;AACQ;AAMV;AACE;AAEE;AAOe;AAGf;AAAyC;AAG3C;AAIE;AAEuC;AACzC;AAIF;AACE;AACA;AAAyD;;AAMzD;AAGA;AAGA;AACA;AAEA;AACE;AACA;AACA;AAAiD;AAInB;AAMlC;AAAO;AACL;AACA;AACA;AACU;AAEN;AACA;AACA;AACA;AAAA;AAGmC;AAAE;AAEvC;AAEE;AACA;AACA;AACE;AACA;AAEA;AAAA;AAEF;AACA;AACA;AACA;AACa;AACf;AAC0C;AAExC;AACe;AACjB;AAAA;AAGN;;;;;"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
export interface GraphCanvasProps extends React.ComponentProps<"div"> {
|
|
3
|
+
/** The chrome — a toolbar, a legend, an inspector — positioned over the surface. */
|
|
4
|
+
children?: ReactNode;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* **The element, and what the look declares over it** — the grid, the vignette, the labels and the
|
|
8
|
+
* hover card are fields of `Look`, so drawing them is the canvas's; the marquee and lasso gesture is
|
|
9
|
+
* too. Two layers: cosmos.gl fills the surface with a canvas of its own, so chrome parented there
|
|
10
|
+
* would be a sibling inside an element the renderer resizes. The frame is `isolate`, so a host's
|
|
11
|
+
* `z-index` on a child cannot escape into the page.
|
|
12
|
+
*
|
|
13
|
+
* The surface is never gated on the first answer: rendered behind a placeholder it deadlocks — no
|
|
14
|
+
* element, no renderer, no camera, no question. Waiting is an overlay over an empty canvas.
|
|
15
|
+
*/
|
|
16
|
+
export declare function GraphCanvas({ children, className, slot, ...rest }: GraphCanvasProps): import("react").JSX.Element;
|
|
17
|
+
//# sourceMappingURL=graph-canvas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-canvas.d.ts","sourceRoot":"","sources":["../../src/parts/graph-canvas.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAqD,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAa1F,MAAM,WAAW,gBAAiB,SAAQ,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC;IACnE,oFAAoF;IACpF,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AA+BD;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,EAAE,gBAAgB,+BA0JnF"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs as g, jsx as t } from "react/jsx-runtime";
|
|
3
|
+
import { useThemeTick as Q, categoricalCapacity as U, Show as v, cn as V } from "@kanzo-tech/ui";
|
|
4
|
+
import { useMemo as w, useCallback as L, useRef as X, useState as Y, useEffect as G } from "react";
|
|
5
|
+
import { nameOf as Z } from "../core/categories.js";
|
|
6
|
+
import { denseOf as ee } from "../core/resident.js";
|
|
7
|
+
import { useGraphContext as te } from "../react/graph-root.js";
|
|
8
|
+
import { internalsOf as re } from "../react/use-graph.js";
|
|
9
|
+
import { useGraphState as f } from "../react/use-graph-state.js";
|
|
10
|
+
import { resolveLook as oe } from "../render/graph-looks.js";
|
|
11
|
+
import { scaleOf as ne } from "../render/graph-model.js";
|
|
12
|
+
import { useGesture as se, cursorChip as ae } from "./gesture.js";
|
|
13
|
+
import { useOverlays as ie } from "./overlays.js";
|
|
14
|
+
import { ShapeGlyph as le } from "./shape-glyph.js";
|
|
15
|
+
const D = "var(--brand-a5)";
|
|
16
|
+
function ce(p, x, b) {
|
|
17
|
+
const y = p.titles;
|
|
18
|
+
if (!y || x <= 0) return [];
|
|
19
|
+
const n = Array.from({ length: p.vertices }, (l, c) => c), u = p.sizes;
|
|
20
|
+
u && n.sort((l, c) => (u[c] ?? 0) - (u[l] ?? 0));
|
|
21
|
+
const i = n.slice(0, x), s = b === null ? void 0 : p.resident.indexOf(b);
|
|
22
|
+
return s !== void 0 && !i.includes(s) && i.unshift(s), i.flatMap((l) => {
|
|
23
|
+
const c = p.resident.at(l), o = y[l];
|
|
24
|
+
return c === void 0 || !o ? [] : [{ vertex: c, text: o }];
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
const de = {
|
|
28
|
+
opening: "Opening the corpus…",
|
|
29
|
+
reading: "Reading the corpus…"
|
|
30
|
+
};
|
|
31
|
+
function Re({ children: p, className: x, slot: b, ...y }) {
|
|
32
|
+
const n = te(), { attach: u, renderer: i } = re(n), s = f((e) => e.hovered), l = f((e) => e.focus), c = f((e) => e.tool), o = f((e) => e.options), N = f((e) => {
|
|
33
|
+
var a;
|
|
34
|
+
return ((a = e.drawn) == null ? void 0 : a.domain) ?? e.domain;
|
|
35
|
+
}), _ = f((e) => e.drawn === null ? de[e.status] : void 0), h = w(() => oe(o.look), [o.look]), M = L(() => {
|
|
36
|
+
var e;
|
|
37
|
+
return ((e = i()) == null ? void 0 : e.graph) ?? null;
|
|
38
|
+
}, [i]), E = ie({ getGraph: M, getResident: n.getResident }), { cardRef: F, gridRef: q, hostRef: R, labelRef: B, schedule: k, setHovered: T, setLabelOrder: z, track: W } = E, j = X(null), [d, J] = Y(null);
|
|
39
|
+
G(() => {
|
|
40
|
+
const e = j.current;
|
|
41
|
+
if (e)
|
|
42
|
+
return u(e, { onFrame: k, onComposed: J });
|
|
43
|
+
}, [u, k]);
|
|
44
|
+
const K = Q();
|
|
45
|
+
G(() => {
|
|
46
|
+
var e;
|
|
47
|
+
(e = i()) == null || e.repaint();
|
|
48
|
+
}, [i, K]);
|
|
49
|
+
const O = w(
|
|
50
|
+
() => d ? ce(d, h.labels, l) : [],
|
|
51
|
+
[d, l, h.labels]
|
|
52
|
+
);
|
|
53
|
+
G(() => {
|
|
54
|
+
z(O.map((e) => e.vertex)), T(s), W(), k();
|
|
55
|
+
}, [s, O, k, T, z, W, h.grid]);
|
|
56
|
+
const A = se({
|
|
57
|
+
getGraph: M,
|
|
58
|
+
getResident: n.getResident,
|
|
59
|
+
getSelection: L(() => n.getState().selection, [n]),
|
|
60
|
+
commit: (e, a, C) => n.select(e ? [...e] : null, a, C),
|
|
61
|
+
setTool: n.setTool,
|
|
62
|
+
tool: c
|
|
63
|
+
}), { active: P, drag: r, preview: S } = A, I = R.current ? U(R.current) : void 0, $ = w(() => ne(o, I), [o, I]), m = w(() => {
|
|
64
|
+
var H;
|
|
65
|
+
if (s === null || !d) return null;
|
|
66
|
+
const e = d.resident.indexOf(s);
|
|
67
|
+
if (e === void 0) return null;
|
|
68
|
+
const a = d.categories[e] ?? 0, C = o.fill !== void 0 || o.symbol !== void 0;
|
|
69
|
+
return {
|
|
70
|
+
rank: a,
|
|
71
|
+
title: ((H = d.titles) == null ? void 0 : H[e]) || `#${ee(s)}`,
|
|
72
|
+
category: C && a < N.length ? Z(N[a], o.categories) : null
|
|
73
|
+
};
|
|
74
|
+
}, [d, N, s, o]);
|
|
75
|
+
return /* @__PURE__ */ g(
|
|
76
|
+
"div",
|
|
77
|
+
{
|
|
78
|
+
...y,
|
|
79
|
+
className: V("relative isolate size-full overflow-hidden bg-background", x),
|
|
80
|
+
"data-slot": b ?? "graph-canvas",
|
|
81
|
+
ref: R,
|
|
82
|
+
children: [
|
|
83
|
+
/* @__PURE__ */ t("div", { className: "size-full", "data-slot": "graph-canvas-surface", ref: j }),
|
|
84
|
+
/* @__PURE__ */ t(v, { when: h.grid, children: /* @__PURE__ */ t(
|
|
85
|
+
"div",
|
|
86
|
+
{
|
|
87
|
+
className: "pointer-events-none absolute inset-0",
|
|
88
|
+
ref: q,
|
|
89
|
+
style: { backgroundImage: "radial-gradient(var(--border) 1px, transparent 1px)" }
|
|
90
|
+
}
|
|
91
|
+
) }),
|
|
92
|
+
/* @__PURE__ */ t(v, { when: h.vignette, children: /* @__PURE__ */ t(
|
|
93
|
+
"div",
|
|
94
|
+
{
|
|
95
|
+
className: "pointer-events-none absolute inset-0",
|
|
96
|
+
style: { background: "radial-gradient(ellipse 75% 65% at 50% 45%, transparent 30%, var(--background) 100%)" }
|
|
97
|
+
}
|
|
98
|
+
) }),
|
|
99
|
+
/* @__PURE__ */ g("div", { className: "pointer-events-none absolute inset-0 overflow-hidden", children: [
|
|
100
|
+
O.map((e) => /* @__PURE__ */ t(
|
|
101
|
+
"span",
|
|
102
|
+
{
|
|
103
|
+
className: "absolute top-0 left-0 whitespace-nowrap font-medium text-[10px] text-foreground leading-none opacity-0 transition-opacity [text-shadow:0_0_3px_var(--background),0_0_6px_var(--background)]",
|
|
104
|
+
ref: B(e.vertex),
|
|
105
|
+
children: e.text
|
|
106
|
+
},
|
|
107
|
+
String(e.vertex)
|
|
108
|
+
)),
|
|
109
|
+
m && /* @__PURE__ */ g(
|
|
110
|
+
"div",
|
|
111
|
+
{
|
|
112
|
+
className: "absolute top-0 left-0 flex w-max max-w-60 items-center gap-2 rounded-lg border bg-popover px-2.5 py-2 opacity-0 shadow-lg",
|
|
113
|
+
"data-slot": "graph-canvas-card",
|
|
114
|
+
ref: F,
|
|
115
|
+
children: [
|
|
116
|
+
/* @__PURE__ */ t(le, { className: "size-2.5 shrink-0", color: $.color(m.rank), shape: $.shape(m.rank) }),
|
|
117
|
+
/* @__PURE__ */ t("span", { className: "truncate font-medium text-popover-foreground text-sm leading-none", children: m.title }),
|
|
118
|
+
m.category !== null && /* @__PURE__ */ t("span", { className: "text-muted-foreground text-xs", children: m.category })
|
|
119
|
+
]
|
|
120
|
+
}
|
|
121
|
+
)
|
|
122
|
+
] }),
|
|
123
|
+
/* @__PURE__ */ t(v, { when: P !== null, children: /* @__PURE__ */ g("div", { className: "absolute inset-0 cursor-crosshair", "data-slot": "graph-canvas-gesture", ...A.handlers, children: [
|
|
124
|
+
r && /* @__PURE__ */ t("svg", { className: "pointer-events-none size-full", children: r.tool === "rect" ? /* @__PURE__ */ t(
|
|
125
|
+
"rect",
|
|
126
|
+
{
|
|
127
|
+
className: "stroke-primary",
|
|
128
|
+
height: Math.abs(r.to[1] - r.from[1]),
|
|
129
|
+
strokeDasharray: "4 3",
|
|
130
|
+
strokeWidth: 1,
|
|
131
|
+
style: { fill: D },
|
|
132
|
+
width: Math.abs(r.to[0] - r.from[0]),
|
|
133
|
+
x: Math.min(r.from[0], r.to[0]),
|
|
134
|
+
y: Math.min(r.from[1], r.to[1])
|
|
135
|
+
}
|
|
136
|
+
) : r.path.length > 1 && /* @__PURE__ */ t(
|
|
137
|
+
"polygon",
|
|
138
|
+
{
|
|
139
|
+
className: "stroke-primary",
|
|
140
|
+
points: r.path.map(([e, a]) => `${e},${a}`).join(" "),
|
|
141
|
+
strokeWidth: 1,
|
|
142
|
+
style: { fill: D }
|
|
143
|
+
}
|
|
144
|
+
) }),
|
|
145
|
+
/* @__PURE__ */ t(v, { when: S !== null, children: /* @__PURE__ */ g(
|
|
146
|
+
"span",
|
|
147
|
+
{
|
|
148
|
+
className: "pointer-events-none absolute rounded-sm bg-primary px-1.5 py-0.5 font-medium text-[10px] text-primary-foreground tabular-nums",
|
|
149
|
+
style: ae(r),
|
|
150
|
+
children: [
|
|
151
|
+
S,
|
|
152
|
+
" node",
|
|
153
|
+
S === 1 ? "" : "s"
|
|
154
|
+
]
|
|
155
|
+
}
|
|
156
|
+
) })
|
|
157
|
+
] }) }),
|
|
158
|
+
/* @__PURE__ */ t(v, { when: _ !== void 0, children: /* @__PURE__ */ t(
|
|
159
|
+
"p",
|
|
160
|
+
{
|
|
161
|
+
className: "pointer-events-none absolute inset-0 grid place-items-center text-muted-foreground text-xs",
|
|
162
|
+
"data-slot": "graph-canvas-waiting",
|
|
163
|
+
children: _
|
|
164
|
+
}
|
|
165
|
+
) }),
|
|
166
|
+
p
|
|
167
|
+
]
|
|
168
|
+
}
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
export {
|
|
172
|
+
Re as GraphCanvas
|
|
173
|
+
};
|
|
174
|
+
//# sourceMappingURL=graph-canvas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-canvas.js","sources":["../../src/parts/graph-canvas.tsx"],"sourcesContent":["\"use client\";\n\nimport { categoricalCapacity, cn, Show, useThemeTick } from \"@kanzo-tech/ui\";\nimport { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport { nameOf } from \"../core/categories\";\nimport { denseOf, type VertexId } from \"../core/resident\";\nimport { useGraphContext } from \"../react/graph-root\";\nimport { internalsOf } from \"../react/use-graph\";\nimport { useGraphState } from \"../react/use-graph-state\";\nimport type { Composition } from \"../render/compose\";\nimport { resolveLook } from \"../render/graph-looks\";\nimport { scaleOf } from \"../render/graph-model\";\nimport { cursorChip, useGesture } from \"./gesture\";\nimport { useOverlays } from \"./overlays\";\nimport { ShapeGlyph } from \"./shape-glyph\";\n\nexport interface GraphCanvasProps extends React.ComponentProps<\"div\"> {\n /** The chrome — a toolbar, a legend, an inspector — positioned over the surface. */\n children?: ReactNode;\n}\n\nconst WASH = \"var(--brand-a5)\";\n\ninterface Label {\n vertex: VertexId;\n text: string;\n}\n\n/** The biggest `budget` vertices by the ramp, the focused one first, each with its `title`. */\nfunction labelsOf(composition: Composition, budget: number, focus: VertexId | null): Label[] {\n const titles = composition.titles;\n if (!titles || budget <= 0) return [];\n const order = Array.from({ length: composition.vertices }, (_, i) => i);\n const ramp = composition.sizes;\n if (ramp) order.sort((a, b) => (ramp[b] ?? 0) - (ramp[a] ?? 0));\n const chosen = order.slice(0, budget);\n const focused = focus === null ? undefined : composition.resident.indexOf(focus);\n if (focused !== undefined && !chosen.includes(focused)) chosen.unshift(focused);\n return chosen.flatMap((i) => {\n const vertex = composition.resident.at(i);\n const text = titles[i];\n return vertex === undefined || !text ? [] : [{ vertex, text }];\n });\n}\n\nconst WAITING: Partial<Record<string, string>> = {\n opening: \"Opening the corpus…\",\n reading: \"Reading the corpus…\",\n};\n\n/**\n * **The element, and what the look declares over it** — the grid, the vignette, the labels and the\n * hover card are fields of `Look`, so drawing them is the canvas's; the marquee and lasso gesture is\n * too. Two layers: cosmos.gl fills the surface with a canvas of its own, so chrome parented there\n * would be a sibling inside an element the renderer resizes. The frame is `isolate`, so a host's\n * `z-index` on a child cannot escape into the page.\n *\n * The surface is never gated on the first answer: rendered behind a placeholder it deadlocks — no\n * element, no renderer, no camera, no question. Waiting is an overlay over an empty canvas.\n */\nexport function GraphCanvas({ children, className, slot, ...rest }: GraphCanvasProps) {\n const api = useGraphContext();\n const { attach, renderer } = internalsOf(api);\n const hovered = useGraphState((s) => s.hovered);\n const focus = useGraphState((s) => s.focus);\n const tool = useGraphState((s) => s.tool);\n const options = useGraphState((s) => s.options);\n const domain = useGraphState((s) => s.drawn?.domain ?? s.domain);\n const waiting = useGraphState((s) => (s.drawn === null ? WAITING[s.status] : undefined));\n const look = useMemo(() => resolveLook(options.look), [options.look]);\n const getGraph = useCallback(() => renderer()?.graph ?? null, [renderer]);\n const overlays = useOverlays({ getGraph, getResident: api.getResident });\n const { cardRef, gridRef, hostRef, labelRef, schedule, setHovered, setLabelOrder, track } = overlays;\n const surfaceRef = useRef<HTMLDivElement>(null);\n const [composition, setComposition] = useState<Composition | null>(null);\n\n useEffect(() => {\n const surface = surfaceRef.current;\n if (!surface) return;\n return attach(surface, { onFrame: schedule, onComposed: setComposition });\n }, [attach, schedule]);\n\n const themeTick = useThemeTick();\n useEffect(() => {\n renderer()?.repaint();\n }, [renderer, themeTick]);\n\n const labels = useMemo(\n () => (composition ? labelsOf(composition, look.labels, focus) : []),\n [composition, focus, look.labels],\n );\n useEffect(() => {\n setLabelOrder(labels.map((label) => label.vertex));\n setHovered(hovered);\n track();\n schedule();\n }, [hovered, labels, schedule, setHovered, setLabelOrder, track, look.grid]);\n\n const gesture = useGesture({\n getGraph,\n getResident: api.getResident,\n getSelection: useCallback(() => api.getState().selection, [api]),\n commit: (vertices, source, label) => api.select(vertices ? [...vertices] : null, source, label),\n setTool: api.setTool,\n tool,\n });\n const { active, drag, preview } = gesture;\n\n const capacity = hostRef.current ? categoricalCapacity(hostRef.current) : undefined;\n const scale = useMemo(() => scaleOf(options, capacity), [options, capacity]);\n const card = useMemo(() => {\n if (hovered === null || !composition) return null;\n const index = composition.resident.indexOf(hovered);\n if (index === undefined) return null;\n const rank = composition.categories[index] ?? 0;\n const bound = options.fill !== undefined || options.symbol !== undefined;\n return {\n rank,\n title: composition.titles?.[index] || `#${denseOf(hovered)}`,\n category: bound && rank < domain.length ? nameOf(domain[rank], options.categories) : null,\n };\n }, [composition, domain, hovered, options]);\n\n return (\n <div\n {...rest}\n className={cn(\"relative isolate size-full overflow-hidden bg-background\", className)}\n data-slot={slot ?? \"graph-canvas\"}\n ref={hostRef}\n >\n <div className=\"size-full\" data-slot=\"graph-canvas-surface\" ref={surfaceRef} />\n <Show when={look.grid}>\n <div\n className=\"pointer-events-none absolute inset-0\"\n ref={gridRef}\n style={{ backgroundImage: \"radial-gradient(var(--border) 1px, transparent 1px)\" }}\n />\n </Show>\n <Show when={look.vignette}>\n <div\n className=\"pointer-events-none absolute inset-0\"\n style={{ background: \"radial-gradient(ellipse 75% 65% at 50% 45%, transparent 30%, var(--background) 100%)\" }}\n />\n </Show>\n <div className=\"pointer-events-none absolute inset-0 overflow-hidden\">\n {labels.map((label) => (\n <span\n className=\"absolute top-0 left-0 whitespace-nowrap font-medium text-[10px] text-foreground leading-none opacity-0 transition-opacity [text-shadow:0_0_3px_var(--background),0_0_6px_var(--background)]\"\n key={String(label.vertex)}\n ref={labelRef(label.vertex)}\n >\n {label.text}\n </span>\n ))}\n {card && (\n <div\n className=\"absolute top-0 left-0 flex w-max max-w-60 items-center gap-2 rounded-lg border bg-popover px-2.5 py-2 opacity-0 shadow-lg\"\n data-slot=\"graph-canvas-card\"\n ref={cardRef}\n >\n <ShapeGlyph className=\"size-2.5 shrink-0\" color={scale.color(card.rank)} shape={scale.shape(card.rank)} />\n <span className=\"truncate font-medium text-popover-foreground text-sm leading-none\">{card.title}</span>\n {card.category !== null && <span className=\"text-muted-foreground text-xs\">{card.category}</span>}\n </div>\n )}\n </div>\n <Show when={active !== null}>\n <div className=\"absolute inset-0 cursor-crosshair\" data-slot=\"graph-canvas-gesture\" {...gesture.handlers}>\n {drag && (\n <svg className=\"pointer-events-none size-full\">\n {drag.tool === \"rect\" ? (\n <rect\n className=\"stroke-primary\"\n height={Math.abs(drag.to[1] - drag.from[1])}\n strokeDasharray=\"4 3\"\n strokeWidth={1}\n style={{ fill: WASH }}\n width={Math.abs(drag.to[0] - drag.from[0])}\n x={Math.min(drag.from[0], drag.to[0])}\n y={Math.min(drag.from[1], drag.to[1])}\n />\n ) : (\n drag.path.length > 1 && (\n <polygon\n className=\"stroke-primary\"\n points={drag.path.map(([x, y]) => `${x},${y}`).join(\" \")}\n strokeWidth={1}\n style={{ fill: WASH }}\n />\n )\n )}\n </svg>\n )}\n <Show when={preview !== null}>\n <span\n className=\"pointer-events-none absolute rounded-sm bg-primary px-1.5 py-0.5 font-medium text-[10px] text-primary-foreground tabular-nums\"\n style={cursorChip(drag)}\n >\n {preview} node{preview === 1 ? \"\" : \"s\"}\n </span>\n </Show>\n </div>\n </Show>\n <Show when={waiting !== undefined}>\n <p\n className=\"pointer-events-none absolute inset-0 grid place-items-center text-muted-foreground text-xs\"\n data-slot=\"graph-canvas-waiting\"\n >\n {waiting}\n </p>\n </Show>\n {children}\n </div>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;AAqBA;AAQA;AACE;AACA;AACA;AAEA;AACA;AAEA;AAEE;AAEA;AAA6D;AAEjE;AAEA;AAAiD;AACtC;AAEX;AAYO;AACL;;AAMoC;AAAqB;;AAGtB;AAAqB;AAMxD;AACE;AACA;AACA;AAAwE;AAG1E;AACA;;AACE;AAAY;AAGd;AAAe;AACoD;AACjC;AAElC;AACE;AAGA;AAGF;AAA2B;AACzB;AACiB;AAC8C;AAC+B;AACjF;AACb;;AAOA;AACA;AACA;AACA;AAEA;AAAO;AACL;AAC0D;AAC2B;AAAA;AAIzF;AACE;AAAC;AAAA;AACK;AAC+E;AAChE;AACd;AAEL;AAA6E;AAE3E;AAAC;AAAA;AACW;AACL;AACqB;AAAsD;AAEpF;AAEE;AAAC;AAAA;AACW;AACW;AAAuF;AAEhH;AAEG;AACC;AAAC;AAAA;AACW;AAEgB;AAEnB;AAAA;AAHiB;AAK3B;AAEC;AAAC;AAAA;AACW;AACA;AACL;AAEL;AAAwG;AACR;AACN;AAAA;AAAA;AAAA;AAGhG;AAGK;AAGK;AAAC;AAAA;AACW;AACgC;AAC1B;AACH;AACE;AAC0B;AACL;AACA;AAAA;AAIpC;AAAC;AAAA;AACW;AAC6C;AAC1C;AACE;AAAK;AAI5B;AAGA;AAAC;AAAA;AACW;AACY;AAErB;AAAA;AAAQ;AAA2B;AAAA;AAAA;AAExC;AAEJ;AAEE;AAAC;AAAA;AACW;AACA;AAET;AAAA;AAEL;AACC;AAAA;AAAA;AAGP;;;;"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { VertexDetail } from '../core/detail';
|
|
3
|
+
export interface GraphInspectorProps extends Omit<React.ComponentProps<"div">, "children"> {
|
|
4
|
+
/**
|
|
5
|
+
* More fields for the focused vertex, drawn inside its list after the corpus's own — a
|
|
6
|
+
* `DataListItem` each. A render prop rather than a table of formatters: what a product adds is
|
|
7
|
+
* markup, and the part never learns what any of it means.
|
|
8
|
+
*/
|
|
9
|
+
children?: (detail: VertexDetail) => ReactNode;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* **The focused vertex, fetched and laid out by the corpus's own types.** A tile carries what the
|
|
13
|
+
* channels project and nothing else, so the rest of the row is read when a reader focuses it — one
|
|
14
|
+
* payload tile, filtered to one `dense_id`, cancelled when the focus moves on. The fields are the
|
|
15
|
+
* type's, in the order the corpus declares them; the address and the position are the canvas's.
|
|
16
|
+
*/
|
|
17
|
+
export declare function GraphInspector({ children, className, slot, ...rest }: GraphInspectorProps): import("react").JSX.Element;
|
|
18
|
+
//# sourceMappingURL=graph-inspector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-inspector.d.ts","sourceRoot":"","sources":["../../src/parts/graph-inspector.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAgC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGrE,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAQ/D,MAAM,WAAW,mBAAoB,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IACxF;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,SAAS,CAAC;CAChD;AAWD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,EAAE,mBAAmB,+BAoFzF"}
|