@dxos/react-ui-canvas-compute 0.7.5-labs.5f04cf6
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 +8 -0
- package/README.md +1 -0
- package/dist/lib/browser/index.mjs +2499 -0
- package/dist/lib/browser/index.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -0
- package/dist/lib/node/index.cjs +2591 -0
- package/dist/lib/node/index.cjs.map +7 -0
- package/dist/lib/node/meta.json +1 -0
- package/dist/lib/node-esm/index.mjs +2499 -0
- package/dist/lib/node-esm/index.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -0
- package/dist/types/src/compute-layout.d.ts +9 -0
- package/dist/types/src/compute-layout.d.ts.map +1 -0
- package/dist/types/src/compute.stories.d.ts +28 -0
- package/dist/types/src/compute.stories.d.ts.map +1 -0
- package/dist/types/src/graph/controller.d.ts +139 -0
- package/dist/types/src/graph/controller.d.ts.map +1 -0
- package/dist/types/src/graph/index.d.ts +3 -0
- package/dist/types/src/graph/index.d.ts.map +1 -0
- package/dist/types/src/graph/node-defs.d.ts +6 -0
- package/dist/types/src/graph/node-defs.d.ts.map +1 -0
- package/dist/types/src/hooks/compute-context.d.ts +7 -0
- package/dist/types/src/hooks/compute-context.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +4 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -0
- package/dist/types/src/hooks/useComputeNodeState.d.ts +19 -0
- package/dist/types/src/hooks/useComputeNodeState.d.ts.map +1 -0
- package/dist/types/src/hooks/useGraphMonitor.d.ts +14 -0
- package/dist/types/src/hooks/useGraphMonitor.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +6 -0
- package/dist/types/src/index.d.ts.map +1 -0
- package/dist/types/src/json.test.d.ts +21 -0
- package/dist/types/src/json.test.d.ts.map +1 -0
- package/dist/types/src/registry.d.ts +9 -0
- package/dist/types/src/registry.d.ts.map +1 -0
- package/dist/types/src/schema.test.d.ts +2 -0
- package/dist/types/src/schema.test.d.ts.map +1 -0
- package/dist/types/src/shapes/Append.d.ts +54 -0
- package/dist/types/src/shapes/Append.d.ts.map +1 -0
- package/dist/types/src/shapes/Array.d.ts +38 -0
- package/dist/types/src/shapes/Array.d.ts.map +1 -0
- package/dist/types/src/shapes/Audio.d.ts +54 -0
- package/dist/types/src/shapes/Audio.d.ts.map +1 -0
- package/dist/types/src/shapes/Beacon.d.ts +54 -0
- package/dist/types/src/shapes/Beacon.d.ts.map +1 -0
- package/dist/types/src/shapes/Boolean.d.ts +233 -0
- package/dist/types/src/shapes/Boolean.d.ts.map +1 -0
- package/dist/types/src/shapes/Chat.d.ts +57 -0
- package/dist/types/src/shapes/Chat.d.ts.map +1 -0
- package/dist/types/src/shapes/Constant.d.ts +60 -0
- package/dist/types/src/shapes/Constant.d.ts.map +1 -0
- package/dist/types/src/shapes/Database.d.ts +54 -0
- package/dist/types/src/shapes/Database.d.ts.map +1 -0
- package/dist/types/src/shapes/Function.d.ts +54 -0
- package/dist/types/src/shapes/Function.d.ts.map +1 -0
- package/dist/types/src/shapes/Gpt.d.ts +54 -0
- package/dist/types/src/shapes/Gpt.d.ts.map +1 -0
- package/dist/types/src/shapes/GptRealtime.d.ts +54 -0
- package/dist/types/src/shapes/GptRealtime.d.ts.map +1 -0
- package/dist/types/src/shapes/Json.d.ts +107 -0
- package/dist/types/src/shapes/Json.d.ts.map +1 -0
- package/dist/types/src/shapes/Logic.d.ts +109 -0
- package/dist/types/src/shapes/Logic.d.ts.map +1 -0
- package/dist/types/src/shapes/Queue.d.ts +58 -0
- package/dist/types/src/shapes/Queue.d.ts.map +1 -0
- package/dist/types/src/shapes/RNG.d.ts +58 -0
- package/dist/types/src/shapes/RNG.d.ts.map +1 -0
- package/dist/types/src/shapes/Scope.d.ts +54 -0
- package/dist/types/src/shapes/Scope.d.ts.map +1 -0
- package/dist/types/src/shapes/Surface.d.ts +54 -0
- package/dist/types/src/shapes/Surface.d.ts.map +1 -0
- package/dist/types/src/shapes/Switch.d.ts +54 -0
- package/dist/types/src/shapes/Switch.d.ts.map +1 -0
- package/dist/types/src/shapes/Table.d.ts +54 -0
- package/dist/types/src/shapes/Table.d.ts.map +1 -0
- package/dist/types/src/shapes/Template.d.ts +56 -0
- package/dist/types/src/shapes/Template.d.ts.map +1 -0
- package/dist/types/src/shapes/Text.d.ts +54 -0
- package/dist/types/src/shapes/Text.d.ts.map +1 -0
- package/dist/types/src/shapes/TextToImage.d.ts +54 -0
- package/dist/types/src/shapes/TextToImage.d.ts.map +1 -0
- package/dist/types/src/shapes/Thread.d.ts +58 -0
- package/dist/types/src/shapes/Thread.d.ts.map +1 -0
- package/dist/types/src/shapes/Trigger.d.ts +64 -0
- package/dist/types/src/shapes/Trigger.d.ts.map +1 -0
- package/dist/types/src/shapes/common/Box.d.ts +25 -0
- package/dist/types/src/shapes/common/Box.d.ts.map +1 -0
- package/dist/types/src/shapes/common/FunctionBody.d.ts +15 -0
- package/dist/types/src/shapes/common/FunctionBody.d.ts.map +1 -0
- package/dist/types/src/shapes/common/TypeSelect.d.ts +4 -0
- package/dist/types/src/shapes/common/TypeSelect.d.ts.map +1 -0
- package/dist/types/src/shapes/common/index.d.ts +4 -0
- package/dist/types/src/shapes/common/index.d.ts.map +1 -0
- package/dist/types/src/shapes/defs.d.ts +39 -0
- package/dist/types/src/shapes/defs.d.ts.map +1 -0
- package/dist/types/src/shapes/index.d.ts +27 -0
- package/dist/types/src/shapes/index.d.ts.map +1 -0
- package/dist/types/src/testing/circuits.d.ts +193 -0
- package/dist/types/src/testing/circuits.d.ts.map +1 -0
- package/dist/types/src/testing/index.d.ts +2 -0
- package/dist/types/src/testing/index.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -0
- package/package.json +85 -0
- package/src/README.md +47 -0
- package/src/compute-layout.ts +37 -0
- package/src/compute.stories.tsx +362 -0
- package/src/graph/controller.ts +405 -0
- package/src/graph/index.ts +6 -0
- package/src/graph/node-defs.ts +82 -0
- package/src/hooks/compute-context.ts +19 -0
- package/src/hooks/index.ts +7 -0
- package/src/hooks/useComputeNodeState.ts +83 -0
- package/src/hooks/useGraphMonitor.ts +133 -0
- package/src/index.ts +9 -0
- package/src/json.test.ts +35 -0
- package/src/registry.ts +100 -0
- package/src/schema.test.ts +62 -0
- package/src/shapes/Append.tsx +43 -0
- package/src/shapes/Array.tsx +61 -0
- package/src/shapes/Audio.tsx +55 -0
- package/src/shapes/Beacon.tsx +56 -0
- package/src/shapes/Boolean.tsx +215 -0
- package/src/shapes/Chat.tsx +77 -0
- package/src/shapes/Constant.tsx +125 -0
- package/src/shapes/Database.tsx +39 -0
- package/src/shapes/Function.tsx +40 -0
- package/src/shapes/Gpt.tsx +91 -0
- package/src/shapes/GptRealtime.tsx +168 -0
- package/src/shapes/Json.tsx +103 -0
- package/src/shapes/Logic.tsx +82 -0
- package/src/shapes/Queue.tsx +78 -0
- package/src/shapes/RNG.tsx +84 -0
- package/src/shapes/Scope.tsx +54 -0
- package/src/shapes/Surface.tsx +57 -0
- package/src/shapes/Switch.tsx +53 -0
- package/src/shapes/Table.tsx +45 -0
- package/src/shapes/Template.tsx +98 -0
- package/src/shapes/Text.tsx +56 -0
- package/src/shapes/TextToImage.tsx +39 -0
- package/src/shapes/Thread.tsx +87 -0
- package/src/shapes/Trigger.tsx +152 -0
- package/src/shapes/common/Box.tsx +74 -0
- package/src/shapes/common/FunctionBody.tsx +122 -0
- package/src/shapes/common/TypeSelect.tsx +27 -0
- package/src/shapes/common/index.ts +7 -0
- package/src/shapes/defs.ts +50 -0
- package/src/shapes/index.ts +31 -0
- package/src/testing/circuits.ts +320 -0
- package/src/testing/index.ts +5 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { useMemo } from 'react';
|
|
6
|
+
|
|
7
|
+
import { type ComputeEdge, ComputeGraphModel, type ComputeNode, DEFAULT_INPUT, DEFAULT_OUTPUT } from '@dxos/conductor';
|
|
8
|
+
import { ObjectId } from '@dxos/echo-schema';
|
|
9
|
+
import { invariant } from '@dxos/invariant';
|
|
10
|
+
import { DXN } from '@dxos/keys';
|
|
11
|
+
import { getSpace } from '@dxos/react-client/echo';
|
|
12
|
+
import { type GraphMonitor, type CanvasGraphModel, type Connection } from '@dxos/react-ui-canvas-editor';
|
|
13
|
+
import { nonNullable } from '@dxos/util';
|
|
14
|
+
|
|
15
|
+
import { createComputeNode, isValidComputeNode } from '../graph';
|
|
16
|
+
import { type ComputeShape, type TriggerShape } from '../shapes';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Map canvas edge to compute edge.
|
|
20
|
+
*/
|
|
21
|
+
export const mapEdge = (
|
|
22
|
+
graph: CanvasGraphModel,
|
|
23
|
+
{ source, target, output = DEFAULT_OUTPUT, input = DEFAULT_INPUT }: Connection,
|
|
24
|
+
): ComputeEdge => {
|
|
25
|
+
const sourceNode = graph.findNode(source) as ComputeShape;
|
|
26
|
+
const targetNode = graph.findNode(target) as ComputeShape;
|
|
27
|
+
invariant(sourceNode?.node);
|
|
28
|
+
invariant(targetNode?.node);
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
id: ObjectId.random(),
|
|
32
|
+
source: sourceNode.node,
|
|
33
|
+
target: targetNode.node,
|
|
34
|
+
output,
|
|
35
|
+
input,
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Listens for changes to the graph and updates the compute graph.
|
|
41
|
+
* @param model Compute graph to update on change.
|
|
42
|
+
*/
|
|
43
|
+
// TODO(burdon): Generalize into sync function.
|
|
44
|
+
export const useGraphMonitor = (model?: ComputeGraphModel): GraphMonitor<ComputeShape> => {
|
|
45
|
+
return useMemo<GraphMonitor<ComputeShape>>(() => {
|
|
46
|
+
return {
|
|
47
|
+
onCreate: ({ node }) => {
|
|
48
|
+
if (!model) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Ignore shapes that don't have a corresponding node factory.
|
|
53
|
+
invariant(node.type);
|
|
54
|
+
if (!isValidComputeNode(node.type)) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const computeNode = createComputeNode(node);
|
|
59
|
+
if (node.type === 'trigger') {
|
|
60
|
+
linkTriggerToCompute(model, computeNode, node as TriggerShape);
|
|
61
|
+
}
|
|
62
|
+
model.addNode(computeNode);
|
|
63
|
+
node.node = computeNode.id;
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
onLink: ({ graph, edge }) => {
|
|
67
|
+
if (model) {
|
|
68
|
+
model.addEdge(mapEdge(graph, edge));
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
onDelete: ({ subgraph }) => {
|
|
73
|
+
if (model) {
|
|
74
|
+
const nodeIds = subgraph.nodes.map((shape) => (shape as ComputeShape).node) as string[];
|
|
75
|
+
|
|
76
|
+
// NOTE(ZaymonFC): Based on the information we have, this is O(edges to remove * compute edges).
|
|
77
|
+
const edgeIds = subgraph.edges
|
|
78
|
+
.map(({ source, target, output = DEFAULT_OUTPUT, input = DEFAULT_INPUT }) => {
|
|
79
|
+
return model.edges.find((computeEdge) => computeEdge.input === input && computeEdge.output === output)
|
|
80
|
+
?.id;
|
|
81
|
+
})
|
|
82
|
+
.filter(nonNullable);
|
|
83
|
+
|
|
84
|
+
model.removeNodes(nodeIds);
|
|
85
|
+
model.removeEdges(edgeIds);
|
|
86
|
+
|
|
87
|
+
deleteTriggerObjects(model, subgraph);
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
}, [model]);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export const createComputeGraph = (graph?: CanvasGraphModel<ComputeShape>) => {
|
|
95
|
+
const computeGraph = ComputeGraphModel.create();
|
|
96
|
+
|
|
97
|
+
if (graph) {
|
|
98
|
+
for (const shape of graph.nodes) {
|
|
99
|
+
if (isValidComputeNode(shape.type)) {
|
|
100
|
+
const node = createComputeNode(shape);
|
|
101
|
+
computeGraph.addNode(node);
|
|
102
|
+
shape.node = node.id;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
for (const edge of graph.edges) {
|
|
107
|
+
computeGraph.addEdge(mapEdge(graph, edge));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return computeGraph;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const linkTriggerToCompute = (graph: ComputeGraphModel, computeNode: ComputeNode, triggerData: TriggerShape) => {
|
|
115
|
+
const functionTrigger = triggerData.functionTrigger?.target;
|
|
116
|
+
invariant(functionTrigger);
|
|
117
|
+
functionTrigger.function = DXN.fromLocalObjectId(graph.root.id).toString();
|
|
118
|
+
functionTrigger.meta ??= {};
|
|
119
|
+
functionTrigger.meta.computeNodeId = computeNode.id;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const deleteTriggerObjects = (computeGraph: ComputeGraphModel, deleted: CanvasGraphModel) => {
|
|
123
|
+
const space = getSpace(computeGraph.root);
|
|
124
|
+
if (!space) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
for (const node of deleted.nodes) {
|
|
128
|
+
if (node.type === 'trigger') {
|
|
129
|
+
const trigger = node as TriggerShape;
|
|
130
|
+
space.db.remove(trigger.functionTrigger!.target!);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
};
|
package/src/index.ts
ADDED
package/src/json.test.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { describe, test } from 'vitest';
|
|
6
|
+
|
|
7
|
+
import { S } from '@dxos/echo-schema';
|
|
8
|
+
import { BaseGraphEdge, BaseGraphNode } from '@dxos/graph';
|
|
9
|
+
|
|
10
|
+
import { createGptCircuit } from './testing';
|
|
11
|
+
|
|
12
|
+
export const Shape = S.extend(
|
|
13
|
+
BaseGraphNode,
|
|
14
|
+
S.Struct({
|
|
15
|
+
text: S.optional(S.String),
|
|
16
|
+
guide: S.optional(S.Boolean),
|
|
17
|
+
classNames: S.optional(S.String),
|
|
18
|
+
}),
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
export const Connection = S.extend(
|
|
22
|
+
BaseGraphEdge,
|
|
23
|
+
S.Struct({
|
|
24
|
+
input: S.optional(S.String),
|
|
25
|
+
output: S.optional(S.String),
|
|
26
|
+
}),
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
describe('Compute Graph JSON encoding', () => {
|
|
30
|
+
test('compute graph toJSON', async ({ expect }) => {
|
|
31
|
+
const model = createGptCircuit({ db: true, artifact: true, cot: true });
|
|
32
|
+
const json = JSON.stringify(model.graph, null, 2);
|
|
33
|
+
expect(json).to.exist;
|
|
34
|
+
});
|
|
35
|
+
});
|
package/src/registry.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import type { ShapeDef } from '@dxos/react-ui-canvas-editor';
|
|
6
|
+
import { noteShape } from '@dxos/react-ui-canvas-editor';
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
andShape,
|
|
10
|
+
appendShape,
|
|
11
|
+
audioShape,
|
|
12
|
+
beaconShape,
|
|
13
|
+
chatShape,
|
|
14
|
+
constantShape,
|
|
15
|
+
databaseShape,
|
|
16
|
+
functionShape,
|
|
17
|
+
gptRealtimeShape,
|
|
18
|
+
gptShape,
|
|
19
|
+
ifElseShape,
|
|
20
|
+
ifShape,
|
|
21
|
+
jsonShape,
|
|
22
|
+
jsonTransformShape,
|
|
23
|
+
notShape,
|
|
24
|
+
orShape,
|
|
25
|
+
queueShape,
|
|
26
|
+
randomShape,
|
|
27
|
+
reducerShape,
|
|
28
|
+
scopeShape,
|
|
29
|
+
surfaceShape,
|
|
30
|
+
switchShape,
|
|
31
|
+
templateShape,
|
|
32
|
+
threadShape,
|
|
33
|
+
textToImageShape,
|
|
34
|
+
triggerShape,
|
|
35
|
+
textShape,
|
|
36
|
+
} from './shapes';
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Order used by toolbar.
|
|
40
|
+
*/
|
|
41
|
+
export const computeShapes: { title: string; shapes: ShapeDef[] }[] = [
|
|
42
|
+
{
|
|
43
|
+
title: 'Inputs',
|
|
44
|
+
shapes: [
|
|
45
|
+
//
|
|
46
|
+
constantShape,
|
|
47
|
+
templateShape,
|
|
48
|
+
chatShape,
|
|
49
|
+
switchShape,
|
|
50
|
+
audioShape,
|
|
51
|
+
triggerShape,
|
|
52
|
+
randomShape,
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
title: 'Transform',
|
|
57
|
+
shapes: [
|
|
58
|
+
//
|
|
59
|
+
gptShape,
|
|
60
|
+
gptRealtimeShape,
|
|
61
|
+
functionShape,
|
|
62
|
+
databaseShape,
|
|
63
|
+
textToImageShape,
|
|
64
|
+
appendShape,
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
title: 'Operations',
|
|
69
|
+
shapes: [
|
|
70
|
+
//
|
|
71
|
+
ifShape,
|
|
72
|
+
ifElseShape,
|
|
73
|
+
andShape,
|
|
74
|
+
orShape,
|
|
75
|
+
notShape,
|
|
76
|
+
reducerShape,
|
|
77
|
+
jsonTransformShape,
|
|
78
|
+
],
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
title: 'Outputs',
|
|
82
|
+
shapes: [
|
|
83
|
+
//
|
|
84
|
+
jsonShape,
|
|
85
|
+
queueShape,
|
|
86
|
+
threadShape,
|
|
87
|
+
textShape,
|
|
88
|
+
surfaceShape,
|
|
89
|
+
beaconShape,
|
|
90
|
+
scopeShape,
|
|
91
|
+
],
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
title: 'Misc',
|
|
95
|
+
shapes: [
|
|
96
|
+
//
|
|
97
|
+
noteShape,
|
|
98
|
+
],
|
|
99
|
+
},
|
|
100
|
+
];
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { describe, test } from 'vitest';
|
|
6
|
+
|
|
7
|
+
import { create } from '@dxos/client/echo';
|
|
8
|
+
import { S } from '@dxos/echo-schema';
|
|
9
|
+
import { BaseGraphNode, Graph } from '@dxos/graph';
|
|
10
|
+
import {
|
|
11
|
+
Polygon,
|
|
12
|
+
createEllipse,
|
|
13
|
+
createPath,
|
|
14
|
+
createRectangle,
|
|
15
|
+
isPath,
|
|
16
|
+
isPolygon,
|
|
17
|
+
Shape,
|
|
18
|
+
} from '@dxos/react-ui-canvas-editor';
|
|
19
|
+
|
|
20
|
+
import { createSwitch, ComputeShape, createFunction } from './shapes';
|
|
21
|
+
|
|
22
|
+
describe('compute', () => {
|
|
23
|
+
test('model', ({ expect }) => {
|
|
24
|
+
// const model = CanvasGraphModel.create<ComputeShape>();
|
|
25
|
+
const node = createSwitch({ id: 'x', center: { x: 0, y: 0 }, size: { width: 80, height: 80 } });
|
|
26
|
+
console.log(JSON.stringify(node, null, 2));
|
|
27
|
+
expect(S.is(ComputeShape)(node)).toBe(true);
|
|
28
|
+
expect(S.is(Polygon)(node)).toBe(true);
|
|
29
|
+
expect(S.is(Shape)(node)).toBe(true);
|
|
30
|
+
expect(S.is(BaseGraphNode)(node)).toBe(true);
|
|
31
|
+
|
|
32
|
+
const graph = create(Graph, { nodes: [], edges: [] });
|
|
33
|
+
graph.nodes.push(node); // Throws.
|
|
34
|
+
|
|
35
|
+
// model.createNode(node);
|
|
36
|
+
// console.log(JSON.stringify(model, null, 2));
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
describe('schema', () => {
|
|
41
|
+
test('basic types', ({ expect }) => {
|
|
42
|
+
const shapes: Shape[] = [];
|
|
43
|
+
shapes.push(createRectangle({ id: 'shape-1', center: { x: 0, y: 0 }, size: { width: 80, height: 80 } }));
|
|
44
|
+
shapes.push(createEllipse({ id: 'shape-2', center: { x: 0, y: 0 }, size: { width: 80, height: 80 } }));
|
|
45
|
+
shapes.push(createFunction({ id: 'shape-3', center: { x: 0, y: 0 } }));
|
|
46
|
+
shapes.push(
|
|
47
|
+
createPath({
|
|
48
|
+
id: 'shape-4',
|
|
49
|
+
points: [
|
|
50
|
+
{ x: 0, y: 0 },
|
|
51
|
+
{ x: 0, y: 0 },
|
|
52
|
+
],
|
|
53
|
+
}),
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
const polygons = shapes.filter((shape) => isPolygon(shape)).map((shape) => shape.center);
|
|
57
|
+
expect(polygons).to.have.length(3);
|
|
58
|
+
|
|
59
|
+
const paths = shapes.filter((shape) => isPath(shape)).map((shape) => shape.path);
|
|
60
|
+
expect(paths).to.have.length(1);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
|
|
7
|
+
import { AppendInput } from '@dxos/conductor';
|
|
8
|
+
import { S } from '@dxos/echo-schema';
|
|
9
|
+
import { type ShapeComponentProps, type ShapeDef } from '@dxos/react-ui-canvas-editor';
|
|
10
|
+
|
|
11
|
+
import { createFunctionAnchors, FunctionBody, getHeight } from './common';
|
|
12
|
+
import { ComputeShape, createShape, type CreateShapeProps } from './defs';
|
|
13
|
+
|
|
14
|
+
export const AppendShape = S.extend(
|
|
15
|
+
ComputeShape,
|
|
16
|
+
S.Struct({
|
|
17
|
+
type: S.Literal('append'),
|
|
18
|
+
}),
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
export type AppendShape = S.Schema.Type<typeof AppendShape>;
|
|
22
|
+
|
|
23
|
+
export type CreateAppendProps = CreateShapeProps<AppendShape>;
|
|
24
|
+
|
|
25
|
+
export const createAppend = (props: CreateAppendProps) =>
|
|
26
|
+
createShape<AppendShape>({
|
|
27
|
+
type: 'append',
|
|
28
|
+
size: { width: 128, height: getHeight(AppendInput) },
|
|
29
|
+
...props,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
export const AppendComponent = ({ shape }: ShapeComponentProps<AppendShape>) => {
|
|
33
|
+
return <FunctionBody shape={shape} inputSchema={AppendInput} />;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const appendShape: ShapeDef<AppendShape> = {
|
|
37
|
+
type: 'append',
|
|
38
|
+
name: 'Append',
|
|
39
|
+
icon: 'ph--list-plus--regular',
|
|
40
|
+
component: AppendComponent,
|
|
41
|
+
createShape: createAppend,
|
|
42
|
+
getAnchors: (shape) => createFunctionAnchors(shape, AppendInput),
|
|
43
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
|
|
7
|
+
import { ReducerInput, ReducerOutput } from '@dxos/conductor';
|
|
8
|
+
import { S } from '@dxos/echo-schema';
|
|
9
|
+
import { type ShapeComponentProps, type ShapeDef } from '@dxos/react-ui-canvas-editor';
|
|
10
|
+
|
|
11
|
+
import { createFunctionAnchors, FunctionBody, getHeight } from './common';
|
|
12
|
+
import { ComputeShape, createShape, type CreateShapeProps } from './defs';
|
|
13
|
+
|
|
14
|
+
//
|
|
15
|
+
// Data
|
|
16
|
+
//
|
|
17
|
+
|
|
18
|
+
export const ReducerShape = S.extend(
|
|
19
|
+
ComputeShape,
|
|
20
|
+
S.Struct({
|
|
21
|
+
type: S.Literal('reducer'),
|
|
22
|
+
}),
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
export type ReducerShape = S.Schema.Type<typeof ReducerShape>;
|
|
26
|
+
|
|
27
|
+
//
|
|
28
|
+
// Components
|
|
29
|
+
//
|
|
30
|
+
|
|
31
|
+
export type ReducerComponentProps = ShapeComponentProps<ReducerShape>;
|
|
32
|
+
|
|
33
|
+
export const ReducerComponent = ({ shape }: ReducerComponentProps) => {
|
|
34
|
+
return <FunctionBody shape={shape} inputSchema={ReducerInput} outputSchema={ReducerOutput} />;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
//
|
|
38
|
+
// Defs
|
|
39
|
+
//
|
|
40
|
+
|
|
41
|
+
export type CreateReduceProps = CreateShapeProps<ReducerShape> & { reduce?: string };
|
|
42
|
+
|
|
43
|
+
export const createReducer = ({
|
|
44
|
+
id,
|
|
45
|
+
size = { width: 192, height: getHeight(ReducerInput) },
|
|
46
|
+
...rest
|
|
47
|
+
}: CreateReduceProps): ReducerShape =>
|
|
48
|
+
createShape<ReducerShape>({
|
|
49
|
+
type: 'reducer',
|
|
50
|
+
size,
|
|
51
|
+
...rest,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
export const reducerShape: ShapeDef<ReducerShape> = {
|
|
55
|
+
type: 'reducer',
|
|
56
|
+
name: 'Reducer',
|
|
57
|
+
icon: 'ph--repeat--regular',
|
|
58
|
+
component: (props) => <ReducerComponent {...props} />,
|
|
59
|
+
createShape: createReducer,
|
|
60
|
+
getAnchors: (shape) => createFunctionAnchors(shape, ReducerInput, ReducerOutput),
|
|
61
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { useEffect, useState } from 'react';
|
|
6
|
+
|
|
7
|
+
import { S } from '@dxos/echo-schema';
|
|
8
|
+
import { Icon } from '@dxos/react-ui';
|
|
9
|
+
import { createAnchorMap, type ShapeComponentProps, type ShapeDef } from '@dxos/react-ui-canvas-editor';
|
|
10
|
+
|
|
11
|
+
import { ComputeShape, createAnchorId, createShape, type CreateShapeProps } from './defs';
|
|
12
|
+
import { useComputeNodeState } from '../hooks';
|
|
13
|
+
|
|
14
|
+
export const AudioShape = S.extend(
|
|
15
|
+
ComputeShape,
|
|
16
|
+
S.Struct({
|
|
17
|
+
type: S.Literal('audio'),
|
|
18
|
+
}),
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
export type AudioShape = S.Schema.Type<typeof AudioShape>;
|
|
22
|
+
|
|
23
|
+
export type CreateAudioProps = CreateShapeProps<AudioShape>;
|
|
24
|
+
|
|
25
|
+
export const createAudio = (props: CreateAudioProps) =>
|
|
26
|
+
createShape<AudioShape>({ type: 'audio', size: { width: 64, height: 64 }, ...props });
|
|
27
|
+
|
|
28
|
+
export const AudioComponent = ({ shape }: ShapeComponentProps<AudioShape>) => {
|
|
29
|
+
const { node } = useComputeNodeState(shape);
|
|
30
|
+
const [active, setActive] = useState(false);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
node.value = active;
|
|
33
|
+
}, [active]);
|
|
34
|
+
|
|
35
|
+
// https://docs.pmnd.rs/react-three-fiber/api/canvas#render-props
|
|
36
|
+
return (
|
|
37
|
+
<div className='flex w-full justify-center items-center'>
|
|
38
|
+
<Icon
|
|
39
|
+
icon={active ? 'ph--microphone--regular' : 'ph--microphone-slash--regular'}
|
|
40
|
+
classNames={['transition opacity-20 duration-1000', active && 'opacity-100 text-red-500']}
|
|
41
|
+
size={8}
|
|
42
|
+
onClick={() => setActive(!active)}
|
|
43
|
+
/>
|
|
44
|
+
</div>
|
|
45
|
+
);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const audioShape: ShapeDef<AudioShape> = {
|
|
49
|
+
type: 'audio',
|
|
50
|
+
name: 'Audio',
|
|
51
|
+
icon: 'ph--microphone--regular',
|
|
52
|
+
component: AudioComponent,
|
|
53
|
+
createShape: createAudio,
|
|
54
|
+
getAnchors: (shape) => createAnchorMap(shape, { [createAnchorId('output')]: { x: 1, y: 0 } }),
|
|
55
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
|
|
7
|
+
import { DEFAULT_INPUT, isTruthy } from '@dxos/conductor';
|
|
8
|
+
import { S } from '@dxos/echo-schema';
|
|
9
|
+
import { Icon } from '@dxos/react-ui';
|
|
10
|
+
import { createAnchorMap, type ShapeComponentProps, type ShapeDef } from '@dxos/react-ui-canvas-editor';
|
|
11
|
+
import { mx } from '@dxos/react-ui-theme';
|
|
12
|
+
|
|
13
|
+
import { ComputeShape, createAnchorId, createShape, type CreateShapeProps } from './defs';
|
|
14
|
+
import { useComputeNodeState } from '../hooks';
|
|
15
|
+
|
|
16
|
+
export const BeaconShape = S.extend(
|
|
17
|
+
ComputeShape,
|
|
18
|
+
S.Struct({
|
|
19
|
+
type: S.Literal('beacon'),
|
|
20
|
+
}),
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
export type BeaconShape = S.Schema.Type<typeof BeaconShape>;
|
|
24
|
+
|
|
25
|
+
export type CreateBeaconProps = CreateShapeProps<BeaconShape>;
|
|
26
|
+
|
|
27
|
+
export const createBeacon = (props: CreateBeaconProps) =>
|
|
28
|
+
createShape<BeaconShape>({ type: 'beacon', size: { width: 64, height: 64 }, ...props });
|
|
29
|
+
|
|
30
|
+
export const BeaconComponent = ({ shape }: ShapeComponentProps<BeaconShape>) => {
|
|
31
|
+
const { runtime } = useComputeNodeState(shape);
|
|
32
|
+
const input = runtime.inputs[DEFAULT_INPUT];
|
|
33
|
+
const value = input?.type === 'executed' ? input.value : false;
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<div className='flex w-full justify-center items-center'>
|
|
37
|
+
<Icon
|
|
38
|
+
icon='ph--sun--regular'
|
|
39
|
+
classNames={mx('transition opacity-20 duration-1000', isTruthy(value) && 'opacity-100 text-yellow-500')}
|
|
40
|
+
size={8}
|
|
41
|
+
/>
|
|
42
|
+
</div>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const beaconShape: ShapeDef<BeaconShape> = {
|
|
47
|
+
type: 'beacon',
|
|
48
|
+
name: 'Beacon',
|
|
49
|
+
icon: 'ph--sun--regular',
|
|
50
|
+
component: BeaconComponent,
|
|
51
|
+
createShape: createBeacon,
|
|
52
|
+
getAnchors: (shape) =>
|
|
53
|
+
createAnchorMap(shape, {
|
|
54
|
+
[createAnchorId('input')]: { x: -1, y: 0 },
|
|
55
|
+
}),
|
|
56
|
+
};
|