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