@dxos/plugin-explorer 0.8.4-main.406dc2a → 0.8.4-main.4668b7de9b
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/PLUGIN.mdl +340 -0
- package/dist/lib/neutral/ExplorerArticle-4I7PNGDC.mjs +459 -0
- package/dist/lib/neutral/ExplorerArticle-4I7PNGDC.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/neutral/chunk-3D7BYXOR.mjs +37 -0
- package/dist/lib/neutral/chunk-3D7BYXOR.mjs.map +7 -0
- package/dist/lib/neutral/chunk-42BYLQQA.mjs +42 -0
- package/dist/lib/neutral/chunk-42BYLQQA.mjs.map +7 -0
- package/dist/lib/neutral/chunk-7XUDLV6E.mjs +287 -0
- package/dist/lib/neutral/chunk-7XUDLV6E.mjs.map +7 -0
- package/dist/lib/neutral/chunk-HI324IB4.mjs +69 -0
- package/dist/lib/neutral/chunk-HI324IB4.mjs.map +7 -0
- package/dist/lib/neutral/chunk-IKHJV3Q4.mjs +20 -0
- package/dist/lib/neutral/chunk-IKHJV3Q4.mjs.map +7 -0
- package/dist/lib/{browser/chunk-MOM5KCKC.mjs → neutral/components/index.mjs} +882 -556
- package/dist/lib/neutral/components/index.mjs.map +7 -0
- package/dist/lib/neutral/containers/index.mjs +9 -0
- package/dist/lib/neutral/containers/index.mjs.map +7 -0
- package/dist/lib/neutral/create-object-F6TKVAGV.mjs +39 -0
- package/dist/lib/neutral/create-object-F6TKVAGV.mjs.map +7 -0
- package/dist/lib/neutral/hooks/index.mjs +45 -0
- package/dist/lib/neutral/hooks/index.mjs.map +7 -0
- package/dist/lib/neutral/index.mjs +14 -0
- package/dist/lib/neutral/meta.json +1 -0
- package/dist/lib/{browser → neutral}/meta.mjs +1 -1
- package/dist/lib/neutral/plugin.mjs +12 -0
- package/dist/lib/neutral/plugin.mjs.map +7 -0
- package/dist/lib/neutral/react-surface-APBW2VQG.mjs +26 -0
- package/dist/lib/neutral/react-surface-APBW2VQG.mjs.map +7 -0
- package/dist/lib/neutral/testing/index.mjs +139 -0
- package/dist/lib/neutral/testing/index.mjs.map +7 -0
- package/dist/lib/neutral/translations.mjs +33 -0
- package/dist/lib/neutral/translations.mjs.map +7 -0
- package/dist/lib/{browser → neutral}/types/index.mjs +1 -2
- 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 +3 -1
- package/dist/types/src/ExplorerPlugin.d.ts.map +1 -1
- package/dist/types/src/ExplorerPlugin.test.d.ts +2 -0
- package/dist/types/src/ExplorerPlugin.test.d.ts.map +1 -0
- package/dist/types/src/capabilities/create-object.d.ts +11 -0
- package/dist/types/src/capabilities/create-object.d.ts.map +1 -0
- package/dist/types/src/capabilities/index.d.ts +8 -2
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts +3 -2
- package/dist/types/src/capabilities/react-surface.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 +4 -1
- package/dist/types/src/components/Chart/Chart.stories.d.ts.map +1 -1
- package/dist/types/src/components/Globe/Globe.d.ts +1 -1
- package/dist/types/src/components/Globe/Globe.d.ts.map +1 -1
- package/dist/types/src/components/Globe/Globe.stories.d.ts +5 -2
- package/dist/types/src/components/Globe/Globe.stories.d.ts.map +1 -1
- package/dist/types/src/components/Graph/CanvasForceGraph.d.ts +13 -0
- package/dist/types/src/components/Graph/CanvasForceGraph.d.ts.map +1 -0
- package/dist/types/src/components/Graph/CanvasForceGraph.stories.d.ts +17 -0
- 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 +4 -2
- 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} +2 -2
- package/dist/types/src/components/Graph/graph-adapter.d.ts.map +1 -0
- package/dist/types/src/components/Graph/index.d.ts +1 -1
- package/dist/types/src/components/Graph/index.d.ts.map +1 -1
- package/dist/types/src/components/Lattice/Lattice.d.ts +20 -0
- package/dist/types/src/components/Lattice/Lattice.d.ts.map +1 -0
- package/dist/types/src/components/Lattice/Lattice.stories.d.ts +8 -0
- package/dist/types/src/components/Lattice/Lattice.stories.d.ts.map +1 -0
- package/dist/types/src/components/Lattice/index.d.ts +2 -0
- package/dist/types/src/components/Lattice/index.d.ts.map +1 -0
- package/dist/types/src/components/Tree/EdgeBundling.stories.d.ts +21 -0
- package/dist/types/src/components/Tree/EdgeBundling.stories.d.ts.map +1 -0
- package/dist/types/src/components/Tree/Tree.d.ts +20 -23
- package/dist/types/src/components/Tree/Tree.d.ts.map +1 -1
- package/dist/types/src/components/Tree/Tree.stories.d.ts +5 -12
- package/dist/types/src/components/Tree/Tree.stories.d.ts.map +1 -1
- package/dist/types/src/components/Tree/index.d.ts +2 -0
- package/dist/types/src/components/Tree/index.d.ts.map +1 -1
- package/dist/types/src/components/Tree/layout/HierarchicalEdgeBundling.d.ts +37 -2
- package/dist/types/src/components/Tree/layout/HierarchicalEdgeBundling.d.ts.map +1 -1
- package/dist/types/src/components/Tree/layout/RadialTree.d.ts +35 -2
- package/dist/types/src/components/Tree/layout/RadialTree.d.ts.map +1 -1
- package/dist/types/src/components/Tree/layout/TidyTree.d.ts +24 -2
- package/dist/types/src/components/Tree/layout/TidyTree.d.ts.map +1 -1
- package/dist/types/src/components/Tree/layout/hierarchy.d.ts +17 -0
- package/dist/types/src/components/Tree/layout/hierarchy.d.ts.map +1 -0
- package/dist/types/src/components/Tree/layout/index.d.ts +5 -4
- package/dist/types/src/components/Tree/layout/index.d.ts.map +1 -1
- package/dist/types/src/components/Tree/layout/slots.d.ts +7 -0
- package/dist/types/src/components/Tree/layout/slots.d.ts.map +1 -0
- package/dist/types/src/components/Tree/layout/useContainerSize.d.ts +15 -0
- package/dist/types/src/components/Tree/layout/useContainerSize.d.ts.map +1 -0
- package/dist/types/src/components/Tree/types/tree.d.ts +50 -27
- package/dist/types/src/components/Tree/types/tree.d.ts.map +1 -1
- package/dist/types/src/components/Tree/types/types.d.ts +14 -4
- package/dist/types/src/components/Tree/types/types.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +1 -4
- package/dist/types/src/components/index.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 +15 -0
- package/dist/types/src/containers/ExplorerArticle/ExplorerArticle.stories.d.ts.map +1 -0
- package/dist/types/src/containers/ExplorerArticle/Visualization.d.ts +18 -0
- package/dist/types/src/containers/ExplorerArticle/Visualization.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/ExplorerArticle/variants.d.ts +9 -0
- package/dist/types/src/containers/ExplorerArticle/variants.d.ts.map +1 -0
- package/dist/types/src/containers/index.d.ts +3 -0
- package/dist/types/src/containers/index.d.ts.map +1 -0
- 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/meta.d.ts +2 -2
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/plugin.d.ts +3 -0
- package/dist/types/src/plugin.d.ts.map +1 -0
- package/dist/types/src/{components/Tree/testing → testing}/generator.d.ts +1 -1
- package/dist/types/src/testing/generator.d.ts.map +1 -0
- package/dist/types/src/testing/index.d.ts +4 -0
- package/dist/types/src/testing/index.d.ts.map +1 -0
- package/dist/types/src/testing/relations.d.ts +32 -0
- package/dist/types/src/testing/relations.d.ts.map +1 -0
- package/dist/types/src/translations.d.ts +31 -22
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/ExplorerAction.d.ts +1 -18
- package/dist/types/src/types/ExplorerAction.d.ts.map +1 -1
- package/dist/types/src/types/Graph.d.ts +14 -25
- package/dist/types/src/types/Graph.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +3 -0
- package/dist/types/src/util/index.d.ts.map +1 -0
- package/dist/types/src/util/node-color.d.ts +13 -0
- package/dist/types/src/util/node-color.d.ts.map +1 -0
- package/dist/types/src/{components → util}/plot.d.ts +1 -1
- package/dist/types/src/util/plot.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +113 -65
- package/src/ExplorerPlugin.test.ts +26 -0
- package/src/ExplorerPlugin.tsx +20 -54
- package/src/capabilities/create-object.ts +36 -0
- package/src/capabilities/index.ts +3 -3
- package/src/capabilities/react-surface.tsx +24 -19
- package/src/components/Chart/Chart.stories.tsx +16 -23
- package/src/components/Chart/Chart.tsx +1 -1
- package/src/components/Globe/Globe.stories.tsx +19 -22
- package/src/components/Globe/Globe.tsx +1 -1
- package/src/components/Graph/CanvasForceGraph.stories.tsx +97 -0
- package/src/components/Graph/CanvasForceGraph.tsx +124 -0
- package/src/components/Graph/ForceGraph.stories.tsx +98 -42
- package/src/components/Graph/ForceGraph.tsx +105 -85
- package/src/components/Graph/{adapter.ts → graph-adapter.ts} +14 -8
- package/src/components/Graph/index.ts +1 -1
- package/src/components/Lattice/Lattice.stories.tsx +104 -0
- package/src/components/Lattice/Lattice.tsx +182 -0
- package/src/components/Lattice/index.ts +5 -0
- package/src/components/Tree/EdgeBundling.stories.tsx +144 -0
- package/src/components/Tree/Tree.stories.tsx +20 -38
- package/src/components/Tree/Tree.tsx +69 -95
- package/src/components/Tree/index.ts +2 -0
- package/src/components/Tree/layout/HierarchicalEdgeBundling.tsx +335 -0
- package/src/components/Tree/layout/RadialTree.tsx +242 -0
- package/src/components/Tree/layout/TidyTree.tsx +246 -0
- package/src/components/Tree/layout/hierarchy.ts +32 -0
- package/src/components/Tree/layout/index.ts +5 -5
- package/src/components/Tree/layout/slots.ts +19 -0
- package/src/components/Tree/layout/useContainerSize.ts +43 -0
- package/src/components/Tree/types/tree.test.ts +8 -7
- package/src/components/Tree/types/tree.ts +51 -35
- package/src/components/Tree/types/types.ts +38 -29
- package/src/components/index.ts +1 -4
- package/src/containers/ExplorerArticle/ExplorerArticle.stories.tsx +152 -0
- package/src/containers/ExplorerArticle/ExplorerArticle.tsx +120 -0
- package/src/containers/ExplorerArticle/Visualization.tsx +523 -0
- package/src/containers/ExplorerArticle/index.ts +5 -0
- package/src/containers/ExplorerArticle/variants.ts +47 -0
- package/src/containers/index.ts +7 -0
- package/src/hooks/useGraphModel.ts +25 -14
- package/src/index.ts +1 -4
- package/src/meta.ts +30 -6
- package/src/plugin.ts +9 -0
- package/src/{components/Tree/testing → testing}/generator.ts +6 -4
- package/src/testing/index.ts +9 -0
- package/src/testing/relations.ts +117 -0
- package/src/translations.ts +16 -13
- package/src/types/ExplorerAction.ts +10 -19
- package/src/types/Graph.ts +20 -24
- package/src/typings.d.ts +8 -0
- package/src/util/index.ts +6 -0
- package/src/util/node-color.ts +23 -0
- package/src/{components → util}/plot.ts +16 -4
- package/src/vite-env.d.ts +10 -0
- package/dist/lib/browser/ExplorerContainer-6SHZJ6AK.mjs +0 -50
- package/dist/lib/browser/ExplorerContainer-6SHZJ6AK.mjs.map +0 -7
- package/dist/lib/browser/chunk-2DGFNLRO.mjs +0 -19
- package/dist/lib/browser/chunk-2DGFNLRO.mjs.map +0 -7
- package/dist/lib/browser/chunk-2MKBRIUT.mjs +0 -31
- package/dist/lib/browser/chunk-2MKBRIUT.mjs.map +0 -7
- package/dist/lib/browser/chunk-BZ65T5M3.mjs +0 -79
- package/dist/lib/browser/chunk-BZ65T5M3.mjs.map +0 -7
- package/dist/lib/browser/chunk-MOM5KCKC.mjs.map +0 -7
- package/dist/lib/browser/chunk-NXGP6NTP.mjs +0 -203
- package/dist/lib/browser/chunk-NXGP6NTP.mjs.map +0 -7
- package/dist/lib/browser/index.mjs +0 -118
- package/dist/lib/browser/index.mjs.map +0 -7
- package/dist/lib/browser/intent-resolver-K57C3LIX.mjs +0 -31
- package/dist/lib/browser/intent-resolver-K57C3LIX.mjs.map +0 -7
- package/dist/lib/browser/meta.json +0 -1
- package/dist/lib/browser/react-surface-OPBND5W3.mjs +0 -35
- package/dist/lib/browser/react-surface-OPBND5W3.mjs.map +0 -7
- package/dist/lib/node-esm/ExplorerContainer-FRTDXZI5.mjs +0 -51
- package/dist/lib/node-esm/ExplorerContainer-FRTDXZI5.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-3ODK27PU.mjs +0 -33
- package/dist/lib/node-esm/chunk-3ODK27PU.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-6JACZE7E.mjs +0 -205
- package/dist/lib/node-esm/chunk-6JACZE7E.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-ES6AOMCY.mjs +0 -80
- package/dist/lib/node-esm/chunk-ES6AOMCY.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +0 -11
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-PX6LHR2N.mjs +0 -21
- package/dist/lib/node-esm/chunk-PX6LHR2N.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-ZCV4U7LT.mjs +0 -11343
- package/dist/lib/node-esm/chunk-ZCV4U7LT.mjs.map +0 -7
- package/dist/lib/node-esm/index.mjs +0 -119
- package/dist/lib/node-esm/index.mjs.map +0 -7
- package/dist/lib/node-esm/intent-resolver-BLPPTTEY.mjs +0 -32
- package/dist/lib/node-esm/intent-resolver-BLPPTTEY.mjs.map +0 -7
- package/dist/lib/node-esm/meta.json +0 -1
- package/dist/lib/node-esm/meta.mjs +0 -9
- package/dist/lib/node-esm/react-surface-HCKQSHKJ.mjs +0 -36
- package/dist/lib/node-esm/react-surface-HCKQSHKJ.mjs.map +0 -7
- package/dist/lib/node-esm/types/index.mjs +0 -12
- package/dist/types/src/capabilities/intent-resolver.d.ts +0 -4
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +0 -1
- package/dist/types/src/components/ExplorerContainer.d.ts +0 -9
- package/dist/types/src/components/ExplorerContainer.d.ts.map +0 -1
- package/dist/types/src/components/Graph/D3ForceGraph.d.ts +0 -14
- package/dist/types/src/components/Graph/D3ForceGraph.d.ts.map +0 -1
- package/dist/types/src/components/Graph/D3ForceGraph.stories.d.ts +0 -15
- package/dist/types/src/components/Graph/D3ForceGraph.stories.d.ts.map +0 -1
- package/dist/types/src/components/Graph/adapter.d.ts.map +0 -1
- package/dist/types/src/components/Graph/testing.d.ts +0 -14
- package/dist/types/src/components/Graph/testing.d.ts.map +0 -1
- package/dist/types/src/components/Tree/testing/generator.d.ts.map +0 -1
- package/dist/types/src/components/Tree/testing/index.d.ts +0 -2
- package/dist/types/src/components/Tree/testing/index.d.ts.map +0 -1
- package/dist/types/src/components/plot.d.ts.map +0 -1
- package/src/capabilities/intent-resolver.ts +0 -21
- package/src/components/ExplorerContainer.tsx +0 -54
- package/src/components/Graph/D3ForceGraph.stories.tsx +0 -77
- package/src/components/Graph/D3ForceGraph.tsx +0 -101
- package/src/components/Graph/testing.ts +0 -55
- package/src/components/Tree/layout/HierarchicalEdgeBundling.ts +0 -162
- package/src/components/Tree/layout/RadialTree.ts +0 -94
- package/src/components/Tree/layout/TidyTree.ts +0 -101
- package/src/components/Tree/testing/index.ts +0 -5
- /package/dist/lib/{browser/chunk-J5LGTIGS.mjs.map → neutral/ExplorerPlugin.mjs.map} +0 -0
- /package/dist/lib/{browser → neutral}/chunk-J5LGTIGS.mjs +0 -0
- /package/dist/lib/{browser/meta.mjs.map → neutral/chunk-J5LGTIGS.mjs.map} +0 -0
- /package/dist/lib/{browser/types → neutral}/index.mjs.map +0 -0
- /package/dist/lib/{node-esm → neutral}/meta.mjs.map +0 -0
- /package/dist/lib/{node-esm → neutral}/types/index.mjs.map +0 -0
|
@@ -4,38 +4,34 @@
|
|
|
4
4
|
|
|
5
5
|
import * as Schema from 'effect/Schema';
|
|
6
6
|
|
|
7
|
-
import { Key, Obj, Type } from '@dxos/echo';
|
|
7
|
+
import { DXN, Key, Obj, Ref, Type } from '@dxos/echo';
|
|
8
|
+
import { TestSchema } from '@dxos/echo/testing';
|
|
8
9
|
import { invariant } from '@dxos/invariant';
|
|
9
10
|
|
|
10
11
|
// TODO(burdon): Reconcile with @dxos/graph (i.e., common types).
|
|
11
12
|
|
|
12
13
|
export const TreeNodeType = Schema.Struct({
|
|
13
|
-
id: Key.
|
|
14
|
-
children: Schema.mutable(Schema.Array(Key.
|
|
14
|
+
id: Key.EntityId,
|
|
15
|
+
children: Schema.mutable(Schema.Array(Key.EntityId)),
|
|
15
16
|
data: Schema.mutable(Schema.Record({ key: Schema.String, value: Schema.Any })),
|
|
16
|
-
ref: Schema.optional(
|
|
17
|
+
ref: Schema.optional(Ref.Ref(TestSchema.Expando)),
|
|
17
18
|
}).pipe(Schema.mutable);
|
|
18
19
|
|
|
19
|
-
export
|
|
20
|
+
export type TreeNodeType = Schema.Schema.Type<typeof TreeNodeType>;
|
|
20
21
|
|
|
21
22
|
export const TreeType = Schema.Struct({
|
|
22
|
-
root: Key.
|
|
23
|
-
nodes: Schema.mutable(Schema.Record({ key: Key.
|
|
24
|
-
}).pipe(
|
|
25
|
-
Type.Obj({
|
|
26
|
-
typename: 'dxos.org/type/Tree',
|
|
27
|
-
version: '0.1.0',
|
|
28
|
-
}),
|
|
29
|
-
);
|
|
23
|
+
root: Key.EntityId,
|
|
24
|
+
nodes: Schema.mutable(Schema.Record({ key: Key.EntityId, value: TreeNodeType })),
|
|
25
|
+
}).pipe(Type.makeObject(DXN.make('org.dxos.type.tree', '0.1.0')));
|
|
30
26
|
|
|
31
|
-
export
|
|
27
|
+
export type TreeType = Type.InstanceType<typeof TreeType>;
|
|
32
28
|
|
|
33
29
|
/**
|
|
34
30
|
* Wrapper object for tree.
|
|
35
31
|
*/
|
|
36
32
|
export class Tree {
|
|
37
33
|
static create = (): TreeType => {
|
|
38
|
-
const id = Key.
|
|
34
|
+
const id = Key.EntityId.random();
|
|
39
35
|
return Obj.make(TreeType, {
|
|
40
36
|
root: id,
|
|
41
37
|
nodes: {
|
|
@@ -76,7 +72,7 @@ export class Tree {
|
|
|
76
72
|
*/
|
|
77
73
|
tranverse<T>(
|
|
78
74
|
callback: (node: TreeNodeType, depth: number) => T | void,
|
|
79
|
-
root: Key.
|
|
75
|
+
root: Key.EntityId = this._tree.root,
|
|
80
76
|
depth = 0,
|
|
81
77
|
): T | void {
|
|
82
78
|
const node = this._tree.nodes[root];
|
|
@@ -93,7 +89,7 @@ export class Tree {
|
|
|
93
89
|
}
|
|
94
90
|
}
|
|
95
91
|
|
|
96
|
-
getNode(id: Key.
|
|
92
|
+
getNode(id: Key.EntityId): TreeNodeType {
|
|
97
93
|
const node = this._tree.nodes[id];
|
|
98
94
|
invariant(node);
|
|
99
95
|
return node;
|
|
@@ -184,9 +180,11 @@ export class Tree {
|
|
|
184
180
|
clear(): void {
|
|
185
181
|
const root = this._tree.nodes[this._tree.root];
|
|
186
182
|
root.children.length = 0;
|
|
187
|
-
this._tree
|
|
188
|
-
|
|
189
|
-
|
|
183
|
+
Obj.update(this._tree, (obj) => {
|
|
184
|
+
obj.nodes = {
|
|
185
|
+
[root.id]: root,
|
|
186
|
+
};
|
|
187
|
+
});
|
|
190
188
|
}
|
|
191
189
|
|
|
192
190
|
/**
|
|
@@ -194,28 +192,35 @@ export class Tree {
|
|
|
194
192
|
*/
|
|
195
193
|
addNode(parent: TreeNodeType, node?: TreeNodeType, index?: number): TreeNodeType {
|
|
196
194
|
if (!node) {
|
|
197
|
-
const id = Key.
|
|
195
|
+
const id = Key.EntityId.random();
|
|
198
196
|
node = { id, children: [], data: { text: '' } }; // TODO(burdon): Generic.
|
|
199
197
|
}
|
|
200
198
|
|
|
201
|
-
|
|
202
|
-
|
|
199
|
+
const nodeToAdd = node;
|
|
200
|
+
Obj.update(this._tree, (obj) => {
|
|
201
|
+
obj.nodes[nodeToAdd.id] = nodeToAdd;
|
|
202
|
+
parent.children.splice(index ?? parent.children.length, 0, nodeToAdd.id);
|
|
203
|
+
});
|
|
203
204
|
return node;
|
|
204
205
|
}
|
|
205
206
|
|
|
206
207
|
/**
|
|
207
208
|
* Delete node.
|
|
208
209
|
*/
|
|
209
|
-
deleteNode(parent: TreeNodeType, id: Key.
|
|
210
|
+
deleteNode(parent: TreeNodeType, id: Key.EntityId): TreeNodeType | undefined {
|
|
210
211
|
const node = this._tree.nodes[id];
|
|
211
212
|
if (!node) {
|
|
212
213
|
return undefined;
|
|
213
214
|
}
|
|
214
215
|
|
|
215
|
-
|
|
216
|
+
Obj.update(this._tree, (obj) => {
|
|
217
|
+
delete obj.nodes[node.id];
|
|
218
|
+
});
|
|
216
219
|
const idx = parent.children.findIndex((child) => child === id);
|
|
217
220
|
if (idx !== -1) {
|
|
218
|
-
|
|
221
|
+
Obj.update(this._tree, () => {
|
|
222
|
+
parent.children.splice(idx, 1);
|
|
223
|
+
});
|
|
219
224
|
}
|
|
220
225
|
|
|
221
226
|
return node;
|
|
@@ -232,8 +237,10 @@ export class Tree {
|
|
|
232
237
|
}
|
|
233
238
|
|
|
234
239
|
const child = node.children[from];
|
|
235
|
-
|
|
236
|
-
|
|
240
|
+
Obj.update(this._tree, () => {
|
|
241
|
+
node.children.splice(from, 1);
|
|
242
|
+
node.children.splice(to, 0, child);
|
|
243
|
+
});
|
|
237
244
|
return this.getNode(child);
|
|
238
245
|
}
|
|
239
246
|
|
|
@@ -252,8 +259,10 @@ export class Tree {
|
|
|
252
259
|
}
|
|
253
260
|
|
|
254
261
|
const previous = this.getNode(parent.children[idx - 1]);
|
|
255
|
-
|
|
256
|
-
|
|
262
|
+
Obj.update(this._tree, () => {
|
|
263
|
+
parent.children.splice(idx, 1);
|
|
264
|
+
previous.children.push(node.id);
|
|
265
|
+
});
|
|
257
266
|
}
|
|
258
267
|
|
|
259
268
|
/**
|
|
@@ -270,16 +279,23 @@ export class Tree {
|
|
|
270
279
|
return;
|
|
271
280
|
}
|
|
272
281
|
|
|
273
|
-
// Remove node from parent.
|
|
282
|
+
// Remove node from parent and get following siblings.
|
|
274
283
|
const nodeIdx = parent.children.findIndex((id) => id === node.id);
|
|
275
|
-
|
|
276
|
-
|
|
284
|
+
let rest: Key.EntityId[] = [];
|
|
285
|
+
Obj.update(this._tree, () => {
|
|
286
|
+
const removed = parent.children.splice(nodeIdx, parent.children.length - nodeIdx);
|
|
287
|
+
rest = removed.slice(1); // Skip the node itself.
|
|
288
|
+
});
|
|
277
289
|
|
|
278
290
|
// Add to ancestor.
|
|
279
291
|
const parentIdx = this.getChildNodes(ancestor).findIndex((n) => n.id === parent.id);
|
|
280
|
-
|
|
292
|
+
Obj.update(this._tree, () => {
|
|
293
|
+
ancestor.children.splice(parentIdx + 1, 0, node.id);
|
|
294
|
+
});
|
|
281
295
|
|
|
282
296
|
// Transplant following siblings to current node.
|
|
283
|
-
|
|
297
|
+
Obj.update(this._tree, () => {
|
|
298
|
+
node.children.push(...rest);
|
|
299
|
+
});
|
|
284
300
|
}
|
|
285
301
|
}
|
|
@@ -2,40 +2,49 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { type
|
|
5
|
+
import { type Key } from '@dxos/echo';
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
import { type TreeType } from './tree';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* In-memory tree shape used by the d3 layouts.
|
|
11
|
+
* `data` carries through to layout callbacks (e.g. hover/inspect) — typically an ECHO object on leaves.
|
|
12
|
+
*/
|
|
13
|
+
export type TreeNode<TData = unknown> = {
|
|
8
14
|
id: string;
|
|
9
15
|
label?: string;
|
|
10
|
-
|
|
16
|
+
data?: TData;
|
|
17
|
+
children?: TreeNode<TData>[];
|
|
11
18
|
};
|
|
12
19
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Convert an ECHO `TreeType` (id-keyed node map) into a nested `TreeNode` hierarchy.
|
|
22
|
+
* Returns `undefined` if the root id is missing — the tree is then incomplete and shouldn't render.
|
|
23
|
+
*/
|
|
24
|
+
export const treeTypeToTreeNode = (
|
|
25
|
+
tree: TreeType,
|
|
26
|
+
rootId: Key.EntityId = tree.root,
|
|
27
|
+
visited: Set<string> = new Set(),
|
|
28
|
+
): TreeNode | undefined => {
|
|
29
|
+
const node = tree.nodes[rootId];
|
|
30
|
+
if (!node) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
if (visited.has(rootId)) {
|
|
34
|
+
return { id: rootId, label: labelOf(node), data: node.data };
|
|
35
|
+
}
|
|
36
|
+
visited.add(rootId);
|
|
27
37
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
// }
|
|
38
|
-
// }
|
|
38
|
+
return {
|
|
39
|
+
id: rootId,
|
|
40
|
+
label: labelOf(node),
|
|
41
|
+
data: node.data,
|
|
42
|
+
children: node.children
|
|
43
|
+
.map((childId) => treeTypeToTreeNode(tree, childId, visited))
|
|
44
|
+
.filter((c): c is TreeNode => Boolean(c)),
|
|
45
|
+
};
|
|
46
|
+
};
|
|
39
47
|
|
|
40
|
-
|
|
48
|
+
const labelOf = (node: { data: Record<string, any> }): string | undefined => {
|
|
49
|
+
return typeof node.data?.text === 'string' ? node.data.text : undefined;
|
|
41
50
|
};
|
package/src/components/index.ts
CHANGED
|
@@ -2,11 +2,8 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { lazy } from 'react';
|
|
6
|
-
|
|
7
|
-
export const ExplorerContainer = lazy(() => import('./ExplorerContainer'));
|
|
8
|
-
|
|
9
5
|
export * from './Chart';
|
|
10
6
|
export * from './Globe';
|
|
11
7
|
export * from './Graph';
|
|
8
|
+
export * from './Lattice';
|
|
12
9
|
export * from './Tree';
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
6
|
+
import * as Effect from 'effect/Effect';
|
|
7
|
+
import React from 'react';
|
|
8
|
+
|
|
9
|
+
import { withPluginManager } from '@dxos/app-framework/testing';
|
|
10
|
+
import { Filter, Query, Type, View } from '@dxos/echo';
|
|
11
|
+
import { ClientPlugin, initializeIdentity } from '@dxos/plugin-client/testing';
|
|
12
|
+
import { PreviewPlugin } from '@dxos/plugin-preview/testing';
|
|
13
|
+
import { StorybookPlugin, corePlugins } from '@dxos/plugin-testing';
|
|
14
|
+
import { random } from '@dxos/random';
|
|
15
|
+
import { useQuery, useSpaces } from '@dxos/react-client/echo';
|
|
16
|
+
import { Loading, withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
17
|
+
import { ViewModel } from '@dxos/schema';
|
|
18
|
+
import { type ValueGenerator, createObjectFactory, createRelationFactory } from '@dxos/schema/testing';
|
|
19
|
+
import { HasConnection, HasRelationship, Organization, Person, Pipeline } from '@dxos/types';
|
|
20
|
+
|
|
21
|
+
import { Graph } from '../../types';
|
|
22
|
+
import { ExplorerArticle, type ExplorerArticleVariant } from './ExplorerArticle';
|
|
23
|
+
|
|
24
|
+
const generator = random as any as ValueGenerator;
|
|
25
|
+
|
|
26
|
+
random.seed(7);
|
|
27
|
+
|
|
28
|
+
type DefaultStoryProps = { variant: ExplorerArticleVariant };
|
|
29
|
+
|
|
30
|
+
const DefaultStory = ({ variant }: DefaultStoryProps) => {
|
|
31
|
+
const [space] = useSpaces();
|
|
32
|
+
const [graph] = useQuery(space?.db, Filter.type(Graph.Graph));
|
|
33
|
+
if (!space || !graph) {
|
|
34
|
+
return <Loading data={{ space: !!space, graph: !!graph }} />;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return <ExplorerArticle role='article' subject={graph as any} attendableId={graph.id} variant={variant} />;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const meta: Meta<DefaultStoryProps> = {
|
|
41
|
+
title: 'plugins/plugin-explorer/containers/ExplorerArticle',
|
|
42
|
+
render: DefaultStory,
|
|
43
|
+
decorators: [
|
|
44
|
+
withTheme(),
|
|
45
|
+
withLayout({ layout: 'fullscreen' }),
|
|
46
|
+
withPluginManager({
|
|
47
|
+
plugins: [
|
|
48
|
+
...corePlugins(),
|
|
49
|
+
StorybookPlugin({}),
|
|
50
|
+
ClientPlugin({
|
|
51
|
+
types: [
|
|
52
|
+
Graph.Graph,
|
|
53
|
+
HasRelationship.HasRelationship,
|
|
54
|
+
Organization.Organization,
|
|
55
|
+
Person.Person,
|
|
56
|
+
Pipeline.Pipeline,
|
|
57
|
+
View.View,
|
|
58
|
+
],
|
|
59
|
+
onClientInitialized: ({ client }) =>
|
|
60
|
+
Effect.gen(function* () {
|
|
61
|
+
const { personalSpace } = yield* initializeIdentity(client);
|
|
62
|
+
yield* Effect.promise(() =>
|
|
63
|
+
createObjectFactory(
|
|
64
|
+
personalSpace.db,
|
|
65
|
+
generator,
|
|
66
|
+
)([
|
|
67
|
+
{ type: Organization.Organization, count: 20 },
|
|
68
|
+
{ type: Person.Person, count: 30 },
|
|
69
|
+
{ type: Pipeline.Pipeline, count: 10 },
|
|
70
|
+
]),
|
|
71
|
+
);
|
|
72
|
+
// Denser HasRelationship graph so the plexus variant shows multiple relation
|
|
73
|
+
// groups (organization ref + relationships) fanning out from a focused person.
|
|
74
|
+
yield* Effect.promise(() =>
|
|
75
|
+
createRelationFactory(
|
|
76
|
+
personalSpace.db,
|
|
77
|
+
generator,
|
|
78
|
+
)([
|
|
79
|
+
{ type: HasRelationship.HasRelationship, count: 40, data: { kind: 'friend' } },
|
|
80
|
+
{ type: HasConnection.HasConnection, count: 20, data: { kind: 'vendor' } },
|
|
81
|
+
]),
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
const { view } = yield* Effect.promise(() =>
|
|
85
|
+
ViewModel.makeFromDatabase({
|
|
86
|
+
db: personalSpace.db,
|
|
87
|
+
typename: Type.getTypename(Graph.Graph),
|
|
88
|
+
}),
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
const graph = personalSpace.db.add(
|
|
92
|
+
Graph.make({
|
|
93
|
+
name: 'Root',
|
|
94
|
+
view,
|
|
95
|
+
query: {
|
|
96
|
+
ast: Query.select(Filter.everything()).ast,
|
|
97
|
+
},
|
|
98
|
+
}),
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
yield* Effect.promise(() => personalSpace.db.flush({ indexes: true }));
|
|
102
|
+
return graph;
|
|
103
|
+
}),
|
|
104
|
+
}),
|
|
105
|
+
PreviewPlugin(),
|
|
106
|
+
],
|
|
107
|
+
}),
|
|
108
|
+
],
|
|
109
|
+
parameters: {
|
|
110
|
+
layout: 'fullscreen',
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
export default meta;
|
|
115
|
+
|
|
116
|
+
type Story = StoryObj<typeof meta>;
|
|
117
|
+
|
|
118
|
+
export const Force: Story = {
|
|
119
|
+
args: {
|
|
120
|
+
variant: 'force',
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
export const Cluster: Story = {
|
|
125
|
+
args: {
|
|
126
|
+
variant: 'cluster',
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
export const Bundle: Story = {
|
|
131
|
+
args: {
|
|
132
|
+
variant: 'bundle',
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
export const Plexus: Story = {
|
|
137
|
+
args: {
|
|
138
|
+
variant: 'plexus',
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
export const Lattice: Story = {
|
|
143
|
+
args: {
|
|
144
|
+
variant: 'lattice',
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
export const Swarm: Story = {
|
|
149
|
+
args: {
|
|
150
|
+
variant: 'swarm',
|
|
151
|
+
},
|
|
152
|
+
};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
6
|
+
|
|
7
|
+
import { type AppSurface } from '@dxos/app-toolkit/ui';
|
|
8
|
+
import { type Filter, Obj, type View } from '@dxos/echo';
|
|
9
|
+
import { QueryBuilder } from '@dxos/echo-query';
|
|
10
|
+
import { useObject } from '@dxos/react-client/echo';
|
|
11
|
+
import { DxAnchorActivate, Icon, Panel, Toolbar } from '@dxos/react-ui';
|
|
12
|
+
import { QueryEditor, type QueryEditorProps } from '@dxos/react-ui-components';
|
|
13
|
+
import '@dxos/react-ui-graph/styles/graph.css';
|
|
14
|
+
|
|
15
|
+
import { type TreeNode } from '#components';
|
|
16
|
+
import { useGraphModel } from '#hooks';
|
|
17
|
+
|
|
18
|
+
import { type ExplorerArticleVariant, VARIANTS, isVariant } from './variants';
|
|
19
|
+
import { Visualization } from './Visualization';
|
|
20
|
+
|
|
21
|
+
export type { ExplorerArticleVariant } from './variants';
|
|
22
|
+
|
|
23
|
+
export type ExplorerArticleProps = AppSurface.ObjectArticleProps<View.View>;
|
|
24
|
+
|
|
25
|
+
export const ExplorerArticle = ({ role, subject, variant }: ExplorerArticleProps) => {
|
|
26
|
+
const [view] = useObject(subject);
|
|
27
|
+
const [filter, setFilter] = useState<Filter.Any>();
|
|
28
|
+
|
|
29
|
+
const db = view && Obj.getDatabase(view);
|
|
30
|
+
const model = useGraphModel(db, filter);
|
|
31
|
+
|
|
32
|
+
const builder = useMemo(() => new QueryBuilder(), []);
|
|
33
|
+
const handleChange = useCallback<NonNullable<QueryEditorProps['onChange']>>(
|
|
34
|
+
(value) => {
|
|
35
|
+
setFilter(builder.build(value).filter);
|
|
36
|
+
},
|
|
37
|
+
[builder],
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
const [selected, setSelected] = useState<ExplorerArticleVariant>(isVariant(variant) ? variant : 'force');
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
if (isVariant(variant)) {
|
|
43
|
+
setSelected(variant);
|
|
44
|
+
}
|
|
45
|
+
}, [variant]);
|
|
46
|
+
|
|
47
|
+
const handleVariantChange = useCallback((value: string) => {
|
|
48
|
+
if (isVariant(value)) {
|
|
49
|
+
setSelected(value);
|
|
50
|
+
}
|
|
51
|
+
}, []);
|
|
52
|
+
|
|
53
|
+
// Dismiss the preview popover. The dxn/label/trigger fields are placeholders ignored on
|
|
54
|
+
// `state: false`.
|
|
55
|
+
const handleDismiss = useCallback(() => {
|
|
56
|
+
document.defaultView?.dispatchEvent(
|
|
57
|
+
new DxAnchorActivate({ dxn: '', label: '', trigger: document.body, state: false }),
|
|
58
|
+
);
|
|
59
|
+
}, []);
|
|
60
|
+
|
|
61
|
+
const handleHover = useCallback((node: TreeNode | null, event?: MouseEvent) => {
|
|
62
|
+
// Pointer left the node/label: keep the popover open so it can be hovered/interacted with.
|
|
63
|
+
// The popover is dismissed only on an explicit click on the component surface (handleDismiss).
|
|
64
|
+
if (!node || !event) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const obj = node.data;
|
|
68
|
+
if (!obj || !Obj.isObject(obj)) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const dxn = Obj.getURI(obj);
|
|
72
|
+
if (!dxn) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const target = event.target as HTMLElement;
|
|
77
|
+
target.dispatchEvent(
|
|
78
|
+
new DxAnchorActivate({
|
|
79
|
+
dxn,
|
|
80
|
+
kind: 'card',
|
|
81
|
+
trigger: target,
|
|
82
|
+
label: Obj.getLabel(obj) ?? dxn,
|
|
83
|
+
}),
|
|
84
|
+
);
|
|
85
|
+
}, []);
|
|
86
|
+
|
|
87
|
+
const showToolbar = role === 'article';
|
|
88
|
+
|
|
89
|
+
if (!db || !model) {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<Panel.Root role={role}>
|
|
95
|
+
{showToolbar && (
|
|
96
|
+
<Panel.Toolbar asChild>
|
|
97
|
+
<Toolbar.Root>
|
|
98
|
+
<QueryEditor db={db} onChange={handleChange} />
|
|
99
|
+
<Toolbar.ToggleGroup type='single' value={selected} onValueChange={handleVariantChange}>
|
|
100
|
+
{VARIANTS.map(({ value, icon, label }) => (
|
|
101
|
+
<Toolbar.ToggleGroupItem key={value} value={value} aria-label={label} title={label}>
|
|
102
|
+
<Icon icon={icon} size={4} />
|
|
103
|
+
</Toolbar.ToggleGroupItem>
|
|
104
|
+
))}
|
|
105
|
+
</Toolbar.ToggleGroup>
|
|
106
|
+
</Toolbar.Root>
|
|
107
|
+
</Panel.Toolbar>
|
|
108
|
+
)}
|
|
109
|
+
<Panel.Content>
|
|
110
|
+
<Visualization
|
|
111
|
+
classNames='bg-base-surface'
|
|
112
|
+
variant={selected}
|
|
113
|
+
model={model}
|
|
114
|
+
onNodeHover={handleHover}
|
|
115
|
+
onSurfaceClick={handleDismiss}
|
|
116
|
+
/>
|
|
117
|
+
</Panel.Content>
|
|
118
|
+
</Panel.Root>
|
|
119
|
+
);
|
|
120
|
+
};
|