@dxos/plugin-explorer 0.8.4-main.74a063c4e0 → 0.8.4-main.765dc60934
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} +10 -8
- 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/chunk-LSUP47BZ.mjs → neutral/chunk-HPIS2WXY.mjs} +1 -1
- package/dist/lib/{browser/chunk-LSUP47BZ.mjs.map → neutral/chunk-HPIS2WXY.mjs.map} +2 -2
- package/dist/lib/{browser → neutral/components}/index.mjs +661 -417
- package/dist/lib/{node-esm → 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/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.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/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 +6 -0
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts.map +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.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/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/generator.d.ts.map +1 -1
- 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/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/plot.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 -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/testing.d.ts +2 -0
- package/dist/types/src/testing.d.ts.map +1 -0
- package/dist/types/src/translations.d.ts +17 -17
- 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/tsconfig.tsbuildinfo +1 -1
- package/package.json +100 -62
- package/src/ExplorerPlugin.test.ts +26 -0
- package/src/ExplorerPlugin.tsx +6 -35
- package/src/capabilities/create-object.ts +36 -0
- package/src/capabilities/index.ts +1 -0
- package/src/capabilities/react-surface.tsx +6 -4
- 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/generator.ts +1 -1
- package/src/components/Tree/testing/index.ts +1 -0
- package/src/components/Tree/testing/relations.ts +182 -0
- package/src/components/Tree/types/tree.test.ts +1 -1
- package/src/components/Tree/types/tree.ts +9 -9
- 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 -4
- package/src/plugin.ts +9 -0
- package/src/testing.ts +7 -0
- package/src/translations.ts +1 -1
- package/src/types/ExplorerAction.ts +1 -1
- package/src/types/Graph.ts +2 -3
- package/dist/lib/browser/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-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/index.mjs +0 -11375
- 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 -71
- package/dist/lib/node-esm/types/index.mjs.map +0 -7
- 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/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-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/{node-esm → neutral}/meta.mjs.map +0 -0
- /package/src/components/Graph/{adapter.ts → graph-adapter.ts} +0 -0
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
meta
|
|
3
|
-
} from "./chunk-LSUP47BZ.mjs";
|
|
4
|
-
import "./chunk-J5LGTIGS.mjs";
|
|
1
|
+
import "../chunk-J5LGTIGS.mjs";
|
|
5
2
|
|
|
6
3
|
// src/components/Chart/Chart.tsx
|
|
7
4
|
import * as Plot from "@observablehq/plot";
|
|
@@ -10825,45 +10822,158 @@ var Globe = ({ items = [], accessor, projection = "orthographic", options = defa
|
|
|
10825
10822
|
});
|
|
10826
10823
|
};
|
|
10827
10824
|
|
|
10828
|
-
// 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
|
|
10829
10935
|
import { Atom, useAtomValue } from "@effect-atom/atom-react";
|
|
10830
|
-
import
|
|
10936
|
+
import React4, { useCallback as useCallback2, useEffect as useEffect4, useMemo, useRef as useRef2, useState as useState2 } from "react";
|
|
10831
10937
|
import { Obj } from "@dxos/echo";
|
|
10832
10938
|
import { SelectionModel } from "@dxos/graph";
|
|
10833
10939
|
import { GraphForceProjector, SVG } from "@dxos/react-ui-graph";
|
|
10834
|
-
import { composable, composableProps, getHashStyles } from "@dxos/ui-theme";
|
|
10940
|
+
import { composable as composable2, composableProps as composableProps2, getHashStyles } from "@dxos/ui-theme";
|
|
10835
10941
|
import "@dxos/react-ui-graph/styles/graph.css";
|
|
10836
10942
|
var EMPTY_ATOM = Atom.make({
|
|
10837
10943
|
nodes: [],
|
|
10838
10944
|
edges: []
|
|
10839
10945
|
});
|
|
10840
|
-
var
|
|
10946
|
+
var ForceGraph = composable2(({ model, selection: selectionProp, grid, drag, onInspect, ...props }, forwardedRef) => {
|
|
10841
10947
|
useAtomValue(model?.graphAtom ?? EMPTY_ATOM);
|
|
10842
|
-
const
|
|
10843
|
-
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(() => {
|
|
10844
10961
|
if (svgRef.current) {
|
|
10845
|
-
|
|
10962
|
+
setProjector(new GraphForceProjector(svgRef.current, {
|
|
10846
10963
|
attributes: {
|
|
10847
|
-
|
|
10848
|
-
|
|
10849
|
-
|
|
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
|
|
10850
10967
|
},
|
|
10851
10968
|
forces: {
|
|
10852
10969
|
point: {
|
|
10853
10970
|
strength: 0.01
|
|
10854
10971
|
}
|
|
10855
10972
|
}
|
|
10856
|
-
});
|
|
10973
|
+
}));
|
|
10857
10974
|
}
|
|
10858
10975
|
}, []);
|
|
10859
|
-
const
|
|
10860
|
-
const selection = useMemo(() => _selection ?? new SelectionModel(), [
|
|
10861
|
-
_selection
|
|
10862
|
-
]);
|
|
10863
|
-
useEffect3(() => selection.subscribe(() => graph.current?.repaint()), [
|
|
10864
|
-
selection
|
|
10865
|
-
]);
|
|
10866
|
-
const handleSelect = useCallback((node) => {
|
|
10976
|
+
const handleSelect = useCallback2((node) => {
|
|
10867
10977
|
if (selection.contains(node.id)) {
|
|
10868
10978
|
selection.remove(node.id);
|
|
10869
10979
|
} else {
|
|
@@ -10872,29 +10982,27 @@ var D3ForceGraph = composable(({ model, selection: _selection, grid, drag, ...pr
|
|
|
10872
10982
|
}, [
|
|
10873
10983
|
selection
|
|
10874
10984
|
]);
|
|
10875
|
-
return /* @__PURE__ */
|
|
10876
|
-
...
|
|
10985
|
+
return /* @__PURE__ */ React4.createElement("div", {
|
|
10986
|
+
...composableProps2(props, {
|
|
10877
10987
|
classNames: "dx-container"
|
|
10878
10988
|
}),
|
|
10879
10989
|
ref: forwardedRef
|
|
10880
|
-
}, /* @__PURE__ */
|
|
10990
|
+
}, /* @__PURE__ */ React4.createElement(SVG.Root, {
|
|
10881
10991
|
ref: svgRef
|
|
10882
|
-
}, /* @__PURE__ */
|
|
10992
|
+
}, /* @__PURE__ */ React4.createElement(SVG.Markers, null), grid && /* @__PURE__ */ React4.createElement(SVG.Grid, {
|
|
10883
10993
|
axis: true
|
|
10884
|
-
}), /* @__PURE__ */
|
|
10994
|
+
}), /* @__PURE__ */ React4.createElement(SVG.Zoom, {
|
|
10885
10995
|
extent: [
|
|
10886
10996
|
1 / 2,
|
|
10887
10997
|
2
|
|
10888
10998
|
]
|
|
10889
|
-
}, /* @__PURE__ */
|
|
10890
|
-
drag,
|
|
10999
|
+
}, /* @__PURE__ */ React4.createElement(SVG.Graph, {
|
|
10891
11000
|
ref: graph,
|
|
11001
|
+
drag,
|
|
10892
11002
|
model,
|
|
10893
11003
|
projector,
|
|
10894
11004
|
labels: {
|
|
10895
|
-
text: (node) =>
|
|
10896
|
-
return node.data?.data.label ?? node.id;
|
|
10897
|
-
}
|
|
11005
|
+
text: (node) => node.data?.data.label ?? node.id
|
|
10898
11006
|
},
|
|
10899
11007
|
attributes: {
|
|
10900
11008
|
node: (node) => {
|
|
@@ -10909,217 +11017,402 @@ var D3ForceGraph = composable(({ model, selection: _selection, grid, drag, ...pr
|
|
|
10909
11017
|
};
|
|
10910
11018
|
}
|
|
10911
11019
|
},
|
|
10912
|
-
onSelect: handleSelect
|
|
11020
|
+
onSelect: handleSelect,
|
|
11021
|
+
onInspect
|
|
10913
11022
|
}))));
|
|
10914
11023
|
});
|
|
10915
11024
|
|
|
10916
|
-
// src/components/
|
|
10917
|
-
import {
|
|
10918
|
-
import NativeForceGraph from "force-graph";
|
|
10919
|
-
import React4, { useEffect as useEffect4, useRef as useRef2, useState } from "react";
|
|
10920
|
-
import { useResizeDetector as useResizeDetector3 } from "react-resize-detector";
|
|
10921
|
-
import { filterObjectsSync } from "@dxos/plugin-search";
|
|
11025
|
+
// src/components/Tree/Tree.tsx
|
|
11026
|
+
import React8, { useMemo as useMemo5 } from "react";
|
|
10922
11027
|
|
|
10923
|
-
// src/components/
|
|
10924
|
-
|
|
10925
|
-
|
|
10926
|
-
|
|
10927
|
-
|
|
10928
|
-
|
|
10929
|
-
|
|
10930
|
-
|
|
10931
|
-
|
|
10932
|
-
|
|
10933
|
-
|
|
10934
|
-
|
|
10935
|
-
|
|
10936
|
-
|
|
10937
|
-
type: edge.type,
|
|
10938
|
-
source: edge.source,
|
|
10939
|
-
target: edge.target,
|
|
10940
|
-
data: edge.data
|
|
10941
|
-
}));
|
|
10942
|
-
}
|
|
10943
|
-
get nodes() {
|
|
10944
|
-
return this._nodes;
|
|
10945
|
-
}
|
|
10946
|
-
get links() {
|
|
10947
|
-
return this._links;
|
|
10948
|
-
}
|
|
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"
|
|
10949
11042
|
};
|
|
10950
11043
|
|
|
10951
|
-
// src/components/
|
|
10952
|
-
|
|
10953
|
-
|
|
10954
|
-
|
|
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
|
|
10955
11051
|
});
|
|
10956
|
-
|
|
10957
|
-
|
|
10958
|
-
|
|
10959
|
-
|
|
10960
|
-
|
|
10961
|
-
|
|
10962
|
-
|
|
10963
|
-
|
|
11052
|
+
useEffect5(() => {
|
|
11053
|
+
if (!el) {
|
|
11054
|
+
return;
|
|
11055
|
+
}
|
|
11056
|
+
const rect = el.getBoundingClientRect();
|
|
11057
|
+
setSize({
|
|
11058
|
+
width: rect.width,
|
|
11059
|
+
height: rect.height
|
|
10964
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
|
+
});
|
|
11071
|
+
});
|
|
11072
|
+
observer.observe(el);
|
|
11073
|
+
return () => observer.disconnect();
|
|
10965
11074
|
}, [
|
|
10966
|
-
|
|
11075
|
+
el
|
|
10967
11076
|
]);
|
|
10968
|
-
|
|
10969
|
-
|
|
10970
|
-
|
|
10971
|
-
|
|
10972
|
-
|
|
10973
|
-
|
|
10974
|
-
|
|
10975
|
-
|
|
10976
|
-
|
|
10977
|
-
|
|
10978
|
-
|
|
10979
|
-
|
|
10980
|
-
|
|
10981
|
-
|
|
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) {
|
|
10982
11098
|
return;
|
|
10983
11099
|
}
|
|
10984
|
-
|
|
10985
|
-
|
|
10986
|
-
|
|
10987
|
-
|
|
10988
|
-
|
|
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
|
+
});
|
|
10989
11108
|
}, [
|
|
10990
|
-
|
|
11109
|
+
root,
|
|
10991
11110
|
width,
|
|
10992
11111
|
height,
|
|
10993
|
-
|
|
11112
|
+
padding,
|
|
11113
|
+
tension,
|
|
11114
|
+
label,
|
|
11115
|
+
slots
|
|
10994
11116
|
]);
|
|
10995
|
-
|
|
10996
|
-
|
|
10997
|
-
|
|
10998
|
-
|
|
10999
|
-
ref,
|
|
11000
|
-
|
|
11001
|
-
|
|
11002
|
-
|
|
11003
|
-
|
|
11004
|
-
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}`
|
|
11005
11126
|
}));
|
|
11006
11127
|
};
|
|
11007
|
-
|
|
11008
|
-
|
|
11009
|
-
|
|
11010
|
-
|
|
11011
|
-
|
|
11012
|
-
|
|
11013
|
-
|
|
11014
|
-
|
|
11015
|
-
|
|
11016
|
-
|
|
11017
|
-
|
|
11018
|
-
|
|
11019
|
-
|
|
11020
|
-
|
|
11021
|
-
|
|
11022
|
-
|
|
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([
|
|
11023
11163
|
2 * Math.PI,
|
|
11024
|
-
radius
|
|
11025
|
-
]);
|
|
11026
|
-
const
|
|
11027
|
-
|
|
11028
|
-
|
|
11029
|
-
const
|
|
11030
|
-
|
|
11031
|
-
|
|
11032
|
-
|
|
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);
|
|
11033
11200
|
});
|
|
11034
11201
|
};
|
|
11035
|
-
var
|
|
11036
|
-
const
|
|
11037
|
-
|
|
11038
|
-
|
|
11039
|
-
|
|
11040
|
-
|
|
11041
|
-
|
|
11042
|
-
map.set(d.data.id, d);
|
|
11043
|
-
}
|
|
11044
|
-
return map;
|
|
11045
|
-
}, /* @__PURE__ */ new Map());
|
|
11046
|
-
for (const d of root.leaves()) {
|
|
11047
|
-
const parent = parents.get(d.data.id);
|
|
11048
|
-
if (parent) {
|
|
11049
|
-
d.outgoing = parent.data.children?.slice(1).map((child) => {
|
|
11050
|
-
return [
|
|
11051
|
-
d,
|
|
11052
|
-
nodes.get(child.id)
|
|
11053
|
-
];
|
|
11054
|
-
}) ?? [];
|
|
11055
|
-
} else {
|
|
11056
|
-
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;
|
|
11057
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));
|
|
11058
11211
|
}
|
|
11059
|
-
return root;
|
|
11060
11212
|
};
|
|
11061
|
-
|
|
11062
|
-
|
|
11063
|
-
|
|
11064
|
-
|
|
11065
|
-
|
|
11066
|
-
|
|
11067
|
-
|
|
11068
|
-
|
|
11069
|
-
|
|
11070
|
-
|
|
11071
|
-
|
|
11072
|
-
|
|
11073
|
-
|
|
11074
|
-
|
|
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
|
+
});
|
|
11075
11228
|
};
|
|
11076
|
-
var
|
|
11229
|
+
var isCollapsed = (data, collapsed) => Boolean(data.children?.length) && collapsed.has(data.id);
|
|
11230
|
+
var isLeaf = (data) => !data.children?.length;
|
|
11077
11231
|
|
|
11078
|
-
// src/components/Tree/layout/RadialTree.
|
|
11079
|
-
|
|
11080
|
-
var RadialTree = (
|
|
11081
|
-
const
|
|
11082
|
-
|
|
11083
|
-
const
|
|
11084
|
-
const
|
|
11085
|
-
|
|
11086
|
-
|
|
11087
|
-
|
|
11088
|
-
|
|
11089
|
-
|
|
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,
|
|
11090
11307
|
radius
|
|
11091
|
-
]).separation((a, b) => (a.parent === b.parent ? 1 : 2) / a.depth);
|
|
11092
|
-
|
|
11093
|
-
|
|
11094
|
-
|
|
11095
|
-
|
|
11096
|
-
|
|
11097
|
-
|
|
11098
|
-
|
|
11099
|
-
|
|
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();
|
|
11100
11336
|
};
|
|
11101
|
-
var RadialTree_default = RadialTree;
|
|
11102
11337
|
|
|
11103
|
-
// src/components/Tree/layout/TidyTree.
|
|
11104
|
-
import { curveBumpX,
|
|
11105
|
-
|
|
11106
|
-
|
|
11107
|
-
|
|
11108
|
-
|
|
11109
|
-
const
|
|
11110
|
-
const
|
|
11111
|
-
const
|
|
11112
|
-
const
|
|
11113
|
-
|
|
11114
|
-
|
|
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([
|
|
11115
11411
|
dx,
|
|
11116
11412
|
dy
|
|
11117
|
-
]);
|
|
11118
|
-
layout(root);
|
|
11413
|
+
])(root);
|
|
11119
11414
|
let x0 = Infinity;
|
|
11120
11415
|
let x1 = -x0;
|
|
11121
|
-
let y0 = Infinity;
|
|
11122
|
-
let y1 = -y0;
|
|
11123
11416
|
root.each((d) => {
|
|
11124
11417
|
if (d.x > x1) {
|
|
11125
11418
|
x1 = d.x;
|
|
@@ -11127,27 +11420,139 @@ var TidyTree = (s, data, options) => {
|
|
|
11127
11420
|
if (d.x < x0) {
|
|
11128
11421
|
x0 = d.x;
|
|
11129
11422
|
}
|
|
11130
|
-
if (d.y > y1) {
|
|
11131
|
-
y1 = d.y;
|
|
11132
|
-
}
|
|
11133
|
-
if (d.y < y0) {
|
|
11134
|
-
y0 = d.y;
|
|
11135
|
-
}
|
|
11136
11423
|
});
|
|
11137
|
-
const
|
|
11138
|
-
const
|
|
11139
|
-
|
|
11140
|
-
const
|
|
11141
|
-
|
|
11142
|
-
|
|
11143
|
-
|
|
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);
|
|
11144
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);
|
|
11145
11551
|
};
|
|
11146
|
-
var TidyTree_default = TidyTree;
|
|
11147
11552
|
|
|
11148
11553
|
// src/components/Tree/types/tree.ts
|
|
11149
11554
|
import * as Schema from "effect/Schema";
|
|
11150
|
-
import { Key, Obj as
|
|
11555
|
+
import { Key, Obj as Obj3, Ref, Type } from "@dxos/echo";
|
|
11151
11556
|
import { TestSchema } from "@dxos/echo/testing";
|
|
11152
11557
|
import { invariant } from "@dxos/invariant";
|
|
11153
11558
|
var TreeNodeType = Schema.Struct({
|
|
@@ -11171,204 +11576,43 @@ var TreeType = Schema.Struct({
|
|
|
11171
11576
|
}));
|
|
11172
11577
|
|
|
11173
11578
|
// src/components/Tree/types/types.ts
|
|
11174
|
-
var
|
|
11175
|
-
|
|
11176
|
-
|
|
11177
|
-
|
|
11178
|
-
|
|
11179
|
-
|
|
11180
|
-
|
|
11181
|
-
|
|
11182
|
-
|
|
11183
|
-
|
|
11184
|
-
};
|
|
11185
|
-
var renderers = /* @__PURE__ */ new Map([
|
|
11186
|
-
[
|
|
11187
|
-
"tidy",
|
|
11188
|
-
TidyTree_default
|
|
11189
|
-
],
|
|
11190
|
-
[
|
|
11191
|
-
"radial",
|
|
11192
|
-
RadialTree_default
|
|
11193
|
-
],
|
|
11194
|
-
[
|
|
11195
|
-
"edge",
|
|
11196
|
-
HierarchicalEdgeBundling_default
|
|
11197
|
-
]
|
|
11198
|
-
]);
|
|
11199
|
-
var Tree = ({ space, selected, variant = "tidy", onNodeClick }) => {
|
|
11200
|
-
const registry = useContext(RegistryContext);
|
|
11201
|
-
const [model] = useAsyncState(async () => space ? new SpaceGraphModel(registry).open(space.db) : void 0, [
|
|
11202
|
-
space,
|
|
11203
|
-
selected,
|
|
11204
|
-
registry
|
|
11205
|
-
]);
|
|
11206
|
-
const [tree3, setTree] = useState2();
|
|
11207
|
-
useEffect5(() => {
|
|
11208
|
-
return model?.subscribe(() => {
|
|
11209
|
-
const tree4 = mapGraphToTreeData(model);
|
|
11210
|
-
setTree(tree4);
|
|
11211
|
-
}, true);
|
|
11212
|
-
}, [
|
|
11213
|
-
model
|
|
11214
|
-
]);
|
|
11215
|
-
const context = useRef3(null);
|
|
11216
|
-
useEffect5(() => {
|
|
11217
|
-
if (context.current?.size) {
|
|
11218
|
-
const { width, height } = context.current.size;
|
|
11219
|
-
const size = Math.min(width, height);
|
|
11220
|
-
const radius = size * 0.4;
|
|
11221
|
-
const options = {
|
|
11222
|
-
// TODO(burdon): Type.
|
|
11223
|
-
label: (d) => d.label ?? d.id,
|
|
11224
|
-
width,
|
|
11225
|
-
height,
|
|
11226
|
-
radius,
|
|
11227
|
-
marginLeft: (width - radius * 2) / 2,
|
|
11228
|
-
marginRight: (width - radius * 2) / 2,
|
|
11229
|
-
marginTop: (height - radius * 2) / 2,
|
|
11230
|
-
marginBottom: (height - radius * 2) / 2,
|
|
11231
|
-
slots: defaultTreeLayoutSlots
|
|
11232
|
-
};
|
|
11233
|
-
if (tree3) {
|
|
11234
|
-
const renderer = renderers.get(variant);
|
|
11235
|
-
renderer?.(context.current.svg, tree3, options);
|
|
11236
|
-
}
|
|
11237
|
-
}
|
|
11238
|
-
}, [
|
|
11239
|
-
context.current,
|
|
11240
|
-
tree3
|
|
11241
|
-
]);
|
|
11242
|
-
return /* @__PURE__ */ React5.createElement("div", {
|
|
11243
|
-
className: "grow",
|
|
11244
|
-
onClick: () => onNodeClick?.()
|
|
11245
|
-
}, /* @__PURE__ */ React5.createElement(SVG2.Root, {
|
|
11246
|
-
ref: context
|
|
11247
|
-
}));
|
|
11248
|
-
};
|
|
11249
|
-
|
|
11250
|
-
// src/hooks/useGraphModel.ts
|
|
11251
|
-
import { useEffect as useEffect6, useState as useState3 } from "react";
|
|
11252
|
-
import { Capabilities } from "@dxos/app-framework";
|
|
11253
|
-
import { useCapability } from "@dxos/app-framework/ui";
|
|
11254
|
-
import { SpaceGraphModel as SpaceGraphModel2 } from "@dxos/schema";
|
|
11255
|
-
var useGraphModel = (space, filter, options, queue) => {
|
|
11256
|
-
const registry = useCapability(Capabilities.AtomRegistry);
|
|
11257
|
-
const [model, setModel] = useState3(void 0);
|
|
11258
|
-
useEffect6(() => {
|
|
11259
|
-
if (!space) {
|
|
11260
|
-
setModel(void 0);
|
|
11261
|
-
return;
|
|
11262
|
-
}
|
|
11263
|
-
const newModel = new SpaceGraphModel2(registry);
|
|
11264
|
-
void newModel.open(space.db, queue);
|
|
11265
|
-
setModel(newModel);
|
|
11266
|
-
return () => {
|
|
11267
|
-
setModel(void 0);
|
|
11268
|
-
void newModel.close();
|
|
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
|
|
11269
11589
|
};
|
|
11270
|
-
}, [
|
|
11271
|
-
space,
|
|
11272
|
-
registry,
|
|
11273
|
-
queue
|
|
11274
|
-
]);
|
|
11275
|
-
useEffect6(() => {
|
|
11276
|
-
model?.setFilter(filter).setOptions(options);
|
|
11277
|
-
}, [
|
|
11278
|
-
model,
|
|
11279
|
-
filter,
|
|
11280
|
-
options
|
|
11281
|
-
]);
|
|
11282
|
-
return model;
|
|
11283
|
-
};
|
|
11284
|
-
|
|
11285
|
-
// src/ExplorerPlugin.tsx
|
|
11286
|
-
import * as Effect from "effect/Effect";
|
|
11287
|
-
import * as Option from "effect/Option";
|
|
11288
|
-
import { Plugin } from "@dxos/app-framework";
|
|
11289
|
-
import { AppPlugin } from "@dxos/app-toolkit";
|
|
11290
|
-
import { Annotation, Type as Type3 } from "@dxos/echo";
|
|
11291
|
-
import { Operation } from "@dxos/operation";
|
|
11292
|
-
import { SpaceOperation } from "@dxos/plugin-space/operations";
|
|
11293
|
-
import { ViewModel } from "@dxos/schema";
|
|
11294
|
-
import { ReactSurface } from "#capabilities";
|
|
11295
|
-
import { meta as meta3 } from "#meta";
|
|
11296
|
-
import { ExplorerAction, Graph as Graph2 } from "#types";
|
|
11297
|
-
|
|
11298
|
-
// src/translations.ts
|
|
11299
|
-
import { Type as Type2 } from "@dxos/echo";
|
|
11300
|
-
import { translations as componentsTranslations } from "@dxos/react-ui-components";
|
|
11301
|
-
import { meta as meta2 } from "#meta";
|
|
11302
|
-
import { Graph } from "#types";
|
|
11303
|
-
var translations = [
|
|
11304
|
-
{
|
|
11305
|
-
"en-US": {
|
|
11306
|
-
[Type2.getTypename(Graph.Graph)]: {
|
|
11307
|
-
"typename.label": "Explorer",
|
|
11308
|
-
"typename.label_zero": "Explorers",
|
|
11309
|
-
"typename.label_one": "Explorer",
|
|
11310
|
-
"typename.label_other": "Explorers",
|
|
11311
|
-
"object-name.placeholder": "New explorer",
|
|
11312
|
-
"add-object.label": "Add explorer",
|
|
11313
|
-
"rename-object.label": "Rename explorer",
|
|
11314
|
-
"delete-object.label": "Delete explorer",
|
|
11315
|
-
"object-deleted.label": "Explorer deleted"
|
|
11316
|
-
},
|
|
11317
|
-
[meta2.id]: {
|
|
11318
|
-
"plugin.name": "Explorer",
|
|
11319
|
-
"object-title.label": "Title"
|
|
11320
|
-
}
|
|
11321
|
-
}
|
|
11322
|
-
},
|
|
11323
|
-
...componentsTranslations
|
|
11324
|
-
];
|
|
11325
|
-
|
|
11326
|
-
// src/ExplorerPlugin.tsx
|
|
11327
|
-
var ExplorerPlugin = Plugin.define(meta3).pipe(AppPlugin.addMetadataModule({
|
|
11328
|
-
metadata: {
|
|
11329
|
-
id: Type3.getTypename(Graph2.Graph),
|
|
11330
|
-
metadata: {
|
|
11331
|
-
icon: Annotation.IconAnnotation.get(Graph2.Graph).pipe(Option.getOrThrow).icon,
|
|
11332
|
-
iconHue: Annotation.IconAnnotation.get(Graph2.Graph).pipe(Option.getOrThrow).hue ?? "white",
|
|
11333
|
-
inputSchema: ExplorerAction.GraphProps,
|
|
11334
|
-
createObject: (props, options) => Effect.gen(function* () {
|
|
11335
|
-
const object = yield* Effect.promise(async () => {
|
|
11336
|
-
const { view } = await ViewModel.makeFromDatabase({
|
|
11337
|
-
db: options.db,
|
|
11338
|
-
typename: props.typename
|
|
11339
|
-
});
|
|
11340
|
-
return Graph2.make({
|
|
11341
|
-
name: props.name,
|
|
11342
|
-
view
|
|
11343
|
-
});
|
|
11344
|
-
});
|
|
11345
|
-
return yield* Operation.invoke(SpaceOperation.AddObject, {
|
|
11346
|
-
object,
|
|
11347
|
-
target: options.target,
|
|
11348
|
-
hidden: true,
|
|
11349
|
-
targetNodeId: options.targetNodeId
|
|
11350
|
-
});
|
|
11351
|
-
})
|
|
11352
|
-
}
|
|
11353
11590
|
}
|
|
11354
|
-
|
|
11355
|
-
|
|
11356
|
-
|
|
11357
|
-
|
|
11358
|
-
|
|
11359
|
-
|
|
11360
|
-
}
|
|
11361
|
-
|
|
11362
|
-
|
|
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
|
+
};
|
|
11598
|
+
};
|
|
11599
|
+
var labelOf2 = (node) => {
|
|
11600
|
+
return typeof node.data?.text === "string" ? node.data.text : void 0;
|
|
11601
|
+
};
|
|
11363
11602
|
export {
|
|
11603
|
+
CanvasForceGraph,
|
|
11364
11604
|
Chart,
|
|
11365
|
-
D3ForceGraph,
|
|
11366
|
-
ExplorerPlugin,
|
|
11367
11605
|
ForceGraph,
|
|
11368
11606
|
Globe,
|
|
11607
|
+
HierarchicalEdgeBundling,
|
|
11608
|
+
RadialTree,
|
|
11609
|
+
TidyTree,
|
|
11369
11610
|
Tree,
|
|
11611
|
+
buildHierarchy,
|
|
11370
11612
|
defaultTreeLayoutSlots,
|
|
11371
|
-
|
|
11372
|
-
|
|
11613
|
+
isCollapsed,
|
|
11614
|
+
isLeaf,
|
|
11615
|
+
spaceGraphToHierarchy,
|
|
11616
|
+
treeTypeToTreeNode
|
|
11373
11617
|
};
|
|
11374
11618
|
//# sourceMappingURL=index.mjs.map
|