@dxos/react-ui-canvas-compute 0.7.5-labs.071a3e2

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.
Files changed (155) hide show
  1. package/LICENSE +8 -0
  2. package/README.md +1 -0
  3. package/dist/lib/browser/index.mjs +2535 -0
  4. package/dist/lib/browser/index.mjs.map +7 -0
  5. package/dist/lib/browser/meta.json +1 -0
  6. package/dist/lib/node/index.cjs +2627 -0
  7. package/dist/lib/node/index.cjs.map +7 -0
  8. package/dist/lib/node/meta.json +1 -0
  9. package/dist/lib/node-esm/index.mjs +2535 -0
  10. package/dist/lib/node-esm/index.mjs.map +7 -0
  11. package/dist/lib/node-esm/meta.json +1 -0
  12. package/dist/types/src/components/DiagnosticOverlay.d.ts +7 -0
  13. package/dist/types/src/components/DiagnosticOverlay.d.ts.map +1 -0
  14. package/dist/types/src/components/index.d.ts +2 -0
  15. package/dist/types/src/components/index.d.ts.map +1 -0
  16. package/dist/types/src/compute-layout.d.ts +9 -0
  17. package/dist/types/src/compute-layout.d.ts.map +1 -0
  18. package/dist/types/src/compute.stories.d.ts +28 -0
  19. package/dist/types/src/compute.stories.d.ts.map +1 -0
  20. package/dist/types/src/graph/controller.d.ts +142 -0
  21. package/dist/types/src/graph/controller.d.ts.map +1 -0
  22. package/dist/types/src/graph/index.d.ts +3 -0
  23. package/dist/types/src/graph/index.d.ts.map +1 -0
  24. package/dist/types/src/graph/node-defs.d.ts +6 -0
  25. package/dist/types/src/graph/node-defs.d.ts.map +1 -0
  26. package/dist/types/src/hooks/compute-context.d.ts +7 -0
  27. package/dist/types/src/hooks/compute-context.d.ts.map +1 -0
  28. package/dist/types/src/hooks/index.d.ts +4 -0
  29. package/dist/types/src/hooks/index.d.ts.map +1 -0
  30. package/dist/types/src/hooks/useComputeNodeState.d.ts +19 -0
  31. package/dist/types/src/hooks/useComputeNodeState.d.ts.map +1 -0
  32. package/dist/types/src/hooks/useGraphMonitor.d.ts +14 -0
  33. package/dist/types/src/hooks/useGraphMonitor.d.ts.map +1 -0
  34. package/dist/types/src/index.d.ts +6 -0
  35. package/dist/types/src/index.d.ts.map +1 -0
  36. package/dist/types/src/json.test.d.ts +21 -0
  37. package/dist/types/src/json.test.d.ts.map +1 -0
  38. package/dist/types/src/registry.d.ts +9 -0
  39. package/dist/types/src/registry.d.ts.map +1 -0
  40. package/dist/types/src/schema.test.d.ts +2 -0
  41. package/dist/types/src/schema.test.d.ts.map +1 -0
  42. package/dist/types/src/shapes/Append.d.ts +54 -0
  43. package/dist/types/src/shapes/Append.d.ts.map +1 -0
  44. package/dist/types/src/shapes/Array.d.ts +38 -0
  45. package/dist/types/src/shapes/Array.d.ts.map +1 -0
  46. package/dist/types/src/shapes/Audio.d.ts +54 -0
  47. package/dist/types/src/shapes/Audio.d.ts.map +1 -0
  48. package/dist/types/src/shapes/Beacon.d.ts +54 -0
  49. package/dist/types/src/shapes/Beacon.d.ts.map +1 -0
  50. package/dist/types/src/shapes/Boolean.d.ts +233 -0
  51. package/dist/types/src/shapes/Boolean.d.ts.map +1 -0
  52. package/dist/types/src/shapes/Chat.d.ts +57 -0
  53. package/dist/types/src/shapes/Chat.d.ts.map +1 -0
  54. package/dist/types/src/shapes/Constant.d.ts +60 -0
  55. package/dist/types/src/shapes/Constant.d.ts.map +1 -0
  56. package/dist/types/src/shapes/Database.d.ts +54 -0
  57. package/dist/types/src/shapes/Database.d.ts.map +1 -0
  58. package/dist/types/src/shapes/Function.d.ts +54 -0
  59. package/dist/types/src/shapes/Function.d.ts.map +1 -0
  60. package/dist/types/src/shapes/Gpt.d.ts +54 -0
  61. package/dist/types/src/shapes/Gpt.d.ts.map +1 -0
  62. package/dist/types/src/shapes/GptRealtime.d.ts +54 -0
  63. package/dist/types/src/shapes/GptRealtime.d.ts.map +1 -0
  64. package/dist/types/src/shapes/Json.d.ts +107 -0
  65. package/dist/types/src/shapes/Json.d.ts.map +1 -0
  66. package/dist/types/src/shapes/Logic.d.ts +109 -0
  67. package/dist/types/src/shapes/Logic.d.ts.map +1 -0
  68. package/dist/types/src/shapes/Queue.d.ts +58 -0
  69. package/dist/types/src/shapes/Queue.d.ts.map +1 -0
  70. package/dist/types/src/shapes/RNG.d.ts +58 -0
  71. package/dist/types/src/shapes/RNG.d.ts.map +1 -0
  72. package/dist/types/src/shapes/Scope.d.ts +54 -0
  73. package/dist/types/src/shapes/Scope.d.ts.map +1 -0
  74. package/dist/types/src/shapes/Surface.d.ts +54 -0
  75. package/dist/types/src/shapes/Surface.d.ts.map +1 -0
  76. package/dist/types/src/shapes/Switch.d.ts +54 -0
  77. package/dist/types/src/shapes/Switch.d.ts.map +1 -0
  78. package/dist/types/src/shapes/Table.d.ts +54 -0
  79. package/dist/types/src/shapes/Table.d.ts.map +1 -0
  80. package/dist/types/src/shapes/Template.d.ts +56 -0
  81. package/dist/types/src/shapes/Template.d.ts.map +1 -0
  82. package/dist/types/src/shapes/Text.d.ts +54 -0
  83. package/dist/types/src/shapes/Text.d.ts.map +1 -0
  84. package/dist/types/src/shapes/TextToImage.d.ts +54 -0
  85. package/dist/types/src/shapes/TextToImage.d.ts.map +1 -0
  86. package/dist/types/src/shapes/Thread.d.ts +58 -0
  87. package/dist/types/src/shapes/Thread.d.ts.map +1 -0
  88. package/dist/types/src/shapes/Trigger.d.ts +64 -0
  89. package/dist/types/src/shapes/Trigger.d.ts.map +1 -0
  90. package/dist/types/src/shapes/common/Box.d.ts +25 -0
  91. package/dist/types/src/shapes/common/Box.d.ts.map +1 -0
  92. package/dist/types/src/shapes/common/FunctionBody.d.ts +15 -0
  93. package/dist/types/src/shapes/common/FunctionBody.d.ts.map +1 -0
  94. package/dist/types/src/shapes/common/TypeSelect.d.ts +4 -0
  95. package/dist/types/src/shapes/common/TypeSelect.d.ts.map +1 -0
  96. package/dist/types/src/shapes/common/index.d.ts +4 -0
  97. package/dist/types/src/shapes/common/index.d.ts.map +1 -0
  98. package/dist/types/src/shapes/defs.d.ts +39 -0
  99. package/dist/types/src/shapes/defs.d.ts.map +1 -0
  100. package/dist/types/src/shapes/index.d.ts +27 -0
  101. package/dist/types/src/shapes/index.d.ts.map +1 -0
  102. package/dist/types/src/testing/circuits.d.ts +193 -0
  103. package/dist/types/src/testing/circuits.d.ts.map +1 -0
  104. package/dist/types/src/testing/index.d.ts +2 -0
  105. package/dist/types/src/testing/index.d.ts.map +1 -0
  106. package/dist/types/tsconfig.tsbuildinfo +1 -0
  107. package/package.json +85 -0
  108. package/src/README.md +47 -0
  109. package/src/components/DiagnosticOverlay.tsx +23 -0
  110. package/src/components/index.ts +5 -0
  111. package/src/compute-layout.ts +37 -0
  112. package/src/compute.stories.tsx +365 -0
  113. package/src/graph/controller.ts +419 -0
  114. package/src/graph/index.ts +6 -0
  115. package/src/graph/node-defs.ts +82 -0
  116. package/src/hooks/compute-context.ts +19 -0
  117. package/src/hooks/index.ts +7 -0
  118. package/src/hooks/useComputeNodeState.ts +83 -0
  119. package/src/hooks/useGraphMonitor.ts +133 -0
  120. package/src/index.ts +9 -0
  121. package/src/json.test.ts +35 -0
  122. package/src/registry.ts +100 -0
  123. package/src/schema.test.ts +62 -0
  124. package/src/shapes/Append.tsx +43 -0
  125. package/src/shapes/Array.tsx +61 -0
  126. package/src/shapes/Audio.tsx +55 -0
  127. package/src/shapes/Beacon.tsx +56 -0
  128. package/src/shapes/Boolean.tsx +215 -0
  129. package/src/shapes/Chat.tsx +77 -0
  130. package/src/shapes/Constant.tsx +125 -0
  131. package/src/shapes/Database.tsx +39 -0
  132. package/src/shapes/Function.tsx +40 -0
  133. package/src/shapes/Gpt.tsx +91 -0
  134. package/src/shapes/GptRealtime.tsx +175 -0
  135. package/src/shapes/Json.tsx +103 -0
  136. package/src/shapes/Logic.tsx +82 -0
  137. package/src/shapes/Queue.tsx +78 -0
  138. package/src/shapes/RNG.tsx +84 -0
  139. package/src/shapes/Scope.tsx +54 -0
  140. package/src/shapes/Surface.tsx +57 -0
  141. package/src/shapes/Switch.tsx +53 -0
  142. package/src/shapes/Table.tsx +45 -0
  143. package/src/shapes/Template.tsx +98 -0
  144. package/src/shapes/Text.tsx +56 -0
  145. package/src/shapes/TextToImage.tsx +39 -0
  146. package/src/shapes/Thread.tsx +87 -0
  147. package/src/shapes/Trigger.tsx +152 -0
  148. package/src/shapes/common/Box.tsx +74 -0
  149. package/src/shapes/common/FunctionBody.tsx +122 -0
  150. package/src/shapes/common/TypeSelect.tsx +31 -0
  151. package/src/shapes/common/index.ts +7 -0
  152. package/src/shapes/defs.ts +50 -0
  153. package/src/shapes/index.ts +31 -0
  154. package/src/testing/circuits.ts +320 -0
  155. 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
@@ -0,0 +1,9 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ export * from './graph';
6
+ export * from './hooks';
7
+ export * from './registry';
8
+ export * from './shapes';
9
+ export * from './compute-layout';
@@ -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
+ });
@@ -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
+ };