@dxos/plugin-explorer 0.8.4-main.9735255 → 0.8.4-main.abd8ff62ef
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/dist/lib/browser/{chunk-YNQF4CPY.mjs → chunk-HPIS2WXY.mjs} +2 -2
- package/dist/lib/browser/{chunk-YNQF4CPY.mjs.map → chunk-HPIS2WXY.mjs.map} +3 -3
- package/dist/lib/{node-esm/chunk-QLMTN2XI.mjs → browser/components/index.mjs} +196 -20
- package/dist/lib/{node-esm/chunk-QLMTN2XI.mjs.map → browser/components/index.mjs.map} +4 -4
- package/dist/lib/browser/hooks/index.mjs +40 -0
- package/dist/lib/browser/hooks/index.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +5 -92
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/meta.mjs +1 -1
- package/dist/lib/browser/types/index.mjs +66 -4
- package/dist/lib/browser/types/index.mjs.map +4 -4
- package/dist/lib/node-esm/{chunk-DK77RB6M.mjs → chunk-6EUBRHHX.mjs} +2 -2
- package/dist/lib/node-esm/{chunk-DK77RB6M.mjs.map → chunk-6EUBRHHX.mjs.map} +3 -3
- package/dist/lib/{browser/chunk-AGZAGILW.mjs → node-esm/components/index.mjs} +198 -19
- package/dist/lib/{browser/chunk-AGZAGILW.mjs.map → node-esm/components/index.mjs.map} +4 -4
- package/dist/lib/node-esm/hooks/index.mjs +41 -0
- package/dist/lib/node-esm/hooks/index.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +5 -92
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/meta.mjs +1 -1
- package/dist/lib/node-esm/types/index.mjs +66 -4
- package/dist/lib/node-esm/types/index.mjs.map +4 -4
- package/dist/types/data/cities.d.ts +4 -4
- package/dist/types/data/cities.d.ts.map +1 -1
- package/dist/types/data/countries-110m.d.ts +19 -22
- package/dist/types/data/countries-110m.d.ts.map +1 -1
- package/dist/types/src/ExplorerPlugin.d.ts +1 -0
- package/dist/types/src/ExplorerPlugin.d.ts.map +1 -1
- package/dist/types/src/ExplorerPlugin.test.d.ts +2 -0
- package/dist/types/src/ExplorerPlugin.test.d.ts.map +1 -0
- package/dist/types/src/capabilities/index.d.ts +2 -1
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts +5 -0
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
- package/dist/types/src/components/Chart/Chart.d.ts.map +1 -1
- package/dist/types/src/components/Chart/Chart.stories.d.ts.map +1 -1
- package/dist/types/src/components/Globe/Globe.d.ts.map +1 -1
- package/dist/types/src/components/Globe/Globe.stories.d.ts.map +1 -1
- package/dist/types/src/components/Graph/D3ForceGraph.d.ts +6 -5
- package/dist/types/src/components/Graph/D3ForceGraph.d.ts.map +1 -1
- package/dist/types/src/components/Graph/D3ForceGraph.stories.d.ts +4 -2
- package/dist/types/src/components/Graph/D3ForceGraph.stories.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/adapter.d.ts.map +1 -1
- package/dist/types/src/components/Graph/testing.d.ts.map +1 -1
- package/dist/types/src/components/Tree/Tree.d.ts.map +1 -1
- package/dist/types/src/components/Tree/Tree.stories.d.ts.map +1 -1
- package/dist/types/src/components/Tree/layout/HierarchicalEdgeBundling.d.ts.map +1 -1
- package/dist/types/src/components/Tree/layout/RadialTree.d.ts.map +1 -1
- package/dist/types/src/components/Tree/layout/TidyTree.d.ts.map +1 -1
- package/dist/types/src/components/Tree/testing/generator.d.ts.map +1 -1
- package/dist/types/src/components/Tree/types/tree.d.ts +7 -7
- package/dist/types/src/components/Tree/types/tree.d.ts.map +1 -1
- package/dist/types/src/components/Tree/types/types.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +0 -2
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/components/plot.d.ts.map +1 -1
- package/dist/types/src/containers/ExplorerContainer/ExplorerContainer.d.ts +6 -0
- package/dist/types/src/containers/ExplorerContainer/ExplorerContainer.d.ts.map +1 -0
- package/dist/types/src/containers/ExplorerContainer/index.d.ts +2 -0
- package/dist/types/src/containers/ExplorerContainer/index.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.map +1 -1
- package/dist/types/src/index.d.ts +2 -3
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +28 -26
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/ExplorerAction.d.ts.map +1 -1
- package/dist/types/src/types/Graph.d.ts +3 -10
- package/dist/types/src/types/Graph.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +67 -47
- package/src/ExplorerPlugin.test.ts +26 -0
- package/src/ExplorerPlugin.tsx +31 -17
- package/src/capabilities/index.ts +3 -1
- package/src/capabilities/react-surface.tsx +32 -0
- package/src/components/Chart/Chart.stories.tsx +2 -3
- package/src/components/Globe/Globe.stories.tsx +2 -3
- package/src/components/Graph/D3ForceGraph.stories.tsx +16 -16
- package/src/components/Graph/D3ForceGraph.tsx +82 -75
- package/src/components/Graph/ForceGraph.stories.tsx +16 -16
- package/src/components/Graph/testing.ts +2 -2
- package/src/components/Tree/Tree.stories.tsx +7 -5
- package/src/components/Tree/testing/generator.ts +1 -1
- package/src/components/Tree/types/tree.test.ts +3 -4
- package/src/components/Tree/types/tree.ts +15 -15
- package/src/components/index.ts +0 -4
- package/src/containers/ExplorerContainer/ExplorerContainer.tsx +53 -0
- package/src/containers/ExplorerContainer/index.ts +5 -0
- package/src/containers/index.ts +7 -0
- package/src/hooks/useGraphModel.ts +18 -13
- package/src/index.ts +5 -3
- package/src/meta.ts +1 -1
- package/src/translations.ts +14 -13
- package/src/types/ExplorerAction.ts +0 -1
- package/src/types/Graph.ts +11 -24
- package/src/typings.d.ts +8 -0
- package/dist/lib/browser/ExplorerContainer-BFAWRIAJ.mjs +0 -45
- package/dist/lib/browser/ExplorerContainer-BFAWRIAJ.mjs.map +0 -7
- package/dist/lib/browser/chunk-BZMTFAP3.mjs +0 -34
- package/dist/lib/browser/chunk-BZMTFAP3.mjs.map +0 -7
- package/dist/lib/browser/chunk-HIFLWHXR.mjs +0 -83
- package/dist/lib/browser/chunk-HIFLWHXR.mjs.map +0 -7
- package/dist/lib/browser/chunk-MGBT2ZFU.mjs +0 -177
- package/dist/lib/browser/chunk-MGBT2ZFU.mjs.map +0 -7
- package/dist/lib/browser/react-surface-RWVHQL3J.mjs +0 -35
- package/dist/lib/browser/react-surface-RWVHQL3J.mjs.map +0 -7
- package/dist/lib/node-esm/ExplorerContainer-YQ2KKBVS.mjs +0 -46
- package/dist/lib/node-esm/ExplorerContainer-YQ2KKBVS.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-3OE6TBJI.mjs +0 -84
- package/dist/lib/node-esm/chunk-3OE6TBJI.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-IPIGIQHX.mjs +0 -36
- package/dist/lib/node-esm/chunk-IPIGIQHX.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-YWJBDETV.mjs +0 -179
- package/dist/lib/node-esm/chunk-YWJBDETV.mjs.map +0 -7
- package/dist/lib/node-esm/react-surface-3REUS7KW.mjs +0 -36
- package/dist/lib/node-esm/react-surface-3REUS7KW.mjs.map +0 -7
- package/dist/types/src/capabilities/react-surface/index.d.ts +0 -3
- package/dist/types/src/capabilities/react-surface/index.d.ts.map +0 -1
- package/dist/types/src/capabilities/react-surface/react-surface.d.ts +0 -5
- package/dist/types/src/capabilities/react-surface/react-surface.d.ts.map +0 -1
- package/dist/types/src/components/ExplorerContainer.d.ts +0 -7
- package/dist/types/src/components/ExplorerContainer.d.ts.map +0 -1
- package/src/capabilities/react-surface/index.ts +0 -7
- package/src/capabilities/react-surface/react-surface.tsx +0 -30
- package/src/components/ExplorerContainer.tsx +0 -52
|
@@ -6,27 +6,27 @@ import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
|
6
6
|
import React, { useState } from 'react';
|
|
7
7
|
|
|
8
8
|
import { Type } from '@dxos/echo';
|
|
9
|
-
import {
|
|
9
|
+
import { View } from '@dxos/echo';
|
|
10
|
+
import { random } from '@dxos/random';
|
|
10
11
|
import { useClient } from '@dxos/react-client';
|
|
11
12
|
import { type Space } from '@dxos/react-client/echo';
|
|
12
13
|
import { withClientProvider } from '@dxos/react-client/testing';
|
|
13
14
|
import { useAsyncEffect } from '@dxos/react-ui';
|
|
14
|
-
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
15
|
-
import {
|
|
15
|
+
import { Loading, withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
16
|
+
import { ViewModel } from '@dxos/schema';
|
|
16
17
|
import { type ValueGenerator } from '@dxos/schema/testing';
|
|
17
18
|
import { withRegistry } from '@dxos/storybook-utils';
|
|
18
|
-
import {
|
|
19
|
-
import { HasRelationship, Organization, Person, Project } from '@dxos/types';
|
|
19
|
+
import { HasRelationship, Organization, Person, Pipeline } from '@dxos/types';
|
|
20
20
|
|
|
21
|
-
import { useGraphModel } from '
|
|
22
|
-
import { Graph } from '
|
|
21
|
+
import { useGraphModel } from '#hooks';
|
|
22
|
+
import { Graph } from '#types';
|
|
23
23
|
|
|
24
24
|
import { ForceGraph } from './ForceGraph';
|
|
25
25
|
import { generate } from './testing';
|
|
26
26
|
|
|
27
|
-
const generator =
|
|
27
|
+
const generator = random as any as ValueGenerator;
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
random.seed(1);
|
|
30
30
|
|
|
31
31
|
const DefaultStory = () => {
|
|
32
32
|
const client = useClient();
|
|
@@ -34,9 +34,9 @@ const DefaultStory = () => {
|
|
|
34
34
|
const [graph, setGraph] = useState<Graph.Graph>();
|
|
35
35
|
|
|
36
36
|
useAsyncEffect(async () => {
|
|
37
|
-
const space = client.spaces.
|
|
37
|
+
const space = client.spaces.get()[0];
|
|
38
38
|
void generate(space, generator);
|
|
39
|
-
const { view } = await
|
|
39
|
+
const { view } = await ViewModel.makeFromDatabase({ db: space.db, typename: Type.getTypename(Graph.Graph) });
|
|
40
40
|
const graph = Graph.make({ name: 'Test', view });
|
|
41
41
|
space.db.add(graph);
|
|
42
42
|
setSpace(space);
|
|
@@ -45,19 +45,19 @@ const DefaultStory = () => {
|
|
|
45
45
|
|
|
46
46
|
const model = useGraphModel(space);
|
|
47
47
|
if (!model || !space || !graph) {
|
|
48
|
-
return
|
|
48
|
+
return <Loading data={{ model: !!model, space: !!space, graph: !!graph }} />;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
return <ForceGraph model={model} />;
|
|
52
52
|
};
|
|
53
53
|
|
|
54
54
|
const meta = {
|
|
55
|
-
title: 'plugins/plugin-explorer/ForceGraph',
|
|
55
|
+
title: 'plugins/plugin-explorer/components/ForceGraph',
|
|
56
56
|
component: ForceGraph,
|
|
57
|
-
render:
|
|
57
|
+
render: DefaultStory,
|
|
58
58
|
decorators: [
|
|
59
59
|
withRegistry,
|
|
60
|
-
withTheme,
|
|
60
|
+
withTheme(),
|
|
61
61
|
withLayout(),
|
|
62
62
|
withClientProvider({
|
|
63
63
|
createSpace: true,
|
|
@@ -66,7 +66,7 @@ const meta = {
|
|
|
66
66
|
View.View,
|
|
67
67
|
HasRelationship.HasRelationship,
|
|
68
68
|
Organization.Organization,
|
|
69
|
-
|
|
69
|
+
Pipeline.Pipeline,
|
|
70
70
|
Person.Person,
|
|
71
71
|
],
|
|
72
72
|
}),
|
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
import { type Space } from '@dxos/client/echo';
|
|
6
6
|
import { type Obj, Query, Relation } from '@dxos/echo';
|
|
7
7
|
import { type TypeSpec, type ValueGenerator, createObjectFactory } from '@dxos/schema/testing';
|
|
8
|
-
import { HasRelationship, Organization, Person,
|
|
8
|
+
import { HasRelationship, Organization, Person, Pipeline } from '@dxos/types';
|
|
9
9
|
import { range } from '@dxos/util';
|
|
10
10
|
|
|
11
11
|
const getObject = (objects: Obj.Unknown[]) => objects[Math.floor(Math.random() * objects.length)];
|
|
12
12
|
|
|
13
13
|
const defaultTypes: TypeSpec[] = [
|
|
14
14
|
{ type: Organization.Organization, count: 5 },
|
|
15
|
-
{ type:
|
|
15
|
+
{ type: Pipeline.Pipeline, count: 5 },
|
|
16
16
|
{ type: Person.Person, count: 10 },
|
|
17
17
|
];
|
|
18
18
|
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
6
6
|
import React, { useEffect, useState } from 'react';
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { invariant } from '@dxos/invariant';
|
|
9
|
+
import { random } from '@dxos/random';
|
|
9
10
|
import { useClient } from '@dxos/react-client';
|
|
10
11
|
import { type ClientRepeatedComponentProps, ClientRepeater } from '@dxos/react-client/testing';
|
|
11
12
|
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
@@ -17,13 +18,14 @@ import { Tree as TreeModel, TreeType } from './types';
|
|
|
17
18
|
// TODO(burdon): Storybook for Graph/Tree/Plot (generics); incl. GraphModel.
|
|
18
19
|
// TODO(burdon): Type for all Explorer components (Space, Object, Query, etc.) incl.
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
random.seed(1);
|
|
21
22
|
|
|
22
23
|
type ComponentProps = ClientRepeatedComponentProps & { type?: TreeComponentProps<any>['variant'] };
|
|
23
24
|
|
|
24
25
|
const Component = ({ type }: ComponentProps) => {
|
|
25
26
|
const client = useClient();
|
|
26
|
-
const space = client.spaces.
|
|
27
|
+
const space = client.spaces.get()[0];
|
|
28
|
+
invariant(space, 'Tree story requires at least one space');
|
|
27
29
|
const [object, setObject] = useState<TreeType>();
|
|
28
30
|
useEffect(() => {
|
|
29
31
|
setTimeout(() => {
|
|
@@ -44,10 +46,10 @@ const DefaultStory = () => {
|
|
|
44
46
|
};
|
|
45
47
|
|
|
46
48
|
const meta = {
|
|
47
|
-
title: 'plugins/plugin-explorer/Tree',
|
|
49
|
+
title: 'plugins/plugin-explorer/components/Tree',
|
|
48
50
|
component: Tree as any,
|
|
49
51
|
render: DefaultStory,
|
|
50
|
-
decorators: [withRegistry, withTheme, withLayout()],
|
|
52
|
+
decorators: [withRegistry, withTheme(), withLayout()],
|
|
51
53
|
parameters: {
|
|
52
54
|
layout: 'fullscreen',
|
|
53
55
|
},
|
|
@@ -16,7 +16,7 @@ const random = (min: number, max: number) => Math.floor(Math.random() * (max - m
|
|
|
16
16
|
*/
|
|
17
17
|
export const createTree = (spec: NumberOrNumberArray[] = [], createText?: () => string): Tree => {
|
|
18
18
|
const tree = new Tree();
|
|
19
|
-
Obj.
|
|
19
|
+
Obj.update(tree.tree, () => {
|
|
20
20
|
tree.root.data = { text: 'root' };
|
|
21
21
|
});
|
|
22
22
|
|
|
@@ -5,14 +5,13 @@
|
|
|
5
5
|
import { describe, test } from 'vitest';
|
|
6
6
|
|
|
7
7
|
import { Obj, Ref } from '@dxos/echo';
|
|
8
|
-
import {
|
|
8
|
+
import { random } from '@dxos/random';
|
|
9
9
|
import { Task } from '@dxos/types';
|
|
10
10
|
|
|
11
11
|
import { createTree } from '../testing';
|
|
12
|
-
|
|
13
12
|
import { type Tree } from './tree';
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
random.seed(0);
|
|
16
15
|
|
|
17
16
|
const print = (tree: Tree) => {
|
|
18
17
|
let count = 0;
|
|
@@ -129,7 +128,7 @@ describe('tree', () => {
|
|
|
129
128
|
|
|
130
129
|
const tree = createTree();
|
|
131
130
|
const node = tree.addNode(tree.root);
|
|
132
|
-
Obj.
|
|
131
|
+
Obj.update(tree.tree, () => {
|
|
133
132
|
node.ref = Ref.make(task);
|
|
134
133
|
});
|
|
135
134
|
});
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import * as Schema from 'effect/Schema';
|
|
6
6
|
|
|
7
|
-
import { Key, Obj, Type } from '@dxos/echo';
|
|
7
|
+
import { Key, Obj, Ref, Type } from '@dxos/echo';
|
|
8
8
|
import { TestSchema } from '@dxos/echo/testing';
|
|
9
9
|
import { invariant } from '@dxos/invariant';
|
|
10
10
|
|
|
@@ -14,7 +14,7 @@ export const TreeNodeType = Schema.Struct({
|
|
|
14
14
|
id: Key.ObjectId,
|
|
15
15
|
children: Schema.mutable(Schema.Array(Key.ObjectId)),
|
|
16
16
|
data: Schema.mutable(Schema.Record({ key: Schema.String, value: Schema.Any })),
|
|
17
|
-
ref: Schema.optional(
|
|
17
|
+
ref: Schema.optional(Ref.Ref(TestSchema.Expando)),
|
|
18
18
|
}).pipe(Schema.mutable);
|
|
19
19
|
|
|
20
20
|
export interface TreeNodeType extends Schema.Schema.Type<typeof TreeNodeType> {}
|
|
@@ -24,7 +24,7 @@ export const TreeType = Schema.Struct({
|
|
|
24
24
|
nodes: Schema.mutable(Schema.Record({ key: Key.ObjectId, value: TreeNodeType })),
|
|
25
25
|
}).pipe(
|
|
26
26
|
Type.object({
|
|
27
|
-
typename: 'dxos.
|
|
27
|
+
typename: 'org.dxos.type.tree',
|
|
28
28
|
version: '0.1.0',
|
|
29
29
|
}),
|
|
30
30
|
);
|
|
@@ -185,8 +185,8 @@ export class Tree {
|
|
|
185
185
|
clear(): void {
|
|
186
186
|
const root = this._tree.nodes[this._tree.root];
|
|
187
187
|
root.children.length = 0;
|
|
188
|
-
Obj.
|
|
189
|
-
|
|
188
|
+
Obj.update(this._tree, (obj) => {
|
|
189
|
+
obj.nodes = {
|
|
190
190
|
[root.id]: root,
|
|
191
191
|
};
|
|
192
192
|
});
|
|
@@ -202,8 +202,8 @@ export class Tree {
|
|
|
202
202
|
}
|
|
203
203
|
|
|
204
204
|
const nodeToAdd = node;
|
|
205
|
-
Obj.
|
|
206
|
-
|
|
205
|
+
Obj.update(this._tree, (obj) => {
|
|
206
|
+
obj.nodes[nodeToAdd.id] = nodeToAdd;
|
|
207
207
|
parent.children.splice(index ?? parent.children.length, 0, nodeToAdd.id);
|
|
208
208
|
});
|
|
209
209
|
return node;
|
|
@@ -218,12 +218,12 @@ export class Tree {
|
|
|
218
218
|
return undefined;
|
|
219
219
|
}
|
|
220
220
|
|
|
221
|
-
Obj.
|
|
222
|
-
delete
|
|
221
|
+
Obj.update(this._tree, (obj) => {
|
|
222
|
+
delete obj.nodes[node.id];
|
|
223
223
|
});
|
|
224
224
|
const idx = parent.children.findIndex((child) => child === id);
|
|
225
225
|
if (idx !== -1) {
|
|
226
|
-
Obj.
|
|
226
|
+
Obj.update(this._tree, () => {
|
|
227
227
|
parent.children.splice(idx, 1);
|
|
228
228
|
});
|
|
229
229
|
}
|
|
@@ -242,7 +242,7 @@ export class Tree {
|
|
|
242
242
|
}
|
|
243
243
|
|
|
244
244
|
const child = node.children[from];
|
|
245
|
-
Obj.
|
|
245
|
+
Obj.update(this._tree, () => {
|
|
246
246
|
node.children.splice(from, 1);
|
|
247
247
|
node.children.splice(to, 0, child);
|
|
248
248
|
});
|
|
@@ -264,7 +264,7 @@ export class Tree {
|
|
|
264
264
|
}
|
|
265
265
|
|
|
266
266
|
const previous = this.getNode(parent.children[idx - 1]);
|
|
267
|
-
Obj.
|
|
267
|
+
Obj.update(this._tree, () => {
|
|
268
268
|
parent.children.splice(idx, 1);
|
|
269
269
|
previous.children.push(node.id);
|
|
270
270
|
});
|
|
@@ -287,19 +287,19 @@ export class Tree {
|
|
|
287
287
|
// Remove node from parent and get following siblings.
|
|
288
288
|
const nodeIdx = parent.children.findIndex((id) => id === node.id);
|
|
289
289
|
let rest: Key.ObjectId[] = [];
|
|
290
|
-
Obj.
|
|
290
|
+
Obj.update(this._tree, () => {
|
|
291
291
|
const removed = parent.children.splice(nodeIdx, parent.children.length - nodeIdx);
|
|
292
292
|
rest = removed.slice(1); // Skip the node itself.
|
|
293
293
|
});
|
|
294
294
|
|
|
295
295
|
// Add to ancestor.
|
|
296
296
|
const parentIdx = this.getChildNodes(ancestor).findIndex((n) => n.id === parent.id);
|
|
297
|
-
Obj.
|
|
297
|
+
Obj.update(this._tree, () => {
|
|
298
298
|
ancestor.children.splice(parentIdx + 1, 0, node.id);
|
|
299
299
|
});
|
|
300
300
|
|
|
301
301
|
// Transplant following siblings to current node.
|
|
302
|
-
Obj.
|
|
302
|
+
Obj.update(this._tree, () => {
|
|
303
303
|
node.children.push(...rest);
|
|
304
304
|
});
|
|
305
305
|
}
|
package/src/components/index.ts
CHANGED
|
@@ -2,11 +2,7 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { type ComponentType, lazy } from 'react';
|
|
6
|
-
|
|
7
5
|
export * from './Chart';
|
|
8
6
|
export * from './Globe';
|
|
9
7
|
export * from './Graph';
|
|
10
8
|
export * from './Tree';
|
|
11
|
-
|
|
12
|
-
export const ExplorerContainer: ComponentType<any> = lazy(() => import('./ExplorerContainer'));
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { useCallback, useMemo, useState } from 'react';
|
|
6
|
+
|
|
7
|
+
import { type AppSurface } from '@dxos/app-toolkit/ui';
|
|
8
|
+
import { type Filter } from '@dxos/echo';
|
|
9
|
+
import { type View } from '@dxos/echo';
|
|
10
|
+
import { QueryBuilder } from '@dxos/echo-query';
|
|
11
|
+
import { useGlobalSearch } from '@dxos/plugin-search';
|
|
12
|
+
import { getSpace, useObject } from '@dxos/react-client/echo';
|
|
13
|
+
import { Panel, Toolbar } from '@dxos/react-ui';
|
|
14
|
+
import { QueryEditor, type QueryEditorProps } from '@dxos/react-ui-components';
|
|
15
|
+
|
|
16
|
+
import { D3ForceGraph } from '#components';
|
|
17
|
+
import { useGraphModel } from '#hooks';
|
|
18
|
+
|
|
19
|
+
export type ExplorerContainerProps = AppSurface.ObjectArticleProps<View.View>;
|
|
20
|
+
|
|
21
|
+
export const ExplorerContainer = ({ role, subject, attendableId: _attendableId }: ExplorerContainerProps) => {
|
|
22
|
+
const [view] = useObject(subject);
|
|
23
|
+
const space = view && getSpace(view);
|
|
24
|
+
const [filter, setFilter] = useState<Filter.Any>();
|
|
25
|
+
const model = useGraphModel(space, filter);
|
|
26
|
+
const { match } = useGlobalSearch();
|
|
27
|
+
|
|
28
|
+
const builder = useMemo(() => new QueryBuilder(), []);
|
|
29
|
+
const handleChange = useCallback<NonNullable<QueryEditorProps['onChange']>>((value) => {
|
|
30
|
+
setFilter(builder.build(value).filter);
|
|
31
|
+
}, []);
|
|
32
|
+
|
|
33
|
+
const showToolbar = role === 'article';
|
|
34
|
+
|
|
35
|
+
if (!space || !model) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<Panel.Root role={role}>
|
|
41
|
+
{showToolbar && (
|
|
42
|
+
<Panel.Toolbar asChild>
|
|
43
|
+
<Toolbar.Root>
|
|
44
|
+
<QueryEditor db={space.db} onChange={handleChange} />
|
|
45
|
+
</Toolbar.Root>
|
|
46
|
+
</Panel.Toolbar>
|
|
47
|
+
)}
|
|
48
|
+
<Panel.Content asChild>
|
|
49
|
+
<D3ForceGraph model={model} match={match} />
|
|
50
|
+
</Panel.Content>
|
|
51
|
+
</Panel.Root>
|
|
52
|
+
);
|
|
53
|
+
};
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import { useContext, useEffect, useState } from 'react';
|
|
5
|
+
import { useEffect, useState } from 'react';
|
|
7
6
|
|
|
7
|
+
import { Capabilities } from '@dxos/app-framework';
|
|
8
|
+
import { useCapability } from '@dxos/app-framework/ui';
|
|
8
9
|
import { type Filter, type Queue, type Space } from '@dxos/client/echo';
|
|
9
10
|
import { SpaceGraphModel, type SpaceGraphModelOptions } from '@dxos/schema';
|
|
10
11
|
|
|
@@ -15,24 +16,28 @@ export const useGraphModel = (
|
|
|
15
16
|
options?: SpaceGraphModelOptions,
|
|
16
17
|
queue?: Queue,
|
|
17
18
|
): SpaceGraphModel | undefined => {
|
|
18
|
-
const registry =
|
|
19
|
+
const registry = useCapability(Capabilities.AtomRegistry);
|
|
19
20
|
const [model, setModel] = useState<SpaceGraphModel | undefined>(undefined);
|
|
21
|
+
|
|
20
22
|
useEffect(() => {
|
|
21
23
|
if (!space) {
|
|
22
|
-
void model?.close();
|
|
23
24
|
setModel(undefined);
|
|
24
25
|
return;
|
|
25
26
|
}
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
}, [space,
|
|
28
|
+
const newModel = new SpaceGraphModel(registry);
|
|
29
|
+
void newModel.open(space.db, queue);
|
|
30
|
+
setModel(newModel);
|
|
31
|
+
|
|
32
|
+
return () => {
|
|
33
|
+
setModel(undefined);
|
|
34
|
+
void newModel.close();
|
|
35
|
+
};
|
|
36
|
+
}, [space, registry, queue]);
|
|
37
|
+
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
model?.setFilter(filter).setOptions(options);
|
|
40
|
+
}, [model, filter, options]);
|
|
36
41
|
|
|
37
42
|
return model;
|
|
38
43
|
};
|
package/src/index.ts
CHANGED
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
import { Plugin } from '@dxos/app-framework';
|
|
6
|
+
|
|
7
|
+
import { meta } from './meta';
|
|
8
|
+
|
|
7
9
|
export * from './meta';
|
|
8
10
|
|
|
9
|
-
export
|
|
11
|
+
export const ExplorerPlugin = Plugin.lazy(meta, () => import('#plugin'));
|
package/src/meta.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { type Plugin } from '@dxos/app-framework';
|
|
|
6
6
|
import { trim } from '@dxos/util';
|
|
7
7
|
|
|
8
8
|
export const meta: Plugin.Meta = {
|
|
9
|
-
id: 'dxos.
|
|
9
|
+
id: 'org.dxos.plugin.explorer',
|
|
10
10
|
name: 'Explorer',
|
|
11
11
|
description: trim`
|
|
12
12
|
Interactive hypergraph visualization that reveals relationships between objects in your workspace.
|
package/src/translations.ts
CHANGED
|
@@ -4,27 +4,28 @@
|
|
|
4
4
|
|
|
5
5
|
import { Type } from '@dxos/echo';
|
|
6
6
|
import { type Resource } from '@dxos/react-ui';
|
|
7
|
-
import { translations as componentsTranslations } from '@dxos/react-ui-components';
|
|
7
|
+
import { translations as componentsTranslations } from '@dxos/react-ui-components/translations';
|
|
8
8
|
|
|
9
|
-
import { meta } from '
|
|
10
|
-
import { Graph } from '
|
|
9
|
+
import { meta } from '#meta';
|
|
10
|
+
import { Graph } from '#types';
|
|
11
11
|
|
|
12
12
|
export const translations = [
|
|
13
13
|
{
|
|
14
14
|
'en-US': {
|
|
15
15
|
[Type.getTypename(Graph.Graph)]: {
|
|
16
|
-
'typename
|
|
17
|
-
'typename
|
|
18
|
-
'typename
|
|
19
|
-
'typename
|
|
20
|
-
'object
|
|
21
|
-
'
|
|
22
|
-
'
|
|
23
|
-
'object
|
|
16
|
+
'typename.label': 'Explorer',
|
|
17
|
+
'typename.label_zero': 'Explorers',
|
|
18
|
+
'typename.label_one': 'Explorer',
|
|
19
|
+
'typename.label_other': 'Explorers',
|
|
20
|
+
'object-name.placeholder': 'New explorer',
|
|
21
|
+
'add-object.label': 'Add explorer',
|
|
22
|
+
'rename-object.label': 'Rename explorer',
|
|
23
|
+
'delete-object.label': 'Delete explorer',
|
|
24
|
+
'object-deleted.label': 'Explorer deleted',
|
|
24
25
|
},
|
|
25
26
|
[meta.id]: {
|
|
26
|
-
'plugin
|
|
27
|
-
'object
|
|
27
|
+
'plugin.name': 'Explorer',
|
|
28
|
+
'object-title.label': 'Title',
|
|
28
29
|
},
|
|
29
30
|
},
|
|
30
31
|
},
|
package/src/types/Graph.ts
CHANGED
|
@@ -4,14 +4,15 @@
|
|
|
4
4
|
|
|
5
5
|
import * as Schema from 'effect/Schema';
|
|
6
6
|
|
|
7
|
-
import { Filter, Obj, Query, QueryAST, Ref, Type } from '@dxos/echo';
|
|
7
|
+
import { Annotation, Filter, Obj, Query, QueryAST, Ref, Type } from '@dxos/echo';
|
|
8
|
+
import { View } from '@dxos/echo';
|
|
8
9
|
import { FormInputAnnotation, LabelAnnotation } from '@dxos/echo/internal';
|
|
9
|
-
import {
|
|
10
|
+
import { ViewAnnotation } from '@dxos/schema';
|
|
10
11
|
|
|
11
12
|
const GraphSchema = Schema.Struct({
|
|
12
13
|
name: Schema.optional(Schema.String),
|
|
13
14
|
|
|
14
|
-
view:
|
|
15
|
+
view: Ref.Ref(View.View).pipe(FormInputAnnotation.set(false)),
|
|
15
16
|
|
|
16
17
|
query: Schema.Struct({
|
|
17
18
|
raw: Schema.optional(Schema.String),
|
|
@@ -19,11 +20,15 @@ const GraphSchema = Schema.Struct({
|
|
|
19
20
|
}).pipe(FormInputAnnotation.set(false)),
|
|
20
21
|
}).pipe(
|
|
21
22
|
Type.object({
|
|
22
|
-
typename: 'dxos.
|
|
23
|
-
version: '0.
|
|
23
|
+
typename: 'org.dxos.type.graph',
|
|
24
|
+
version: '0.1.0',
|
|
24
25
|
}),
|
|
25
26
|
LabelAnnotation.set(['name']),
|
|
26
|
-
ViewAnnotation.set(
|
|
27
|
+
ViewAnnotation.set(['view']),
|
|
28
|
+
Annotation.IconAnnotation.set({
|
|
29
|
+
icon: 'ph--graph--regular',
|
|
30
|
+
hue: 'green',
|
|
31
|
+
}),
|
|
27
32
|
);
|
|
28
33
|
export interface Graph extends Schema.Schema.Type<typeof GraphSchema> {}
|
|
29
34
|
export const Graph: Type.Obj<Graph> = GraphSchema as any;
|
|
@@ -42,21 +47,3 @@ export const make = ({
|
|
|
42
47
|
}: MakeProps): Graph => {
|
|
43
48
|
return Obj.make(Graph, { name, view: Ref.make(view), query });
|
|
44
49
|
};
|
|
45
|
-
|
|
46
|
-
//
|
|
47
|
-
// V1
|
|
48
|
-
//
|
|
49
|
-
|
|
50
|
-
export const GraphV1 = Schema.Struct({
|
|
51
|
-
name: Schema.optional(Schema.String),
|
|
52
|
-
query: Schema.Struct({
|
|
53
|
-
raw: Schema.optional(Schema.String),
|
|
54
|
-
ast: QueryAST.Query,
|
|
55
|
-
}),
|
|
56
|
-
}).pipe(
|
|
57
|
-
Type.object({
|
|
58
|
-
typename: 'dxos.org/type/Graph',
|
|
59
|
-
version: '0.1.0',
|
|
60
|
-
}),
|
|
61
|
-
LabelAnnotation.set(['name']),
|
|
62
|
-
);
|
package/src/typings.d.ts
ADDED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
useGraphModel
|
|
3
|
-
} from "./chunk-BZMTFAP3.mjs";
|
|
4
|
-
import {
|
|
5
|
-
D3ForceGraph
|
|
6
|
-
} from "./chunk-MGBT2ZFU.mjs";
|
|
7
|
-
import "./chunk-J5LGTIGS.mjs";
|
|
8
|
-
|
|
9
|
-
// src/components/ExplorerContainer.tsx
|
|
10
|
-
import React, { useCallback, useMemo, useState } from "react";
|
|
11
|
-
import { QueryBuilder } from "@dxos/echo-query";
|
|
12
|
-
import { useGlobalSearch } from "@dxos/plugin-search";
|
|
13
|
-
import { getSpace } from "@dxos/react-client/echo";
|
|
14
|
-
import { Toolbar } from "@dxos/react-ui";
|
|
15
|
-
import { QueryEditor } from "@dxos/react-ui-components";
|
|
16
|
-
import { Layout } from "@dxos/react-ui-mosaic";
|
|
17
|
-
var ExplorerContainer = ({ role, subject: view }) => {
|
|
18
|
-
const space = getSpace(view);
|
|
19
|
-
const [filter, setFilter] = useState();
|
|
20
|
-
const model = useGraphModel(space, filter);
|
|
21
|
-
const { match } = useGlobalSearch();
|
|
22
|
-
const builder = useMemo(() => new QueryBuilder(), []);
|
|
23
|
-
const handleChange = useCallback((value) => {
|
|
24
|
-
setFilter(builder.build(value).filter);
|
|
25
|
-
}, []);
|
|
26
|
-
const showToolbar = role === "article";
|
|
27
|
-
if (!space || !model) {
|
|
28
|
-
return null;
|
|
29
|
-
}
|
|
30
|
-
return /* @__PURE__ */ React.createElement(Layout.Main, {
|
|
31
|
-
role,
|
|
32
|
-
toolbar: showToolbar
|
|
33
|
-
}, showToolbar && /* @__PURE__ */ React.createElement(Toolbar.Root, null, /* @__PURE__ */ React.createElement(QueryEditor, {
|
|
34
|
-
db: space.db,
|
|
35
|
-
onChange: handleChange
|
|
36
|
-
})), /* @__PURE__ */ React.createElement(D3ForceGraph, {
|
|
37
|
-
model,
|
|
38
|
-
match
|
|
39
|
-
}));
|
|
40
|
-
};
|
|
41
|
-
var ExplorerContainer_default = ExplorerContainer;
|
|
42
|
-
export {
|
|
43
|
-
ExplorerContainer_default as default
|
|
44
|
-
};
|
|
45
|
-
//# sourceMappingURL=ExplorerContainer-BFAWRIAJ.mjs.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/components/ExplorerContainer.tsx"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport React, { useCallback, useMemo, useState } from 'react';\n\nimport { type SurfaceComponentProps } from '@dxos/app-framework/react';\nimport { type Filter } from '@dxos/echo';\nimport { QueryBuilder } from '@dxos/echo-query';\nimport { useGlobalSearch } from '@dxos/plugin-search';\nimport { getSpace } from '@dxos/react-client/echo';\nimport { Toolbar } from '@dxos/react-ui';\nimport { QueryEditor, type QueryEditorProps } from '@dxos/react-ui-components';\nimport { Layout } from '@dxos/react-ui-mosaic';\nimport { type View } from '@dxos/schema';\n\nimport { useGraphModel } from '../hooks';\n\nimport { D3ForceGraph } from './Graph';\n\nexport type ExplorerContainerProps = SurfaceComponentProps<View.View>;\n\nconst ExplorerContainer = ({ role, subject: view }: ExplorerContainerProps) => {\n const space = getSpace(view);\n const [filter, setFilter] = useState<Filter.Any>();\n const model = useGraphModel(space, filter);\n const { match } = useGlobalSearch();\n\n const builder = useMemo(() => new QueryBuilder(), []);\n const handleChange = useCallback<NonNullable<QueryEditorProps['onChange']>>((value) => {\n setFilter(builder.build(value).filter);\n }, []);\n\n const showToolbar = role === 'article';\n\n if (!space || !model) {\n return null;\n }\n\n return (\n <Layout.Main role={role} toolbar={showToolbar}>\n {showToolbar && (\n <Toolbar.Root>\n <QueryEditor db={space.db} onChange={handleChange} />\n </Toolbar.Root>\n )}\n <D3ForceGraph model={model} match={match} />\n </Layout.Main>\n );\n};\n\nexport default ExplorerContainer;\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;AAIA,OAAOA,SAASC,aAAaC,SAASC,gBAAgB;AAItD,SAASC,oBAAoB;AAC7B,SAASC,uBAAuB;AAChC,SAASC,gBAAgB;AACzB,SAASC,eAAe;AACxB,SAASC,mBAA0C;AACnD,SAASC,cAAc;AASvB,IAAMC,oBAAoB,CAAC,EAAEC,MAAMC,SAASC,KAAI,MAA0B;AACxE,QAAMC,QAAQC,SAASF,IAAAA;AACvB,QAAM,CAACG,QAAQC,SAAAA,IAAaC,SAAAA;AAC5B,QAAMC,QAAQC,cAAcN,OAAOE,MAAAA;AACnC,QAAM,EAAEK,MAAK,IAAKC,gBAAAA;AAElB,QAAMC,UAAUC,QAAQ,MAAM,IAAIC,aAAAA,GAAgB,CAAA,CAAE;AACpD,QAAMC,eAAeC,YAAuD,CAACC,UAAAA;AAC3EX,cAAUM,QAAQM,MAAMD,KAAAA,EAAOZ,MAAM;EACvC,GAAG,CAAA,CAAE;AAEL,QAAMc,cAAcnB,SAAS;AAE7B,MAAI,CAACG,SAAS,CAACK,OAAO;AACpB,WAAO;EACT;AAEA,SACE,sBAAA,cAACY,OAAOC,MAAI;IAACrB;IAAYsB,SAASH;KAC/BA,eACC,sBAAA,cAACI,QAAQC,MAAI,MACX,sBAAA,cAACC,aAAAA;IAAYC,IAAIvB,MAAMuB;IAAIC,UAAUZ;OAGzC,sBAAA,cAACa,cAAAA;IAAapB;IAAcE;;AAGlC;AAEA,IAAA,4BAAeX;",
|
|
6
|
-
"names": ["React", "useCallback", "useMemo", "useState", "QueryBuilder", "useGlobalSearch", "getSpace", "Toolbar", "QueryEditor", "Layout", "ExplorerContainer", "role", "subject", "view", "space", "getSpace", "filter", "setFilter", "useState", "model", "useGraphModel", "match", "useGlobalSearch", "builder", "useMemo", "QueryBuilder", "handleChange", "useCallback", "value", "build", "showToolbar", "Layout", "Main", "toolbar", "Toolbar", "Root", "QueryEditor", "db", "onChange", "D3ForceGraph"]
|
|
7
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
// src/hooks/useGraphModel.ts
|
|
2
|
-
import { RegistryContext } from "@effect-atom/atom-react";
|
|
3
|
-
import { useContext, useEffect, useState } from "react";
|
|
4
|
-
import { SpaceGraphModel } from "@dxos/schema";
|
|
5
|
-
var useGraphModel = (space, filter, options, queue) => {
|
|
6
|
-
const registry = useContext(RegistryContext);
|
|
7
|
-
const [model, setModel] = useState(void 0);
|
|
8
|
-
useEffect(() => {
|
|
9
|
-
if (!space) {
|
|
10
|
-
void model?.close();
|
|
11
|
-
setModel(void 0);
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
if (!model || model.queue !== queue) {
|
|
15
|
-
const model2 = new SpaceGraphModel(registry).setFilter(filter).setOptions(options);
|
|
16
|
-
void model2.open(space.db, queue);
|
|
17
|
-
setModel(model2);
|
|
18
|
-
} else {
|
|
19
|
-
model.setFilter(filter).setOptions(options);
|
|
20
|
-
}
|
|
21
|
-
}, [
|
|
22
|
-
space,
|
|
23
|
-
filter,
|
|
24
|
-
options,
|
|
25
|
-
queue,
|
|
26
|
-
registry
|
|
27
|
-
]);
|
|
28
|
-
return model;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
export {
|
|
32
|
-
useGraphModel
|
|
33
|
-
};
|
|
34
|
-
//# sourceMappingURL=chunk-BZMTFAP3.mjs.map
|