@dxos/app-graph 0.8.4-main.f9ba587 → 0.8.4-main.fffef41
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/index.mjs +249 -191
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +249 -191
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/graph-builder.d.ts +29 -18
- package/dist/types/src/graph-builder.d.ts.map +1 -1
- package/dist/types/src/graph.d.ts +25 -21
- package/dist/types/src/graph.d.ts.map +1 -1
- package/dist/types/src/node.d.ts +1 -1
- package/dist/types/src/node.d.ts.map +1 -1
- package/dist/types/src/stories/EchoGraph.stories.d.ts +8 -10
- package/dist/types/src/stories/EchoGraph.stories.d.ts.map +1 -1
- package/dist/types/src/testing.d.ts +3 -3
- package/dist/types/src/testing.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +32 -34
- package/src/graph-builder.test.ts +90 -32
- package/src/graph-builder.ts +109 -60
- package/src/graph.test.ts +4 -4
- package/src/graph.ts +130 -89
- package/src/node.ts +5 -3
- package/src/signals-integration.test.ts +29 -28
- package/src/stories/EchoGraph.stories.tsx +49 -39
- package/src/stories/Tree.tsx +1 -1
- package/src/testing.ts +4 -4
|
@@ -2,40 +2,39 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import '@
|
|
6
|
-
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import { type Meta } from '@storybook/react-vite';
|
|
10
|
-
import { Option, pipe } from 'effect';
|
|
5
|
+
import { Atom, type Registry, RegistryContext, useAtomValue } from '@effect-atom/atom-react';
|
|
6
|
+
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
7
|
+
import * as Function from 'effect/Function';
|
|
8
|
+
import * as Option from 'effect/Option';
|
|
11
9
|
import React, { type PropsWithChildren, useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
|
12
10
|
|
|
13
11
|
import {
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
Expando,
|
|
13
|
+
Filter,
|
|
14
|
+
type Live,
|
|
16
15
|
Query,
|
|
17
16
|
type QueryResult,
|
|
18
17
|
type Space,
|
|
19
18
|
SpaceState,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
Filter,
|
|
19
|
+
isSpace,
|
|
20
|
+
live,
|
|
23
21
|
} from '@dxos/client/echo';
|
|
24
22
|
import { Obj, Type } from '@dxos/echo';
|
|
25
23
|
import { faker } from '@dxos/random';
|
|
26
24
|
import { type Client, useClient } from '@dxos/react-client';
|
|
27
25
|
import { withClientProvider } from '@dxos/react-client/testing';
|
|
28
|
-
import {
|
|
26
|
+
import { Icon, IconButton, Input, Select } from '@dxos/react-ui';
|
|
27
|
+
import { withTheme } from '@dxos/react-ui/testing';
|
|
29
28
|
import { Path, Tree } from '@dxos/react-ui-list';
|
|
30
29
|
import { getSize, mx } from '@dxos/react-ui-theme';
|
|
31
|
-
import { withTheme } from '@dxos/storybook-utils';
|
|
32
30
|
import { byPosition, isNonNullable, safeParseInt } from '@dxos/util';
|
|
33
31
|
|
|
34
|
-
import { JsonTree } from './Tree';
|
|
35
32
|
import { type ExpandableGraph, ROOT_ID } from '../graph';
|
|
36
|
-
import { GraphBuilder,
|
|
33
|
+
import { GraphBuilder, atomFromObservable, createExtension } from '../graph-builder';
|
|
37
34
|
import { type Node } from '../node';
|
|
38
|
-
import {
|
|
35
|
+
import { atomFromQuery } from '../testing';
|
|
36
|
+
|
|
37
|
+
import { JsonTree } from './Tree';
|
|
39
38
|
|
|
40
39
|
const DEFAULT_PERIOD = 500;
|
|
41
40
|
|
|
@@ -61,18 +60,20 @@ const createGraph = (client: Client, registry: Registry.Registry): ExpandableGra
|
|
|
61
60
|
const spaceBuilderExtension = createExtension({
|
|
62
61
|
id: 'space',
|
|
63
62
|
connector: (node) =>
|
|
64
|
-
|
|
65
|
-
pipe(
|
|
63
|
+
Atom.make((get) =>
|
|
64
|
+
Function.pipe(
|
|
66
65
|
get(node),
|
|
67
66
|
Option.flatMap((node) => (node.id === ROOT_ID ? Option.some(node) : Option.none())),
|
|
68
67
|
Option.map(() => {
|
|
69
|
-
const spaces = get(
|
|
68
|
+
const spaces = get(atomFromObservable(client.spaces)) ?? [];
|
|
70
69
|
return spaces
|
|
71
|
-
.filter((space) => get(
|
|
70
|
+
.filter((space) => get(atomFromObservable(space.state)) === SpaceState.SPACE_READY)
|
|
72
71
|
.map((space) => ({
|
|
73
72
|
id: space.id,
|
|
74
73
|
type: 'dxos.org/type/Space',
|
|
75
|
-
properties: {
|
|
74
|
+
properties: {
|
|
75
|
+
label: get(atomFromObservable(space.properties.name)),
|
|
76
|
+
},
|
|
76
77
|
data: space,
|
|
77
78
|
}));
|
|
78
79
|
}),
|
|
@@ -85,15 +86,15 @@ const createGraph = (client: Client, registry: Registry.Registry): ExpandableGra
|
|
|
85
86
|
id: 'object',
|
|
86
87
|
connector: (node) => {
|
|
87
88
|
let query: QueryResult<Live<Expando>> | undefined;
|
|
88
|
-
return
|
|
89
|
-
pipe(
|
|
89
|
+
return Atom.make((get) =>
|
|
90
|
+
Function.pipe(
|
|
90
91
|
get(node),
|
|
91
92
|
Option.flatMap((node) => (isSpace(node.data) ? Option.some(node.data) : Option.none())),
|
|
92
93
|
Option.map((space) => {
|
|
93
94
|
if (!query) {
|
|
94
95
|
query = space.db.query(Query.type(Expando, { type: 'test' }));
|
|
95
96
|
}
|
|
96
|
-
const objects = get(
|
|
97
|
+
const objects = get(atomFromQuery(query));
|
|
97
98
|
return objects.map((object) => ({
|
|
98
99
|
id: object.id,
|
|
99
100
|
type: 'dxos.org/type/test',
|
|
@@ -160,7 +161,12 @@ const runAction = async (client: Client, action: Action) => {
|
|
|
160
161
|
}
|
|
161
162
|
|
|
162
163
|
case Action.ADD_OBJECT:
|
|
163
|
-
getRandomSpace(client)?.db.add(
|
|
164
|
+
getRandomSpace(client)?.db.add(
|
|
165
|
+
Obj.make(Type.Expando, {
|
|
166
|
+
type: 'test',
|
|
167
|
+
name: faker.commerce.productName(),
|
|
168
|
+
}),
|
|
169
|
+
);
|
|
164
170
|
break;
|
|
165
171
|
|
|
166
172
|
case Action.REMOVE_OBJECT: {
|
|
@@ -205,23 +211,25 @@ const Controls = ({ children }: PropsWithChildren) => {
|
|
|
205
211
|
return (
|
|
206
212
|
<>
|
|
207
213
|
<div className='flex shrink-0 p-2 space-x-2'>
|
|
208
|
-
<
|
|
214
|
+
<IconButton
|
|
215
|
+
icon={generating ? 'ph--pause--regular' : 'ph--play--regular'}
|
|
216
|
+
label={generating ? 'Pause' : 'Play'}
|
|
217
|
+
onClick={() => setGenerating((generating) => !generating)}
|
|
218
|
+
/>
|
|
209
219
|
<div className='relative' title='mutation period'>
|
|
210
220
|
<Input.Root>
|
|
211
221
|
<Input.TextInput
|
|
212
222
|
autoComplete='off'
|
|
213
223
|
size={5}
|
|
214
|
-
classNames='
|
|
224
|
+
classNames='is-[100px] text-right pie-[22px]'
|
|
215
225
|
placeholder='Interval'
|
|
216
226
|
value={actionInterval}
|
|
217
227
|
onChange={({ target: { value } }) => setActionInterval(value)}
|
|
218
228
|
/>
|
|
219
229
|
</Input.Root>
|
|
220
|
-
<
|
|
230
|
+
<Icon icon='ph--timer--regular' classNames={mx('absolute inline-end-1 block-start-1 mt-[6px]', getSize(3))} />
|
|
221
231
|
</div>
|
|
222
|
-
<
|
|
223
|
-
<Plus />
|
|
224
|
-
</Button>
|
|
232
|
+
<IconButton icon='ph--plus--regular' label='Add' onClick={() => action && runAction(client, action)} />
|
|
225
233
|
<Select.Root value={action?.toString()} onValueChange={(action) => setAction(action as unknown as Action)}>
|
|
226
234
|
<Select.TriggerButton placeholder='Select value' />
|
|
227
235
|
<Select.Portal>
|
|
@@ -245,28 +253,30 @@ const Controls = ({ children }: PropsWithChildren) => {
|
|
|
245
253
|
);
|
|
246
254
|
};
|
|
247
255
|
|
|
248
|
-
const meta
|
|
256
|
+
const meta = {
|
|
249
257
|
title: 'sdk/app-graph/EchoGraph',
|
|
250
258
|
decorators: [
|
|
259
|
+
withTheme,
|
|
251
260
|
withClientProvider({
|
|
252
261
|
createIdentity: true,
|
|
253
|
-
|
|
262
|
+
onCreateIdentity: async ({ client }) => {
|
|
254
263
|
await client.spaces.create();
|
|
255
264
|
await client.spaces.create();
|
|
256
265
|
},
|
|
257
266
|
}),
|
|
258
|
-
withTheme,
|
|
259
267
|
],
|
|
260
|
-
};
|
|
268
|
+
} satisfies Meta;
|
|
261
269
|
|
|
262
270
|
export default meta;
|
|
263
271
|
|
|
264
|
-
|
|
272
|
+
type Story = StoryObj<typeof meta>;
|
|
273
|
+
|
|
274
|
+
export const JsonView: Story = {
|
|
265
275
|
render: () => {
|
|
266
276
|
const client = useClient();
|
|
267
277
|
const registry = useContext(RegistryContext);
|
|
268
278
|
const graph = useMemo(() => createGraph(client, registry), [client, registry]);
|
|
269
|
-
const data =
|
|
279
|
+
const data = useAtomValue(graph.json());
|
|
270
280
|
|
|
271
281
|
return (
|
|
272
282
|
<>
|
|
@@ -277,7 +287,7 @@ export const JsonView = {
|
|
|
277
287
|
},
|
|
278
288
|
};
|
|
279
289
|
|
|
280
|
-
export const TreeView = {
|
|
290
|
+
export const TreeView: Story = {
|
|
281
291
|
render: () => {
|
|
282
292
|
const client = useClient();
|
|
283
293
|
const registry = useContext(RegistryContext);
|
|
@@ -286,7 +296,7 @@ export const TreeView = {
|
|
|
286
296
|
|
|
287
297
|
const useItems = useCallback(
|
|
288
298
|
(node?: Node, options?: { disposition?: string; sort?: boolean }) => {
|
|
289
|
-
const connections =
|
|
299
|
+
const connections = useAtomValue(graph.connections(node?.id ?? ROOT_ID));
|
|
290
300
|
return options?.sort ? connections.toSorted((a, b) => byPosition(a.properties, b.properties)) : connections;
|
|
291
301
|
},
|
|
292
302
|
[graph],
|
package/src/stories/Tree.tsx
CHANGED
|
@@ -72,7 +72,7 @@ const Scalar: FC<{ value: any }> = ({ value }) => {
|
|
|
72
72
|
|
|
73
73
|
const Box: FC<HTMLAttributes<HTMLDivElement>> = ({ children, className, ...props }) => {
|
|
74
74
|
return (
|
|
75
|
-
<div className={mx('flex
|
|
75
|
+
<div className={mx('flex pli-2 border border-l-0 font-mono truncate', className)} {...props}>
|
|
76
76
|
{children}
|
|
77
77
|
</div>
|
|
78
78
|
);
|
package/src/testing.ts
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { Atom } from '@effect-atom/atom-react';
|
|
6
6
|
|
|
7
|
+
import { type AnyEchoObject } from '@dxos/echo/internal';
|
|
7
8
|
import { type QueryResult } from '@dxos/echo-db';
|
|
8
|
-
import { type AnyEchoObject } from '@dxos/echo-schema';
|
|
9
9
|
|
|
10
|
-
export const
|
|
11
|
-
return
|
|
10
|
+
export const atomFromQuery = <T extends AnyEchoObject>(query: QueryResult<T>): Atom.Atom<T[]> => {
|
|
11
|
+
return Atom.make((get) => {
|
|
12
12
|
const unsubscribe = query.subscribe((result) => {
|
|
13
13
|
get.setSelf(result.objects);
|
|
14
14
|
});
|