@dxos/plugin-explorer 0.9.0 → 0.9.1-staging.ee54ba693a
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/dist/lib/neutral/ExplorerArticle-2WPXYTXV.mjs +101 -0
- package/dist/lib/neutral/ExplorerArticle-2WPXYTXV.mjs.map +7 -0
- package/dist/lib/neutral/ExplorerPlugin.mjs +1 -1
- package/dist/lib/neutral/NeighborhoodCompanion-WC6E3YE6.mjs +90 -0
- package/dist/lib/neutral/NeighborhoodCompanion-WC6E3YE6.mjs.map +7 -0
- package/dist/lib/neutral/app-graph-builder-L2TJ6GNR.mjs +37 -0
- package/dist/lib/neutral/app-graph-builder-L2TJ6GNR.mjs.map +7 -0
- package/dist/lib/neutral/capabilities/index.mjs +4 -2
- package/dist/lib/neutral/capabilities/index.mjs.map +3 -3
- package/dist/lib/neutral/{chunk-3D7BYXOR.mjs → chunk-4F6AT7RA.mjs} +6 -4
- package/dist/lib/neutral/chunk-4F6AT7RA.mjs.map +7 -0
- package/dist/lib/neutral/chunk-C56B464A.mjs +53 -0
- package/dist/lib/neutral/chunk-C56B464A.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-7XUDLV6E.mjs → chunk-EZ52JY7X.mjs} +34 -31
- package/dist/lib/neutral/chunk-EZ52JY7X.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-YBCHBVCJ.mjs → chunk-TTFPTHAQ.mjs} +8 -8
- package/dist/lib/neutral/chunk-TTFPTHAQ.mjs.map +7 -0
- package/dist/lib/neutral/components/index.mjs +430 -506
- package/dist/lib/neutral/components/index.mjs.map +4 -4
- package/dist/lib/neutral/containers/index.mjs +4 -2
- package/dist/lib/neutral/containers/index.mjs.map +3 -3
- package/dist/lib/neutral/{create-object-F6TKVAGV.mjs → create-object-WKIN3OB6.mjs} +3 -4
- package/dist/lib/neutral/{create-object-F6TKVAGV.mjs.map → create-object-WKIN3OB6.mjs.map} +3 -3
- package/dist/lib/neutral/hooks/index.mjs +64 -1
- package/dist/lib/neutral/hooks/index.mjs.map +4 -4
- package/dist/lib/neutral/index.mjs +2 -2
- package/dist/lib/neutral/meta.json +1 -1
- package/dist/lib/neutral/meta.mjs +1 -1
- package/dist/lib/neutral/plugin.mjs +1 -1
- package/dist/lib/neutral/react-surface-EWPG5PUQ.mjs +39 -0
- package/dist/lib/neutral/react-surface-EWPG5PUQ.mjs.map +7 -0
- package/dist/lib/neutral/testing/index.mjs +2 -2
- package/dist/lib/neutral/testing/index.mjs.map +2 -2
- package/dist/lib/neutral/translations.mjs +5 -2
- package/dist/lib/neutral/translations.mjs.map +3 -3
- package/dist/lib/neutral/types/index.mjs +1 -1
- package/dist/types/dx.config.d.ts +28 -0
- package/dist/types/dx.config.d.ts.map +1 -0
- package/dist/types/src/ExplorerPlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/app-graph-builder.d.ts +9 -0
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
- package/dist/types/src/capabilities/create-object.d.ts +1 -7
- package/dist/types/src/capabilities/create-object.d.ts.map +1 -1
- package/dist/types/src/capabilities/index.d.ts +3 -7
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts +2 -2
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
- package/dist/types/src/components/Lattice/Lattice.d.ts +1 -1
- package/dist/types/src/components/Lattice/Lattice.d.ts.map +1 -1
- package/dist/types/src/components/Tree/EdgeBundling.stories.d.ts +1 -1
- package/dist/types/src/components/Tree/EdgeBundling.stories.d.ts.map +1 -1
- package/dist/types/src/components/Tree/Tree.stories.d.ts +1 -1
- package/dist/types/src/components/Tree/Tree.stories.d.ts.map +1 -1
- package/dist/types/src/components/Tree/index.d.ts +1 -3
- package/dist/types/src/components/Tree/index.d.ts.map +1 -1
- package/dist/types/src/components/Tree/types/tree.d.ts +10 -27
- package/dist/types/src/components/Tree/types/tree.d.ts.map +1 -1
- package/dist/types/src/components/Tree/types/types.d.ts +1 -10
- package/dist/types/src/components/Tree/types/types.d.ts.map +1 -1
- package/dist/types/src/components/Visualization/Visualization.d.ts +39 -0
- package/dist/types/src/components/Visualization/Visualization.d.ts.map +1 -0
- package/dist/types/src/components/Visualization/Visualization.stories.d.ts +13 -0
- package/dist/types/src/components/Visualization/Visualization.stories.d.ts.map +1 -0
- package/dist/types/src/components/Visualization/index.d.ts +3 -0
- package/dist/types/src/components/Visualization/index.d.ts.map +1 -0
- package/dist/types/src/components/Visualization/variants.d.ts +53 -0
- package/dist/types/src/components/Visualization/variants.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +1 -0
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/containers/ExplorerArticle/ExplorerArticle.d.ts +2 -2
- package/dist/types/src/containers/ExplorerArticle/ExplorerArticle.d.ts.map +1 -1
- package/dist/types/src/containers/ExplorerArticle/ExplorerArticle.stories.d.ts +2 -2
- package/dist/types/src/containers/ExplorerArticle/ExplorerArticle.stories.d.ts.map +1 -1
- package/dist/types/src/containers/NeighborhoodCompanion/NeighborhoodCompanion.d.ts +14 -0
- package/dist/types/src/containers/NeighborhoodCompanion/NeighborhoodCompanion.d.ts.map +1 -0
- package/dist/types/src/containers/NeighborhoodCompanion/index.d.ts +2 -0
- package/dist/types/src/containers/NeighborhoodCompanion/index.d.ts.map +1 -0
- package/dist/types/src/containers/index.d.ts +1 -0
- package/dist/types/src/containers/index.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +1 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useNeighborhoodModel.d.ts +14 -0
- package/dist/types/src/hooks/useNeighborhoodModel.d.ts.map +1 -0
- package/dist/types/src/meta.d.ts +32 -2
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/testing/relations.d.ts +1 -2
- package/dist/types/src/testing/relations.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +6 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/Graph.d.ts +6 -8
- package/dist/types/src/types/Graph.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/{dist/lib/neutral/chunk-42BYLQQA.mjs → dx.config.ts} +18 -21
- package/package.json +42 -37
- package/src/ExplorerPlugin.test.ts +1 -1
- package/src/ExplorerPlugin.tsx +3 -2
- package/src/capabilities/app-graph-builder.ts +40 -0
- package/src/capabilities/create-object.ts +3 -2
- package/src/capabilities/index.ts +1 -0
- package/src/capabilities/react-surface.tsx +14 -4
- package/src/components/Lattice/Lattice.tsx +1 -2
- package/src/components/Tree/EdgeBundling.stories.tsx +5 -3
- package/src/components/Tree/Tree.stories.tsx +7 -2
- package/src/components/Tree/index.ts +3 -3
- package/src/components/Tree/types/tree.ts +6 -6
- package/src/components/Tree/types/types.ts +1 -11
- package/src/components/Visualization/Visualization.stories.tsx +104 -0
- package/src/components/Visualization/Visualization.tsx +209 -0
- package/src/components/Visualization/index.ts +6 -0
- package/src/components/Visualization/variants.ts +508 -0
- package/src/components/index.ts +1 -0
- package/src/containers/ExplorerArticle/ExplorerArticle.stories.tsx +3 -3
- package/src/containers/ExplorerArticle/ExplorerArticle.tsx +9 -10
- package/src/containers/NeighborhoodCompanion/NeighborhoodCompanion.tsx +102 -0
- package/src/containers/NeighborhoodCompanion/index.ts +5 -0
- package/src/containers/index.ts +1 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useNeighborhoodModel.ts +81 -0
- package/src/meta.ts +2 -32
- package/src/testing/relations.ts +1 -3
- package/src/translations.ts +4 -1
- package/src/types/Graph.ts +18 -20
- package/dist/lib/neutral/ExplorerArticle-4I7PNGDC.mjs +0 -459
- package/dist/lib/neutral/ExplorerArticle-4I7PNGDC.mjs.map +0 -7
- package/dist/lib/neutral/chunk-3D7BYXOR.mjs.map +0 -7
- package/dist/lib/neutral/chunk-42BYLQQA.mjs.map +0 -7
- package/dist/lib/neutral/chunk-7XUDLV6E.mjs.map +0 -7
- package/dist/lib/neutral/chunk-IKHJV3Q4.mjs +0 -20
- package/dist/lib/neutral/chunk-IKHJV3Q4.mjs.map +0 -7
- package/dist/lib/neutral/chunk-YBCHBVCJ.mjs.map +0 -7
- package/dist/lib/neutral/react-surface-APBW2VQG.mjs +0 -26
- package/dist/lib/neutral/react-surface-APBW2VQG.mjs.map +0 -7
- package/dist/types/src/components/Tree/Tree.d.ts +0 -24
- package/dist/types/src/components/Tree/Tree.d.ts.map +0 -1
- package/dist/types/src/components/Tree/layout/HierarchicalEdgeBundling.d.ts +0 -40
- package/dist/types/src/components/Tree/layout/HierarchicalEdgeBundling.d.ts.map +0 -1
- package/dist/types/src/components/Tree/layout/RadialTree.d.ts +0 -37
- package/dist/types/src/components/Tree/layout/RadialTree.d.ts.map +0 -1
- package/dist/types/src/components/Tree/layout/TidyTree.d.ts +0 -26
- package/dist/types/src/components/Tree/layout/TidyTree.d.ts.map +0 -1
- package/dist/types/src/components/Tree/layout/hierarchy.d.ts +0 -17
- package/dist/types/src/components/Tree/layout/hierarchy.d.ts.map +0 -1
- package/dist/types/src/components/Tree/layout/index.d.ts +0 -6
- package/dist/types/src/components/Tree/layout/index.d.ts.map +0 -1
- package/dist/types/src/components/Tree/layout/slots.d.ts +0 -7
- package/dist/types/src/components/Tree/layout/slots.d.ts.map +0 -1
- package/dist/types/src/components/Tree/layout/useContainerSize.d.ts +0 -15
- package/dist/types/src/components/Tree/layout/useContainerSize.d.ts.map +0 -1
- package/dist/types/src/containers/ExplorerArticle/Visualization.d.ts +0 -18
- package/dist/types/src/containers/ExplorerArticle/Visualization.d.ts.map +0 -1
- package/dist/types/src/containers/ExplorerArticle/variants.d.ts +0 -9
- package/dist/types/src/containers/ExplorerArticle/variants.d.ts.map +0 -1
- package/src/components/Tree/Tree.tsx +0 -81
- package/src/components/Tree/layout/HierarchicalEdgeBundling.tsx +0 -335
- package/src/components/Tree/layout/RadialTree.tsx +0 -242
- package/src/components/Tree/layout/TidyTree.tsx +0 -246
- package/src/components/Tree/layout/hierarchy.ts +0 -32
- package/src/components/Tree/layout/index.ts +0 -9
- package/src/components/Tree/layout/slots.ts +0 -19
- package/src/components/Tree/layout/useContainerSize.ts +0 -43
- package/src/containers/ExplorerArticle/Visualization.tsx +0 -523
- package/src/containers/ExplorerArticle/variants.ts +0 -47
package/src/containers/index.ts
CHANGED
package/src/hooks/index.ts
CHANGED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { useEffect, useState } from 'react';
|
|
6
|
+
|
|
7
|
+
import { Obj } from '@dxos/echo';
|
|
8
|
+
import { type SpaceGraphEdge, type SpaceGraphModel, type SpaceGraphNode } from '@dxos/schema';
|
|
9
|
+
|
|
10
|
+
import { useGraphModel } from './useGraphModel';
|
|
11
|
+
|
|
12
|
+
/** Default traversal depth (hops) for the neighborhood graph. */
|
|
13
|
+
export const DEFAULT_NEIGHBORHOOD_DEPTH = 2;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Builds an ego graph around `object`: the n-hop neighbourhood reached by following refs and
|
|
17
|
+
* relations from the active node. The full space graph is materialised (reactively) and then
|
|
18
|
+
* narrowed to the nodes within `depth` hops, keeping only edges whose endpoints both survive.
|
|
19
|
+
*
|
|
20
|
+
* NOTE: Derives the subgraph from the whole-space model — the same cost the main explorer pays.
|
|
21
|
+
* A direct ECHO traversal that loads only the reachable objects is a future optimisation.
|
|
22
|
+
*/
|
|
23
|
+
export const useNeighborhoodModel = (
|
|
24
|
+
object: Obj.Unknown | undefined,
|
|
25
|
+
depth = DEFAULT_NEIGHBORHOOD_DEPTH,
|
|
26
|
+
): SpaceGraphModel | undefined => {
|
|
27
|
+
const db = object ? Obj.getDatabase(object) : undefined;
|
|
28
|
+
const fullModel = useGraphModel(db);
|
|
29
|
+
const [model, setModel] = useState<SpaceGraphModel | undefined>(undefined);
|
|
30
|
+
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
if (!fullModel || !object) {
|
|
33
|
+
setModel(undefined);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const recompute = () => setModel(buildNeighborhood(fullModel, object.id, depth));
|
|
38
|
+
recompute();
|
|
39
|
+
return fullModel.subscribe(recompute);
|
|
40
|
+
}, [fullModel, object?.id, depth]);
|
|
41
|
+
|
|
42
|
+
return model;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Narrow the full graph to the BFS neighbourhood of `rootId` within `depth` hops (edges treated as
|
|
47
|
+
* undirected so the neighbourhood reads as graph distance regardless of ref/relation direction).
|
|
48
|
+
*/
|
|
49
|
+
const buildNeighborhood = (fullModel: SpaceGraphModel, rootId: string, depth: number): SpaceGraphModel => {
|
|
50
|
+
const { nodes, edges } = fullModel.graph;
|
|
51
|
+
|
|
52
|
+
const adjacency = new Map<string, string[]>();
|
|
53
|
+
const link = (from: string, to: string) => {
|
|
54
|
+
const list = adjacency.get(from) ?? [];
|
|
55
|
+
list.push(to);
|
|
56
|
+
adjacency.set(from, list);
|
|
57
|
+
};
|
|
58
|
+
for (const edge of edges) {
|
|
59
|
+
link(edge.source, edge.target);
|
|
60
|
+
link(edge.target, edge.source);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const included = new Set<string>([rootId]);
|
|
64
|
+
let frontier = [rootId];
|
|
65
|
+
for (let hop = 0; hop < depth && frontier.length; hop++) {
|
|
66
|
+
const next: string[] = [];
|
|
67
|
+
for (const id of frontier) {
|
|
68
|
+
for (const neighbour of adjacency.get(id) ?? []) {
|
|
69
|
+
if (!included.has(neighbour)) {
|
|
70
|
+
included.add(neighbour);
|
|
71
|
+
next.push(neighbour);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
frontier = next;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const subNodes = nodes.filter((node: SpaceGraphNode) => included.has(node.id));
|
|
79
|
+
const subEdges = edges.filter((edge: SpaceGraphEdge) => included.has(edge.source) && included.has(edge.target));
|
|
80
|
+
return fullModel.copy({ nodes: subNodes, edges: subEdges });
|
|
81
|
+
};
|
package/src/meta.ts
CHANGED
|
@@ -3,37 +3,7 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { Plugin } from '@dxos/app-framework';
|
|
6
|
-
import { DXN } from '@dxos/keys';
|
|
7
|
-
import { trim } from '@dxos/util';
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
key: DXN.make('org.dxos.plugin.explorer'),
|
|
11
|
-
name: 'Explorer',
|
|
12
|
-
author: 'DXOS',
|
|
13
|
-
description: trim`
|
|
14
|
-
Explorer is an interactive hypergraph visualization plugin that reveals the relationships
|
|
15
|
-
between objects stored in your DXOS workspace. Each Graph document is backed by a live
|
|
16
|
-
ECHO query and a View that you configure — Explorer keeps the visualization synchronized
|
|
17
|
-
with the database in real time so every peer immediately sees changes made by collaborators.
|
|
7
|
+
import config from '../dx.config';
|
|
18
8
|
|
|
19
|
-
|
|
20
|
-
force-directed graph for freeform exploration, a radial cluster layout that groups objects
|
|
21
|
-
by type around a central root, an edge-bundling layout that tames visual clutter on dense
|
|
22
|
-
graphs, and a lattice grid that arranges objects in a sorted matrix sorted by type and label.
|
|
23
|
-
Switching between layouts smoothly tweens node positions so spatial context is preserved.
|
|
24
|
-
|
|
25
|
-
Nodes are coloured by their ECHO object type, and hovering any node opens an anchor-card
|
|
26
|
-
preview panel with the object's details without leaving the graph view.
|
|
27
|
-
The toolbar's query editor lets you filter the visible node set on the fly using
|
|
28
|
-
the same query syntax available across Composer.
|
|
29
|
-
|
|
30
|
-
A new Graph document can be created from the object-creation dialog; Explorer automatically
|
|
31
|
-
derives an initial View from the chosen type and persists both to ECHO so the graph is
|
|
32
|
-
immediately shareable and replicable across the space.
|
|
33
|
-
`,
|
|
34
|
-
icon: 'ph--graph--regular',
|
|
35
|
-
iconHue: 'green',
|
|
36
|
-
source: 'https://github.com/dxos/dxos/tree/main/packages/plugins/plugin-explorer',
|
|
37
|
-
spec: 'PLUGIN.mdl',
|
|
38
|
-
screenshots: ['https://dxos.network/plugin-details-explorer-dark.png'],
|
|
39
|
-
});
|
|
9
|
+
export const meta = Plugin.getMetaFromConfig(config);
|
package/src/testing/relations.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { type Space } from '@dxos/client/echo';
|
|
6
6
|
import { Obj, Query, Relation } from '@dxos/echo';
|
|
7
|
+
import { type BundleEdge, type TreeNode } from '@dxos/react-ui-graph';
|
|
7
8
|
import {
|
|
8
9
|
type RelationSpec,
|
|
9
10
|
type TypeSpec,
|
|
@@ -13,9 +14,6 @@ import {
|
|
|
13
14
|
} from '@dxos/schema/testing';
|
|
14
15
|
import { HasConnection, Organization, Person } from '@dxos/types';
|
|
15
16
|
|
|
16
|
-
import { type BundleEdge } from '../components/Tree/layout';
|
|
17
|
-
import { type TreeNode } from '../components/Tree/types';
|
|
18
|
-
|
|
19
17
|
const SECTORS = ['Technology', 'Finance', 'Research', 'Media'];
|
|
20
18
|
const CONNECTION_KINDS = ['partner', 'investor', 'vendor', 'customer'];
|
|
21
19
|
|
package/src/translations.ts
CHANGED
|
@@ -23,9 +23,12 @@ export const translations = [
|
|
|
23
23
|
'delete-object.label': 'Delete explorer',
|
|
24
24
|
'object-deleted.label': 'Explorer deleted',
|
|
25
25
|
},
|
|
26
|
-
[meta.
|
|
26
|
+
[meta.profile.key]: {
|
|
27
27
|
'plugin.name': 'Explorer',
|
|
28
28
|
'object-title.label': 'Title',
|
|
29
|
+
'neighborhood-companion.label': 'Graph',
|
|
30
|
+
'depth.label_one': '{{count}} hop',
|
|
31
|
+
'depth.label_other': '{{count}} hops',
|
|
29
32
|
},
|
|
30
33
|
},
|
|
31
34
|
},
|
package/src/types/Graph.ts
CHANGED
|
@@ -4,29 +4,27 @@
|
|
|
4
4
|
|
|
5
5
|
import * as Schema from 'effect/Schema';
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import { Annotation, DXN, Filter, Obj, Query, QueryAST, Ref, Type, View } from '@dxos/echo';
|
|
8
8
|
import { FormInputAnnotation, LabelAnnotation } from '@dxos/echo/Annotation';
|
|
9
9
|
import { ViewAnnotation } from '@dxos/schema';
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}).pipe(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
export interface Graph extends Type.InstanceType<typeof GraphSchema> {}
|
|
26
|
-
export const Graph: Type.Obj<Graph> = GraphSchema as any;
|
|
11
|
+
export class Graph extends Type.makeObject<Graph>(DXN.make('org.dxos.type.graph', '0.1.0'))(
|
|
12
|
+
Schema.Struct({
|
|
13
|
+
name: Schema.optional(Schema.String),
|
|
14
|
+
view: Ref.Ref(View.View).pipe(FormInputAnnotation.set(false), Schema.optional),
|
|
15
|
+
query: Schema.Struct({
|
|
16
|
+
raw: Schema.optional(Schema.String),
|
|
17
|
+
ast: QueryAST.Query,
|
|
18
|
+
}).pipe(FormInputAnnotation.set(false)),
|
|
19
|
+
}).pipe(
|
|
20
|
+
LabelAnnotation.set(['name']),
|
|
21
|
+
ViewAnnotation.set(['view']),
|
|
22
|
+
Annotation.IconAnnotation.set({ icon: 'ph--graph--regular', hue: 'green' }),
|
|
23
|
+
),
|
|
24
|
+
) {}
|
|
27
25
|
|
|
28
26
|
type MakeProps = Omit<Partial<Obj.MakeProps<typeof Graph>>, 'view'> & {
|
|
29
|
-
view
|
|
27
|
+
view?: View.View;
|
|
30
28
|
};
|
|
31
29
|
|
|
32
30
|
/**
|
|
@@ -36,6 +34,6 @@ export const make = ({
|
|
|
36
34
|
name,
|
|
37
35
|
query = { raw: '', ast: Query.select(Filter.nothing()).ast },
|
|
38
36
|
view,
|
|
39
|
-
}: MakeProps): Graph => {
|
|
40
|
-
return Obj.make(Graph, { name, view: Ref.make(view), query });
|
|
37
|
+
}: MakeProps = {}): Graph => {
|
|
38
|
+
return Obj.make(Graph, { name, view: view && Ref.make(view), query });
|
|
41
39
|
};
|
|
@@ -1,459 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getNodeFillForObject
|
|
3
|
-
} from "./chunk-IKHJV3Q4.mjs";
|
|
4
|
-
import "./chunk-J5LGTIGS.mjs";
|
|
5
|
-
|
|
6
|
-
// src/containers/ExplorerArticle/ExplorerArticle.tsx
|
|
7
|
-
import React2, { useCallback as useCallback2, useEffect as useEffect2, useMemo as useMemo2, useState as useState2 } from "react";
|
|
8
|
-
import { Obj as Obj2 } from "@dxos/echo";
|
|
9
|
-
import { QueryBuilder } from "@dxos/echo-query";
|
|
10
|
-
import { useObject } from "@dxos/react-client/echo";
|
|
11
|
-
import { DxAnchorActivate, Icon, Panel, Toolbar } from "@dxos/react-ui";
|
|
12
|
-
import { QueryEditor } from "@dxos/react-ui-components";
|
|
13
|
-
import "@dxos/react-ui-graph/styles/graph.css";
|
|
14
|
-
import { useGraphModel } from "#hooks";
|
|
15
|
-
|
|
16
|
-
// src/containers/ExplorerArticle/variants.ts
|
|
17
|
-
var VARIANTS = [
|
|
18
|
-
{
|
|
19
|
-
value: "force",
|
|
20
|
-
icon: "ph--graph--regular",
|
|
21
|
-
label: "Force-directed"
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
value: "cluster",
|
|
25
|
-
icon: "ph--asterisk-simple--regular",
|
|
26
|
-
label: "Radial"
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
value: "bundle",
|
|
30
|
-
icon: "ph--circles-three-plus--regular",
|
|
31
|
-
label: "Connections"
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
value: "plexus",
|
|
35
|
-
icon: "ph--share-network--regular",
|
|
36
|
-
label: "Plexus"
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
value: "lattice",
|
|
40
|
-
icon: "ph--grid-four--regular",
|
|
41
|
-
label: "Lattice"
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
value: "swarm",
|
|
45
|
-
icon: "ph--microscope--regular",
|
|
46
|
-
label: "Swarm"
|
|
47
|
-
}
|
|
48
|
-
];
|
|
49
|
-
var isVariant = (value) => value === "force" || value === "cluster" || value === "bundle" || value === "lattice" || value === "swarm" || value === "plexus";
|
|
50
|
-
|
|
51
|
-
// src/containers/ExplorerArticle/Visualization.tsx
|
|
52
|
-
import { curveCatmullRom, line as d3Line } from "d3";
|
|
53
|
-
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
54
|
-
import { Obj } from "@dxos/echo";
|
|
55
|
-
import { CLUSTER_NODE_TYPE_LEAF, CLUSTER_NODE_TYPE_ROOT, GraphBundleProjector, GraphClusterProjector, GraphForceProjector, GraphLatticeProjector, GraphPlexusProjector, GraphSwarmProjector, PLEXUS_NODE_TYPE_FOCUS, PLEXUS_NODE_TYPE_RELATION, SVG, appendRadialGroupLabel, appendRadialLeafLabel, appendRootLabel } from "@dxos/react-ui-graph";
|
|
56
|
-
import { mx } from "@dxos/ui-theme";
|
|
57
|
-
var Visualization = ({ classNames, debug = true, variant, model, onNodeHover, onSurfaceClick }) => {
|
|
58
|
-
const svgRef = useRef(null);
|
|
59
|
-
const [projector, setProjector] = useState();
|
|
60
|
-
const projectorRef = useRef(void 0);
|
|
61
|
-
projectorRef.current = projector;
|
|
62
|
-
const [focusId, setFocusId] = useState(void 0);
|
|
63
|
-
const lastLayoutRef = useRef(void 0);
|
|
64
|
-
useEffect(() => model?.subscribe(() => void 0), [
|
|
65
|
-
model
|
|
66
|
-
]);
|
|
67
|
-
useEffect(() => {
|
|
68
|
-
if (variant !== "plexus") {
|
|
69
|
-
setFocusId(void 0);
|
|
70
|
-
}
|
|
71
|
-
}, [
|
|
72
|
-
variant
|
|
73
|
-
]);
|
|
74
|
-
useEffect(() => {
|
|
75
|
-
if (projectorRef.current?.layout) {
|
|
76
|
-
lastLayoutRef.current = projectorRef.current.layout;
|
|
77
|
-
}
|
|
78
|
-
if (!svgRef.current) {
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
setProjector(createProjector(svgRef.current, variant, focusId, lastLayoutRef.current));
|
|
82
|
-
}, [
|
|
83
|
-
variant,
|
|
84
|
-
focusId
|
|
85
|
-
]);
|
|
86
|
-
const handleSelect = useCallback((node) => {
|
|
87
|
-
if (variant !== "plexus") {
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
if (!node.data?.data?.object) {
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
setFocusId((current) => current === node.id ? void 0 : node.id);
|
|
94
|
-
}, [
|
|
95
|
-
variant
|
|
96
|
-
]);
|
|
97
|
-
const renderNode = useMemo(() => createRenderNode(variant), [
|
|
98
|
-
variant
|
|
99
|
-
]);
|
|
100
|
-
const applyNode = useMemo(() => variant === "swarm" ? applyNodeSwarm : void 0, [
|
|
101
|
-
variant
|
|
102
|
-
]);
|
|
103
|
-
const handlePointerMove = useCallback((point) => {
|
|
104
|
-
if (projector instanceof GraphSwarmProjector) {
|
|
105
|
-
projector.setCursor(point.x, point.y);
|
|
106
|
-
}
|
|
107
|
-
}, [
|
|
108
|
-
projector
|
|
109
|
-
]);
|
|
110
|
-
const handlePointerLeave = useCallback(() => {
|
|
111
|
-
if (projector instanceof GraphSwarmProjector) {
|
|
112
|
-
projector.setCursor(null);
|
|
113
|
-
}
|
|
114
|
-
}, [
|
|
115
|
-
projector
|
|
116
|
-
]);
|
|
117
|
-
const handleInspect = useCallback((node, event) => {
|
|
118
|
-
if (variant === "plexus") {
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
onNodeHover?.(node ? {
|
|
122
|
-
id: node.id,
|
|
123
|
-
data: node.data?.data?.object
|
|
124
|
-
} : null, event);
|
|
125
|
-
}, [
|
|
126
|
-
variant === "plexus" ? void 0 : onNodeHover
|
|
127
|
-
]);
|
|
128
|
-
const swarmPointerProps = variant === "swarm" ? {
|
|
129
|
-
onPointerMove: handlePointerMove,
|
|
130
|
-
onPointerLeave: handlePointerLeave
|
|
131
|
-
} : void 0;
|
|
132
|
-
return /* @__PURE__ */ React.createElement("div", {
|
|
133
|
-
className: mx("dx-expander relative", classNames),
|
|
134
|
-
onClick: onSurfaceClick
|
|
135
|
-
}, /* @__PURE__ */ React.createElement(SVG.Root, {
|
|
136
|
-
ref: svgRef
|
|
137
|
-
}, /* @__PURE__ */ React.createElement(SVG.Zoom, {
|
|
138
|
-
extent: [
|
|
139
|
-
1 / 2,
|
|
140
|
-
2
|
|
141
|
-
]
|
|
142
|
-
}, /* @__PURE__ */ React.createElement(SVG.Graph, {
|
|
143
|
-
model,
|
|
144
|
-
projector,
|
|
145
|
-
renderNode,
|
|
146
|
-
applyNode,
|
|
147
|
-
edgeOpacity: variant === "swarm" ? 0.3 : void 0,
|
|
148
|
-
drag: variant === "force",
|
|
149
|
-
highlightOnHover: variant === "bundle",
|
|
150
|
-
onSelect: handleSelect,
|
|
151
|
-
onInspect: handleInspect,
|
|
152
|
-
...swarmPointerProps
|
|
153
|
-
})), debug && /* @__PURE__ */ React.createElement(SVG.FPS, null)));
|
|
154
|
-
};
|
|
155
|
-
var TWEEN_MS = 500;
|
|
156
|
-
var LABEL_FADE_MS = 200;
|
|
157
|
-
var PLEXUS_LEAF_RADIUS = 5;
|
|
158
|
-
var PLEXUS_FOCUS_RADIUS = PLEXUS_LEAF_RADIUS * 2;
|
|
159
|
-
var swarmTrailLine = d3Line().curve(curveCatmullRom.alpha(0.5));
|
|
160
|
-
var applyNodeSwarm = (group, node) => {
|
|
161
|
-
const swarm = node;
|
|
162
|
-
const path = group.querySelector("path.dx-swarm-tail");
|
|
163
|
-
const grad = group.querySelector("linearGradient");
|
|
164
|
-
if (!path || !grad) {
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
167
|
-
const history = swarm.history ?? [];
|
|
168
|
-
if (history.length === 0) {
|
|
169
|
-
path.setAttribute("d", "");
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
const hx = swarm.x ?? 0;
|
|
173
|
-
const hy = swarm.y ?? 0;
|
|
174
|
-
const points = [
|
|
175
|
-
[
|
|
176
|
-
0,
|
|
177
|
-
0
|
|
178
|
-
]
|
|
179
|
-
];
|
|
180
|
-
for (let i = history.length - 1; i >= 0; i--) {
|
|
181
|
-
points.push([
|
|
182
|
-
history[i].x - hx,
|
|
183
|
-
history[i].y - hy
|
|
184
|
-
]);
|
|
185
|
-
}
|
|
186
|
-
path.setAttribute("d", swarmTrailLine(points) ?? "");
|
|
187
|
-
const oldest = history[0];
|
|
188
|
-
grad.setAttribute("x2", String(oldest.x - hx));
|
|
189
|
-
grad.setAttribute("y2", String(oldest.y - hy));
|
|
190
|
-
};
|
|
191
|
-
var createProjector = (ctx, variant, focusId, prev) => {
|
|
192
|
-
switch (variant) {
|
|
193
|
-
case "force":
|
|
194
|
-
return new GraphForceProjector(ctx, void 0, void 0, prev);
|
|
195
|
-
case "swarm":
|
|
196
|
-
return new GraphSwarmProjector(ctx, void 0, void 0, prev);
|
|
197
|
-
case "lattice":
|
|
198
|
-
return new GraphLatticeProjector(ctx, {
|
|
199
|
-
duration: TWEEN_MS,
|
|
200
|
-
// Plugin-explorer overrides the projector's force-matched default (6)
|
|
201
|
-
// with a smaller node so the lattice reads as a dense matrix.
|
|
202
|
-
radius: 4,
|
|
203
|
-
// Cluster by typename first so same-type rects sit together; break ties by label.
|
|
204
|
-
sortBy: (node) => {
|
|
205
|
-
const obj = node.data?.data?.object;
|
|
206
|
-
const typename = obj ? Obj.getTypename(obj) ?? "(untyped)" : "(untyped)";
|
|
207
|
-
const label = (obj && Obj.getLabel(obj)) ?? node.data?.data?.label ?? node.id;
|
|
208
|
-
return `${typename} ${label}`;
|
|
209
|
-
}
|
|
210
|
-
}, void 0, prev);
|
|
211
|
-
case "cluster":
|
|
212
|
-
return new GraphClusterProjector(ctx, {
|
|
213
|
-
duration: TWEEN_MS,
|
|
214
|
-
groupOf: typenameGroupOf,
|
|
215
|
-
rootLabel: "Database",
|
|
216
|
-
groupLabel: shortTypename,
|
|
217
|
-
// All three node kinds share the same radius — leaves, groups, and root read
|
|
218
|
-
// as members of the same circle rather than ranked by size.
|
|
219
|
-
rootRadius: 4,
|
|
220
|
-
groupRadius: 4
|
|
221
|
-
}, void 0, prev);
|
|
222
|
-
case "bundle":
|
|
223
|
-
return new GraphBundleProjector(ctx, {
|
|
224
|
-
duration: TWEEN_MS,
|
|
225
|
-
groupOf: typenameGroupOf
|
|
226
|
-
}, void 0, prev);
|
|
227
|
-
case "plexus":
|
|
228
|
-
if (!focusId) {
|
|
229
|
-
return new GraphBundleProjector(ctx, {
|
|
230
|
-
duration: TWEEN_MS,
|
|
231
|
-
groupOf: typenameGroupOf
|
|
232
|
-
}, void 0, prev);
|
|
233
|
-
}
|
|
234
|
-
return new GraphPlexusProjector(ctx, {
|
|
235
|
-
duration: TWEEN_MS,
|
|
236
|
-
focus: focusId,
|
|
237
|
-
relationOf: plexusRelationOf,
|
|
238
|
-
leafRadius: PLEXUS_LEAF_RADIUS,
|
|
239
|
-
relationRadius: PLEXUS_LEAF_RADIUS,
|
|
240
|
-
focusRadius: PLEXUS_FOCUS_RADIUS
|
|
241
|
-
}, void 0, prev);
|
|
242
|
-
}
|
|
243
|
-
};
|
|
244
|
-
var plexusRelationOf = (edge, focusId) => {
|
|
245
|
-
const outgoing = edge.source.id === focusId;
|
|
246
|
-
const incoming = edge.target.id === focusId;
|
|
247
|
-
if (!outgoing && !incoming) {
|
|
248
|
-
return void 0;
|
|
249
|
-
}
|
|
250
|
-
const direction = outgoing ? "out" : "in";
|
|
251
|
-
const arrow = outgoing ? "\u2192" : "\u2190";
|
|
252
|
-
if (edge.type === "relation") {
|
|
253
|
-
const relation = edge.data?.object;
|
|
254
|
-
const typename = relation ? Obj.getTypename(relation) : void 0;
|
|
255
|
-
const name = typename ? shortTypename(typename) : "Relation";
|
|
256
|
-
return {
|
|
257
|
-
key: `relation:${direction}:${typename ?? "?"}`,
|
|
258
|
-
label: `${name} ${arrow}`
|
|
259
|
-
};
|
|
260
|
-
}
|
|
261
|
-
if (edge.type === "ref") {
|
|
262
|
-
const property = edge.data?.property;
|
|
263
|
-
const name = property ?? "References";
|
|
264
|
-
return {
|
|
265
|
-
key: `ref:${direction}:${property ?? "?"}`,
|
|
266
|
-
label: `${name} ${arrow}`
|
|
267
|
-
};
|
|
268
|
-
}
|
|
269
|
-
return void 0;
|
|
270
|
-
};
|
|
271
|
-
var createRenderNode = (variant) => {
|
|
272
|
-
switch (variant) {
|
|
273
|
-
case "force":
|
|
274
|
-
return (group, node) => {
|
|
275
|
-
const r = node.r ?? 6;
|
|
276
|
-
group.append("circle").attr("r", r).style("cursor", "pointer").style("fill", getNodeFillForObject(node.data?.data?.object));
|
|
277
|
-
};
|
|
278
|
-
case "swarm":
|
|
279
|
-
return (group, node) => {
|
|
280
|
-
const fill = getNodeFillForObject(node.data?.data?.object);
|
|
281
|
-
const r = node.r ?? 6;
|
|
282
|
-
const strokeWidth = Math.max(1, r * 0.6);
|
|
283
|
-
const gradId = `dx-swarm-grad-${String(node.id).replace(/[^\w-]/g, "_")}`;
|
|
284
|
-
const grad = group.append("defs").append("linearGradient").attr("id", gradId).attr("gradientUnits", "userSpaceOnUse").attr("x1", 0).attr("y1", 0).attr("x2", 0).attr("y2", 0);
|
|
285
|
-
grad.append("stop").attr("offset", 0).attr("stop-color", fill).attr("stop-opacity", 0.7);
|
|
286
|
-
grad.append("stop").attr("offset", 1).attr("stop-color", fill).attr("stop-opacity", 0);
|
|
287
|
-
group.append("path").classed("dx-swarm-tail", true).attr("fill", "none").attr("stroke", `url(#${gradId})`).attr("stroke-width", strokeWidth).attr("stroke-linecap", "round").attr("stroke-linejoin", "round").attr("pointer-events", "none");
|
|
288
|
-
group.append("circle").attr("r", r).style("cursor", "pointer").style("fill", fill);
|
|
289
|
-
};
|
|
290
|
-
case "lattice":
|
|
291
|
-
return (group, node) => {
|
|
292
|
-
const r = node.r ?? 6;
|
|
293
|
-
const sz = r * 2;
|
|
294
|
-
group.append("rect").attr("x", -r).attr("y", -r).attr("width", sz).attr("height", sz).attr("rx", r * 0.3).attr("ry", r * 0.3).style("cursor", "pointer").style("fill", getNodeFillForObject(node.data?.data?.object));
|
|
295
|
-
};
|
|
296
|
-
case "cluster":
|
|
297
|
-
return (group, node) => {
|
|
298
|
-
const obj = node.data?.data?.object;
|
|
299
|
-
const r = node.r ?? 4;
|
|
300
|
-
group.append("circle").attr("r", r).style("cursor", "pointer").style("fill", obj ? getNodeFillForObject(obj) : "var(--color-neutral-500)");
|
|
301
|
-
const labelOptions = {
|
|
302
|
-
delay: TWEEN_MS,
|
|
303
|
-
duration: LABEL_FADE_MS
|
|
304
|
-
};
|
|
305
|
-
if (node.type === CLUSTER_NODE_TYPE_LEAF) {
|
|
306
|
-
const text = labelForLeaf(node, obj);
|
|
307
|
-
if (text) {
|
|
308
|
-
appendRadialLeafLabel(group, node, text, r, labelOptions);
|
|
309
|
-
}
|
|
310
|
-
} else if (node.type === CLUSTER_NODE_TYPE_ROOT) {
|
|
311
|
-
if (node.label) {
|
|
312
|
-
appendRootLabel(group, node.label, r, labelOptions);
|
|
313
|
-
}
|
|
314
|
-
} else {
|
|
315
|
-
if (node.label) {
|
|
316
|
-
appendRadialGroupLabel(group, node, node.label, r, labelOptions);
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
};
|
|
320
|
-
case "bundle":
|
|
321
|
-
return (group, node) => {
|
|
322
|
-
const obj = node.data?.data?.object;
|
|
323
|
-
const r = node.r ?? 4;
|
|
324
|
-
group.append("circle").attr("r", r).style("cursor", "pointer").style("fill", obj ? getNodeFillForObject(obj) : "var(--color-neutral-500)");
|
|
325
|
-
const text = labelForLeaf(node, obj);
|
|
326
|
-
if (text) {
|
|
327
|
-
appendRadialLeafLabel(group, node, text, r, {
|
|
328
|
-
delay: TWEEN_MS,
|
|
329
|
-
duration: LABEL_FADE_MS
|
|
330
|
-
});
|
|
331
|
-
}
|
|
332
|
-
};
|
|
333
|
-
case "plexus":
|
|
334
|
-
return (group, node) => {
|
|
335
|
-
const obj = node.data?.data?.object;
|
|
336
|
-
const labelOptions = {
|
|
337
|
-
delay: TWEEN_MS,
|
|
338
|
-
duration: LABEL_FADE_MS
|
|
339
|
-
};
|
|
340
|
-
if (node.type === PLEXUS_NODE_TYPE_RELATION) {
|
|
341
|
-
const r2 = PLEXUS_LEAF_RADIUS;
|
|
342
|
-
group.append("circle").attr("r", r2).style("cursor", "default").style("fill", "var(--color-neutral-500)");
|
|
343
|
-
if (node.label) {
|
|
344
|
-
appendRadialGroupLabel(group, node, node.label, r2, labelOptions);
|
|
345
|
-
}
|
|
346
|
-
return;
|
|
347
|
-
}
|
|
348
|
-
const isFocus = node.type === PLEXUS_NODE_TYPE_FOCUS;
|
|
349
|
-
const r = isFocus ? PLEXUS_FOCUS_RADIUS : PLEXUS_LEAF_RADIUS;
|
|
350
|
-
group.append("circle").attr("r", r).style("cursor", "pointer").style("fill", obj ? getNodeFillForObject(obj) : "var(--color-neutral-500)");
|
|
351
|
-
const text = labelForLeaf(node, obj);
|
|
352
|
-
if (text) {
|
|
353
|
-
if (isFocus) {
|
|
354
|
-
appendRootLabel(group, text, r, labelOptions);
|
|
355
|
-
} else {
|
|
356
|
-
appendRadialLeafLabel(group, node, text, r, labelOptions);
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
};
|
|
360
|
-
}
|
|
361
|
-
};
|
|
362
|
-
var typenameGroupOf = (node) => {
|
|
363
|
-
const obj = node.data?.data?.object;
|
|
364
|
-
return obj ? Obj.getTypename(obj) ?? "(untyped)" : void 0;
|
|
365
|
-
};
|
|
366
|
-
var shortTypename = (typename) => {
|
|
367
|
-
const last = typename.split(".").pop() ?? typename;
|
|
368
|
-
return last.charAt(0).toUpperCase() + last.slice(1);
|
|
369
|
-
};
|
|
370
|
-
var labelForLeaf = (node, obj) => (obj && Obj.getLabel(obj)) ?? node.data?.data?.label ?? node.id;
|
|
371
|
-
|
|
372
|
-
// src/containers/ExplorerArticle/ExplorerArticle.tsx
|
|
373
|
-
var ExplorerArticle = ({ role, subject, variant }) => {
|
|
374
|
-
const [view] = useObject(subject);
|
|
375
|
-
const [filter, setFilter] = useState2();
|
|
376
|
-
const db = view && Obj2.getDatabase(view);
|
|
377
|
-
const model = useGraphModel(db, filter);
|
|
378
|
-
const builder = useMemo2(() => new QueryBuilder(), []);
|
|
379
|
-
const handleChange = useCallback2((value) => {
|
|
380
|
-
setFilter(builder.build(value).filter);
|
|
381
|
-
}, [
|
|
382
|
-
builder
|
|
383
|
-
]);
|
|
384
|
-
const [selected, setSelected] = useState2(isVariant(variant) ? variant : "force");
|
|
385
|
-
useEffect2(() => {
|
|
386
|
-
if (isVariant(variant)) {
|
|
387
|
-
setSelected(variant);
|
|
388
|
-
}
|
|
389
|
-
}, [
|
|
390
|
-
variant
|
|
391
|
-
]);
|
|
392
|
-
const handleVariantChange = useCallback2((value) => {
|
|
393
|
-
if (isVariant(value)) {
|
|
394
|
-
setSelected(value);
|
|
395
|
-
}
|
|
396
|
-
}, []);
|
|
397
|
-
const handleDismiss = useCallback2(() => {
|
|
398
|
-
document.defaultView?.dispatchEvent(new DxAnchorActivate({
|
|
399
|
-
dxn: "",
|
|
400
|
-
label: "",
|
|
401
|
-
trigger: document.body,
|
|
402
|
-
state: false
|
|
403
|
-
}));
|
|
404
|
-
}, []);
|
|
405
|
-
const handleHover = useCallback2((node, event) => {
|
|
406
|
-
if (!node || !event) {
|
|
407
|
-
return;
|
|
408
|
-
}
|
|
409
|
-
const obj = node.data;
|
|
410
|
-
if (!obj || !Obj2.isObject(obj)) {
|
|
411
|
-
return;
|
|
412
|
-
}
|
|
413
|
-
const dxn = Obj2.getURI(obj);
|
|
414
|
-
if (!dxn) {
|
|
415
|
-
return;
|
|
416
|
-
}
|
|
417
|
-
const target = event.target;
|
|
418
|
-
target.dispatchEvent(new DxAnchorActivate({
|
|
419
|
-
dxn,
|
|
420
|
-
kind: "card",
|
|
421
|
-
trigger: target,
|
|
422
|
-
label: Obj2.getLabel(obj) ?? dxn
|
|
423
|
-
}));
|
|
424
|
-
}, []);
|
|
425
|
-
const showToolbar = role === "article";
|
|
426
|
-
if (!db || !model) {
|
|
427
|
-
return null;
|
|
428
|
-
}
|
|
429
|
-
return /* @__PURE__ */ React2.createElement(Panel.Root, {
|
|
430
|
-
role
|
|
431
|
-
}, showToolbar && /* @__PURE__ */ React2.createElement(Panel.Toolbar, {
|
|
432
|
-
asChild: true
|
|
433
|
-
}, /* @__PURE__ */ React2.createElement(Toolbar.Root, null, /* @__PURE__ */ React2.createElement(QueryEditor, {
|
|
434
|
-
db,
|
|
435
|
-
onChange: handleChange
|
|
436
|
-
}), /* @__PURE__ */ React2.createElement(Toolbar.ToggleGroup, {
|
|
437
|
-
type: "single",
|
|
438
|
-
value: selected,
|
|
439
|
-
onValueChange: handleVariantChange
|
|
440
|
-
}, VARIANTS.map(({ value, icon, label }) => /* @__PURE__ */ React2.createElement(Toolbar.ToggleGroupItem, {
|
|
441
|
-
key: value,
|
|
442
|
-
value,
|
|
443
|
-
"aria-label": label,
|
|
444
|
-
title: label
|
|
445
|
-
}, /* @__PURE__ */ React2.createElement(Icon, {
|
|
446
|
-
icon,
|
|
447
|
-
size: 4
|
|
448
|
-
})))))), /* @__PURE__ */ React2.createElement(Panel.Content, null, /* @__PURE__ */ React2.createElement(Visualization, {
|
|
449
|
-
classNames: "bg-base-surface",
|
|
450
|
-
variant: selected,
|
|
451
|
-
model,
|
|
452
|
-
onNodeHover: handleHover,
|
|
453
|
-
onSurfaceClick: handleDismiss
|
|
454
|
-
})));
|
|
455
|
-
};
|
|
456
|
-
export {
|
|
457
|
-
ExplorerArticle as default
|
|
458
|
-
};
|
|
459
|
-
//# sourceMappingURL=ExplorerArticle-4I7PNGDC.mjs.map
|