@dxos/plugin-explorer 0.8.4-main.7996785055 → 0.8.4-main.8baae0fced
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/LICENSE +102 -5
- package/dist/lib/neutral/ExplorerArticle-EAKRB55W.mjs +277 -0
- package/dist/lib/neutral/ExplorerArticle-EAKRB55W.mjs.map +7 -0
- package/dist/lib/neutral/ExplorerPlugin.mjs +10 -0
- package/dist/lib/neutral/capabilities/index.mjs +11 -0
- package/dist/lib/neutral/capabilities/index.mjs.map +7 -0
- package/dist/lib/{browser/chunk-6KEHUEEZ.mjs → neutral/chunk-7SPMPHRS.mjs} +6 -5
- package/dist/lib/neutral/chunk-7SPMPHRS.mjs.map +7 -0
- package/dist/lib/{browser/chunk-LSUP47BZ.mjs → neutral/chunk-DXIWQFYO.mjs} +2 -4
- package/dist/lib/neutral/chunk-DXIWQFYO.mjs.map +7 -0
- package/dist/lib/neutral/chunk-EM2BV4PF.mjs +290 -0
- package/dist/lib/neutral/chunk-EM2BV4PF.mjs.map +7 -0
- package/dist/lib/neutral/chunk-GRJXLL4Z.mjs +25 -0
- package/dist/lib/neutral/chunk-GRJXLL4Z.mjs.map +7 -0
- package/dist/lib/neutral/chunk-V2OFO6PI.mjs +14 -0
- package/dist/lib/neutral/chunk-V2OFO6PI.mjs.map +7 -0
- package/dist/lib/{browser/chunk-56VV76WZ.mjs → neutral/components/index.mjs} +706 -356
- package/dist/lib/neutral/components/index.mjs.map +7 -0
- package/dist/lib/neutral/containers/index.mjs +9 -0
- package/dist/lib/neutral/containers/index.mjs.map +7 -0
- package/dist/lib/neutral/create-object-F6TKVAGV.mjs +39 -0
- package/dist/lib/neutral/create-object-F6TKVAGV.mjs.map +7 -0
- package/dist/lib/neutral/hooks/index.mjs +45 -0
- package/dist/lib/neutral/hooks/index.mjs.map +7 -0
- package/dist/lib/neutral/index.mjs +14 -0
- package/dist/lib/neutral/meta.json +1 -0
- package/dist/lib/{browser → neutral}/meta.mjs +1 -1
- package/dist/lib/neutral/plugin.mjs +12 -0
- package/dist/lib/neutral/plugin.mjs.map +7 -0
- package/dist/lib/neutral/react-surface-APBW2VQG.mjs +26 -0
- package/dist/lib/neutral/react-surface-APBW2VQG.mjs.map +7 -0
- package/dist/lib/neutral/testing/index.mjs +193 -0
- package/dist/lib/neutral/testing/index.mjs.map +7 -0
- package/dist/lib/neutral/translations.mjs +33 -0
- package/dist/lib/neutral/translations.mjs.map +7 -0
- package/dist/lib/{browser → neutral}/types/index.mjs +1 -1
- package/dist/types/data/cities.d.ts +4 -4
- package/dist/types/data/cities.d.ts.map +1 -1
- package/dist/types/data/countries-110m.d.ts +19 -22
- package/dist/types/data/countries-110m.d.ts.map +1 -1
- package/dist/types/src/ExplorerPlugin.d.ts +1 -0
- package/dist/types/src/ExplorerPlugin.d.ts.map +1 -1
- package/dist/types/src/ExplorerPlugin.test.d.ts +2 -0
- package/dist/types/src/ExplorerPlugin.test.d.ts.map +1 -0
- package/dist/types/src/capabilities/create-object.d.ts +11 -0
- package/dist/types/src/capabilities/create-object.d.ts.map +1 -0
- package/dist/types/src/capabilities/index.d.ts +8 -1
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
- package/dist/types/src/components/Chart/Chart.d.ts +1 -1
- package/dist/types/src/components/Chart/Chart.d.ts.map +1 -1
- package/dist/types/src/components/Chart/Chart.stories.d.ts +4 -1
- package/dist/types/src/components/Chart/Chart.stories.d.ts.map +1 -1
- package/dist/types/src/components/Globe/Globe.d.ts +1 -1
- package/dist/types/src/components/Globe/Globe.d.ts.map +1 -1
- package/dist/types/src/components/Globe/Globe.stories.d.ts +5 -2
- package/dist/types/src/components/Globe/Globe.stories.d.ts.map +1 -1
- package/dist/types/src/components/Graph/CanvasForceGraph.d.ts +13 -0
- package/dist/types/src/components/Graph/CanvasForceGraph.d.ts.map +1 -0
- package/dist/types/src/components/Graph/{D3ForceGraph.stories.d.ts → CanvasForceGraph.stories.d.ts} +3 -7
- package/dist/types/src/components/Graph/CanvasForceGraph.stories.d.ts.map +1 -0
- package/dist/types/src/components/Graph/ForceGraph.d.ts +12 -5
- package/dist/types/src/components/Graph/ForceGraph.d.ts.map +1 -1
- package/dist/types/src/components/Graph/ForceGraph.stories.d.ts +3 -1
- package/dist/types/src/components/Graph/ForceGraph.stories.d.ts.map +1 -1
- package/dist/types/src/components/Graph/{adapter.d.ts → graph-adapter.d.ts} +1 -1
- package/dist/types/src/components/Graph/graph-adapter.d.ts.map +1 -0
- package/dist/types/src/components/Graph/index.d.ts +1 -1
- package/dist/types/src/components/Graph/index.d.ts.map +1 -1
- package/dist/types/src/components/Lattice/Lattice.d.ts +20 -0
- package/dist/types/src/components/Lattice/Lattice.d.ts.map +1 -0
- package/dist/types/src/components/Lattice/Lattice.stories.d.ts +8 -0
- package/dist/types/src/components/Lattice/Lattice.stories.d.ts.map +1 -0
- package/dist/types/src/components/Lattice/index.d.ts +2 -0
- package/dist/types/src/components/Lattice/index.d.ts.map +1 -0
- package/dist/types/src/components/Tree/EdgeBundling.stories.d.ts +21 -0
- package/dist/types/src/components/Tree/EdgeBundling.stories.d.ts.map +1 -0
- package/dist/types/src/components/Tree/Tree.d.ts +20 -23
- package/dist/types/src/components/Tree/Tree.d.ts.map +1 -1
- package/dist/types/src/components/Tree/Tree.stories.d.ts +5 -12
- package/dist/types/src/components/Tree/Tree.stories.d.ts.map +1 -1
- package/dist/types/src/components/Tree/index.d.ts +2 -0
- package/dist/types/src/components/Tree/index.d.ts.map +1 -1
- package/dist/types/src/components/Tree/layout/HierarchicalEdgeBundling.d.ts +37 -2
- package/dist/types/src/components/Tree/layout/HierarchicalEdgeBundling.d.ts.map +1 -1
- package/dist/types/src/components/Tree/layout/RadialTree.d.ts +35 -2
- package/dist/types/src/components/Tree/layout/RadialTree.d.ts.map +1 -1
- package/dist/types/src/components/Tree/layout/TidyTree.d.ts +24 -2
- package/dist/types/src/components/Tree/layout/TidyTree.d.ts.map +1 -1
- package/dist/types/src/components/Tree/layout/hierarchy.d.ts +17 -0
- package/dist/types/src/components/Tree/layout/hierarchy.d.ts.map +1 -0
- package/dist/types/src/components/Tree/layout/index.d.ts +5 -4
- package/dist/types/src/components/Tree/layout/index.d.ts.map +1 -1
- package/dist/types/src/components/Tree/layout/slots.d.ts +7 -0
- package/dist/types/src/components/Tree/layout/slots.d.ts.map +1 -0
- package/dist/types/src/components/Tree/layout/useContainerSize.d.ts +15 -0
- package/dist/types/src/components/Tree/layout/useContainerSize.d.ts.map +1 -0
- package/dist/types/src/components/Tree/types/tree.d.ts +6 -6
- package/dist/types/src/components/Tree/types/tree.d.ts.map +1 -1
- package/dist/types/src/components/Tree/types/types.d.ts +14 -4
- package/dist/types/src/components/Tree/types/types.d.ts.map +1 -1
- 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 +9 -0
- package/dist/types/src/containers/ExplorerArticle/ExplorerArticle.d.ts.map +1 -0
- package/dist/types/src/containers/ExplorerArticle/ExplorerArticle.stories.d.ts +29 -0
- package/dist/types/src/containers/ExplorerArticle/ExplorerArticle.stories.d.ts.map +1 -0
- package/dist/types/src/containers/ExplorerArticle/experimental.stories.d.ts +7 -0
- package/dist/types/src/containers/ExplorerArticle/experimental.stories.d.ts.map +1 -0
- package/dist/types/src/containers/ExplorerArticle/index.d.ts +2 -0
- package/dist/types/src/containers/ExplorerArticle/index.d.ts.map +1 -0
- package/dist/types/src/containers/index.d.ts +1 -1
- package/dist/types/src/containers/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useGraphModel.d.ts +2 -2
- package/dist/types/src/hooks/useGraphModel.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -3
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/plugin.d.ts +3 -0
- package/dist/types/src/plugin.d.ts.map +1 -0
- package/dist/types/src/{components/Tree/testing → testing}/generator.d.ts +1 -1
- package/dist/types/src/testing/generator.d.ts.map +1 -0
- package/dist/types/src/testing/index.d.ts +4 -0
- package/dist/types/src/testing/index.d.ts.map +1 -0
- package/dist/types/src/testing/relations.d.ts +47 -0
- package/dist/types/src/testing/relations.d.ts.map +1 -0
- package/dist/types/src/translations.d.ts +28 -28
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/Graph.d.ts +3 -4
- package/dist/types/src/types/Graph.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +3 -0
- package/dist/types/src/util/index.d.ts.map +1 -0
- package/dist/types/src/util/node-color.d.ts +13 -0
- package/dist/types/src/util/node-color.d.ts.map +1 -0
- package/dist/types/src/{components → util}/plot.d.ts +1 -1
- package/dist/types/src/util/plot.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +102 -56
- package/src/ExplorerPlugin.test.ts +26 -0
- package/src/ExplorerPlugin.tsx +7 -35
- package/src/capabilities/create-object.ts +36 -0
- package/src/capabilities/index.ts +4 -1
- package/src/capabilities/react-surface.tsx +32 -0
- package/src/components/Chart/Chart.stories.tsx +14 -21
- package/src/components/Chart/Chart.tsx +1 -1
- package/src/components/Globe/Globe.stories.tsx +17 -20
- package/src/components/Globe/Globe.tsx +1 -1
- package/src/components/Graph/CanvasForceGraph.stories.tsx +83 -0
- package/src/components/Graph/CanvasForceGraph.tsx +124 -0
- package/src/components/Graph/ForceGraph.stories.tsx +78 -42
- package/src/components/Graph/ForceGraph.tsx +104 -85
- package/src/components/Graph/index.ts +1 -1
- package/src/components/Lattice/Lattice.stories.tsx +90 -0
- package/src/components/Lattice/Lattice.tsx +182 -0
- package/src/components/Lattice/index.ts +5 -0
- package/src/components/Tree/EdgeBundling.stories.tsx +144 -0
- package/src/components/Tree/Tree.stories.tsx +19 -40
- package/src/components/Tree/Tree.tsx +69 -100
- package/src/components/Tree/index.ts +2 -0
- package/src/components/Tree/layout/HierarchicalEdgeBundling.tsx +296 -0
- package/src/components/Tree/layout/RadialTree.tsx +242 -0
- package/src/components/Tree/layout/TidyTree.tsx +246 -0
- package/src/components/Tree/layout/hierarchy.ts +32 -0
- package/src/components/Tree/layout/index.ts +5 -5
- package/src/components/Tree/layout/slots.ts +19 -0
- package/src/components/Tree/layout/useContainerSize.ts +43 -0
- package/src/components/Tree/types/tree.test.ts +4 -5
- package/src/components/Tree/types/tree.ts +9 -9
- package/src/components/Tree/types/types.ts +38 -29
- package/src/components/index.ts +1 -0
- package/src/containers/ExplorerArticle/ExplorerArticle.stories.tsx +136 -0
- package/src/containers/ExplorerArticle/ExplorerArticle.tsx +465 -0
- package/src/containers/ExplorerArticle/experimental.stories.tsx +446 -0
- package/src/containers/ExplorerArticle/index.ts +5 -0
- package/src/containers/index.ts +1 -1
- package/src/hooks/useGraphModel.ts +10 -6
- package/src/index.ts +1 -4
- package/src/meta.ts +1 -1
- package/src/plugin.ts +9 -0
- package/src/{components/Tree/testing → testing}/generator.ts +2 -2
- package/src/testing/index.ts +9 -0
- package/src/testing/relations.ts +192 -0
- package/src/translations.ts +14 -14
- package/src/types/ExplorerAction.ts +1 -1
- package/src/types/Graph.ts +2 -3
- package/src/typings.d.ts +8 -0
- package/src/util/index.ts +6 -0
- package/src/util/node-color.ts +23 -0
- package/src/{components → util}/plot.ts +16 -4
- package/dist/lib/browser/ExplorerContainer-H5RGY6AD.mjs +0 -48
- package/dist/lib/browser/ExplorerContainer-H5RGY6AD.mjs.map +0 -7
- package/dist/lib/browser/chunk-56VV76WZ.mjs.map +0 -7
- package/dist/lib/browser/chunk-6KEHUEEZ.mjs.map +0 -7
- package/dist/lib/browser/chunk-LSUP47BZ.mjs.map +0 -7
- package/dist/lib/browser/index.mjs +0 -107
- package/dist/lib/browser/index.mjs.map +0 -7
- package/dist/lib/browser/meta.json +0 -1
- package/dist/lib/browser/react-surface-JYGFP5ZN.mjs +0 -38
- package/dist/lib/browser/react-surface-JYGFP5ZN.mjs.map +0 -7
- package/dist/lib/node-esm/ExplorerContainer-KFHE5KU3.mjs +0 -49
- package/dist/lib/node-esm/ExplorerContainer-KFHE5KU3.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-35JCF4SD.mjs +0 -11292
- package/dist/lib/node-esm/chunk-35JCF4SD.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-EN3JZNEY.mjs +0 -26
- package/dist/lib/node-esm/chunk-EN3JZNEY.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +0 -11
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-WSE2Z4OT.mjs +0 -72
- package/dist/lib/node-esm/chunk-WSE2Z4OT.mjs.map +0 -7
- package/dist/lib/node-esm/index.mjs +0 -108
- package/dist/lib/node-esm/index.mjs.map +0 -7
- package/dist/lib/node-esm/meta.json +0 -1
- package/dist/lib/node-esm/meta.mjs +0 -9
- package/dist/lib/node-esm/react-surface-HJEJL53N.mjs +0 -39
- package/dist/lib/node-esm/react-surface-HJEJL53N.mjs.map +0 -7
- package/dist/lib/node-esm/types/index.mjs +0 -11
- package/dist/types/src/capabilities/react-surface/index.d.ts +0 -3
- package/dist/types/src/capabilities/react-surface/index.d.ts.map +0 -1
- package/dist/types/src/capabilities/react-surface/react-surface.d.ts.map +0 -1
- package/dist/types/src/components/Graph/D3ForceGraph.d.ts +0 -19
- package/dist/types/src/components/Graph/D3ForceGraph.d.ts.map +0 -1
- package/dist/types/src/components/Graph/D3ForceGraph.stories.d.ts.map +0 -1
- package/dist/types/src/components/Graph/adapter.d.ts.map +0 -1
- package/dist/types/src/components/Graph/testing.d.ts +0 -14
- package/dist/types/src/components/Graph/testing.d.ts.map +0 -1
- package/dist/types/src/components/Tree/testing/generator.d.ts.map +0 -1
- package/dist/types/src/components/Tree/testing/index.d.ts +0 -2
- package/dist/types/src/components/Tree/testing/index.d.ts.map +0 -1
- package/dist/types/src/components/plot.d.ts.map +0 -1
- package/dist/types/src/containers/ExplorerContainer/ExplorerContainer.d.ts +0 -6
- package/dist/types/src/containers/ExplorerContainer/ExplorerContainer.d.ts.map +0 -1
- package/dist/types/src/containers/ExplorerContainer/index.d.ts +0 -3
- package/dist/types/src/containers/ExplorerContainer/index.d.ts.map +0 -1
- package/src/capabilities/react-surface/index.ts +0 -7
- package/src/capabilities/react-surface/react-surface.tsx +0 -31
- package/src/components/Graph/D3ForceGraph.stories.tsx +0 -83
- package/src/components/Graph/D3ForceGraph.tsx +0 -109
- package/src/components/Graph/testing.ts +0 -58
- package/src/components/Tree/layout/HierarchicalEdgeBundling.ts +0 -162
- package/src/components/Tree/layout/RadialTree.ts +0 -94
- package/src/components/Tree/layout/TidyTree.ts +0 -101
- package/src/components/Tree/testing/index.ts +0 -5
- package/src/containers/ExplorerContainer/ExplorerContainer.tsx +0 -53
- package/src/containers/ExplorerContainer/index.ts +0 -7
- /package/dist/lib/{browser/chunk-J5LGTIGS.mjs.map → neutral/ExplorerPlugin.mjs.map} +0 -0
- /package/dist/lib/{browser → neutral}/chunk-J5LGTIGS.mjs +0 -0
- /package/dist/lib/{browser/meta.mjs.map → neutral/chunk-J5LGTIGS.mjs.map} +0 -0
- /package/dist/lib/{browser/types → neutral}/index.mjs.map +0 -0
- /package/dist/lib/{node-esm → neutral}/meta.mjs.map +0 -0
- /package/dist/lib/{node-esm → neutral}/types/index.mjs.map +0 -0
- /package/dist/types/src/capabilities/{react-surface/react-surface.d.ts → react-surface.d.ts} +0 -0
- /package/src/components/Graph/{adapter.ts → graph-adapter.ts} +0 -0
|
@@ -1,9 +1,17 @@
|
|
|
1
|
+
import {
|
|
2
|
+
treeTypeToTreeNode
|
|
3
|
+
} from "../chunk-EM2BV4PF.mjs";
|
|
4
|
+
import {
|
|
5
|
+
getNodeFillForObject
|
|
6
|
+
} from "../chunk-V2OFO6PI.mjs";
|
|
7
|
+
import "../chunk-J5LGTIGS.mjs";
|
|
8
|
+
|
|
1
9
|
// src/components/Chart/Chart.tsx
|
|
2
10
|
import * as Plot from "@observablehq/plot";
|
|
3
11
|
import React, { useEffect } from "react";
|
|
4
12
|
import { useResizeDetector } from "react-resize-detector";
|
|
5
13
|
|
|
6
|
-
// src/
|
|
14
|
+
// src/util/plot.ts
|
|
7
15
|
var createAdapter = (prop, accessor) => accessor ? {
|
|
8
16
|
transform: (values) => values.map((value) => accessor(value)[prop])
|
|
9
17
|
} : prop;
|
|
@@ -10820,45 +10828,158 @@ var Globe = ({ items = [], accessor, projection = "orthographic", options = defa
|
|
|
10820
10828
|
});
|
|
10821
10829
|
};
|
|
10822
10830
|
|
|
10823
|
-
// src/components/Graph/
|
|
10831
|
+
// src/components/Graph/CanvasForceGraph.tsx
|
|
10832
|
+
import { forceLink, forceManyBody } from "d3";
|
|
10833
|
+
import NativeForceGraph from "force-graph";
|
|
10834
|
+
import React3, { useCallback, useEffect as useEffect3, useRef, useState } from "react";
|
|
10835
|
+
import { useResizeDetector as useResizeDetector3 } from "react-resize-detector";
|
|
10836
|
+
import { composable, composableProps } from "@dxos/ui-theme";
|
|
10837
|
+
|
|
10838
|
+
// src/components/Graph/graph-adapter.ts
|
|
10839
|
+
var GraphAdapter = class {
|
|
10840
|
+
graph;
|
|
10841
|
+
_nodes = [];
|
|
10842
|
+
_links = [];
|
|
10843
|
+
constructor(graph) {
|
|
10844
|
+
this.graph = graph;
|
|
10845
|
+
this._nodes = graph.nodes.map((node) => ({
|
|
10846
|
+
id: node.id,
|
|
10847
|
+
type: node.type,
|
|
10848
|
+
data: node.data
|
|
10849
|
+
}));
|
|
10850
|
+
const nodeIds = new Set(this._nodes.map((node) => node.id));
|
|
10851
|
+
this._links = graph.edges.filter((edge) => nodeIds.has(edge.source) && nodeIds.has(edge.target)).map((edge) => ({
|
|
10852
|
+
type: edge.type,
|
|
10853
|
+
source: edge.source,
|
|
10854
|
+
target: edge.target,
|
|
10855
|
+
data: edge.data
|
|
10856
|
+
}));
|
|
10857
|
+
}
|
|
10858
|
+
get nodes() {
|
|
10859
|
+
return this._nodes;
|
|
10860
|
+
}
|
|
10861
|
+
get links() {
|
|
10862
|
+
return this._links;
|
|
10863
|
+
}
|
|
10864
|
+
};
|
|
10865
|
+
|
|
10866
|
+
// src/components/Graph/CanvasForceGraph.tsx
|
|
10867
|
+
var CanvasForceGraph = composable(({ model, match, onClick, ...props }, forwardedRef) => {
|
|
10868
|
+
const { ref: resizeRef, width, height } = useResizeDetector3({
|
|
10869
|
+
refreshRate: 200
|
|
10870
|
+
});
|
|
10871
|
+
const setRef = useCallback((node) => {
|
|
10872
|
+
resizeRef(node);
|
|
10873
|
+
assignRef(forwardedRef, node);
|
|
10874
|
+
}, [
|
|
10875
|
+
resizeRef,
|
|
10876
|
+
forwardedRef
|
|
10877
|
+
]);
|
|
10878
|
+
const rootRef = useRef(null);
|
|
10879
|
+
const forceGraph = useRef(null);
|
|
10880
|
+
const [data, setData] = useState();
|
|
10881
|
+
useEffect3(() => {
|
|
10882
|
+
return model?.subscribe((model2) => setData(new GraphAdapter(model2.graph)));
|
|
10883
|
+
}, [
|
|
10884
|
+
model
|
|
10885
|
+
]);
|
|
10886
|
+
useEffect3(() => {
|
|
10887
|
+
if (rootRef.current) {
|
|
10888
|
+
forceGraph.current = new NativeForceGraph(rootRef.current).nodeRelSize(6).nodeLabel((node) => node.type === "schema" ? node.data.typename : node.data.label ?? node.id).nodeAutoColorBy((node) => node.type === "schema" ? "schema" : node.data.typename).linkAutoColorBy((link) => link.type);
|
|
10889
|
+
}
|
|
10890
|
+
return () => {
|
|
10891
|
+
forceGraph.current?.pauseAnimation().graphData({
|
|
10892
|
+
nodes: [],
|
|
10893
|
+
links: []
|
|
10894
|
+
});
|
|
10895
|
+
forceGraph.current = null;
|
|
10896
|
+
};
|
|
10897
|
+
}, []);
|
|
10898
|
+
useEffect3(() => {
|
|
10899
|
+
if (!data || !width || !height || !forceGraph.current) {
|
|
10900
|
+
return;
|
|
10901
|
+
}
|
|
10902
|
+
forceGraph.current.pauseAnimation().width(width).height(height).onEngineStop(() => handleZoomToFit()).onNodeClick((node) => {
|
|
10903
|
+
forceGraph.current?.emitParticle(node);
|
|
10904
|
+
}).d3Force("link", forceLink().distance(160).strength(0.5)).d3Force("charge", forceManyBody().strength(-30)).graphData(data).warmupTicks(100).cooldownTime(1e3).resumeAnimation();
|
|
10905
|
+
}, [
|
|
10906
|
+
data,
|
|
10907
|
+
width,
|
|
10908
|
+
height
|
|
10909
|
+
]);
|
|
10910
|
+
const handleZoomToFit = () => {
|
|
10911
|
+
forceGraph.current?.zoomToFit(400, 40);
|
|
10912
|
+
};
|
|
10913
|
+
const handleClick = useCallback((event) => {
|
|
10914
|
+
onClick?.(event);
|
|
10915
|
+
if (!event.defaultPrevented) {
|
|
10916
|
+
handleZoomToFit();
|
|
10917
|
+
}
|
|
10918
|
+
}, [
|
|
10919
|
+
onClick
|
|
10920
|
+
]);
|
|
10921
|
+
return /* @__PURE__ */ React3.createElement("div", {
|
|
10922
|
+
...composableProps(props, {
|
|
10923
|
+
classNames: "relative grow"
|
|
10924
|
+
}),
|
|
10925
|
+
onClick: handleClick,
|
|
10926
|
+
ref: setRef
|
|
10927
|
+
}, /* @__PURE__ */ React3.createElement("div", {
|
|
10928
|
+
ref: rootRef,
|
|
10929
|
+
className: "absolute inset-0"
|
|
10930
|
+
}));
|
|
10931
|
+
});
|
|
10932
|
+
var assignRef = (ref, value) => {
|
|
10933
|
+
if (typeof ref === "function") {
|
|
10934
|
+
ref(value);
|
|
10935
|
+
} else if (ref) {
|
|
10936
|
+
ref.current = value;
|
|
10937
|
+
}
|
|
10938
|
+
};
|
|
10939
|
+
|
|
10940
|
+
// src/components/Graph/ForceGraph.tsx
|
|
10824
10941
|
import { Atom, useAtomValue } from "@effect-atom/atom-react";
|
|
10825
|
-
import
|
|
10942
|
+
import React4, { useCallback as useCallback2, useEffect as useEffect4, useMemo, useRef as useRef2, useState as useState2 } from "react";
|
|
10826
10943
|
import { Obj } from "@dxos/echo";
|
|
10827
10944
|
import { SelectionModel } from "@dxos/graph";
|
|
10828
10945
|
import { GraphForceProjector, SVG } from "@dxos/react-ui-graph";
|
|
10829
|
-
import { composable, composableProps, getHashStyles } from "@dxos/ui-theme";
|
|
10946
|
+
import { composable as composable2, composableProps as composableProps2, getHashStyles } from "@dxos/ui-theme";
|
|
10830
10947
|
import "@dxos/react-ui-graph/styles/graph.css";
|
|
10831
10948
|
var EMPTY_ATOM = Atom.make({
|
|
10832
10949
|
nodes: [],
|
|
10833
10950
|
edges: []
|
|
10834
10951
|
});
|
|
10835
|
-
var
|
|
10952
|
+
var ForceGraph = composable2(({ model, selection: selectionProp, grid, drag, onInspect, ...props }, forwardedRef) => {
|
|
10836
10953
|
useAtomValue(model?.graphAtom ?? EMPTY_ATOM);
|
|
10837
|
-
const
|
|
10838
|
-
const
|
|
10954
|
+
const graph = useRef2(null);
|
|
10955
|
+
const selection = useMemo(() => selectionProp ?? new SelectionModel(), [
|
|
10956
|
+
selectionProp
|
|
10957
|
+
]);
|
|
10958
|
+
useEffect4(() => {
|
|
10959
|
+
const unsubscribe = selection.subscribe(() => graph.current?.repaint());
|
|
10960
|
+
return unsubscribe;
|
|
10961
|
+
}, [
|
|
10962
|
+
selection
|
|
10963
|
+
]);
|
|
10964
|
+
const svgRef = useRef2(null);
|
|
10965
|
+
const [projector, setProjector] = useState2();
|
|
10966
|
+
useEffect4(() => {
|
|
10839
10967
|
if (svgRef.current) {
|
|
10840
|
-
|
|
10968
|
+
setProjector(new GraphForceProjector(svgRef.current, {
|
|
10841
10969
|
attributes: {
|
|
10842
|
-
|
|
10843
|
-
|
|
10844
|
-
|
|
10970
|
+
// TODO(burdon): Check type (currently assumes Employee property).
|
|
10971
|
+
// Edge shouldn't contribute to force if it's not active.
|
|
10972
|
+
linkForce: (edge) => edge.data?.object?.active !== false
|
|
10845
10973
|
},
|
|
10846
10974
|
forces: {
|
|
10847
10975
|
point: {
|
|
10848
10976
|
strength: 0.01
|
|
10849
10977
|
}
|
|
10850
10978
|
}
|
|
10851
|
-
});
|
|
10979
|
+
}));
|
|
10852
10980
|
}
|
|
10853
10981
|
}, []);
|
|
10854
|
-
const
|
|
10855
|
-
const selection = useMemo(() => _selection ?? new SelectionModel(), [
|
|
10856
|
-
_selection
|
|
10857
|
-
]);
|
|
10858
|
-
useEffect3(() => selection.subscribe(() => graph.current?.repaint()), [
|
|
10859
|
-
selection
|
|
10860
|
-
]);
|
|
10861
|
-
const handleSelect = useCallback((node) => {
|
|
10982
|
+
const handleSelect = useCallback2((node) => {
|
|
10862
10983
|
if (selection.contains(node.id)) {
|
|
10863
10984
|
selection.remove(node.id);
|
|
10864
10985
|
} else {
|
|
@@ -10867,30 +10988,27 @@ var D3ForceGraph = composable(({ model, selection: _selection, grid, drag, ...pr
|
|
|
10867
10988
|
}, [
|
|
10868
10989
|
selection
|
|
10869
10990
|
]);
|
|
10870
|
-
return /* @__PURE__ */
|
|
10871
|
-
...
|
|
10872
|
-
role: "none",
|
|
10991
|
+
return /* @__PURE__ */ React4.createElement("div", {
|
|
10992
|
+
...composableProps2(props, {
|
|
10873
10993
|
classNames: "dx-container"
|
|
10874
10994
|
}),
|
|
10875
10995
|
ref: forwardedRef
|
|
10876
|
-
}, /* @__PURE__ */
|
|
10996
|
+
}, /* @__PURE__ */ React4.createElement(SVG.Root, {
|
|
10877
10997
|
ref: svgRef
|
|
10878
|
-
}, /* @__PURE__ */
|
|
10998
|
+
}, /* @__PURE__ */ React4.createElement(SVG.Markers, null), grid && /* @__PURE__ */ React4.createElement(SVG.Grid, {
|
|
10879
10999
|
axis: true
|
|
10880
|
-
}), /* @__PURE__ */
|
|
11000
|
+
}), /* @__PURE__ */ React4.createElement(SVG.Zoom, {
|
|
10881
11001
|
extent: [
|
|
10882
11002
|
1 / 2,
|
|
10883
11003
|
2
|
|
10884
11004
|
]
|
|
10885
|
-
}, /* @__PURE__ */
|
|
10886
|
-
drag,
|
|
11005
|
+
}, /* @__PURE__ */ React4.createElement(SVG.Graph, {
|
|
10887
11006
|
ref: graph,
|
|
11007
|
+
drag,
|
|
10888
11008
|
model,
|
|
10889
11009
|
projector,
|
|
10890
11010
|
labels: {
|
|
10891
|
-
text: (node) =>
|
|
10892
|
-
return node.data?.data.label ?? node.id;
|
|
10893
|
-
}
|
|
11011
|
+
text: (node) => node.data?.data.label ?? node.id
|
|
10894
11012
|
},
|
|
10895
11013
|
attributes: {
|
|
10896
11014
|
node: (node) => {
|
|
@@ -10905,217 +11023,515 @@ var D3ForceGraph = composable(({ model, selection: _selection, grid, drag, ...pr
|
|
|
10905
11023
|
};
|
|
10906
11024
|
}
|
|
10907
11025
|
},
|
|
10908
|
-
onSelect: handleSelect
|
|
11026
|
+
onSelect: handleSelect,
|
|
11027
|
+
onInspect
|
|
10909
11028
|
}))));
|
|
10910
11029
|
});
|
|
10911
11030
|
|
|
10912
|
-
// src/components/
|
|
10913
|
-
import {
|
|
10914
|
-
import
|
|
10915
|
-
import
|
|
10916
|
-
import { useResizeDetector as useResizeDetector3 } from "react-resize-detector";
|
|
10917
|
-
import { filterObjectsSync } from "@dxos/plugin-search";
|
|
11031
|
+
// src/components/Lattice/Lattice.tsx
|
|
11032
|
+
import { select } from "d3";
|
|
11033
|
+
import React5, { useEffect as useEffect6, useMemo as useMemo2, useRef as useRef3 } from "react";
|
|
11034
|
+
import { Obj as Obj2 } from "@dxos/echo";
|
|
10918
11035
|
|
|
10919
|
-
// src/components/
|
|
10920
|
-
|
|
10921
|
-
|
|
10922
|
-
|
|
10923
|
-
|
|
10924
|
-
|
|
10925
|
-
|
|
10926
|
-
this._nodes = graph.nodes.map((node) => ({
|
|
10927
|
-
id: node.id,
|
|
10928
|
-
type: node.type,
|
|
10929
|
-
data: node.data
|
|
10930
|
-
}));
|
|
10931
|
-
const nodeIds = new Set(this._nodes.map((node) => node.id));
|
|
10932
|
-
this._links = graph.edges.filter((edge) => nodeIds.has(edge.source) && nodeIds.has(edge.target)).map((edge) => ({
|
|
10933
|
-
type: edge.type,
|
|
10934
|
-
source: edge.source,
|
|
10935
|
-
target: edge.target,
|
|
10936
|
-
data: edge.data
|
|
10937
|
-
}));
|
|
10938
|
-
}
|
|
10939
|
-
get nodes() {
|
|
10940
|
-
return this._nodes;
|
|
10941
|
-
}
|
|
10942
|
-
get links() {
|
|
10943
|
-
return this._links;
|
|
10944
|
-
}
|
|
10945
|
-
};
|
|
10946
|
-
|
|
10947
|
-
// src/components/Graph/ForceGraph.tsx
|
|
10948
|
-
var ForceGraph = ({ model, match }) => {
|
|
10949
|
-
const { ref, width, height } = useResizeDetector3({
|
|
10950
|
-
refreshRate: 200
|
|
11036
|
+
// src/components/Tree/layout/useContainerSize.ts
|
|
11037
|
+
import { useEffect as useEffect5, useState as useState3 } from "react";
|
|
11038
|
+
var useContainerSize = () => {
|
|
11039
|
+
const [el, setEl] = useState3(null);
|
|
11040
|
+
const [size, setSize] = useState3({
|
|
11041
|
+
width: 0,
|
|
11042
|
+
height: 0
|
|
10951
11043
|
});
|
|
10952
|
-
|
|
10953
|
-
|
|
10954
|
-
|
|
10955
|
-
|
|
10956
|
-
|
|
10957
|
-
|
|
10958
|
-
|
|
10959
|
-
|
|
11044
|
+
useEffect5(() => {
|
|
11045
|
+
if (!el) {
|
|
11046
|
+
return;
|
|
11047
|
+
}
|
|
11048
|
+
const rect = el.getBoundingClientRect();
|
|
11049
|
+
setSize({
|
|
11050
|
+
width: rect.width,
|
|
11051
|
+
height: rect.height
|
|
10960
11052
|
});
|
|
11053
|
+
const observer = new ResizeObserver((entries) => {
|
|
11054
|
+
const entry = entries[0];
|
|
11055
|
+
if (!entry) {
|
|
11056
|
+
return;
|
|
11057
|
+
}
|
|
11058
|
+
const { width, height } = entry.contentRect;
|
|
11059
|
+
setSize((prev) => prev.width === width && prev.height === height ? prev : {
|
|
11060
|
+
width,
|
|
11061
|
+
height
|
|
11062
|
+
});
|
|
11063
|
+
});
|
|
11064
|
+
observer.observe(el);
|
|
11065
|
+
return () => observer.disconnect();
|
|
10961
11066
|
}, [
|
|
10962
|
-
|
|
11067
|
+
el
|
|
10963
11068
|
]);
|
|
10964
|
-
|
|
10965
|
-
|
|
10966
|
-
|
|
11069
|
+
return {
|
|
11070
|
+
setRef: setEl,
|
|
11071
|
+
width: size.width,
|
|
11072
|
+
height: size.height
|
|
11073
|
+
};
|
|
11074
|
+
};
|
|
11075
|
+
|
|
11076
|
+
// src/components/Lattice/Lattice.tsx
|
|
11077
|
+
var TRANSITION_MS = 350;
|
|
11078
|
+
var Lattice = ({ nodes, padding = 16, onNodeHover }) => {
|
|
11079
|
+
const svgRef = useRef3(null);
|
|
11080
|
+
const { setRef, width, height } = useContainerSize();
|
|
11081
|
+
const cells = useMemo2(() => {
|
|
11082
|
+
return nodes.map((node) => {
|
|
11083
|
+
const object = node.data?.object;
|
|
11084
|
+
if (!object) {
|
|
11085
|
+
return void 0;
|
|
11086
|
+
}
|
|
11087
|
+
const label = node.data?.label ?? Obj2.getLabel(object) ?? node.id;
|
|
11088
|
+
const typename = Obj2.getTypename(object) ?? "(untyped)";
|
|
11089
|
+
return {
|
|
11090
|
+
id: node.id,
|
|
11091
|
+
label,
|
|
11092
|
+
typename,
|
|
11093
|
+
object
|
|
11094
|
+
};
|
|
11095
|
+
}).filter((cell) => cell !== void 0).sort((a, b) => a.typename.localeCompare(b.typename) || a.label.localeCompare(b.label));
|
|
11096
|
+
}, [
|
|
11097
|
+
nodes
|
|
11098
|
+
]);
|
|
11099
|
+
const handleHoverRef = useRef3(void 0);
|
|
11100
|
+
handleHoverRef.current = onNodeHover;
|
|
11101
|
+
useEffect6(() => {
|
|
11102
|
+
if (!svgRef.current || !width || !height) {
|
|
11103
|
+
return;
|
|
10967
11104
|
}
|
|
11105
|
+
renderLattice(svgRef.current, cells, {
|
|
11106
|
+
width,
|
|
11107
|
+
height,
|
|
11108
|
+
padding,
|
|
11109
|
+
onNodeHover: (n, e) => handleHoverRef.current?.(n, e)
|
|
11110
|
+
});
|
|
10968
11111
|
return () => {
|
|
10969
|
-
|
|
10970
|
-
nodes: [],
|
|
10971
|
-
links: []
|
|
10972
|
-
});
|
|
10973
|
-
forceGraph.current = null;
|
|
11112
|
+
handleHoverRef.current?.(null);
|
|
10974
11113
|
};
|
|
10975
|
-
}, []);
|
|
10976
|
-
useEffect4(() => {
|
|
10977
|
-
if (!data || !width || !height || !forceGraph.current) {
|
|
10978
|
-
return;
|
|
10979
|
-
}
|
|
10980
|
-
forceGraph.current.pauseAnimation().width(width).height(height).onEngineStop(() => {
|
|
10981
|
-
handleZoomToFit();
|
|
10982
|
-
}).onNodeClick((node) => {
|
|
10983
|
-
forceGraph.current?.emitParticle(node);
|
|
10984
|
-
}).d3Force("link", forceLink().distance(160).strength(0.5)).d3Force("charge", forceManyBody().strength(-30)).graphData(data).warmupTicks(100).cooldownTime(1e3).resumeAnimation();
|
|
10985
11114
|
}, [
|
|
10986
|
-
|
|
11115
|
+
cells,
|
|
10987
11116
|
width,
|
|
10988
11117
|
height,
|
|
10989
|
-
|
|
11118
|
+
padding
|
|
10990
11119
|
]);
|
|
10991
|
-
|
|
10992
|
-
|
|
10993
|
-
|
|
10994
|
-
|
|
10995
|
-
ref,
|
|
10996
|
-
|
|
10997
|
-
|
|
10998
|
-
|
|
10999
|
-
|
|
11000
|
-
className: "absolute inset-0"
|
|
11120
|
+
return /* @__PURE__ */ React5.createElement("div", {
|
|
11121
|
+
ref: setRef,
|
|
11122
|
+
className: "dx-expander relative"
|
|
11123
|
+
}, width > 0 && height > 0 && /* @__PURE__ */ React5.createElement("svg", {
|
|
11124
|
+
ref: svgRef,
|
|
11125
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
11126
|
+
width,
|
|
11127
|
+
height,
|
|
11128
|
+
viewBox: `0 0 ${width} ${height}`
|
|
11001
11129
|
}));
|
|
11002
11130
|
};
|
|
11131
|
+
var renderLattice = (svgElement, cells, options) => {
|
|
11132
|
+
const { width, height, padding, onNodeHover } = options;
|
|
11133
|
+
const svg = select(svgElement);
|
|
11134
|
+
if (!cells.length) {
|
|
11135
|
+
onNodeHover(null);
|
|
11136
|
+
svg.selectAll("g.dx-lattice-root").remove();
|
|
11137
|
+
return;
|
|
11138
|
+
}
|
|
11139
|
+
const count = cells.length;
|
|
11140
|
+
const columns = Math.max(1, Math.ceil(Math.sqrt(count)));
|
|
11141
|
+
const rows = Math.ceil(count / columns);
|
|
11142
|
+
const innerW = Math.max(0, width - 2 * padding);
|
|
11143
|
+
const innerH = Math.max(0, height - 2 * padding);
|
|
11144
|
+
const cellSize = Math.max(0, Math.min(innerW / columns, innerH / rows));
|
|
11145
|
+
const gutter = Math.max(2, cellSize * 0.12);
|
|
11146
|
+
const rectSize = Math.max(0, cellSize - gutter);
|
|
11147
|
+
const radius = Math.max(2, rectSize * 0.18);
|
|
11148
|
+
const gridW = cellSize * columns;
|
|
11149
|
+
const gridH = cellSize * rows;
|
|
11150
|
+
const offsetX = (width - gridW) / 2;
|
|
11151
|
+
const offsetY = (height - gridH) / 2;
|
|
11152
|
+
const g = svg.selectAll("g.dx-lattice-root").data([
|
|
11153
|
+
null
|
|
11154
|
+
]).join("g").classed("dx-lattice-root", true);
|
|
11155
|
+
const positioned = cells.map((cell, i) => ({
|
|
11156
|
+
...cell,
|
|
11157
|
+
x: offsetX + i % columns * cellSize + gutter / 2,
|
|
11158
|
+
y: offsetY + Math.floor(i / columns) * cellSize + gutter / 2
|
|
11159
|
+
}));
|
|
11160
|
+
const node = g.selectAll("g.dx-lattice-cell").data(positioned, (d) => d.id).join((enter) => {
|
|
11161
|
+
const ge = enter.append("g").classed("dx-lattice-cell", true).attr("opacity", 0);
|
|
11162
|
+
ge.append("rect").style("cursor", "pointer");
|
|
11163
|
+
return ge;
|
|
11164
|
+
}, (update) => update, (exit) => exit.each(function() {
|
|
11165
|
+
select(this).interrupt();
|
|
11166
|
+
}).transition().duration(TRANSITION_MS).attr("opacity", 0).remove());
|
|
11167
|
+
node.transition().duration(TRANSITION_MS).attr("opacity", 1).attr("transform", (d) => `translate(${d.x},${d.y})`);
|
|
11168
|
+
node.select("rect").attr("width", rectSize).attr("height", rectSize).attr("rx", radius).attr("ry", radius).style("fill", (d) => getNodeFillForObject(d.object)).on("pointerenter", (event, d) => onNodeHover({
|
|
11169
|
+
id: d.id,
|
|
11170
|
+
label: d.label,
|
|
11171
|
+
data: d.object
|
|
11172
|
+
}, event)).on("pointerleave", () => onNodeHover(null));
|
|
11173
|
+
};
|
|
11003
11174
|
|
|
11004
11175
|
// src/components/Tree/Tree.tsx
|
|
11005
|
-
import {
|
|
11006
|
-
import React5, { useContext, useEffect as useEffect5, useRef as useRef3, useState as useState2 } from "react";
|
|
11007
|
-
import { useAsyncState } from "@dxos/react-ui";
|
|
11008
|
-
import { SVG as SVG2 } from "@dxos/react-ui-graph";
|
|
11009
|
-
import { SpaceGraphModel } from "@dxos/schema";
|
|
11176
|
+
import React9, { useMemo as useMemo6 } from "react";
|
|
11010
11177
|
|
|
11011
|
-
// src/components/Tree/layout/HierarchicalEdgeBundling.
|
|
11012
|
-
import { cluster, curveBundle, hierarchy, lineRadial, select } from "d3";
|
|
11013
|
-
|
|
11014
|
-
|
|
11015
|
-
|
|
11016
|
-
|
|
11017
|
-
|
|
11018
|
-
|
|
11019
|
-
|
|
11020
|
-
|
|
11178
|
+
// src/components/Tree/layout/HierarchicalEdgeBundling.tsx
|
|
11179
|
+
import { cluster, curveBundle, hierarchy, lineRadial, select as select2 } from "d3";
|
|
11180
|
+
import React6, { useEffect as useEffect7, useMemo as useMemo3, useRef as useRef4 } from "react";
|
|
11181
|
+
import { mx } from "@dxos/ui-theme";
|
|
11182
|
+
|
|
11183
|
+
// src/components/Tree/layout/slots.ts
|
|
11184
|
+
var defaultTreeLayoutSlots = {
|
|
11185
|
+
// Cursor + transition so the hover swap reads clearly; SVG circles support the `:hover` pseudo-class
|
|
11186
|
+
// via Tailwind variants exactly like HTML elements.
|
|
11187
|
+
node: "fill-blue-600 hover:fill-orange-500 cursor-pointer transition-colors",
|
|
11188
|
+
// 0.5px is fine on a white background, but on a dark Storybook background the lines disappear.
|
|
11189
|
+
// Use stroke-1 with opacity 50% so they read in both themes; dx-bundle-dim/out/in further tune on hover.
|
|
11190
|
+
path: "fill-none stroke-blue-500/50 stroke-[1px] dark:stroke-blue-400/60",
|
|
11191
|
+
text: "fill-neutral-700 dark:fill-neutral-300 text-xs hover:fill-orange-500 cursor-pointer transition-colors"
|
|
11192
|
+
};
|
|
11193
|
+
|
|
11194
|
+
// src/components/Tree/layout/HierarchicalEdgeBundling.tsx
|
|
11195
|
+
var TRANSITION_MS2 = 350;
|
|
11196
|
+
var HierarchicalEdgeBundling = ({ classNames, data, edges = [], label = (d) => d.label ?? d.id, padding = 120, tension = 0.85, r = 4, slots = defaultTreeLayoutSlots, onNodeHover }) => {
|
|
11197
|
+
const svgRef = useRef4(null);
|
|
11198
|
+
const { setRef, width, height } = useContainerSize();
|
|
11199
|
+
const root = useMemo3(() => buildBundleHierarchy(data, edges), [
|
|
11200
|
+
data,
|
|
11201
|
+
edges
|
|
11021
11202
|
]);
|
|
11022
|
-
const
|
|
11023
|
-
const node = svg.append("g").selectAll().data(layout.leaves()).join("g").attr("transform", (d) => `rotate(${d.x * (180 / Math.PI) - 90}) translate(${d.y},0)`).append("text").attr("class", slots?.text ?? "").attr("dy", "0.31em").attr("x", (d) => d.x < Math.PI ? 6 : -6).attr("text-anchor", (d) => d.x < Math.PI ? "start" : "end").attr("transform", (d) => d.x >= Math.PI ? "rotate(180)" : null).call((text) => text.text((d) => d.data.id.slice(0, 8)));
|
|
11024
|
-
const line = lineRadial().curve(curveBundle.beta(0.85)).radius((d) => d.y).angle((d) => d.x);
|
|
11025
|
-
const links = svg.append("g").selectAll().data(layout.leaves().flatMap((leaf) => leaf.outgoing)).join("path").style("mix-blend-mode", "multiply").attr("class", slots?.path ?? "").attr("d", ([i, o]) => {
|
|
11026
|
-
return line(i.path(o));
|
|
11027
|
-
}).each(function(d) {
|
|
11028
|
-
d.path = this;
|
|
11203
|
+
const handleHoverRef = useRef4(() => {
|
|
11029
11204
|
});
|
|
11030
|
-
|
|
11031
|
-
|
|
11032
|
-
|
|
11033
|
-
|
|
11034
|
-
d
|
|
11035
|
-
]));
|
|
11036
|
-
const parents = root.descendants().reduce((map, d) => {
|
|
11037
|
-
if (d.children?.length) {
|
|
11038
|
-
map.set(d.data.id, d);
|
|
11205
|
+
handleHoverRef.current = (node, event) => onNodeHover?.(node, event);
|
|
11206
|
+
useEffect7(() => {
|
|
11207
|
+
if (!svgRef.current || !width || !height) {
|
|
11208
|
+
return;
|
|
11039
11209
|
}
|
|
11040
|
-
|
|
11041
|
-
|
|
11042
|
-
|
|
11043
|
-
|
|
11044
|
-
|
|
11045
|
-
|
|
11046
|
-
|
|
11047
|
-
|
|
11048
|
-
|
|
11049
|
-
|
|
11050
|
-
|
|
11051
|
-
|
|
11052
|
-
|
|
11210
|
+
const radius = Math.max(0, Math.min(width, height) / 2 - padding);
|
|
11211
|
+
renderBundling(svgRef.current, root, {
|
|
11212
|
+
radius,
|
|
11213
|
+
r,
|
|
11214
|
+
label,
|
|
11215
|
+
slots,
|
|
11216
|
+
tension,
|
|
11217
|
+
onNodeHover: (n, e) => handleHoverRef.current(n, e)
|
|
11218
|
+
});
|
|
11219
|
+
}, [
|
|
11220
|
+
root,
|
|
11221
|
+
width,
|
|
11222
|
+
height,
|
|
11223
|
+
padding,
|
|
11224
|
+
tension,
|
|
11225
|
+
r,
|
|
11226
|
+
label,
|
|
11227
|
+
slots
|
|
11228
|
+
]);
|
|
11229
|
+
return /* @__PURE__ */ React6.createElement("div", {
|
|
11230
|
+
ref: setRef,
|
|
11231
|
+
className: mx("dx-expander relative", classNames)
|
|
11232
|
+
}, width > 0 && height > 0 && /* @__PURE__ */ React6.createElement("svg", {
|
|
11233
|
+
ref: svgRef,
|
|
11234
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
11235
|
+
width,
|
|
11236
|
+
height,
|
|
11237
|
+
viewBox: `${-width / 2} ${-height / 2} ${width} ${height}`
|
|
11238
|
+
}));
|
|
11239
|
+
};
|
|
11240
|
+
var buildBundleHierarchy = (data, edges) => {
|
|
11241
|
+
const root = hierarchy(data);
|
|
11242
|
+
const byId = /* @__PURE__ */ new Map();
|
|
11243
|
+
for (const node of root.descendants()) {
|
|
11244
|
+
byId.set(node.data.id, node);
|
|
11245
|
+
node.outgoing = [];
|
|
11246
|
+
node.incoming = [];
|
|
11247
|
+
}
|
|
11248
|
+
for (const edge of edges) {
|
|
11249
|
+
const source = byId.get(edge.source);
|
|
11250
|
+
const target = byId.get(edge.target);
|
|
11251
|
+
if (!source || !target || source === target) {
|
|
11252
|
+
continue;
|
|
11053
11253
|
}
|
|
11254
|
+
source.outgoing.push([
|
|
11255
|
+
source,
|
|
11256
|
+
target,
|
|
11257
|
+
edge
|
|
11258
|
+
]);
|
|
11259
|
+
target.incoming.push([
|
|
11260
|
+
source,
|
|
11261
|
+
target,
|
|
11262
|
+
edge
|
|
11263
|
+
]);
|
|
11054
11264
|
}
|
|
11055
11265
|
return root;
|
|
11056
11266
|
};
|
|
11057
|
-
var
|
|
11058
|
-
const
|
|
11059
|
-
|
|
11267
|
+
var renderBundling = (svgElement, root, options) => {
|
|
11268
|
+
const { radius, r, tension, label, slots, onNodeHover } = options;
|
|
11269
|
+
const svg = select2(svgElement);
|
|
11270
|
+
if (!root.children?.length) {
|
|
11271
|
+
svg.selectAll("g.dx-bundle-root").remove();
|
|
11272
|
+
return;
|
|
11273
|
+
}
|
|
11274
|
+
cluster().size([
|
|
11275
|
+
2 * Math.PI,
|
|
11276
|
+
radius
|
|
11277
|
+
])(root);
|
|
11278
|
+
const g = svg.selectAll("g.dx-bundle-root").data([
|
|
11279
|
+
null
|
|
11280
|
+
]).join("g").classed("dx-bundle-root", true);
|
|
11281
|
+
const linksLayer = g.selectAll("g.dx-bundle-links").data([
|
|
11282
|
+
null
|
|
11283
|
+
]).join("g").classed("dx-bundle-links", true);
|
|
11284
|
+
const nodesLayer = g.selectAll("g.dx-bundle-nodes").data([
|
|
11285
|
+
null
|
|
11286
|
+
]).join("g").classed("dx-bundle-nodes", true);
|
|
11287
|
+
const line = lineRadial().curve(curveBundle.beta(tension)).radius((d) => d.y).angle((d) => d.x);
|
|
11288
|
+
const leaves = root.leaves();
|
|
11289
|
+
const flatEdges = leaves.flatMap((leaf) => leaf.outgoing ?? []);
|
|
11290
|
+
const paths = linksLayer.selectAll("path").data(flatEdges, (d) => `${d[0].data.id}->${d[1].data.id}`).join((enter) => enter.append("path").attr("class", slots.path ?? "").attr("fill", "none").attr("opacity", 0), (update) => update, (exit) => exit.each(function() {
|
|
11291
|
+
select2(this).interrupt();
|
|
11292
|
+
}).transition().duration(TRANSITION_MS2).attr("opacity", 0).remove());
|
|
11293
|
+
paths.each(function(d) {
|
|
11294
|
+
d[0].pathEl = this;
|
|
11295
|
+
}).transition().duration(TRANSITION_MS2).attr("opacity", 1).attr("d", ([s, t]) => line(s.path(t)));
|
|
11296
|
+
const labels = nodesLayer.selectAll("g.dx-bundle-leaf").data(leaves, (d) => d.data.id).join((enter) => {
|
|
11297
|
+
const ge = enter.append("g").classed("dx-bundle-leaf", true).attr("opacity", 0);
|
|
11298
|
+
ge.append("circle").style("cursor", "pointer");
|
|
11299
|
+
ge.append("text").attr("dy", "0.32em").attr("paint-order", "stroke").style("cursor", "pointer");
|
|
11300
|
+
return ge;
|
|
11301
|
+
}, (update) => update, (exit) => exit.each(function() {
|
|
11302
|
+
select2(this).interrupt();
|
|
11303
|
+
}).transition().duration(TRANSITION_MS2).attr("opacity", 0).remove());
|
|
11304
|
+
labels.transition().duration(TRANSITION_MS2).attr("opacity", 1).attr("transform", (d) => `rotate(${d.x * 180 / Math.PI - 90}) translate(${d.y},0)`);
|
|
11305
|
+
const onEnter = function(event, d) {
|
|
11306
|
+
onNodeHover(d.data, event);
|
|
11307
|
+
hover(linksLayer, leaves, d, true);
|
|
11060
11308
|
};
|
|
11061
|
-
|
|
11062
|
-
|
|
11063
|
-
|
|
11064
|
-
|
|
11065
|
-
|
|
11066
|
-
|
|
11067
|
-
|
|
11068
|
-
|
|
11309
|
+
const onLeave = function(event, d) {
|
|
11310
|
+
onNodeHover(null);
|
|
11311
|
+
hover(linksLayer, leaves, d, false);
|
|
11312
|
+
};
|
|
11313
|
+
labels.select("circle").attr("class", [
|
|
11314
|
+
slots.node ?? "",
|
|
11315
|
+
"dx-leaf"
|
|
11316
|
+
].filter(Boolean).join(" ")).attr("r", r).style("fill", (d) => getNodeFillForObject(d.data.data)).on("pointerenter", onEnter).on("pointerleave", onLeave);
|
|
11317
|
+
labels.select("text").attr("class", slots.text ?? "").attr("x", (d) => d.x < Math.PI ? r + 4 : -(r + 4)).attr("text-anchor", (d) => d.x < Math.PI ? "start" : "end").attr("transform", (d) => d.x >= Math.PI ? "rotate(180)" : null).each(function(d) {
|
|
11318
|
+
d.text = this;
|
|
11319
|
+
}).text((d) => label(d.data)).on("pointerenter", onEnter).on("pointerleave", onLeave);
|
|
11320
|
+
};
|
|
11321
|
+
var hover = (linksLayer, leaves, focused, on) => {
|
|
11322
|
+
const outgoing = new Set((focused.outgoing ?? []).map(([, t]) => t));
|
|
11323
|
+
const incoming = new Set((focused.incoming ?? []).map(([s]) => s));
|
|
11324
|
+
linksLayer.selectAll("path").classed("dx-bundle-out", (d) => on && d[0] === focused).classed("dx-bundle-in", (d) => on && d[1] === focused).classed("dx-bundle-dim", (d) => on && d[0] !== focused && d[1] !== focused);
|
|
11325
|
+
for (const leaf of leaves) {
|
|
11326
|
+
if (!leaf.text) {
|
|
11327
|
+
continue;
|
|
11328
|
+
}
|
|
11329
|
+
select2(leaf.text).classed("dx-bundle-focused", on && leaf === focused).classed("dx-bundle-out-text", on && outgoing.has(leaf)).classed("dx-bundle-in-text", on && incoming.has(leaf));
|
|
11069
11330
|
}
|
|
11070
|
-
return clone;
|
|
11071
11331
|
};
|
|
11072
|
-
var HierarchicalEdgeBundling_default = HierarchicalEdgeBundling;
|
|
11073
11332
|
|
|
11074
|
-
// src/components/Tree/layout/RadialTree.
|
|
11075
|
-
import {
|
|
11076
|
-
|
|
11077
|
-
|
|
11078
|
-
|
|
11079
|
-
|
|
11080
|
-
|
|
11081
|
-
|
|
11082
|
-
|
|
11083
|
-
|
|
11084
|
-
|
|
11085
|
-
|
|
11333
|
+
// src/components/Tree/layout/RadialTree.tsx
|
|
11334
|
+
import { cluster as d3Cluster, linkRadial, select as select3, tree as d3Tree } from "d3";
|
|
11335
|
+
import React7, { useCallback as useCallback3, useEffect as useEffect8, useMemo as useMemo4, useRef as useRef5, useState as useState4 } from "react";
|
|
11336
|
+
import { mx as mx2 } from "@dxos/ui-theme";
|
|
11337
|
+
|
|
11338
|
+
// src/components/Tree/layout/hierarchy.ts
|
|
11339
|
+
import { hierarchy as d3Hierarchy } from "d3";
|
|
11340
|
+
var buildHierarchy = (data, collapsed = /* @__PURE__ */ new Set()) => {
|
|
11341
|
+
return d3Hierarchy(data, (d) => {
|
|
11342
|
+
if (!d.children?.length) {
|
|
11343
|
+
return void 0;
|
|
11344
|
+
}
|
|
11345
|
+
return collapsed.has(d.id) ? void 0 : d.children;
|
|
11346
|
+
});
|
|
11347
|
+
};
|
|
11348
|
+
var isCollapsed = (data, collapsed) => Boolean(data.children?.length) && collapsed.has(data.id);
|
|
11349
|
+
var isLeaf = (data) => !data.children?.length;
|
|
11350
|
+
|
|
11351
|
+
// src/components/Tree/layout/RadialTree.tsx
|
|
11352
|
+
var TRANSITION_MS3 = 350;
|
|
11353
|
+
var RadialTree = ({ classNames, data, label = (d) => d.label ?? d.id, slots = defaultTreeLayoutSlots, r = 4, padding = 80, initialCollapsed, cluster: cluster2 = false, onNodeClick, onNodeHover }) => {
|
|
11354
|
+
const svgRef = useRef5(null);
|
|
11355
|
+
const { setRef, width, height } = useContainerSize();
|
|
11356
|
+
const [collapsed, setCollapsed] = useState4(() => new Set(initialCollapsed ?? []));
|
|
11357
|
+
const toggle = useCallback3((id) => {
|
|
11358
|
+
setCollapsed((prev) => {
|
|
11359
|
+
const next = new Set(prev);
|
|
11360
|
+
if (next.has(id)) {
|
|
11361
|
+
next.delete(id);
|
|
11362
|
+
} else {
|
|
11363
|
+
next.add(id);
|
|
11364
|
+
}
|
|
11365
|
+
return next;
|
|
11366
|
+
});
|
|
11367
|
+
}, []);
|
|
11368
|
+
const handleClickRef = useRef5(() => {
|
|
11369
|
+
});
|
|
11370
|
+
handleClickRef.current = (node) => {
|
|
11371
|
+
onNodeClick?.(node);
|
|
11372
|
+
if (node.children?.length) {
|
|
11373
|
+
toggle(node.id);
|
|
11374
|
+
}
|
|
11375
|
+
};
|
|
11376
|
+
const handleHoverRef = useRef5(() => {
|
|
11377
|
+
});
|
|
11378
|
+
handleHoverRef.current = (node, event) => onNodeHover?.(node, event);
|
|
11379
|
+
const root = useMemo4(() => buildHierarchy(data, collapsed), [
|
|
11380
|
+
data,
|
|
11381
|
+
collapsed
|
|
11382
|
+
]);
|
|
11383
|
+
useEffect8(() => {
|
|
11384
|
+
if (!svgRef.current || !width || !height) {
|
|
11385
|
+
return;
|
|
11386
|
+
}
|
|
11387
|
+
const radius = Math.max(0, Math.min(width, height) / 2 - padding);
|
|
11388
|
+
renderRadialTree(svgRef.current, root, {
|
|
11389
|
+
radius,
|
|
11390
|
+
r,
|
|
11391
|
+
label,
|
|
11392
|
+
slots,
|
|
11393
|
+
collapsed,
|
|
11394
|
+
cluster: cluster2,
|
|
11395
|
+
onNodeClick: (n) => handleClickRef.current(n),
|
|
11396
|
+
onNodeHover: (n, e) => handleHoverRef.current(n, e)
|
|
11397
|
+
});
|
|
11398
|
+
}, [
|
|
11399
|
+
root,
|
|
11400
|
+
width,
|
|
11401
|
+
height,
|
|
11402
|
+
r,
|
|
11403
|
+
padding,
|
|
11404
|
+
label,
|
|
11405
|
+
slots,
|
|
11406
|
+
collapsed,
|
|
11407
|
+
cluster2
|
|
11408
|
+
]);
|
|
11409
|
+
return /* @__PURE__ */ React7.createElement("div", {
|
|
11410
|
+
ref: setRef,
|
|
11411
|
+
className: mx2("dx-expander relative", classNames)
|
|
11412
|
+
}, width > 0 && height > 0 && /* @__PURE__ */ React7.createElement("svg", {
|
|
11413
|
+
ref: svgRef,
|
|
11414
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
11415
|
+
width,
|
|
11416
|
+
height,
|
|
11417
|
+
viewBox: `${-width / 2} ${-height / 2} ${width} ${height}`
|
|
11418
|
+
}));
|
|
11419
|
+
};
|
|
11420
|
+
var renderRadialTree = (svgElement, root, options) => {
|
|
11421
|
+
const { radius, r, label, slots, collapsed, cluster: cluster2, onNodeClick, onNodeHover } = options;
|
|
11422
|
+
const svg = select3(svgElement);
|
|
11423
|
+
const layout = cluster2 ? d3Cluster() : d3Tree();
|
|
11424
|
+
layout.size([
|
|
11425
|
+
2 * Math.PI,
|
|
11086
11426
|
radius
|
|
11087
|
-
]).separation((a, b) => (a.parent === b.parent ? 1 : 2) / a.depth);
|
|
11088
|
-
|
|
11089
|
-
|
|
11090
|
-
|
|
11091
|
-
|
|
11092
|
-
|
|
11093
|
-
|
|
11094
|
-
|
|
11095
|
-
|
|
11427
|
+
]).separation((a, b) => (a.parent === b.parent ? 1 : 2) / Math.max(1, a.depth))(root);
|
|
11428
|
+
const g = svg.selectAll("g.dx-radial-root").data([
|
|
11429
|
+
null
|
|
11430
|
+
]).join("g").classed("dx-radial-root", true);
|
|
11431
|
+
const linksLayer = g.selectAll("g.dx-radial-links").data([
|
|
11432
|
+
null
|
|
11433
|
+
]).join("g").classed("dx-radial-links", true);
|
|
11434
|
+
const nodesLayer = g.selectAll("g.dx-radial-nodes").data([
|
|
11435
|
+
null
|
|
11436
|
+
]).join("g").classed("dx-radial-nodes", true);
|
|
11437
|
+
const linkPath = linkRadial().angle((d) => d.x).radius((d) => d.y);
|
|
11438
|
+
linksLayer.selectAll("path").data(root.links(), (d) => `${d.source.data.id}->${d.target.data.id}`).join((enter) => enter.append("path").attr("class", slots.path ?? "").attr("fill", "none").attr("opacity", 0), (update) => update, (exit) => exit.transition().duration(TRANSITION_MS3).attr("opacity", 0).remove()).transition().duration(TRANSITION_MS3).attr("opacity", 1).attr("d", linkPath);
|
|
11439
|
+
const node = nodesLayer.selectAll("g.dx-radial-node").data(root.descendants(), (d) => d.data.id);
|
|
11440
|
+
const nodeEnter = node.enter().append("g").classed("dx-radial-node", true).attr("opacity", 0).attr("transform", (d) => `rotate(${d.x * 180 / Math.PI - 90}) translate(${d.y},0)`).style("cursor", (d) => d.data.children?.length ? "pointer" : "default").on("click", (_, d) => onNodeClick(d.data));
|
|
11441
|
+
nodeEnter.append("circle").attr("r", r).on("pointerenter", (event, d) => onNodeHover(d.data, event)).on("pointerleave", (event) => onNodeHover(null, event));
|
|
11442
|
+
nodeEnter.append("text").attr("dy", "0.32em").attr("paint-order", "stroke").text((d) => label(d.data));
|
|
11443
|
+
const nodeMerge = nodeEnter.merge(node);
|
|
11444
|
+
nodeMerge.transition().duration(TRANSITION_MS3).attr("opacity", 1).attr("transform", (d) => `rotate(${d.x * 180 / Math.PI - 90}) translate(${d.y},0)`);
|
|
11445
|
+
nodeMerge.select("circle").attr("class", (d) => {
|
|
11446
|
+
const collapsedHere = isCollapsed(d.data, collapsed);
|
|
11447
|
+
const leaf = isLeaf(d.data);
|
|
11448
|
+
return [
|
|
11449
|
+
slots.node ?? "",
|
|
11450
|
+
collapsedHere ? "dx-collapsed" : leaf ? "dx-leaf" : "dx-branch"
|
|
11451
|
+
].filter(Boolean).join(" ");
|
|
11452
|
+
}).attr("r", r).style("fill", (d) => isLeaf(d.data) ? getNodeFillForObject(d.data.data) : null);
|
|
11453
|
+
nodeMerge.select("text").attr("class", slots.text ?? "").attr("transform", (d) => d.x >= Math.PI ? "rotate(180)" : null).attr("x", (d) => d.x < Math.PI === !d.children ? r + 4 : -(r + 4)).attr("text-anchor", (d) => d.x < Math.PI === !d.children ? "start" : "end").text((d) => label(d.data));
|
|
11454
|
+
node.exit().transition().duration(TRANSITION_MS3).attr("opacity", 0).remove();
|
|
11096
11455
|
};
|
|
11097
|
-
var RadialTree_default = RadialTree;
|
|
11098
11456
|
|
|
11099
|
-
// src/components/Tree/layout/TidyTree.
|
|
11100
|
-
import { curveBumpX,
|
|
11101
|
-
|
|
11102
|
-
|
|
11103
|
-
|
|
11104
|
-
|
|
11105
|
-
const
|
|
11106
|
-
const
|
|
11107
|
-
const
|
|
11108
|
-
const
|
|
11109
|
-
|
|
11110
|
-
|
|
11457
|
+
// src/components/Tree/layout/TidyTree.tsx
|
|
11458
|
+
import { curveBumpX, link as d3Link, select as select4, tree as d3Tree2 } from "d3";
|
|
11459
|
+
import React8, { useCallback as useCallback4, useEffect as useEffect9, useMemo as useMemo5, useRef as useRef6, useState as useState5 } from "react";
|
|
11460
|
+
import { mx as mx3 } from "@dxos/ui-theme";
|
|
11461
|
+
var TRANSITION_MS4 = 350;
|
|
11462
|
+
var TidyTree = ({ classNames, data, label = (d) => d.label ?? d.id, slots = defaultTreeLayoutSlots, r = 4, margin = 24, initialCollapsed, onNodeClick }) => {
|
|
11463
|
+
const svgRef = useRef6(null);
|
|
11464
|
+
const { setRef, width, height } = useContainerSize();
|
|
11465
|
+
const [collapsed, setCollapsed] = useState5(() => new Set(initialCollapsed ?? []));
|
|
11466
|
+
const toggle = useCallback4((id) => {
|
|
11467
|
+
setCollapsed((prev) => {
|
|
11468
|
+
const next = new Set(prev);
|
|
11469
|
+
if (next.has(id)) {
|
|
11470
|
+
next.delete(id);
|
|
11471
|
+
} else {
|
|
11472
|
+
next.add(id);
|
|
11473
|
+
}
|
|
11474
|
+
return next;
|
|
11475
|
+
});
|
|
11476
|
+
}, []);
|
|
11477
|
+
const handleClickRef = useRef6(() => {
|
|
11478
|
+
});
|
|
11479
|
+
handleClickRef.current = (node) => {
|
|
11480
|
+
onNodeClick?.(node);
|
|
11481
|
+
if (node.children?.length) {
|
|
11482
|
+
toggle(node.id);
|
|
11483
|
+
}
|
|
11484
|
+
};
|
|
11485
|
+
const root = useMemo5(() => buildHierarchy(data, collapsed), [
|
|
11486
|
+
data,
|
|
11487
|
+
collapsed
|
|
11488
|
+
]);
|
|
11489
|
+
useEffect9(() => {
|
|
11490
|
+
if (!svgRef.current || !width || !height) {
|
|
11491
|
+
return;
|
|
11492
|
+
}
|
|
11493
|
+
renderTidyTree(svgRef.current, root, {
|
|
11494
|
+
width,
|
|
11495
|
+
height,
|
|
11496
|
+
r,
|
|
11497
|
+
margin,
|
|
11498
|
+
label,
|
|
11499
|
+
slots,
|
|
11500
|
+
collapsed,
|
|
11501
|
+
onNodeClick: (n) => handleClickRef.current(n)
|
|
11502
|
+
});
|
|
11503
|
+
}, [
|
|
11504
|
+
root,
|
|
11505
|
+
width,
|
|
11506
|
+
height,
|
|
11507
|
+
r,
|
|
11508
|
+
margin,
|
|
11509
|
+
label,
|
|
11510
|
+
slots,
|
|
11511
|
+
collapsed
|
|
11512
|
+
]);
|
|
11513
|
+
return /* @__PURE__ */ React8.createElement("div", {
|
|
11514
|
+
ref: setRef,
|
|
11515
|
+
className: mx3("dx-expander relative", classNames)
|
|
11516
|
+
}, width > 0 && height > 0 && /* @__PURE__ */ React8.createElement("svg", {
|
|
11517
|
+
ref: svgRef,
|
|
11518
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
11519
|
+
width,
|
|
11520
|
+
height,
|
|
11521
|
+
viewBox: `${-width / 2} ${-height / 2} ${width} ${height}`
|
|
11522
|
+
}));
|
|
11523
|
+
};
|
|
11524
|
+
var renderTidyTree = (svgElement, root, options) => {
|
|
11525
|
+
const { width, height, r, margin, label, slots, collapsed, onNodeClick } = options;
|
|
11526
|
+
const svg = select4(svgElement);
|
|
11527
|
+
const dx = 18;
|
|
11528
|
+
const dy = Math.max(60, (width - margin * 2) / Math.max(1, root.height + 1));
|
|
11529
|
+
d3Tree2().nodeSize([
|
|
11111
11530
|
dx,
|
|
11112
11531
|
dy
|
|
11113
|
-
]);
|
|
11114
|
-
layout(root);
|
|
11532
|
+
])(root);
|
|
11115
11533
|
let x0 = Infinity;
|
|
11116
11534
|
let x1 = -x0;
|
|
11117
|
-
let y0 = Infinity;
|
|
11118
|
-
let y1 = -y0;
|
|
11119
11535
|
root.each((d) => {
|
|
11120
11536
|
if (d.x > x1) {
|
|
11121
11537
|
x1 = d.x;
|
|
@@ -11123,168 +11539,102 @@ var TidyTree = (s, data, options) => {
|
|
|
11123
11539
|
if (d.x < x0) {
|
|
11124
11540
|
x0 = d.x;
|
|
11125
11541
|
}
|
|
11126
|
-
if (d.y > y1) {
|
|
11127
|
-
y1 = d.y;
|
|
11128
|
-
}
|
|
11129
|
-
if (d.y < y0) {
|
|
11130
|
-
y0 = d.y;
|
|
11131
|
-
}
|
|
11132
11542
|
});
|
|
11133
|
-
const
|
|
11134
|
-
const
|
|
11135
|
-
|
|
11136
|
-
const
|
|
11137
|
-
|
|
11138
|
-
|
|
11139
|
-
|
|
11140
|
-
|
|
11141
|
-
|
|
11142
|
-
|
|
11143
|
-
|
|
11144
|
-
|
|
11145
|
-
|
|
11146
|
-
|
|
11147
|
-
|
|
11148
|
-
|
|
11149
|
-
|
|
11150
|
-
|
|
11151
|
-
|
|
11152
|
-
|
|
11153
|
-
|
|
11154
|
-
|
|
11155
|
-
|
|
11156
|
-
|
|
11157
|
-
|
|
11158
|
-
|
|
11159
|
-
|
|
11160
|
-
|
|
11161
|
-
|
|
11162
|
-
|
|
11163
|
-
|
|
11164
|
-
|
|
11165
|
-
|
|
11166
|
-
|
|
11167
|
-
}));
|
|
11168
|
-
|
|
11169
|
-
// src/components/Tree/types/types.ts
|
|
11170
|
-
var mapGraphToTreeData = (model, maxDepth = 8) => {
|
|
11171
|
-
let data;
|
|
11172
|
-
return data;
|
|
11543
|
+
const treeWidth = width - margin * 2;
|
|
11544
|
+
const treeHeight = x1 - x0;
|
|
11545
|
+
const scaleY = treeHeight > 0 ? Math.min(1, (height - margin * 2) / treeHeight) : 1;
|
|
11546
|
+
const offsetX = -treeWidth / 2;
|
|
11547
|
+
const offsetY = -(x0 + x1) / 2;
|
|
11548
|
+
const g = svg.selectAll("g.dx-tidy-root").data([
|
|
11549
|
+
null
|
|
11550
|
+
]).join("g").classed("dx-tidy-root", true);
|
|
11551
|
+
const linksLayer = g.selectAll("g.dx-tidy-links").data([
|
|
11552
|
+
null
|
|
11553
|
+
]).join("g").classed("dx-tidy-links", true);
|
|
11554
|
+
const nodesLayer = g.selectAll("g.dx-tidy-nodes").data([
|
|
11555
|
+
null
|
|
11556
|
+
]).join("g").classed("dx-tidy-nodes", true);
|
|
11557
|
+
const linkPath = d3Link(curveBumpX).x((d) => offsetX + d.y).y((d) => (d.x + offsetY) * scaleY);
|
|
11558
|
+
linksLayer.selectAll("path").data(root.links(), (d) => `${d.source.data.id}->${d.target.data.id}`).join((enter) => enter.append("path").attr("class", slots.path ?? "").attr("fill", "none").attr("opacity", 0), (update) => update, (exit) => exit.transition().duration(TRANSITION_MS4).attr("opacity", 0).remove()).transition().duration(TRANSITION_MS4).attr("opacity", 1).attr("d", linkPath);
|
|
11559
|
+
const node = nodesLayer.selectAll("g.dx-tidy-node").data(root.descendants(), (d) => d.data.id);
|
|
11560
|
+
const nodeEnter = node.enter().append("g").classed("dx-tidy-node", true).attr("transform", (d) => `translate(${offsetX + d.y},${(d.x + offsetY) * scaleY})`).attr("opacity", 0).style("cursor", (d) => d.data.children?.length ? "pointer" : "default").on("click", (_, d) => onNodeClick(d.data));
|
|
11561
|
+
nodeEnter.append("circle").attr("r", r);
|
|
11562
|
+
nodeEnter.append("text").attr("dy", "0.32em").attr("x", (d) => d.children ? -(r + 4) : r + 4).attr("text-anchor", (d) => d.children ? "end" : "start").text((d) => label(d.data));
|
|
11563
|
+
const nodeMerge = nodeEnter.merge(node);
|
|
11564
|
+
nodeMerge.transition().duration(TRANSITION_MS4).attr("opacity", 1).attr("transform", (d) => `translate(${offsetX + d.y},${(d.x + offsetY) * scaleY})`);
|
|
11565
|
+
nodeMerge.select("circle").attr("class", (d) => {
|
|
11566
|
+
const collapsedHere = isCollapsed(d.data, collapsed);
|
|
11567
|
+
const leaf = isLeaf(d.data);
|
|
11568
|
+
return [
|
|
11569
|
+
slots.node ?? "",
|
|
11570
|
+
collapsedHere ? "dx-collapsed" : leaf ? "dx-leaf" : "dx-branch"
|
|
11571
|
+
].filter(Boolean).join(" ");
|
|
11572
|
+
}).attr("r", r);
|
|
11573
|
+
nodeMerge.select("text").attr("class", slots.text ?? "").attr("x", (d) => d.children ? -(r + 4) : r + 4).attr("text-anchor", (d) => d.children ? "end" : "start").text((d) => label(d.data));
|
|
11574
|
+
node.exit().each(function() {
|
|
11575
|
+
select4(this).interrupt();
|
|
11576
|
+
}).transition().duration(TRANSITION_MS4).attr("opacity", 0).remove();
|
|
11173
11577
|
};
|
|
11174
11578
|
|
|
11175
11579
|
// src/components/Tree/Tree.tsx
|
|
11176
|
-
var
|
|
11177
|
-
|
|
11178
|
-
|
|
11179
|
-
|
|
11180
|
-
|
|
11181
|
-
|
|
11182
|
-
|
|
11183
|
-
|
|
11184
|
-
|
|
11185
|
-
|
|
11186
|
-
|
|
11187
|
-
|
|
11188
|
-
|
|
11189
|
-
|
|
11190
|
-
|
|
11191
|
-
|
|
11192
|
-
|
|
11193
|
-
|
|
11194
|
-
|
|
11195
|
-
|
|
11196
|
-
|
|
11197
|
-
|
|
11198
|
-
|
|
11199
|
-
|
|
11200
|
-
|
|
11201
|
-
|
|
11202
|
-
|
|
11203
|
-
|
|
11204
|
-
|
|
11205
|
-
|
|
11206
|
-
|
|
11207
|
-
}, true);
|
|
11208
|
-
}, [
|
|
11209
|
-
model
|
|
11210
|
-
]);
|
|
11211
|
-
const context = useRef3(null);
|
|
11212
|
-
useEffect5(() => {
|
|
11213
|
-
if (context.current?.size) {
|
|
11214
|
-
const { width, height } = context.current.size;
|
|
11215
|
-
const size = Math.min(width, height);
|
|
11216
|
-
const radius = size * 0.4;
|
|
11217
|
-
const options = {
|
|
11218
|
-
// TODO(burdon): Type.
|
|
11219
|
-
label: (d) => d.label ?? d.id,
|
|
11220
|
-
width,
|
|
11221
|
-
height,
|
|
11222
|
-
radius,
|
|
11223
|
-
marginLeft: (width - radius * 2) / 2,
|
|
11224
|
-
marginRight: (width - radius * 2) / 2,
|
|
11225
|
-
marginTop: (height - radius * 2) / 2,
|
|
11226
|
-
marginBottom: (height - radius * 2) / 2,
|
|
11227
|
-
slots: defaultTreeLayoutSlots
|
|
11228
|
-
};
|
|
11229
|
-
if (tree3) {
|
|
11230
|
-
const renderer = renderers.get(variant);
|
|
11231
|
-
renderer?.(context.current.svg, tree3, options);
|
|
11232
|
-
}
|
|
11233
|
-
}
|
|
11234
|
-
}, [
|
|
11235
|
-
context.current,
|
|
11236
|
-
tree3
|
|
11237
|
-
]);
|
|
11238
|
-
return /* @__PURE__ */ React5.createElement("div", {
|
|
11239
|
-
className: "grow",
|
|
11240
|
-
onClick: () => onNodeClick?.()
|
|
11241
|
-
}, /* @__PURE__ */ React5.createElement(SVG2.Root, {
|
|
11242
|
-
ref: context
|
|
11243
|
-
}));
|
|
11244
|
-
};
|
|
11245
|
-
|
|
11246
|
-
// src/hooks/useGraphModel.ts
|
|
11247
|
-
import { useEffect as useEffect6, useState as useState3 } from "react";
|
|
11248
|
-
import { Capabilities } from "@dxos/app-framework";
|
|
11249
|
-
import { useCapability } from "@dxos/app-framework/ui";
|
|
11250
|
-
import { SpaceGraphModel as SpaceGraphModel2 } from "@dxos/schema";
|
|
11251
|
-
var useGraphModel = (space, filter, options, queue) => {
|
|
11252
|
-
const registry = useCapability(Capabilities.AtomRegistry);
|
|
11253
|
-
const [model, setModel] = useState3(void 0);
|
|
11254
|
-
useEffect6(() => {
|
|
11255
|
-
if (!space) {
|
|
11256
|
-
setModel(void 0);
|
|
11257
|
-
return;
|
|
11580
|
+
var Tree = ({ classNames, data, edges, variant = "tidy", label, slots, initialCollapsed, onNodeClick, onNodeHover }) => {
|
|
11581
|
+
return useMemo6(() => {
|
|
11582
|
+
switch (variant) {
|
|
11583
|
+
case "tidy":
|
|
11584
|
+
return /* @__PURE__ */ React9.createElement(TidyTree, {
|
|
11585
|
+
classNames,
|
|
11586
|
+
data,
|
|
11587
|
+
label,
|
|
11588
|
+
slots,
|
|
11589
|
+
initialCollapsed,
|
|
11590
|
+
onNodeClick
|
|
11591
|
+
});
|
|
11592
|
+
case "radial":
|
|
11593
|
+
return /* @__PURE__ */ React9.createElement(RadialTree, {
|
|
11594
|
+
classNames,
|
|
11595
|
+
data,
|
|
11596
|
+
label,
|
|
11597
|
+
slots,
|
|
11598
|
+
initialCollapsed,
|
|
11599
|
+
onNodeClick,
|
|
11600
|
+
onNodeHover
|
|
11601
|
+
});
|
|
11602
|
+
case "edge":
|
|
11603
|
+
return /* @__PURE__ */ React9.createElement(HierarchicalEdgeBundling, {
|
|
11604
|
+
classNames,
|
|
11605
|
+
data,
|
|
11606
|
+
edges: edges ?? [],
|
|
11607
|
+
label,
|
|
11608
|
+
slots,
|
|
11609
|
+
onNodeHover
|
|
11610
|
+
});
|
|
11258
11611
|
}
|
|
11259
|
-
const newModel = new SpaceGraphModel2(registry);
|
|
11260
|
-
void newModel.open(space.db, queue);
|
|
11261
|
-
setModel(newModel);
|
|
11262
|
-
return () => {
|
|
11263
|
-
setModel(void 0);
|
|
11264
|
-
void newModel.close();
|
|
11265
|
-
};
|
|
11266
|
-
}, [
|
|
11267
|
-
space,
|
|
11268
|
-
registry,
|
|
11269
|
-
queue
|
|
11270
|
-
]);
|
|
11271
|
-
useEffect6(() => {
|
|
11272
|
-
model?.setFilter(filter).setOptions(options);
|
|
11273
11612
|
}, [
|
|
11274
|
-
|
|
11275
|
-
|
|
11276
|
-
|
|
11613
|
+
variant,
|
|
11614
|
+
classNames,
|
|
11615
|
+
data,
|
|
11616
|
+
edges,
|
|
11617
|
+
label,
|
|
11618
|
+
slots,
|
|
11619
|
+
initialCollapsed,
|
|
11620
|
+
onNodeClick,
|
|
11621
|
+
onNodeHover
|
|
11277
11622
|
]);
|
|
11278
|
-
return model;
|
|
11279
11623
|
};
|
|
11280
|
-
|
|
11281
11624
|
export {
|
|
11625
|
+
CanvasForceGraph,
|
|
11282
11626
|
Chart,
|
|
11283
|
-
Globe,
|
|
11284
|
-
D3ForceGraph,
|
|
11285
11627
|
ForceGraph,
|
|
11286
|
-
|
|
11628
|
+
Globe,
|
|
11629
|
+
HierarchicalEdgeBundling,
|
|
11630
|
+
Lattice,
|
|
11631
|
+
RadialTree,
|
|
11632
|
+
TidyTree,
|
|
11287
11633
|
Tree,
|
|
11288
|
-
|
|
11634
|
+
buildHierarchy,
|
|
11635
|
+
defaultTreeLayoutSlots,
|
|
11636
|
+
isCollapsed,
|
|
11637
|
+
isLeaf,
|
|
11638
|
+
treeTypeToTreeNode
|
|
11289
11639
|
};
|
|
11290
|
-
//# sourceMappingURL=
|
|
11640
|
+
//# sourceMappingURL=index.mjs.map
|