@dxos/plugin-explorer 0.12.0-next-73daef452f1464b62efdbca75fb0067c1066f264 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/PLUGIN.mdl +63 -10
- package/dist/lib/ForceGraph.mjs +2 -0
- package/dist/lib/Graph.mjs +4 -5
- package/dist/lib/Graph.mjs.map +1 -1
- package/dist/lib/capabilities.browser.mjs +21 -0
- package/dist/lib/capabilities.browser.mjs.map +1 -0
- package/dist/lib/capabilities.mjs +1 -3
- package/dist/lib/capabilities.mjs.map +1 -1
- package/dist/lib/capabilities.node.mjs.map +1 -1
- package/dist/lib/capabilities.tauri.mjs +21 -0
- package/dist/lib/capabilities.tauri.mjs.map +1 -0
- package/dist/lib/capabilities.workerd.mjs.map +1 -1
- package/dist/lib/chunk-ExplorerArticle.mjs +27 -30
- package/dist/lib/chunk-ExplorerArticle.mjs.map +1 -1
- package/dist/lib/chunk-Graph.mjs +161 -0
- package/dist/lib/chunk-Graph.mjs.map +1 -0
- package/dist/lib/chunk-NeighborhoodCompanion.mjs +26 -22
- package/dist/lib/chunk-NeighborhoodCompanion.mjs.map +1 -1
- package/dist/lib/chunk-PLUGIN.mjs +6 -0
- package/dist/lib/chunk-PLUGIN.mjs.map +1 -0
- package/dist/lib/chunk-app-graph-builder.mjs +2 -1
- package/dist/lib/chunk-app-graph-builder.mjs.map +1 -1
- package/dist/lib/chunk-create-object.mjs +1 -1
- package/dist/lib/chunk-react-surface.mjs +2 -2
- package/dist/lib/chunk-react-surface.mjs.map +1 -1
- package/dist/lib/chunk-rolldown-runtime.mjs +15 -1
- package/dist/lib/{chunk-types.mjs → chunk-tree.mjs} +29 -26
- package/dist/lib/chunk-tree.mjs.map +1 -0
- package/dist/lib/components.mjs +15 -164
- package/dist/lib/components.mjs.map +1 -1
- package/dist/lib/containers.mjs.map +1 -1
- package/dist/lib/hooks.mjs +2 -2
- package/dist/lib/hooks.mjs.map +1 -1
- package/dist/lib/index.mjs +3 -2
- package/dist/lib/meta.mjs.map +1 -1
- package/dist/lib/ns/ForceGraph.mjs +11 -0
- package/dist/lib/ns/ForceGraph.mjs.map +1 -0
- package/dist/lib/ns/Hooks.mjs +10 -0
- package/dist/lib/ns/Hooks.mjs.map +1 -0
- package/dist/lib/testing.mjs +9 -9
- package/dist/lib/testing.mjs.map +1 -1
- package/dist/lib/translations.mjs +2 -2
- package/dist/lib/translations.mjs.map +1 -1
- package/dist/types/src/ForceGraph.d.ts +3 -0
- package/dist/types/src/ForceGraph.d.ts.map +1 -0
- package/dist/types/src/Hooks.d.ts +2 -0
- package/dist/types/src/Hooks.d.ts.map +1 -0
- package/dist/types/src/capabilities/gen/browser.d.ts +7 -0
- package/dist/types/src/capabilities/gen/browser.d.ts.map +1 -0
- package/dist/types/src/capabilities/gen/node.d.ts.map +1 -1
- package/dist/types/src/capabilities/gen/tauri.d.ts +7 -0
- package/dist/types/src/capabilities/gen/tauri.d.ts.map +1 -0
- package/dist/types/src/capabilities/gen/workerd.d.ts.map +1 -1
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/components/Chart/Chart.d.ts +1 -1
- package/dist/types/src/components/Chart/Chart.d.ts.map +1 -1
- package/dist/types/src/components/Chart/Chart.stories.d.ts +1 -1
- package/dist/types/src/components/Chart/Chart.stories.d.ts.map +1 -1
- package/dist/types/src/components/Chart/index.d.ts +1 -1
- package/dist/types/src/components/Chart/index.d.ts.map +1 -1
- package/dist/types/src/components/Globe/Globe.d.ts +1 -1
- package/dist/types/src/components/Globe/Globe.d.ts.map +1 -1
- package/dist/types/src/components/Globe/Globe.stories.d.ts +1 -1
- package/dist/types/src/components/Globe/Globe.stories.d.ts.map +1 -1
- package/dist/types/src/components/Globe/index.d.ts +1 -1
- package/dist/types/src/components/Globe/index.d.ts.map +1 -1
- package/dist/types/src/components/Graph/CanvasForceGraph.stories.d.ts +1 -1
- package/dist/types/src/components/Graph/ForceGraph.d.ts +2 -2
- package/dist/types/src/components/Graph/ForceGraph.d.ts.map +1 -1
- package/dist/types/src/components/Graph/ForceGraph.stories.d.ts +1 -1
- package/dist/types/src/components/Graph/ForceGraph.stories.d.ts.map +1 -1
- package/dist/types/src/components/Graph/index.d.ts +2 -2
- package/dist/types/src/components/Graph/index.d.ts.map +1 -1
- package/dist/types/src/components/Lattice/index.d.ts +1 -1
- package/dist/types/src/components/Lattice/index.d.ts.map +1 -1
- package/dist/types/src/components/Tree/index.d.ts +1 -1
- package/dist/types/src/components/Tree/index.d.ts.map +1 -1
- package/dist/types/src/components/Tree/types/index.d.ts +2 -2
- package/dist/types/src/components/Tree/types/index.d.ts.map +1 -1
- package/dist/types/src/components/Tree/types/tree.d.ts.map +1 -1
- package/dist/types/src/components/Tree/types/types.d.ts +1 -1
- package/dist/types/src/components/Tree/types/types.d.ts.map +1 -1
- package/dist/types/src/components/Visualization/Visualization.d.ts +1 -1
- package/dist/types/src/components/Visualization/Visualization.d.ts.map +1 -1
- package/dist/types/src/components/Visualization/Visualization.stories.d.ts +1 -1
- package/dist/types/src/components/Visualization/Visualization.stories.d.ts.map +1 -1
- package/dist/types/src/components/Visualization/index.d.ts +2 -2
- package/dist/types/src/components/Visualization/index.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +6 -6
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/containers/ExplorerArticle/ExplorerArticle.d.ts +1 -1
- package/dist/types/src/containers/ExplorerArticle/ExplorerArticle.d.ts.map +1 -1
- package/dist/types/src/containers/ExplorerArticle/ExplorerArticle.stories.d.ts +1 -1
- package/dist/types/src/containers/ExplorerArticle/ExplorerArticle.stories.d.ts.map +1 -1
- package/dist/types/src/containers/ExplorerArticle/index.d.ts +1 -1
- package/dist/types/src/containers/ExplorerArticle/index.d.ts.map +1 -1
- package/dist/types/src/containers/NeighborhoodCompanion/NeighborhoodCompanion.d.ts.map +1 -1
- package/dist/types/src/containers/NeighborhoodCompanion/index.d.ts +1 -1
- package/dist/types/src/containers/NeighborhoodCompanion/index.d.ts.map +1 -1
- package/dist/types/src/containers/index.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +2 -2
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +3 -2
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/testing/generator.d.ts +1 -1
- package/dist/types/src/testing/generator.d.ts.map +1 -1
- package/dist/types/src/testing/index.d.ts +3 -3
- package/dist/types/src/testing/index.d.ts.map +1 -1
- package/dist/types/src/testing/relations.d.ts +3 -4
- package/dist/types/src/testing/relations.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +2 -3
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/Graph.d.ts.map +1 -1
- package/dist/types/src/types/index.d.ts +3 -3
- package/dist/types/src/types/index.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +2 -2
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +58 -57
- package/src/ForceGraph.ts +8 -0
- package/src/Hooks.ts +7 -0
- package/src/capabilities/app-graph-builder.ts +2 -1
- package/src/capabilities/gen/browser.ts +32 -0
- package/src/capabilities/gen/node.ts +3 -3
- package/src/capabilities/gen/tauri.ts +32 -0
- package/src/capabilities/gen/workerd.ts +3 -3
- package/src/capabilities/index.ts +4 -4
- package/src/capabilities/react-surface.ts +2 -2
- package/src/components/Chart/Chart.stories.tsx +1 -1
- package/src/components/Chart/Chart.tsx +1 -1
- package/src/components/Chart/index.ts +1 -1
- package/src/components/Globe/Globe.stories.tsx +1 -1
- package/src/components/Globe/Globe.tsx +1 -1
- package/src/components/Globe/index.ts +1 -1
- package/src/components/Graph/CanvasForceGraph.stories.tsx +3 -3
- package/src/components/Graph/CanvasForceGraph.tsx +5 -5
- package/src/components/Graph/ForceGraph.stories.tsx +8 -9
- package/src/components/Graph/ForceGraph.tsx +7 -7
- package/src/components/Graph/index.ts +2 -2
- package/src/components/Lattice/Lattice.stories.tsx +4 -4
- package/src/components/Lattice/Lattice.tsx +2 -2
- package/src/components/Lattice/index.ts +1 -1
- package/src/components/Tree/EdgeBundling.stories.tsx +6 -6
- package/src/components/Tree/Tree.stories.tsx +3 -3
- package/src/components/Tree/index.ts +1 -1
- package/src/components/Tree/types/index.ts +2 -2
- package/src/components/Tree/types/tree.test.ts +4 -4
- package/src/components/Tree/types/tree.ts +27 -24
- package/src/components/Tree/types/types.ts +1 -1
- package/src/components/Visualization/Visualization.stories.tsx +3 -3
- package/src/components/Visualization/Visualization.tsx +8 -9
- package/src/components/Visualization/index.ts +2 -2
- package/src/components/Visualization/variants.ts +1 -1
- package/src/components/index.ts +6 -6
- package/src/containers/ExplorerArticle/ExplorerArticle.stories.tsx +3 -3
- package/src/containers/ExplorerArticle/ExplorerArticle.tsx +17 -16
- package/src/containers/ExplorerArticle/index.ts +1 -1
- package/src/containers/NeighborhoodCompanion/NeighborhoodCompanion.tsx +19 -19
- package/src/containers/NeighborhoodCompanion/index.ts +1 -1
- package/src/containers/index.ts +2 -2
- package/src/hooks/index.ts +2 -2
- package/src/hooks/useGraphModel.ts +2 -2
- package/src/hooks/useNeighborhoodModel.ts +1 -1
- package/src/index.ts +3 -2
- package/src/meta.ts +1 -1
- package/src/plugin.test.ts +2 -2
- package/src/testing/generator.ts +3 -3
- package/src/testing/index.ts +3 -3
- package/src/testing/relations.ts +7 -8
- package/src/translations.ts +4 -4
- package/src/types/Graph.ts +4 -4
- package/src/types/index.ts +3 -3
- package/src/util/index.ts +2 -2
- package/dist/lib/chunk-types.mjs.map +0 -1
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import { meta } from "#meta";
|
|
2
|
+
import { DEFAULT_NEIGHBORHOOD_DEPTH, useNeighborhoodModel } from "#hooks";
|
|
2
3
|
import { useCallback, useState } from "react";
|
|
3
|
-
import { Obj } from "@dxos/echo";
|
|
4
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
-
import {
|
|
5
|
+
import { Obj } from "@dxos/echo";
|
|
6
6
|
import "@dxos/react-ui-graph/styles/graph.css";
|
|
7
|
+
import * as Panel from "@dxos/react-ui/Panel";
|
|
8
|
+
import * as ToggleGroup from "@dxos/react-ui/ToggleGroup";
|
|
9
|
+
import * as Toolbar from "@dxos/react-ui/Toolbar";
|
|
10
|
+
import { DxAnchorActivate } from "@dxos/ui-types";
|
|
7
11
|
import { Visualization } from "#components";
|
|
8
|
-
import
|
|
12
|
+
import * as Hooks from "@dxos/react-ui/Hooks";
|
|
13
|
+
import * as Tooltip from "@dxos/react-ui/Tooltip";
|
|
9
14
|
//#region src/containers/NeighborhoodCompanion/NeighborhoodCompanion.tsx
|
|
10
15
|
/** Selectable traversal depths offered in the companion toolbar. */
|
|
11
16
|
var DEPTHS = [
|
|
@@ -18,7 +23,7 @@ var DEPTHS = [
|
|
|
18
23
|
* with the active node at the centre. Depth (number of hops traversed) is adjustable in the toolbar.
|
|
19
24
|
*/
|
|
20
25
|
var NeighborhoodCompanion = ({ role = "article", subject }) => {
|
|
21
|
-
const { t } = useTranslation(meta.profile.key);
|
|
26
|
+
const { t } = Hooks.useTranslation(meta.profile.key);
|
|
22
27
|
const [depth, setDepth] = useState(DEFAULT_NEIGHBORHOOD_DEPTH);
|
|
23
28
|
const model = useNeighborhoodModel(subject, depth);
|
|
24
29
|
const handleDepthChange = useCallback((value) => {
|
|
@@ -27,7 +32,7 @@ var NeighborhoodCompanion = ({ role = "article", subject }) => {
|
|
|
27
32
|
}, []);
|
|
28
33
|
const handleDismiss = useCallback(() => {
|
|
29
34
|
document.defaultView?.dispatchEvent(new DxAnchorActivate({
|
|
30
|
-
|
|
35
|
+
eid: "",
|
|
31
36
|
label: "",
|
|
32
37
|
trigger: document.body,
|
|
33
38
|
state: false
|
|
@@ -37,33 +42,32 @@ var NeighborhoodCompanion = ({ role = "article", subject }) => {
|
|
|
37
42
|
if (!node || !event) return;
|
|
38
43
|
const obj = node.data;
|
|
39
44
|
if (!obj || !Obj.isObject(obj)) return;
|
|
40
|
-
const
|
|
41
|
-
if (!
|
|
45
|
+
const eid = Obj.getURI(obj);
|
|
46
|
+
if (!eid) return;
|
|
42
47
|
const target = event.target;
|
|
43
48
|
target.dispatchEvent(new DxAnchorActivate({
|
|
44
|
-
|
|
49
|
+
eid,
|
|
45
50
|
kind: "card",
|
|
46
51
|
trigger: target,
|
|
47
|
-
label: Obj.getLabel(obj) ??
|
|
52
|
+
label: Obj.getLabel(obj) ?? eid
|
|
48
53
|
}));
|
|
49
54
|
}, []);
|
|
50
55
|
if (!subject || !model) return null;
|
|
51
56
|
return /* @__PURE__ */ jsxs(Panel.Root, {
|
|
52
57
|
role,
|
|
53
|
-
children: [/* @__PURE__ */ jsx(Panel.Toolbar, {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
children: [/* @__PURE__ */ jsx(Panel.Header, { children: /* @__PURE__ */ jsxs(Toolbar.Root, { children: [/* @__PURE__ */ jsx("div", { className: "grow" }), /* @__PURE__ */ jsx(Toolbar.ToggleGroup, {
|
|
59
|
+
type: "single",
|
|
60
|
+
value: String(depth),
|
|
61
|
+
onValueChange: handleDepthChange,
|
|
62
|
+
children: DEPTHS.map((value) => /* @__PURE__ */ jsx(Tooltip.Trigger, {
|
|
63
|
+
asChild: true,
|
|
64
|
+
content: t("depth.label", { count: value }),
|
|
65
|
+
children: /* @__PURE__ */ jsx(ToggleGroup.Item, {
|
|
60
66
|
value: String(value),
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
})] })
|
|
66
|
-
}), /* @__PURE__ */ jsx(Panel.Content, {
|
|
67
|
+
label: String(value)
|
|
68
|
+
})
|
|
69
|
+
}, value))
|
|
70
|
+
})] }) }), /* @__PURE__ */ jsx(Panel.Body, {
|
|
67
71
|
asChild: true,
|
|
68
72
|
children: /* @__PURE__ */ jsx(Visualization.Root, {
|
|
69
73
|
classNames: "dx-base-surface",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunk-NeighborhoodCompanion.mjs","names":[],"sources":["../../src/containers/NeighborhoodCompanion/NeighborhoodCompanion.tsx"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport React, { useCallback, useState } from 'react';\n\nimport { Obj } from '@dxos/echo';\nimport {
|
|
1
|
+
{"version":3,"file":"chunk-NeighborhoodCompanion.mjs","names":[],"sources":["../../src/containers/NeighborhoodCompanion/NeighborhoodCompanion.tsx"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport React, { useCallback, useState } from 'react';\n\nimport { Obj } from '@dxos/echo';\nimport { type TreeNode } from '@dxos/react-ui-graph';\nimport * as Hooks from '@dxos/react-ui/Hooks';\nimport * as Panel from '@dxos/react-ui/Panel';\nimport * as ToggleGroup from '@dxos/react-ui/ToggleGroup';\nimport * as Toolbar from '@dxos/react-ui/Toolbar';\nimport * as Tooltip from '@dxos/react-ui/Tooltip';\nimport { DxAnchorActivate } from '@dxos/ui-types';\nimport '@dxos/react-ui-graph/styles/graph.css';\n\nimport { Visualization } from '#components';\nimport { DEFAULT_NEIGHBORHOOD_DEPTH, useNeighborhoodModel } from '#hooks';\nimport { meta } from '#meta';\n\n/** Selectable traversal depths offered in the companion toolbar. */\nconst DEPTHS = [1, 2, 3] as const;\n\nexport type NeighborhoodCompanionProps = {\n role?: string;\n /** The active node whose neighbourhood is rendered (passed as the companion subject). */\n subject: Obj.Any;\n};\n\n/**\n * Companion that renders the n-hop neighbourhood of the active node as an ego-centric radial graph,\n * with the active node at the centre. Depth (number of hops traversed) is adjustable in the toolbar.\n */\nexport const NeighborhoodCompanion = ({ role = 'article', subject }: NeighborhoodCompanionProps) => {\n const { t } = Hooks.useTranslation(meta.profile.key);\n const [depth, setDepth] = useState<number>(DEFAULT_NEIGHBORHOOD_DEPTH);\n const model = useNeighborhoodModel(subject, depth);\n\n const handleDepthChange = useCallback((value: string) => {\n const next = Number.parseInt(value, 10);\n if (Number.isFinite(next)) {\n setDepth(next);\n }\n }, []);\n\n // Dismiss the preview popover. The eid/label/trigger fields are placeholders ignored on `state: false`.\n const handleDismiss = useCallback(() => {\n document.defaultView?.dispatchEvent(\n new DxAnchorActivate({ eid: '', label: '', trigger: document.body, state: false }),\n );\n }, []);\n\n const handleHover = useCallback((node: TreeNode | null, event?: MouseEvent) => {\n // Pointer left the node/label: keep the popover open so it can be hovered/interacted with.\n if (!node || !event) {\n return;\n }\n const obj = node.data;\n if (!obj || !Obj.isObject(obj)) {\n return;\n }\n const eid = Obj.getURI(obj);\n if (!eid) {\n return;\n }\n\n const target = event.target as HTMLElement;\n target.dispatchEvent(new DxAnchorActivate({ eid, kind: 'card', trigger: target, label: Obj.getLabel(obj) ?? eid }));\n }, []);\n\n if (!subject || !model) {\n return null;\n }\n\n return (\n <Panel.Root role={role}>\n <Panel.Header>\n <Toolbar.Root>\n <div className='grow' />\n <Toolbar.ToggleGroup type='single' value={String(depth)} onValueChange={handleDepthChange}>\n {DEPTHS.map((value) => (\n <Tooltip.Trigger key={value} asChild content={t('depth.label', { count: value })}>\n <ToggleGroup.Item value={String(value)} label={String(value)} />\n </Tooltip.Trigger>\n ))}\n </Toolbar.ToggleGroup>\n </Toolbar.Root>\n </Panel.Header>\n <Panel.Body asChild>\n <Visualization.Root\n classNames='dx-base-surface'\n model={model}\n variant='neighborhood'\n focus={subject.id}\n onSurfaceClick={handleDismiss}\n >\n <Visualization.Graph onNodeHover={handleHover} />\n </Visualization.Root>\n </Panel.Body>\n </Panel.Root>\n );\n};\n\nNeighborhoodCompanion.displayName = 'NeighborhoodCompanion';\n"],"mappings":";;;;;;;;;;;;;;;AAqBA,IAAM,SAAS;CAAC;CAAG;CAAG;AAAC;;;;;AAYvB,IAAa,yBAAyB,EAAE,OAAO,WAAW,cAA0C;CAClG,MAAM,EAAE,MAAM,MAAM,eAAe,KAAK,QAAQ,GAAG;CACnD,MAAM,CAAC,OAAO,YAAY,SAAiB,0BAA0B;CACrE,MAAM,QAAQ,qBAAqB,SAAS,KAAK;CAEjD,MAAM,oBAAoB,aAAa,UAAkB;EACvD,MAAM,OAAO,OAAO,SAAS,OAAO,EAAE;EACtC,IAAI,OAAO,SAAS,IAAI,GACtB,SAAS,IAAI;CAEjB,GAAG,CAAC,CAAC;CAGL,MAAM,gBAAgB,kBAAkB;EACtC,SAAS,aAAa,cACpB,IAAI,iBAAiB;GAAE,KAAK;GAAI,OAAO;GAAI,SAAS,SAAS;GAAM,OAAO;EAAM,CAAC,CACnF;CACF,GAAG,CAAC,CAAC;CAEL,MAAM,cAAc,aAAa,MAAuB,UAAuB;EAE7E,IAAI,CAAC,QAAQ,CAAC,OACZ;EAEF,MAAM,MAAM,KAAK;EACjB,IAAI,CAAC,OAAO,CAAC,IAAI,SAAS,GAAG,GAC3B;EAEF,MAAM,MAAM,IAAI,OAAO,GAAG;EAC1B,IAAI,CAAC,KACH;EAGF,MAAM,SAAS,MAAM;EACrB,OAAO,cAAc,IAAI,iBAAiB;GAAE;GAAK,MAAM;GAAQ,SAAS;GAAQ,OAAO,IAAI,SAAS,GAAG,KAAK;EAAI,CAAC,CAAC;CACpH,GAAG,CAAC,CAAC;CAEL,IAAI,CAAC,WAAW,CAAC,OACf,OAAO;CAGT,OACE,qBAAC,MAAM,MAAP;EAAkB;EAAlB,UAAA,CACE,oBAAC,MAAM,QAAP,EAAA,UACE,qBAAC,QAAQ,MAAT,EAAA,UAAA,CACE,oBAAC,OAAD,EAAK,WAAU,OAAQ,CAAA,GACvB,oBAAC,QAAQ,aAAT;GAAqB,MAAK;GAAS,OAAO,OAAO,KAAK;GAAG,eAAe;GACrE,UAAA,OAAO,KAAK,UACX,oBAAC,QAAQ,SAAT;IAA6B,SAAA;IAAQ,SAAS,EAAE,eAAe,EAAE,OAAO,MAAM,CAAC;IAC7E,UAAA,oBAAC,YAAY,MAAb;KAAkB,OAAO,OAAO,KAAK;KAAG,OAAO,OAAO,KAAK;IAAI,CAAA;GAChD,GAFK,KAEL,CAClB;EACkB,CAAA,CACT,EAAA,CAAA,EACF,CAAA,GACd,oBAAC,MAAM,MAAP;GAAY,SAAA;GACV,UAAA,oBAAC,cAAc,MAAf;IACE,YAAW;IACJ;IACP,SAAQ;IACR,OAAO,QAAQ;IACf,gBAAgB;IAEhB,UAAA,oBAAC,cAAc,OAAf,EAAqB,aAAa,YAAc,CAAA;GAC9B,CAAA;EACV,CAAA,CACF;;AAEhB;AAEA,sBAAsB,cAAc"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
//#region PLUGIN.mdl?raw
|
|
2
|
+
var PLUGIN_default = "---\nid: org.dxos.plugin.explorer\nname: ExplorerPlugin\nversion: 0.1.0\n---\n\nAn interactive hypergraph visualization plugin for `DXOS` Composer that reveals relationships between objects in a workspace.\nThe plugin renders a live `Graph` object — backed by a `View` and a `QueryAST` query — through four switchable layout\nvariants: force-directed, radial cluster, edge bundling, and lattice.\nNode colours are derived from ECHO object types; hovering a node triggers an anchor-card preview.\n\n## Extensions\n\nThe following extension dialects are used in this document.\nEach extension is defined in the Appendix or resolved via its URI.\n\n| Term | URI |\n|-------------|--------------------------------|\n| `type` | `org.dxos.mdl.type@1.0` |\n| `feat` | `org.dxos.mdl.feat@1.0` |\n| `scenario` | `org.dxos.mdl.scenario@1.0` |\n| `component` | `org.dxos.mdl.component@1.0` |\n| `op` | `org.dxos.mdl.op@1.0` |\n| `test` | `org.dxos.mdl.test@1.0` |\n\n## Types\n\n```mdl\ntype QueryInput\n fields:\n raw?: string # raw query string entered by the user\n ast: QueryAST.Query # compiled AST produced by QueryBuilder\n```\n\n```mdl\ntype GraphObject\n desc: ECHO-persistent object that describes a hypergraph visualisation session.\n fields:\n name?: string\n view: Ref<View> # schema view that defines visible fields\n query: QueryInput\n```\n\n```mdl\ntype ExplorerVariant\n literals: force | cluster | bundle | lattice\n```\n\n## Components\n\n```mdl\ncomponent ExplorerArticle\n desc: |\n Top-level article / section surface for a Graph object.\n Renders one of four SVG layout variants and a toolbar for switching between them.\n props:\n role: article | section\n subject: Ref<View>\n attendableId?: string\n state:\n variant: ExplorerVariant # active layout; default force\n filter?: Filter.Any # compiled from toolbar query input\n model?: SpaceGraphModel # live reactive graph built from db + filter\n slots:\n toolbar?: ReactNode # shown only when role === article\n actions:\n setVariant(v: ExplorerVariant)\n setFilter(raw: string)\n layout: |\n ┌────────────────────────────────┐\n │ [toolbar slot — article only] │\n │ [QueryEditor] [variant tabs] │\n ├────────────────────────────────┤\n │ │\n │ SVG canvas (force / cluster │\n │ / bundle / lattice) │\n │ │\n └────────────────────────────────┘\n```\n\n```mdl\ncomponent Visualization\n desc: |\n Internal component that owns a single persistent SVG.Graph mount.\n Swaps the active GraphProjector when the variant changes, seeding the\n new projector with the previous layout so node positions tween smoothly.\n props:\n variant: ExplorerVariant\n model: SpaceGraphModel\n state:\n projector?: GraphProjector<SpaceGraphNode>\n actions:\n createProjector(variant: ExplorerVariant, prev?: GraphLayout) → GraphProjector\n createRenderNode(variant: ExplorerVariant) → RenderNode\n```\n\n## Operations\n\n```mdl\nop createGraph\n desc: |\n Creates a new Graph object scoped to a target space or collection.\n Derives a ViewModel from the database for the selected typename, then\n writes the object via SpaceOperation.AddObject.\n input:\n name?: string\n typename?: string # ECHO typename used to seed the initial view\n target: Space | Collection\n targetNodeId?: string\n output: GraphObject\n effects: [echo:write]\n note: |\n The typename is resolved through ViewModel.makeFromDatabase; the resulting\n View is stored as a Ref inside the Graph object.\n```\n\n```mdl\nop buildFilter\n desc: |\n Compiles a raw query string into a Filter via QueryBuilder.\n Pure — no side effects; result is passed to SpaceGraphModel.setFilter.\n input:\n raw: string\n output: Filter.Any\n errors:\n ParseError: raw string is not valid query syntax\n```\n\n## Features\n\n```mdl\nfeat F-1: Graph Object\n\n req F-1.1: A Graph object stores a name, a View ref, and a compiled QueryAST.\n req F-1.2:\n when: user creates a new graph\n then: op:createGraph derives a ViewModel from the chosen typename and writes the Graph to ECHO\n\n req F-1.3:\n when: Graph is persisted\n then: it appears in the space object list and can be opened as an article\n```\n\n```mdl\nfeat F-2: Live Graph Model\n\n req F-2.1:\n when: ExplorerArticle mounts with a valid Graph subject\n then: SpaceGraphModel is opened against the subject's database\n\n req F-2.2:\n when: user types a query in the toolbar\n then: op:buildFilter compiles the raw string; model.setFilter applied; SVG re-renders\n\n req F-2.3:\n when: Graph is unmounted\n then: SpaceGraphModel is closed and all subscriptions released\n\n req F-2.4:\n when: an ECHO object in the database changes\n then: SpaceGraphModel emits an update and SVG.Graph re-renders without full remount\n tags: [reactive, collaborative]\n```\n\n```mdl\nfeat F-3: Visualization Variants\n\n req F-3.1:\n when: variant tab is selected\n then: Visualization swaps projector; previous node x/y seed the new projector so positions tween\n\n req F-3.2:\n when: variant is force\n then: SVG.Zoom wrapper is mounted enabling pan/zoom drag interaction\n\n req F-3.3:\n when: variant is cluster or bundle\n then: no SVG.Zoom wrapper; leaves grouped by typename; radial labels fade in after tween\n\n req F-3.4:\n when: variant is lattice\n then: nodes rendered as small rounded rectangles sorted by typename then label\n\n req F-3.5:\n when: variant is cluster and user clicks a root or group node\n then: subtree toggles collapsed/expanded via GraphClusterProjector.toggleCollapsed\n```\n\n```mdl\nfeat F-4: Node Interaction\n\n req F-4.1:\n when: pointer enters a node\n then: DxAnchorActivate event dispatched with the object's DXN and label, kind: card\n\n req F-4.2:\n when: pointer leaves a node\n then: DxAnchorActivate cleared (onNodeHover called with null)\n\n req F-4.3:\n when: node has no underlying ECHO object (synthetic root / group)\n then: no preview dispatched; node rendered in neutral colour\n```\n\n## Acceptance\n\n```mdl\nscenario T-1: Graph creation\n given: user opens the object creation dialog and selects Graph\n when: a typename is selected and the form submitted\n then:\n - op:createGraph runs without error\n - new Graph object visible in space object list\n - Graph.view references a valid View object\n```\n\n```mdl\nscenario T-2: Article mounts model\n given: a Graph with a populated query\n when: ExplorerArticle is rendered with role === article\n then:\n - SpaceGraphModel is opened\n - SVG canvas renders nodes derived from the database\n - toolbar shows QueryEditor and variant tabs\n```\n\n```mdl\nscenario T-3: Variant switch preserves positions\n given: force variant is active with nodes positioned\n when: user switches to cluster variant\n then:\n - projector is recreated from previous layout\n - nodes tween from old positions to cluster target positions\n - SVG.Zoom wrapper is absent in the new mount\n```\n\n```mdl\nscenario T-4: Query filter updates graph\n given: ExplorerArticle is open with all objects visible\n when: user types a typename filter in QueryEditor\n then:\n - op:buildFilter returns a Filter without error\n - SpaceGraphModel.setFilter applied\n - only matching nodes remain visible in the SVG\n```\n\n```mdl\nscenario T-5: Node hover preview\n given: force-directed graph with at least one ECHO object node\n when: pointer enters that node\n then:\n - DxAnchorActivate event fired with correct DXN\n - kind === card\n```\n\n```mdl\nscenario T-6: Lattice sort order\n given: database contains objects of two typenames A and B\n when: lattice variant is active\n then:\n - all typename-A nodes appear before typename-B nodes (or vice-versa, consistent order)\n - within each group nodes are ordered alphabetically by label\n```\n\n```mdl\nscenario T-7: Model closed on unmount\n given: ExplorerArticle is mounted and SpaceGraphModel is open\n when: component unmounts\n then:\n - SpaceGraphModel.close() is called\n - no lingering ECHO subscriptions remain\n```\n\n---\n\n## QA\n\nExecutable tests. Each step carries a human instruction (`do`) and, where the step maps to an\ninvocable operation, an agent binding (`invoke`). Report failures by test and step number.\n\nplugin-explorer is not in `getDefaults` or the dev-only default set (see\n`packages/apps/composer-app/src/plugin-defs.tsx`) — it is OFF by default. Neither `createGraph` nor\n`buildFilter` is a registered runtime `Operation` (no `DXN.make` key exists in\n`src/`) — creation goes through the generic `CreateObjectEntry` capability\n(`src/capabilities/create-object.ts`), a UI-driven path with no operation key to invoke, and the\nquery editor calls `buildFilter` as a plain in-process function. Both steps are human-only.\n\n```mdl\ntest QA-1: Create a Graph and switch layout variants\n desc: The core explorer round-trip — create a Graph object, watch it render, switch between layout variants.\n actors: human\n covers: [F-1.1, F-1.2, F-1.3, F-3.1, T-1, T-2, T-3]\n status: unverified\n given:\n - an identity exists\n - space: a space is open, containing at least one object of some typename to visualize\n - no Graph named \"QA Graph\" exists — ABORT rather than reusing one this test did not create\n steps:\n - name: Create the Graph\n do: In the navtree, click + on the space and choose Explorer > Graph. Name it \"QA Graph\" and pick a typename to seed the view.\n expect: a Graph object named \"QA Graph\" is created and opens as an article, rendering an SVG force-directed graph of matching objects\n note: |\n NO `invoke` — `createGraph` has no runtime operation key; the navtree action calls the\n `CreateObjectEntry` capability directly (see above).\n - name: Switch to the cluster variant\n do: Click the \"cluster\" tab in the variant toolbar.\n expect: the projector swaps to radial cluster layout; nodes tween from their force positions rather than jumping; no pan/zoom wrapper is present\n - name: Switch to the lattice variant\n do: Click the \"lattice\" tab.\n expect: nodes render as small rounded rectangles, grouped by typename then sorted alphabetically by label\n - name: Hover a node\n do: Move the pointer over any node with an underlying ECHO object.\n expect: an anchor-card preview appears showing the object's label\n after:\n - name: Delete the Graph\n do: Right-click \"QA Graph\" in the navtree and choose Delete.\n expect: the row leaves the navtree and its plank closes\n note: |\n NO `invoke` here either — the test never captured a live reference to the Graph (its\n creation had no `invoke`/`capture`), so a runner must resolve it by querying\n `space.db.query(dxos.Filter.everything())` for the object named \"QA Graph\" and call\n `org.dxos.operation.space.removeObjects` with that reference, rather than the test\n guessing an id it was never given.\n```\n\n---\n\n## Appendix: Extension Definitions\n\nExtension block types used in this document are defined below using\nthe core `ext` primitive — the only construct the base language provides.\n\n```mdl\next type\n uri: org.dxos.mdl.type@1.0\n desc: A named data structure with typed fields and optional literals.\n fields:\n desc?: Prose\n fields?: FieldMap # name[?]: TypeExpr (# inline comment)\n literals?: UnionList # a | b | c\n extends?: TypeRef[]\n```\n\n```mdl\next feat\n uri: org.dxos.mdl.feat@1.0\n desc: A named feature grouping one or more requirements.\n fields:\n desc?: Prose\n req: RequirementList\n nesting: self # feat blocks may contain feat blocks\n```\n\n```mdl\next scenario\n uri: org.dxos.mdl.scenario@1.0\n desc: An acceptance scenario expressed as given / when / then steps.\n fields:\n given?: Step | Step[]\n when?: Step | Step[]\n then: Step | Step[]\n tags?: TagList\n```\n\n```mdl\next component\n uri: org.dxos.mdl.component@1.0\n desc: A UI component with props, internal state, slots, actions, and events.\n fields:\n desc?: Prose\n props?: FieldMap # external inputs (immutable inside component)\n state?: FieldMap # internal reactive state\n slots?: FieldMap # named ReactNode injection points\n actions?: ActionMap # methods the component exposes or handles\n emits?: EventMap # events the component raises to its parent\n layout?: CodeBlock # ASCII sketch of visual structure (non-normative)\n```\n\n```mdl\next op\n uri: org.dxos.mdl.op@1.0\n desc: |\n A named operation with typed inputs, outputs, and declared errors.\n Pure ops have no effects or requires. Effectful ops declare both.\n fields:\n desc?: Prose\n input?: FieldMap # named input parameters\n output?: TypeExpr # return type\n errors?: ErrorMap # name: Prose (when this error occurs)\n effects?: EffectList # echo:read | echo:write | http | fs | ...\n requires?: ServiceList # injected service dependencies\n note?: Prose # implementation guidance (non-normative)\n```\n";
|
|
3
|
+
//#endregion
|
|
4
|
+
export { PLUGIN_default as t };
|
|
5
|
+
|
|
6
|
+
//# sourceMappingURL=chunk-PLUGIN.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk-PLUGIN.mjs","names":[],"sources":[],"mappings":""}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { meta } from "#meta";
|
|
2
|
-
import { Position } from "@dxos/util";
|
|
3
2
|
import * as Effect from "effect/Effect";
|
|
4
3
|
import * as Capability from "@dxos/app-framework/Capability";
|
|
5
4
|
import * as AppGraphBuilder from "@dxos/app-graph/AppGraphBuilder";
|
|
6
5
|
import * as AppCapabilities from "@dxos/app-toolkit/AppCapabilities";
|
|
7
6
|
import * as AppNode from "@dxos/app-toolkit/AppNode";
|
|
8
7
|
import * as AppNodeMatcher from "@dxos/app-toolkit/AppNodeMatcher";
|
|
8
|
+
import * as Position from "@dxos/util/Position";
|
|
9
9
|
//#region src/capabilities/app-graph-builder.ts
|
|
10
10
|
/**
|
|
11
11
|
* Offers a "Neighborhood" companion on any ECHO object. The matched node is passed through as the
|
|
@@ -14,6 +14,7 @@ import * as AppNodeMatcher from "@dxos/app-toolkit/AppNodeMatcher";
|
|
|
14
14
|
var app_graph_builder_default = Capability.makeModule(Effect.fnUntraced(function* () {
|
|
15
15
|
const extensions = yield* Effect.all([AppGraphBuilder.createExtension({
|
|
16
16
|
id: "neighborhoodCompanion",
|
|
17
|
+
relation: AppNode.companion,
|
|
17
18
|
match: AppNodeMatcher.whenEchoObjectMatches,
|
|
18
19
|
connector: () => Effect.succeed([AppNode.makeCompanion({
|
|
19
20
|
variant: "neighborhood",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunk-app-graph-builder.mjs","names":[],"sources":["../../src/capabilities/app-graph-builder.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport * as Capability from '@dxos/app-framework/Capability';\nimport * as AppGraphBuilder from '@dxos/app-graph/AppGraphBuilder';\nimport * as AppCapabilities from '@dxos/app-toolkit/AppCapabilities';\nimport * as AppNode from '@dxos/app-toolkit/AppNode';\nimport * as AppNodeMatcher from '@dxos/app-toolkit/AppNodeMatcher';\nimport
|
|
1
|
+
{"version":3,"file":"chunk-app-graph-builder.mjs","names":[],"sources":["../../src/capabilities/app-graph-builder.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport * as Capability from '@dxos/app-framework/Capability';\nimport * as AppGraphBuilder from '@dxos/app-graph/AppGraphBuilder';\nimport * as AppCapabilities from '@dxos/app-toolkit/AppCapabilities';\nimport * as AppNode from '@dxos/app-toolkit/AppNode';\nimport * as AppNodeMatcher from '@dxos/app-toolkit/AppNodeMatcher';\nimport * as Position from '@dxos/util/Position';\n\nimport { meta } from '#meta';\n\n/**\n * Offers a \"Neighborhood\" companion on any ECHO object. The matched node is passed through as the\n * companion's `companionTo` (the active node), which the surface renders as an ego-centric graph.\n */\nexport default Capability.makeModule(\n Effect.fnUntraced(function* () {\n const extensions = yield* Effect.all([\n AppGraphBuilder.createExtension({\n id: 'neighborhoodCompanion',\n relation: AppNode.companion,\n match: AppNodeMatcher.whenEchoObjectMatches,\n connector: () =>\n Effect.succeed([\n AppNode.makeCompanion({\n variant: 'neighborhood',\n label: ['neighborhood-companion.label', { ns: meta.profile.key }],\n icon: 'ph--share-network--regular',\n data: 'neighborhood',\n position: Position.last,\n }),\n ]),\n }),\n ]);\n\n return Capability.contribute(AppCapabilities.AppGraphBuilder, extensions);\n }),\n);\n"],"mappings":";;;;;;;;;;;;;AAmBA,IAAA,4BAAe,WAAW,WACxB,OAAO,WAAW,aAAa;CAC7B,MAAM,aAAa,OAAO,OAAO,IAAI,CACnC,gBAAgB,gBAAgB;EAC9B,IAAI;EACJ,UAAU,QAAQ;EAClB,OAAO,eAAe;EACtB,iBACE,OAAO,QAAQ,CACb,QAAQ,cAAc;GACpB,SAAS;GACT,OAAO,CAAC,gCAAgC,EAAE,IAAI,KAAK,QAAQ,IAAI,CAAC;GAChE,MAAM;GACN,MAAM;GACN,UAAU,SAAS;EACrB,CAAC,CACH,CAAC;CACL,CAAC,CACH,CAAC;CAED,OAAO,WAAW,WAAW,gBAAgB,iBAAiB,UAAU;AAC1E,CAAC,CACH"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ExplorerAction, Graph } from "#types";
|
|
2
1
|
import { Type } from "@dxos/echo";
|
|
2
|
+
import { ExplorerAction, Graph } from "#types";
|
|
3
3
|
import { ViewModel } from "@dxos/schema";
|
|
4
4
|
import * as Effect from "effect/Effect";
|
|
5
5
|
import * as Capability from "@dxos/app-framework/Capability";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Graph } from "#types";
|
|
2
2
|
import * as Capabilities from "@dxos/app-framework/Capabilities";
|
|
3
|
-
import { Surface } from "@dxos/app-framework/ui";
|
|
4
3
|
import * as Effect from "effect/Effect";
|
|
5
4
|
import * as Capability from "@dxos/app-framework/Capability";
|
|
6
|
-
import
|
|
5
|
+
import * as Surface from "@dxos/app-framework/Surface";
|
|
6
|
+
import * as AppSurface from "@dxos/app-toolkit/AppSurface";
|
|
7
7
|
import { ExplorerArticle, NeighborhoodCompanion } from "#containers";
|
|
8
8
|
//#region src/capabilities/react-surface.ts
|
|
9
9
|
var react_surface_default = Capability.makeModule(() => Effect.succeed(Capability.contribute(Capabilities.ReactSurface, [Surface.create({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunk-react-surface.mjs","names":[],"sources":["../../src/capabilities/react-surface.ts"],"sourcesContent":["//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport * as Capabilities from '@dxos/app-framework/Capabilities';\nimport * as Capability from '@dxos/app-framework/Capability';\nimport
|
|
1
|
+
{"version":3,"file":"chunk-react-surface.mjs","names":[],"sources":["../../src/capabilities/react-surface.ts"],"sourcesContent":["//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport * as Capabilities from '@dxos/app-framework/Capabilities';\nimport * as Capability from '@dxos/app-framework/Capability';\nimport * as Surface from '@dxos/app-framework/Surface';\nimport * as AppSurface from '@dxos/app-toolkit/AppSurface';\n\nimport { ExplorerArticle, NeighborhoodCompanion } from '#containers';\nimport { Graph } from '#types';\n\nexport default Capability.makeModule(() =>\n Effect.succeed(\n Capability.contribute(Capabilities.ReactSurface, [\n Surface.create({\n id: 'article',\n // TODO(wittjosiah): Split into multiple surfaces if this filter proves too strict for non-article roles.\n filter: AppSurface.oneOf(\n AppSurface.object(AppSurface.Article, Graph.Graph),\n AppSurface.object(AppSurface.Section, Graph.Graph),\n ),\n component: ExplorerArticle,\n props: ({ role, data: { subject, attendableId } }) => ({ role, subject, attendableId }),\n }),\n // Neighborhood companion offered on any ECHO object; `companionTo` is the active node.\n Surface.create({\n id: 'neighborhood',\n filter: AppSurface.allOf(\n AppSurface.literal(AppSurface.Article, 'neighborhood'),\n AppSurface.companion(AppSurface.Article),\n ),\n component: NeighborhoodCompanion,\n props: ({ role, data: { companionTo } }) => ({ role, subject: companionTo }),\n }),\n ]),\n ),\n);\n"],"mappings":";;;;;;;;AAcA,IAAA,wBAAe,WAAW,iBACxB,OAAO,QACL,WAAW,WAAW,aAAa,cAAc,CAC/C,QAAQ,OAAO;CACb,IAAI;CAEJ,QAAQ,WAAW,MACjB,WAAW,OAAO,WAAW,SAAS,MAAM,KAAK,GACjD,WAAW,OAAO,WAAW,SAAS,MAAM,KAAK,CACnD;CACA,WAAW;CACX,QAAQ,EAAE,MAAM,MAAM,EAAE,SAAS,sBAAsB;EAAE;EAAM;EAAS;CAAa;AACvF,CAAC,GAED,QAAQ,OAAO;CACb,IAAI;CACJ,QAAQ,WAAW,MACjB,WAAW,QAAQ,WAAW,SAAS,cAAc,GACrD,WAAW,UAAU,WAAW,OAAO,CACzC;CACA,WAAW;CACX,QAAQ,EAAE,MAAM,MAAM,EAAE,qBAAqB;EAAE;EAAM,SAAS;CAAY;AAC5E,CAAC,CACH,CAAC,CACH,CACF"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
//#region \0rolldown/runtime.js
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
3
6
|
var __exportAll = (all, no_symbols) => {
|
|
4
7
|
let target = {};
|
|
5
8
|
for (var name in all) __defProp(target, name, {
|
|
@@ -9,5 +12,16 @@ var __exportAll = (all, no_symbols) => {
|
|
|
9
12
|
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
10
13
|
return target;
|
|
11
14
|
};
|
|
15
|
+
var __copyProps = (to, from, except, desc) => {
|
|
16
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
17
|
+
key = keys[i];
|
|
18
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
19
|
+
get: ((k) => from[k]).bind(null, key),
|
|
20
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
return to;
|
|
24
|
+
};
|
|
25
|
+
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
12
26
|
//#endregion
|
|
13
|
-
export { __exportAll as t };
|
|
27
|
+
export { __reExport as n, __exportAll as t };
|
|
@@ -121,10 +121,11 @@ var Tree = class Tree {
|
|
|
121
121
|
* Clear tree.
|
|
122
122
|
*/
|
|
123
123
|
clear() {
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
124
|
+
const rootId = this._tree.root;
|
|
125
|
+
Obj.update(this._tree, (tree) => {
|
|
126
|
+
const root = tree.nodes[rootId];
|
|
127
|
+
root.children.length = 0;
|
|
128
|
+
tree.nodes = { [rootId]: root };
|
|
128
129
|
});
|
|
129
130
|
}
|
|
130
131
|
/**
|
|
@@ -137,9 +138,9 @@ var Tree = class Tree {
|
|
|
137
138
|
data: { text: "" }
|
|
138
139
|
};
|
|
139
140
|
const nodeToAdd = node;
|
|
140
|
-
Obj.update(this._tree, (
|
|
141
|
-
|
|
142
|
-
parent.children.splice(index ?? parent.children.length, 0, nodeToAdd.id);
|
|
141
|
+
Obj.update(this._tree, (tree) => {
|
|
142
|
+
tree.nodes[nodeToAdd.id] = nodeToAdd;
|
|
143
|
+
tree.nodes[parent.id].children.splice(index ?? parent.children.length, 0, nodeToAdd.id);
|
|
143
144
|
});
|
|
144
145
|
return node;
|
|
145
146
|
}
|
|
@@ -149,12 +150,12 @@ var Tree = class Tree {
|
|
|
149
150
|
deleteNode(parent, id) {
|
|
150
151
|
const node = this._tree.nodes[id];
|
|
151
152
|
if (!node) return;
|
|
152
|
-
Obj.update(this._tree, (
|
|
153
|
-
delete
|
|
153
|
+
Obj.update(this._tree, (tree) => {
|
|
154
|
+
delete tree.nodes[node.id];
|
|
154
155
|
});
|
|
155
156
|
const idx = parent.children.findIndex((child) => child === id);
|
|
156
|
-
if (idx !== -1) Obj.update(this._tree, () => {
|
|
157
|
-
parent.children.splice(idx, 1);
|
|
157
|
+
if (idx !== -1) Obj.update(this._tree, (tree) => {
|
|
158
|
+
tree.nodes[parent.id].children.splice(idx, 1);
|
|
158
159
|
});
|
|
159
160
|
return node;
|
|
160
161
|
}
|
|
@@ -165,22 +166,23 @@ var Tree = class Tree {
|
|
|
165
166
|
invariant(from >= 0 && from < node.children.length, void 0, {
|
|
166
167
|
"~LogMeta": "~LogMeta",
|
|
167
168
|
F: __dxlog_file,
|
|
168
|
-
L:
|
|
169
|
+
L: 235,
|
|
169
170
|
S: this,
|
|
170
171
|
A: ["from >= 0 && from < node.children.length", ""]
|
|
171
172
|
});
|
|
172
173
|
invariant(to >= 0 && to < node.children.length, void 0, {
|
|
173
174
|
"~LogMeta": "~LogMeta",
|
|
174
175
|
F: __dxlog_file,
|
|
175
|
-
L:
|
|
176
|
+
L: 236,
|
|
176
177
|
S: this,
|
|
177
178
|
A: ["to >= 0 && to < node.children.length", ""]
|
|
178
179
|
});
|
|
179
180
|
if (from === to) return null;
|
|
180
181
|
const child = node.children[from];
|
|
181
|
-
Obj.update(this._tree, () => {
|
|
182
|
-
node.children
|
|
183
|
-
|
|
182
|
+
Obj.update(this._tree, (tree) => {
|
|
183
|
+
const children = tree.nodes[node.id].children;
|
|
184
|
+
children.splice(from, 1);
|
|
185
|
+
children.splice(to, 0, child);
|
|
184
186
|
});
|
|
185
187
|
return this.getNode(child);
|
|
186
188
|
}
|
|
@@ -193,9 +195,9 @@ var Tree = class Tree {
|
|
|
193
195
|
const idx = parent.children.findIndex((child) => child === node.id);
|
|
194
196
|
if (idx < 1 || idx >= parent.children.length) return;
|
|
195
197
|
const previous = this.getNode(parent.children[idx - 1]);
|
|
196
|
-
Obj.update(this._tree, () => {
|
|
197
|
-
parent.children.splice(idx, 1);
|
|
198
|
-
previous.children.push(node.id);
|
|
198
|
+
Obj.update(this._tree, (tree) => {
|
|
199
|
+
tree.nodes[parent.id].children.splice(idx, 1);
|
|
200
|
+
tree.nodes[previous.id].children.push(node.id);
|
|
199
201
|
});
|
|
200
202
|
}
|
|
201
203
|
/**
|
|
@@ -208,19 +210,20 @@ var Tree = class Tree {
|
|
|
208
210
|
if (!ancestor) return;
|
|
209
211
|
const nodeIdx = parent.children.findIndex((id) => id === node.id);
|
|
210
212
|
let rest = [];
|
|
211
|
-
Obj.update(this._tree, () => {
|
|
212
|
-
|
|
213
|
+
Obj.update(this._tree, (tree) => {
|
|
214
|
+
const children = tree.nodes[parent.id].children;
|
|
215
|
+
rest = children.splice(nodeIdx, children.length - nodeIdx).slice(1);
|
|
213
216
|
});
|
|
214
217
|
const parentIdx = this.getChildNodes(ancestor).findIndex((n) => n.id === parent.id);
|
|
215
|
-
Obj.update(this._tree, () => {
|
|
216
|
-
ancestor.children.splice(parentIdx + 1, 0, node.id);
|
|
218
|
+
Obj.update(this._tree, (tree) => {
|
|
219
|
+
tree.nodes[ancestor.id].children.splice(parentIdx + 1, 0, node.id);
|
|
217
220
|
});
|
|
218
|
-
Obj.update(this._tree, () => {
|
|
219
|
-
node.children.push(...rest);
|
|
221
|
+
Obj.update(this._tree, (tree) => {
|
|
222
|
+
tree.nodes[node.id].children.push(...rest);
|
|
220
223
|
});
|
|
221
224
|
}
|
|
222
225
|
};
|
|
223
226
|
//#endregion
|
|
224
227
|
export { TreeNodeType as n, TreeType as r, Tree as t };
|
|
225
228
|
|
|
226
|
-
//# sourceMappingURL=chunk-
|
|
229
|
+
//# sourceMappingURL=chunk-tree.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk-tree.mjs","names":[],"sources":["../../src/components/Tree/types/tree.ts"],"sourcesContent":["//\n// Copyright 2023 DXOS.org\n//\n\nimport * as Schema from 'effect/Schema';\nimport * as Struct from 'effect/Struct';\n\nimport { DXN, Key, Obj, Ref, Type } from '@dxos/echo';\nimport { TestSchema } from '@dxos/echo/testing';\nimport { invariant } from '@dxos/invariant';\n\n// TODO(burdon): Reconcile with @dxos/graph (i.e., common types).\n\nexport const TreeNodeType = Schema.Struct({\n id: Key.EntityId,\n children: Schema.mutable(Schema.Array(Key.EntityId)),\n data: Schema.mutableKey(Schema.Record(Schema.String, Schema.mutableKey(Schema.Any))),\n ref: Schema.optional(Ref.Ref(TestSchema.Expando)),\n}).mapFields(Struct.map(Schema.mutableKey));\n\nexport type TreeNodeType = Schema.Schema.Type<typeof TreeNodeType>;\n\nexport class TreeType extends Type.makeObject<TreeType>(DXN.make('org.dxos.type.tree', '0.1.0'))(\n Schema.Struct({\n root: Key.EntityId,\n nodes: Schema.mutableKey(Schema.Record(Key.EntityId, Schema.mutableKey(TreeNodeType))),\n }),\n) {}\n\n/**\n * Wrapper object for tree.\n */\nexport class Tree {\n static create = (): TreeType => {\n const id = Key.EntityId.random();\n return Obj.make(TreeType, {\n root: id,\n nodes: {\n [id]: {\n id,\n children: [],\n data: { text: '' }, // TODO(burdon): Generic.\n },\n },\n });\n };\n\n private _tree: TreeType;\n\n constructor(tree?: TreeType) {\n this._tree = tree ?? Tree.create();\n }\n\n get tree() {\n return this._tree;\n }\n\n // TODO(burdon): Make reactive.\n get size() {\n return Object.keys(this._tree.nodes).length;\n }\n\n get root() {\n return this.getNode(this._tree.root);\n }\n\n //\n // Traversal\n //\n\n /**\n * Recursively traverse the tree until the callback returns a value.\n */\n tranverse<T>(\n callback: (node: TreeNodeType, depth: number) => T | void,\n root: Key.EntityId = this._tree.root,\n depth = 0,\n ): T | void {\n const node = this._tree.nodes[root];\n const result = callback(node, depth);\n if (result !== undefined) {\n return result;\n }\n\n for (const childId of node.children) {\n const result = this.tranverse(callback, childId, depth + 1);\n if (result !== undefined) {\n return result;\n }\n }\n }\n\n getNode(id: Key.EntityId): TreeNodeType {\n const node = this._tree.nodes[id];\n invariant(node);\n return node;\n }\n\n /**\n * Get the children of a node.\n */\n getChildNodes(node: TreeNodeType): Array<TreeNodeType> {\n return node.children.map((id) => this.getNode(id));\n }\n\n /**\n * Get the parent of a node.\n */\n getParent(node: TreeNodeType): TreeNodeType | null {\n const parent = this.tranverse((n) => {\n if (n.children.includes(node.id)) {\n return n;\n }\n });\n\n return parent ?? null;\n }\n\n /**\n * Get the next node in the tree.\n */\n getNext(node: TreeNodeType, hierarchical = true): TreeNodeType | undefined {\n if (hierarchical && node.children.length) {\n // First child.\n return this.getChildNodes(node)[0];\n } else {\n const parent = this.getParent(node);\n if (parent) {\n const idx = this.getChildNodes(parent).findIndex(({ id }) => id === node.id);\n if (idx < parent.children.length - 1) {\n // Next sibling.\n return this.getNode(parent.children[idx + 1]);\n } else {\n // Get parent's next sibling.\n return this.getNext(parent, false);\n }\n }\n }\n }\n\n /**\n * Get the previous node in the tree.\n */\n getPrevious(node: TreeNodeType, hierarchical = true): TreeNodeType | undefined {\n const parent = this.getParent(node)!;\n const idx = this.getChildNodes(parent).findIndex(({ id }) => id === node.id);\n if (idx === 0) {\n if (hierarchical) {\n return parent;\n }\n } else {\n const previous = this.getNode(parent.children[idx - 1]);\n if (hierarchical && previous.children.length) {\n return this.getLastDescendent(previous);\n }\n\n return previous;\n }\n }\n\n /**\n * Get the last descendent of a node.\n */\n getLastDescendent(node: TreeNodeType): TreeNodeType | undefined {\n const children = this.getChildNodes(node);\n const last = children.length ? children[children.length - 1] : undefined;\n if (last) {\n return this.getLastDescendent(last);\n }\n\n return node;\n }\n\n //\n // Mutations\n //\n\n /**\n * Clear tree.\n */\n clear(): void {\n const rootId = this._tree.root;\n Obj.update(this._tree, (tree) => {\n const root = tree.nodes[rootId];\n root.children.length = 0;\n tree.nodes = {\n [rootId]: root,\n };\n });\n }\n\n /**\n * Add node.\n */\n addNode(parent: TreeNodeType, node?: TreeNodeType, index?: number): TreeNodeType {\n if (!node) {\n const id = Key.EntityId.random();\n node = { id, children: [], data: { text: '' } }; // TODO(burdon): Generic.\n }\n\n const nodeToAdd = node;\n Obj.update(this._tree, (tree) => {\n tree.nodes[nodeToAdd.id] = nodeToAdd;\n tree.nodes[parent.id].children.splice(index ?? parent.children.length, 0, nodeToAdd.id);\n });\n return node;\n }\n\n /**\n * Delete node.\n */\n deleteNode(parent: TreeNodeType, id: Key.EntityId): TreeNodeType | undefined {\n const node = this._tree.nodes[id];\n if (!node) {\n return undefined;\n }\n\n Obj.update(this._tree, (tree) => {\n delete tree.nodes[node.id];\n });\n const idx = parent.children.findIndex((child) => child === id);\n if (idx !== -1) {\n Obj.update(this._tree, (tree) => {\n tree.nodes[parent.id].children.splice(idx, 1);\n });\n }\n\n return node;\n }\n\n /**\n * Move child node.\n */\n moveNode(node: TreeNodeType, from: number, to: number): TreeNodeType | null {\n invariant(from >= 0 && from < node.children.length);\n invariant(to >= 0 && to < node.children.length);\n if (from === to) {\n return null;\n }\n\n const child = node.children[from];\n Obj.update(this._tree, (tree) => {\n const children = tree.nodes[node.id].children;\n children.splice(from, 1);\n children.splice(to, 0, child);\n });\n return this.getNode(child);\n }\n\n /**\n * Indent node.\n */\n indentNode(node: TreeNodeType): void {\n const parent = this.getParent(node);\n if (!parent) {\n return;\n }\n\n const idx = parent.children.findIndex((child) => child === node.id);\n if (idx < 1 || idx >= parent.children.length) {\n return;\n }\n\n const previous = this.getNode(parent.children[idx - 1]);\n Obj.update(this._tree, (tree) => {\n tree.nodes[parent.id].children.splice(idx, 1);\n tree.nodes[previous.id].children.push(node.id);\n });\n }\n\n /**\n * Unindent node.\n */\n unindentNode(node: TreeNodeType): void {\n const parent = this.getParent(node);\n if (!parent) {\n return;\n }\n\n const ancestor = this.getParent(parent);\n if (!ancestor) {\n return;\n }\n\n // Remove node from parent and get following siblings.\n const nodeIdx = parent.children.findIndex((id) => id === node.id);\n let rest: Key.EntityId[] = [];\n Obj.update(this._tree, (tree) => {\n const children = tree.nodes[parent.id].children;\n const removed = children.splice(nodeIdx, children.length - nodeIdx);\n rest = removed.slice(1); // Skip the node itself.\n });\n\n // Add to ancestor.\n const parentIdx = this.getChildNodes(ancestor).findIndex((n) => n.id === parent.id);\n Obj.update(this._tree, (tree) => {\n tree.nodes[ancestor.id].children.splice(parentIdx + 1, 0, node.id);\n });\n\n // Transplant following siblings to current node.\n Obj.update(this._tree, (tree) => {\n tree.nodes[node.id].children.push(...rest);\n });\n }\n}\n"],"mappings":"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"}
|
package/dist/lib/components.mjs
CHANGED
|
@@ -1,21 +1,17 @@
|
|
|
1
|
-
import { n as
|
|
2
|
-
import
|
|
1
|
+
import { n as CanvasForceGraph, t as ForceGraph } from "./chunk-Graph.mjs";
|
|
2
|
+
import { n as TreeNodeType, r as TreeType, t as Tree } from "./chunk-tree.mjs";
|
|
3
|
+
import { curveCatmullRom, line, select } from "d3";
|
|
3
4
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
4
5
|
import { useResizeDetector } from "react-resize-detector";
|
|
5
|
-
import
|
|
6
|
-
import { getHashHue, getHashStyles } from "@dxos/ui-theme";
|
|
6
|
+
import * as Util from "@dxos/react-ui/Util";
|
|
7
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
-
import
|
|
9
|
-
import { curveCatmullRom, forceLink, forceManyBody, line, select } from "d3";
|
|
10
|
-
import NativeForceGraph from "force-graph";
|
|
11
|
-
import { composable, composableProps, slottable } from "@dxos/react-ui";
|
|
12
|
-
import { useAtomValue } from "@effect/atom-react/Hooks";
|
|
13
|
-
import * as Atom from "effect/unstable/reactivity/Atom";
|
|
14
|
-
import { SelectionModel } from "@dxos/graph";
|
|
8
|
+
import { Obj } from "@dxos/echo";
|
|
15
9
|
import { CLUSTER_NODE_TYPE_LEAF, CLUSTER_NODE_TYPE_ROOT, GraphBundleProjector, GraphClusterProjector, GraphForceProjector, GraphLatticeProjector, GraphPlexusProjector, GraphSwarmProjector, GraphTreeProjector, PLEXUS_NODE_TYPE_FOCUS, PLEXUS_NODE_TYPE_RELATION, SVG, TREE_NODE_TYPE_INBOUND, TREE_NODE_TYPE_ROOT, appendRadialGroupLabel, appendRadialLeafLabel, appendRootLabel, useContainerSize } from "@dxos/react-ui-graph";
|
|
16
|
-
import "@dxos/
|
|
17
|
-
import
|
|
18
|
-
import
|
|
10
|
+
import { getHashHue } from "@dxos/ui-theme";
|
|
11
|
+
import * as Plot from "@observablehq/plot";
|
|
12
|
+
import * as topojson from "topojson-client";
|
|
13
|
+
import { ark } from "@ark-ui/react/factory";
|
|
14
|
+
import { createContext } from "@dxos/react-hooks";
|
|
19
15
|
//#region src/util/node-color.ts
|
|
20
16
|
/**
|
|
21
17
|
* Returns the SVG `fill` value for a node, derived from its typename via the
|
|
@@ -11660,151 +11656,6 @@ var Globe = ({ items = [], accessor, projection = "orthographic", options = defa
|
|
|
11660
11656
|
});
|
|
11661
11657
|
};
|
|
11662
11658
|
//#endregion
|
|
11663
|
-
//#region src/components/Graph/graph-adapter.ts
|
|
11664
|
-
/**
|
|
11665
|
-
* Map common graph to force-graph format.
|
|
11666
|
-
*/
|
|
11667
|
-
var GraphAdapter = class {
|
|
11668
|
-
graph;
|
|
11669
|
-
_nodes = [];
|
|
11670
|
-
_links = [];
|
|
11671
|
-
constructor(graph) {
|
|
11672
|
-
this.graph = graph;
|
|
11673
|
-
this._nodes = graph.nodes.map((node) => ({
|
|
11674
|
-
id: node.id,
|
|
11675
|
-
type: node.type,
|
|
11676
|
-
data: node.data
|
|
11677
|
-
}));
|
|
11678
|
-
const nodeIds = new Set(this._nodes.map((node) => node.id));
|
|
11679
|
-
this._links = graph.edges.filter((edge) => nodeIds.has(edge.source) && nodeIds.has(edge.target)).map((edge) => ({
|
|
11680
|
-
type: edge.type,
|
|
11681
|
-
source: edge.source,
|
|
11682
|
-
target: edge.target,
|
|
11683
|
-
data: edge.data
|
|
11684
|
-
}));
|
|
11685
|
-
}
|
|
11686
|
-
get nodes() {
|
|
11687
|
-
return this._nodes;
|
|
11688
|
-
}
|
|
11689
|
-
get links() {
|
|
11690
|
-
return this._links;
|
|
11691
|
-
}
|
|
11692
|
-
};
|
|
11693
|
-
//#endregion
|
|
11694
|
-
//#region src/components/Graph/CanvasForceGraph.tsx
|
|
11695
|
-
/**
|
|
11696
|
-
* More performance optimized version of the ForceGraph.
|
|
11697
|
-
*/
|
|
11698
|
-
var CanvasForceGraph = composable(({ model, match, onClick, ...props }, forwardedRef) => {
|
|
11699
|
-
const { ref: resizeRef, width, height } = useResizeDetector({ refreshRate: 200 });
|
|
11700
|
-
const setRef = useCallback((node) => {
|
|
11701
|
-
resizeRef(node);
|
|
11702
|
-
assignRef(forwardedRef, node);
|
|
11703
|
-
}, [resizeRef, forwardedRef]);
|
|
11704
|
-
const rootRef = useRef(null);
|
|
11705
|
-
const forceGraph = useRef(null);
|
|
11706
|
-
const [data, setData] = useState();
|
|
11707
|
-
useEffect(() => {
|
|
11708
|
-
return model?.subscribe((model) => setData(new GraphAdapter(model.graph)));
|
|
11709
|
-
}, [model]);
|
|
11710
|
-
useEffect(() => {
|
|
11711
|
-
if (rootRef.current) 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);
|
|
11712
|
-
return () => {
|
|
11713
|
-
forceGraph.current?.pauseAnimation().graphData({
|
|
11714
|
-
nodes: [],
|
|
11715
|
-
links: []
|
|
11716
|
-
});
|
|
11717
|
-
forceGraph.current = null;
|
|
11718
|
-
};
|
|
11719
|
-
}, []);
|
|
11720
|
-
useEffect(() => {
|
|
11721
|
-
if (!data || !width || !height || !forceGraph.current) return;
|
|
11722
|
-
forceGraph.current.pauseAnimation().width(width).height(height).onEngineStop(() => handleZoomToFit()).onNodeClick((node) => {
|
|
11723
|
-
forceGraph.current?.emitParticle(node);
|
|
11724
|
-
}).d3Force("link", forceLink().distance(160).strength(.5)).d3Force("charge", forceManyBody().strength(-30)).graphData(data).warmupTicks(100).cooldownTime(1e3).resumeAnimation();
|
|
11725
|
-
}, [
|
|
11726
|
-
data,
|
|
11727
|
-
width,
|
|
11728
|
-
height
|
|
11729
|
-
]);
|
|
11730
|
-
const handleZoomToFit = () => {
|
|
11731
|
-
forceGraph.current?.zoomToFit(400, 40);
|
|
11732
|
-
};
|
|
11733
|
-
const handleClick = useCallback((event) => {
|
|
11734
|
-
onClick?.(event);
|
|
11735
|
-
if (!event.defaultPrevented) handleZoomToFit();
|
|
11736
|
-
}, [onClick]);
|
|
11737
|
-
return /* @__PURE__ */ jsx("div", {
|
|
11738
|
-
...composableProps(props, { classNames: "relative grow" }),
|
|
11739
|
-
onClick: handleClick,
|
|
11740
|
-
ref: setRef,
|
|
11741
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
11742
|
-
ref: rootRef,
|
|
11743
|
-
className: "absolute inset-0"
|
|
11744
|
-
})
|
|
11745
|
-
});
|
|
11746
|
-
});
|
|
11747
|
-
var assignRef = (ref, value) => {
|
|
11748
|
-
if (typeof ref === "function") ref(value);
|
|
11749
|
-
else if (ref) ref.current = value;
|
|
11750
|
-
};
|
|
11751
|
-
//#endregion
|
|
11752
|
-
//#region src/components/Graph/ForceGraph.tsx
|
|
11753
|
-
var EMPTY_ATOM = Atom.make({
|
|
11754
|
-
nodes: [],
|
|
11755
|
-
edges: []
|
|
11756
|
-
});
|
|
11757
|
-
var ForceGraph = composable(({ model, selection: selectionProp, grid, drag, onInspect, ...props }, forwardedRef) => {
|
|
11758
|
-
useAtomValue(model?.graphAtom ?? EMPTY_ATOM);
|
|
11759
|
-
const graph = useRef(null);
|
|
11760
|
-
const selection = useMemo(() => selectionProp ?? new SelectionModel(), [selectionProp]);
|
|
11761
|
-
useEffect(() => {
|
|
11762
|
-
return selection.subscribe(() => graph.current?.repaint());
|
|
11763
|
-
}, [selection]);
|
|
11764
|
-
const svgRef = useRef(null);
|
|
11765
|
-
const [projector, setProjector] = useState();
|
|
11766
|
-
useEffect(() => {
|
|
11767
|
-
if (svgRef.current) setProjector(new GraphForceProjector(svgRef.current, {
|
|
11768
|
-
attributes: { linkForce: (edge) => edge.data?.object?.active !== false },
|
|
11769
|
-
forces: { point: { strength: .01 } }
|
|
11770
|
-
}));
|
|
11771
|
-
}, []);
|
|
11772
|
-
const handleSelect = useCallback((node) => {
|
|
11773
|
-
if (selection.contains(node.id)) selection.remove(node.id);
|
|
11774
|
-
else selection.add(node.id);
|
|
11775
|
-
}, [selection]);
|
|
11776
|
-
return /* @__PURE__ */ jsx("div", {
|
|
11777
|
-
...composableProps(props, { classNames: "dx-container" }),
|
|
11778
|
-
ref: forwardedRef,
|
|
11779
|
-
children: /* @__PURE__ */ jsxs(SVG.Root, {
|
|
11780
|
-
ref: svgRef,
|
|
11781
|
-
children: [
|
|
11782
|
-
/* @__PURE__ */ jsx(SVG.Markers, {}),
|
|
11783
|
-
grid && /* @__PURE__ */ jsx(SVG.Grid, { axis: true }),
|
|
11784
|
-
/* @__PURE__ */ jsx(SVG.Zoom, {
|
|
11785
|
-
extent: [1 / 2, 2],
|
|
11786
|
-
children: /* @__PURE__ */ jsx(SVG.Graph, {
|
|
11787
|
-
ref: graph,
|
|
11788
|
-
drag,
|
|
11789
|
-
model,
|
|
11790
|
-
projector,
|
|
11791
|
-
labels: { text: (node) => node.data?.data.label ?? node.id },
|
|
11792
|
-
attributes: { node: (node) => {
|
|
11793
|
-
const obj = node.data?.data.object;
|
|
11794
|
-
return {
|
|
11795
|
-
data: { color: getHashStyles(obj && Obj.getTypename(obj))?.hue },
|
|
11796
|
-
classes: { "dx-selected": selection.contains(node.id) }
|
|
11797
|
-
};
|
|
11798
|
-
} },
|
|
11799
|
-
onSelect: handleSelect,
|
|
11800
|
-
onInspect
|
|
11801
|
-
})
|
|
11802
|
-
})
|
|
11803
|
-
]
|
|
11804
|
-
})
|
|
11805
|
-
});
|
|
11806
|
-
});
|
|
11807
|
-
//#endregion
|
|
11808
11659
|
//#region src/components/Lattice/Lattice.tsx
|
|
11809
11660
|
var TRANSITION_MS = 350;
|
|
11810
11661
|
/**
|
|
@@ -11851,7 +11702,7 @@ var Lattice = ({ nodes, padding = 16, onNodeHover }) => {
|
|
|
11851
11702
|
]);
|
|
11852
11703
|
return /* @__PURE__ */ jsx("div", {
|
|
11853
11704
|
ref: setRef,
|
|
11854
|
-
className: "dx-
|
|
11705
|
+
className: "dx-expand relative",
|
|
11855
11706
|
children: width > 0 && height > 0 && /* @__PURE__ */ jsx("svg", {
|
|
11856
11707
|
ref: svgRef,
|
|
11857
11708
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -12223,14 +12074,14 @@ var [VisualizationProvider, useVisualizationContext] = createContext("Visualizat
|
|
|
12223
12074
|
* focus) with the child `Visualization.Graph` via context, so the variant string is set in one
|
|
12224
12075
|
* place. The surface element is slottable via `asChild` for composition into a host layout.
|
|
12225
12076
|
*/
|
|
12226
|
-
var VisualizationRoot = slottable(({ children, asChild, model, variant, focus, onSurfaceClick, ...props }, forwardedRef) => {
|
|
12227
|
-
const { className, ...rest } = composableProps(props, { classNames: "dx-
|
|
12228
|
-
const Comp = asChild ? Slot : "div";
|
|
12077
|
+
var VisualizationRoot = Util.slottable(({ children, asChild, model, variant, focus, onSurfaceClick, ...props }, forwardedRef) => {
|
|
12078
|
+
const { className, ...rest } = Util.composableProps(props, { classNames: "dx-expand relative" });
|
|
12229
12079
|
return /* @__PURE__ */ jsx(VisualizationProvider, {
|
|
12230
12080
|
model,
|
|
12231
12081
|
variant: getVariant(variant),
|
|
12232
12082
|
focus,
|
|
12233
|
-
children: /* @__PURE__ */ jsx(
|
|
12083
|
+
children: /* @__PURE__ */ jsx(ark.div, {
|
|
12084
|
+
asChild,
|
|
12234
12085
|
...rest,
|
|
12235
12086
|
className,
|
|
12236
12087
|
onClick: onSurfaceClick,
|