@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.
Files changed (149) hide show
  1. package/LICENSE +8 -0
  2. package/README.md +1 -0
  3. package/dist/lib/browser/index.mjs +2499 -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 +2591 -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 +2499 -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/compute-layout.d.ts +9 -0
  13. package/dist/types/src/compute-layout.d.ts.map +1 -0
  14. package/dist/types/src/compute.stories.d.ts +28 -0
  15. package/dist/types/src/compute.stories.d.ts.map +1 -0
  16. package/dist/types/src/graph/controller.d.ts +139 -0
  17. package/dist/types/src/graph/controller.d.ts.map +1 -0
  18. package/dist/types/src/graph/index.d.ts +3 -0
  19. package/dist/types/src/graph/index.d.ts.map +1 -0
  20. package/dist/types/src/graph/node-defs.d.ts +6 -0
  21. package/dist/types/src/graph/node-defs.d.ts.map +1 -0
  22. package/dist/types/src/hooks/compute-context.d.ts +7 -0
  23. package/dist/types/src/hooks/compute-context.d.ts.map +1 -0
  24. package/dist/types/src/hooks/index.d.ts +4 -0
  25. package/dist/types/src/hooks/index.d.ts.map +1 -0
  26. package/dist/types/src/hooks/useComputeNodeState.d.ts +19 -0
  27. package/dist/types/src/hooks/useComputeNodeState.d.ts.map +1 -0
  28. package/dist/types/src/hooks/useGraphMonitor.d.ts +14 -0
  29. package/dist/types/src/hooks/useGraphMonitor.d.ts.map +1 -0
  30. package/dist/types/src/index.d.ts +6 -0
  31. package/dist/types/src/index.d.ts.map +1 -0
  32. package/dist/types/src/json.test.d.ts +21 -0
  33. package/dist/types/src/json.test.d.ts.map +1 -0
  34. package/dist/types/src/registry.d.ts +9 -0
  35. package/dist/types/src/registry.d.ts.map +1 -0
  36. package/dist/types/src/schema.test.d.ts +2 -0
  37. package/dist/types/src/schema.test.d.ts.map +1 -0
  38. package/dist/types/src/shapes/Append.d.ts +54 -0
  39. package/dist/types/src/shapes/Append.d.ts.map +1 -0
  40. package/dist/types/src/shapes/Array.d.ts +38 -0
  41. package/dist/types/src/shapes/Array.d.ts.map +1 -0
  42. package/dist/types/src/shapes/Audio.d.ts +54 -0
  43. package/dist/types/src/shapes/Audio.d.ts.map +1 -0
  44. package/dist/types/src/shapes/Beacon.d.ts +54 -0
  45. package/dist/types/src/shapes/Beacon.d.ts.map +1 -0
  46. package/dist/types/src/shapes/Boolean.d.ts +233 -0
  47. package/dist/types/src/shapes/Boolean.d.ts.map +1 -0
  48. package/dist/types/src/shapes/Chat.d.ts +57 -0
  49. package/dist/types/src/shapes/Chat.d.ts.map +1 -0
  50. package/dist/types/src/shapes/Constant.d.ts +60 -0
  51. package/dist/types/src/shapes/Constant.d.ts.map +1 -0
  52. package/dist/types/src/shapes/Database.d.ts +54 -0
  53. package/dist/types/src/shapes/Database.d.ts.map +1 -0
  54. package/dist/types/src/shapes/Function.d.ts +54 -0
  55. package/dist/types/src/shapes/Function.d.ts.map +1 -0
  56. package/dist/types/src/shapes/Gpt.d.ts +54 -0
  57. package/dist/types/src/shapes/Gpt.d.ts.map +1 -0
  58. package/dist/types/src/shapes/GptRealtime.d.ts +54 -0
  59. package/dist/types/src/shapes/GptRealtime.d.ts.map +1 -0
  60. package/dist/types/src/shapes/Json.d.ts +107 -0
  61. package/dist/types/src/shapes/Json.d.ts.map +1 -0
  62. package/dist/types/src/shapes/Logic.d.ts +109 -0
  63. package/dist/types/src/shapes/Logic.d.ts.map +1 -0
  64. package/dist/types/src/shapes/Queue.d.ts +58 -0
  65. package/dist/types/src/shapes/Queue.d.ts.map +1 -0
  66. package/dist/types/src/shapes/RNG.d.ts +58 -0
  67. package/dist/types/src/shapes/RNG.d.ts.map +1 -0
  68. package/dist/types/src/shapes/Scope.d.ts +54 -0
  69. package/dist/types/src/shapes/Scope.d.ts.map +1 -0
  70. package/dist/types/src/shapes/Surface.d.ts +54 -0
  71. package/dist/types/src/shapes/Surface.d.ts.map +1 -0
  72. package/dist/types/src/shapes/Switch.d.ts +54 -0
  73. package/dist/types/src/shapes/Switch.d.ts.map +1 -0
  74. package/dist/types/src/shapes/Table.d.ts +54 -0
  75. package/dist/types/src/shapes/Table.d.ts.map +1 -0
  76. package/dist/types/src/shapes/Template.d.ts +56 -0
  77. package/dist/types/src/shapes/Template.d.ts.map +1 -0
  78. package/dist/types/src/shapes/Text.d.ts +54 -0
  79. package/dist/types/src/shapes/Text.d.ts.map +1 -0
  80. package/dist/types/src/shapes/TextToImage.d.ts +54 -0
  81. package/dist/types/src/shapes/TextToImage.d.ts.map +1 -0
  82. package/dist/types/src/shapes/Thread.d.ts +58 -0
  83. package/dist/types/src/shapes/Thread.d.ts.map +1 -0
  84. package/dist/types/src/shapes/Trigger.d.ts +64 -0
  85. package/dist/types/src/shapes/Trigger.d.ts.map +1 -0
  86. package/dist/types/src/shapes/common/Box.d.ts +25 -0
  87. package/dist/types/src/shapes/common/Box.d.ts.map +1 -0
  88. package/dist/types/src/shapes/common/FunctionBody.d.ts +15 -0
  89. package/dist/types/src/shapes/common/FunctionBody.d.ts.map +1 -0
  90. package/dist/types/src/shapes/common/TypeSelect.d.ts +4 -0
  91. package/dist/types/src/shapes/common/TypeSelect.d.ts.map +1 -0
  92. package/dist/types/src/shapes/common/index.d.ts +4 -0
  93. package/dist/types/src/shapes/common/index.d.ts.map +1 -0
  94. package/dist/types/src/shapes/defs.d.ts +39 -0
  95. package/dist/types/src/shapes/defs.d.ts.map +1 -0
  96. package/dist/types/src/shapes/index.d.ts +27 -0
  97. package/dist/types/src/shapes/index.d.ts.map +1 -0
  98. package/dist/types/src/testing/circuits.d.ts +193 -0
  99. package/dist/types/src/testing/circuits.d.ts.map +1 -0
  100. package/dist/types/src/testing/index.d.ts +2 -0
  101. package/dist/types/src/testing/index.d.ts.map +1 -0
  102. package/dist/types/tsconfig.tsbuildinfo +1 -0
  103. package/package.json +85 -0
  104. package/src/README.md +47 -0
  105. package/src/compute-layout.ts +37 -0
  106. package/src/compute.stories.tsx +362 -0
  107. package/src/graph/controller.ts +405 -0
  108. package/src/graph/index.ts +6 -0
  109. package/src/graph/node-defs.ts +82 -0
  110. package/src/hooks/compute-context.ts +19 -0
  111. package/src/hooks/index.ts +7 -0
  112. package/src/hooks/useComputeNodeState.ts +83 -0
  113. package/src/hooks/useGraphMonitor.ts +133 -0
  114. package/src/index.ts +9 -0
  115. package/src/json.test.ts +35 -0
  116. package/src/registry.ts +100 -0
  117. package/src/schema.test.ts +62 -0
  118. package/src/shapes/Append.tsx +43 -0
  119. package/src/shapes/Array.tsx +61 -0
  120. package/src/shapes/Audio.tsx +55 -0
  121. package/src/shapes/Beacon.tsx +56 -0
  122. package/src/shapes/Boolean.tsx +215 -0
  123. package/src/shapes/Chat.tsx +77 -0
  124. package/src/shapes/Constant.tsx +125 -0
  125. package/src/shapes/Database.tsx +39 -0
  126. package/src/shapes/Function.tsx +40 -0
  127. package/src/shapes/Gpt.tsx +91 -0
  128. package/src/shapes/GptRealtime.tsx +168 -0
  129. package/src/shapes/Json.tsx +103 -0
  130. package/src/shapes/Logic.tsx +82 -0
  131. package/src/shapes/Queue.tsx +78 -0
  132. package/src/shapes/RNG.tsx +84 -0
  133. package/src/shapes/Scope.tsx +54 -0
  134. package/src/shapes/Surface.tsx +57 -0
  135. package/src/shapes/Switch.tsx +53 -0
  136. package/src/shapes/Table.tsx +45 -0
  137. package/src/shapes/Template.tsx +98 -0
  138. package/src/shapes/Text.tsx +56 -0
  139. package/src/shapes/TextToImage.tsx +39 -0
  140. package/src/shapes/Thread.tsx +87 -0
  141. package/src/shapes/Trigger.tsx +152 -0
  142. package/src/shapes/common/Box.tsx +74 -0
  143. package/src/shapes/common/FunctionBody.tsx +122 -0
  144. package/src/shapes/common/TypeSelect.tsx +27 -0
  145. package/src/shapes/common/index.ts +7 -0
  146. package/src/shapes/defs.ts +50 -0
  147. package/src/shapes/index.ts +31 -0
  148. package/src/testing/circuits.ts +320 -0
  149. package/src/testing/index.ts +5 -0
@@ -0,0 +1,168 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React, { useState } from 'react';
6
+
7
+ import { S } from '@dxos/echo-schema';
8
+ import { Icon } from '@dxos/react-ui';
9
+ import { type ShapeComponentProps, type ShapeDef } from '@dxos/react-ui-canvas-editor';
10
+
11
+ import { createFunctionAnchors } from './common';
12
+ import { ComputeShape, createShape, type CreateShapeProps } from './defs';
13
+
14
+ export const GptRealtimeShape = S.extend(
15
+ ComputeShape,
16
+ S.Struct({
17
+ type: S.Literal('gpt-realtime'),
18
+ }),
19
+ );
20
+
21
+ export type GptRealtimeShape = S.Schema.Type<typeof GptRealtimeShape>;
22
+
23
+ export type CreateGptRealtimeProps = CreateShapeProps<GptRealtimeShape>;
24
+
25
+ export const createGptRealtime = (props: CreateGptRealtimeProps) =>
26
+ createShape<GptRealtimeShape>({ type: 'gpt-realtime', size: { width: 256, height: 256 }, ...props });
27
+
28
+ export const GptRealtimeComponent = ({ shape }: ShapeComponentProps<GptRealtimeShape>) => {
29
+ const [isLive, setIsLive] = useState(false);
30
+ const [isReady, setIsReady] = useState(false);
31
+
32
+ const start = async () => {
33
+ setIsLive(true);
34
+
35
+ try {
36
+ // Create WebRTC connection
37
+ const peerConnection = new RTCPeerConnection();
38
+
39
+ // Handle incoming audio
40
+ peerConnection.ontrack = (event) => {
41
+ const audioElement = document.createElement('audio');
42
+ audioElement.srcObject = event.streams[0];
43
+ audioElement.autoplay = true;
44
+ audioElement.controls = false;
45
+ audioElement.style.display = 'none';
46
+ document.body.appendChild(audioElement);
47
+ setIsReady(true);
48
+ };
49
+
50
+ // Get microphone stream
51
+ const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
52
+
53
+ // Add microphone track to connection
54
+ stream.getTracks().forEach((track) => peerConnection.addTransceiver(track, { direction: 'sendrecv' }));
55
+
56
+ // Create offer
57
+ const offer = await peerConnection.createOffer();
58
+ await peerConnection.setLocalDescription(offer);
59
+
60
+ // Send offer to backend and get answer
61
+ const response = await fetch(`${AI_SERVICE_URL}/rtc-connect`, {
62
+ method: 'POST',
63
+ body: offer.sdp,
64
+ headers: {
65
+ 'Content-Type': 'application/sdp',
66
+ },
67
+ });
68
+
69
+ const answer = await response.text();
70
+
71
+ // Set remote description with answer
72
+ await peerConnection.setRemoteDescription({
73
+ sdp: answer,
74
+ type: 'answer',
75
+ });
76
+
77
+ const dataChannel = peerConnection.createDataChannel('response');
78
+
79
+ const configureData = () => {
80
+ console.log('Configuring data channel');
81
+ const event = {
82
+ type: 'session.update',
83
+ session: {
84
+ modalities: ['text', 'audio'],
85
+ // Provide the tools. Note they match the keys in the `fns` object above
86
+ tools: [],
87
+ },
88
+ };
89
+ dataChannel.send(JSON.stringify(event));
90
+ };
91
+
92
+ dataChannel.addEventListener('open', (ev) => {
93
+ console.log('Opening data channel', ev);
94
+ configureData();
95
+ });
96
+
97
+ // {
98
+ // "type": "response.function_call_arguments.done",
99
+ // "event_id": "event_Ad2gt864G595umbCs2aF9",
100
+ // "response_id": "resp_Ad2griUWUjsyeLyAVtTtt",
101
+ // "item_id": "item_Ad2gsxA84w9GgEvFwW1Ex",
102
+ // "output_index": 1,
103
+ // "call_id": "call_PG12S5ER7l7HrvZz",
104
+ // "name": "get_weather",
105
+ // "arguments": "{\"location\":\"Portland, Oregon\"}"
106
+ // }
107
+
108
+ dataChannel.addEventListener('message', async (ev) => {
109
+ const msg = JSON.parse(ev.data);
110
+ // console.log('realtime gpt event', msg);
111
+ // Handle function calls
112
+ if (msg.type === 'response.function_call_arguments.done') {
113
+ // const fn = fns[msg.name];
114
+ // if (fn !== undefined) {
115
+ // console.log(`Calling local function ${msg.name} with ${msg.arguments}`);
116
+ // const args = JSON.parse(msg.arguments);
117
+ // const result = await fn(args);
118
+ // console.log('result', result);
119
+ // // Let OpenAI know that the function has been called and share it's output
120
+ // const event = {
121
+ // type: 'conversation.item.create',
122
+ // item: {
123
+ // type: 'function_call_output',
124
+ // call_id: msg.call_id, // call_id from the function_call message
125
+ // output: JSON.stringify(result), // result of the function
126
+ // },
127
+ // };
128
+ // dataChannel.send(JSON.stringify(event));
129
+ // }
130
+ }
131
+ });
132
+ } catch (error) {
133
+ console.error('Error in realtime session:', error);
134
+ throw error;
135
+ }
136
+ };
137
+
138
+ return (
139
+ <div className='flex w-full justify-center items-center'>
140
+ <Icon
141
+ icon={isReady ? 'ph--waveform--regular' : isLive ? 'ph--pulse--regular' : 'ph--play--regular'}
142
+ size={16}
143
+ classNames={!isLive && 'cursor-pointer'}
144
+ onClick={start}
145
+ />
146
+ </div>
147
+ );
148
+ };
149
+
150
+ export const gptRealtimeShape: ShapeDef<GptRealtimeShape> = {
151
+ type: 'gpt-realtime',
152
+ name: 'GPT Realtime',
153
+ icon: 'ph--pulse--regular',
154
+ component: GptRealtimeComponent,
155
+ createShape: createGptRealtime,
156
+ // TODO(dmaretskyi): Can we fetch the schema dynamically?
157
+ getAnchors: (shape) =>
158
+ createFunctionAnchors(
159
+ shape,
160
+ S.Struct({
161
+ audio: S.Any,
162
+ }),
163
+ S.Struct({}),
164
+ ),
165
+ resizable: true,
166
+ };
167
+
168
+ const AI_SERVICE_URL = 'http://localhost:8788';
@@ -0,0 +1,103 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React from 'react';
6
+
7
+ import { DEFAULT_INPUT, DefaultOutput, JsonTransformInput } from '@dxos/conductor';
8
+ import { S } from '@dxos/echo-schema';
9
+ import { type ShapeComponentProps, type ShapeDef } from '@dxos/react-ui-canvas-editor';
10
+ import { createAnchorMap } from '@dxos/react-ui-canvas-editor';
11
+ import { JsonFilter } from '@dxos/react-ui-syntax-highlighter';
12
+
13
+ import { createFunctionAnchors, getHeight, Box } from './common';
14
+ import { ComputeShape, createAnchorId, createShape, type CreateShapeProps } from './defs';
15
+ import { useComputeNodeState } from '../hooks';
16
+
17
+ //
18
+ // Data
19
+ //
20
+
21
+ export const JsonShape = S.extend(
22
+ ComputeShape,
23
+ S.Struct({
24
+ type: S.Literal('json'),
25
+ }),
26
+ );
27
+
28
+ export type JsonShape = S.Schema.Type<typeof JsonShape>;
29
+
30
+ export const JsonTransformShape = S.extend(
31
+ ComputeShape,
32
+ S.Struct({
33
+ type: S.Literal('json-transform'),
34
+ }),
35
+ );
36
+
37
+ export type JsonTransformShape = S.Schema.Type<typeof JsonTransformShape>;
38
+
39
+ //
40
+ // Component
41
+ //
42
+
43
+ export type JsonComponentProps = ShapeComponentProps<JsonShape>;
44
+
45
+ export const JsonComponent = ({ shape, ...props }: JsonComponentProps) => {
46
+ const { runtime } = useComputeNodeState(shape);
47
+ const input = runtime.inputs[DEFAULT_INPUT];
48
+ const value = input?.type === 'executed' ? input.value : undefined;
49
+
50
+ return (
51
+ <Box shape={shape}>
52
+ <JsonFilter data={value} classNames='text-xs' />
53
+ </Box>
54
+ );
55
+ };
56
+
57
+ export type JsonTransformComponentProps = ShapeComponentProps<JsonTransformShape>;
58
+
59
+ export const JsonTransformComponent = ({ shape, ...props }: JsonTransformComponentProps) => {
60
+ return <Box shape={shape} />;
61
+ };
62
+
63
+ //
64
+ // Defs
65
+ //
66
+
67
+ export type CreateJsonProps = CreateShapeProps<JsonShape>;
68
+
69
+ export const createJson = (props: CreateJsonProps) =>
70
+ createShape<JsonShape>({ type: 'json', size: { width: 256, height: 256 }, ...props });
71
+
72
+ export const jsonShape: ShapeDef<JsonShape> = {
73
+ type: 'json',
74
+ name: 'JSON',
75
+ icon: 'ph--code--regular',
76
+ component: (props) => <JsonComponent {...props} />,
77
+ createShape: createJson,
78
+ getAnchors: (shape) =>
79
+ createAnchorMap(shape, {
80
+ [createAnchorId('input')]: { x: -1, y: 0 },
81
+ [createAnchorId('output')]: { x: 1, y: 0 },
82
+ }),
83
+ resizable: true,
84
+ };
85
+
86
+ export type CreateJsonTransformProps = CreateShapeProps<JsonTransformShape> & { expression?: string };
87
+
88
+ export const createJsonTransform = (props: CreateJsonTransformProps) =>
89
+ createShape<JsonTransformShape>({
90
+ type: 'json-transform',
91
+ size: { width: 128, height: getHeight(JsonTransformInput) },
92
+ ...props,
93
+ });
94
+
95
+ export const jsonTransformShape: ShapeDef<JsonTransformShape> = {
96
+ type: 'json-transform',
97
+ name: 'Transform',
98
+ icon: 'ph--shuffle-simple--regular',
99
+ component: (props) => <JsonTransformComponent {...props} />,
100
+ createShape: createJsonTransform,
101
+ getAnchors: (shape) => createFunctionAnchors(shape, JsonTransformInput, DefaultOutput),
102
+ resizable: true,
103
+ };
@@ -0,0 +1,82 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React from 'react';
6
+
7
+ import { IfElseInput, IfElseOutput, IfInput, IfOutput } 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 IfShape = S.extend(
19
+ ComputeShape,
20
+ S.Struct({
21
+ type: S.Literal('if'),
22
+ }),
23
+ );
24
+
25
+ export type IfShape = S.Schema.Type<typeof IfShape>;
26
+
27
+ export const IfElseShape = S.extend(
28
+ ComputeShape,
29
+ S.Struct({
30
+ type: S.Literal('if-else'),
31
+ }),
32
+ );
33
+
34
+ export type IfElseShape = S.Schema.Type<typeof IfElseShape>;
35
+
36
+ //
37
+ // Components
38
+ //
39
+
40
+ export type IfComponentProps = ShapeComponentProps<IfShape>;
41
+
42
+ export const IfComponent = ({ shape, ...props }: IfComponentProps) => {
43
+ return <FunctionBody shape={shape} inputSchema={IfInput} outputSchema={IfOutput} />;
44
+ };
45
+
46
+ export type IfElseComponentProps = ShapeComponentProps<IfElseShape>;
47
+
48
+ export const IfElseComponent = ({ shape, ...props }: IfElseComponentProps) => {
49
+ return <FunctionBody shape={shape} inputSchema={IfElseInput} outputSchema={IfElseOutput} />;
50
+ };
51
+
52
+ //
53
+ // Defs
54
+ //
55
+
56
+ export type CreateIfProps = CreateShapeProps<IfShape> & { if?: string };
57
+
58
+ export const createIf = (props: CreateIfProps) =>
59
+ createShape<IfShape>({ type: 'if', size: { width: 192, height: getHeight(IfInput) }, ...props });
60
+
61
+ export const ifShape: ShapeDef<IfShape> = {
62
+ type: 'if',
63
+ name: 'IF',
64
+ icon: 'ph--arrows-split--regular',
65
+ component: (props) => <IfComponent {...props} />,
66
+ createShape: createIf,
67
+ getAnchors: (shape) => createFunctionAnchors(shape, IfInput, IfOutput),
68
+ };
69
+
70
+ export type CreateIfElseProps = CreateShapeProps<IfShape> & { if?: string };
71
+
72
+ export const createIfElse = (props: CreateIfElseProps) =>
73
+ createShape<IfElseShape>({ type: 'if-else', size: { width: 192, height: getHeight(IfElseInput) }, ...props });
74
+
75
+ export const ifElseShape: ShapeDef<IfElseShape> = {
76
+ type: 'if-else',
77
+ name: 'IF/ELSE',
78
+ icon: 'ph--arrows-merge--regular',
79
+ component: (props) => <IfElseComponent {...props} />,
80
+ createShape: createIfElse,
81
+ getAnchors: (shape) => createFunctionAnchors(shape, IfElseInput, IfElseOutput),
82
+ };
@@ -0,0 +1,78 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React, { Fragment } from 'react';
6
+
7
+ import { DEFAULT_OUTPUT, QueueInput, QueueOutput } from '@dxos/conductor';
8
+ import { S } from '@dxos/echo-schema';
9
+ import { type ThemedClassName } from '@dxos/react-ui';
10
+ import { type ShapeComponentProps, type ShapeDef } from '@dxos/react-ui-canvas-editor';
11
+ import { mx } from '@dxos/react-ui-theme';
12
+
13
+ import { createFunctionAnchors } from './common';
14
+ import { Box, type BoxActionHandler } from './common';
15
+ import { ComputeShape, createShape, type CreateShapeProps } from './defs';
16
+ import { useComputeNodeState } from '../hooks';
17
+
18
+ export const QueueShape = S.extend(
19
+ ComputeShape,
20
+ S.Struct({
21
+ type: S.Literal('queue'),
22
+ }),
23
+ );
24
+
25
+ export type QueueShape = S.Schema.Type<typeof QueueShape>;
26
+
27
+ export type CreateQueueProps = CreateShapeProps<QueueShape>;
28
+
29
+ export const createQueue = (props: CreateQueueProps) =>
30
+ createShape<QueueShape>({ type: 'queue', size: { width: 256, height: 512 }, ...props });
31
+
32
+ export const QueueComponent = ({ shape }: ShapeComponentProps<QueueShape>) => {
33
+ const { runtime } = useComputeNodeState(shape);
34
+ const items = runtime.outputs[DEFAULT_OUTPUT]?.type === 'executed' ? runtime.outputs[DEFAULT_OUTPUT].value : [];
35
+
36
+ const handleAction: BoxActionHandler = (action) => {
37
+ if (action === 'run') {
38
+ runtime.evalNode();
39
+ }
40
+ };
41
+
42
+ return (
43
+ <Box shape={shape} status={`${items.length} items`} onAction={handleAction}>
44
+ <div className='flex flex-col w-full overflow-y-scroll divide-y divide-separator'>
45
+ {[...items].map((item, i) => (
46
+ <QueueItem key={i} classNames='p-1 px-2' item={item} />
47
+ ))}
48
+ </div>
49
+ </Box>
50
+ );
51
+ };
52
+
53
+ export const QueueItem = ({ classNames, item }: ThemedClassName<{ item: any }>) => {
54
+ if (typeof item !== 'object') {
55
+ return <div className={mx(classNames, 'whitespace-pre-wrap')}>{item}</div>;
56
+ }
57
+
58
+ return (
59
+ <div className={mx('grid grid-cols-[80px,1fr]', classNames)}>
60
+ {Object.entries(item).map(([key, value]) => (
61
+ <Fragment key={key}>
62
+ <div className='p-1 text-xs text-subdued'>{key}</div>
63
+ <div>{typeof value === 'string' ? value : JSON.stringify(value)}</div>
64
+ </Fragment>
65
+ ))}
66
+ </div>
67
+ );
68
+ };
69
+
70
+ export const queueShape: ShapeDef<QueueShape> = {
71
+ type: 'queue',
72
+ name: 'Queue',
73
+ icon: 'ph--queue--regular',
74
+ component: QueueComponent,
75
+ createShape: createQueue,
76
+ getAnchors: (shape) => createFunctionAnchors(shape, QueueInput, QueueOutput),
77
+ resizable: true,
78
+ };
@@ -0,0 +1,84 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React, { useEffect, useState } from 'react';
6
+
7
+ import { DEFAULT_OUTPUT } from '@dxos/conductor';
8
+ import { S } from '@dxos/echo-schema';
9
+ import { Icon, type IconProps } 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 RandomShape = S.extend(
17
+ ComputeShape,
18
+ S.Struct({
19
+ type: S.Literal('rng'),
20
+ min: S.optional(S.Number),
21
+ max: S.optional(S.Number),
22
+ }),
23
+ );
24
+
25
+ export type RandomShape = S.Schema.Type<typeof RandomShape>;
26
+
27
+ export type CreateRandomProps = CreateShapeProps<RandomShape>;
28
+
29
+ export const createRandom = (props: CreateRandomProps) =>
30
+ createShape<RandomShape>({ type: 'rng', size: { width: 64, height: 64 }, ...props });
31
+
32
+ const icons = [
33
+ 'ph--dice-one--regular',
34
+ 'ph--dice-two--regular',
35
+ 'ph--dice-three--regular',
36
+ 'ph--dice-four--regular',
37
+ 'ph--dice-five--regular',
38
+ 'ph--dice-six--regular',
39
+ ];
40
+
41
+ const pickIcon = () => icons[Math.floor(Math.random() * icons.length)];
42
+
43
+ // TODO(burdon): Optional range.
44
+ export const RandomComponent = ({ shape }: ShapeComponentProps<RandomShape>) => {
45
+ const { runtime } = useComputeNodeState(shape);
46
+
47
+ const [spin, setSpin] = useState(false);
48
+ const [icon, setIcon] = useState(pickIcon());
49
+ useEffect(() => {
50
+ if (!spin) {
51
+ return;
52
+ }
53
+
54
+ const i = setInterval(() => setIcon(pickIcon()), 250);
55
+ const t1 = setTimeout(() => clearInterval(i), 900);
56
+ const t2 = setTimeout(() => setSpin(false), 1_100);
57
+ return () => {
58
+ clearInterval(i);
59
+ clearTimeout(t1);
60
+ clearTimeout(t2);
61
+ };
62
+ }, [spin]);
63
+
64
+ const handleClick: IconProps['onClick'] = (ev) => {
65
+ ev.stopPropagation();
66
+ runtime.setOutput(DEFAULT_OUTPUT, Math.random());
67
+ setSpin(true);
68
+ };
69
+
70
+ return (
71
+ <div className='flex grow items-center justify-center'>
72
+ <Icon icon={icon} classNames={mx(spin && 'animate-[spin_1s]')} size={10} onClick={handleClick} />
73
+ </div>
74
+ );
75
+ };
76
+
77
+ export const randomShape: ShapeDef<RandomShape> = {
78
+ type: 'rng',
79
+ name: 'Random',
80
+ icon: 'ph--dice-six--regular',
81
+ component: RandomComponent,
82
+ createShape: createRandom,
83
+ getAnchors: (shape) => createAnchorMap(shape, { [createAnchorId('output')]: { x: 1, y: 0 } }),
84
+ };
@@ -0,0 +1,54 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React from 'react';
6
+
7
+ import { DEFAULT_INPUT } from '@dxos/conductor';
8
+ import { S } from '@dxos/echo-schema';
9
+ import { createAnchorMap, type ShapeComponentProps, type ShapeDef } from '@dxos/react-ui-canvas-editor';
10
+ import { useAudioStream, Chaos, shaderPresets } from '@dxos/react-ui-sfx';
11
+
12
+ import { ComputeShape, createAnchorId, createShape, type CreateShapeProps } from './defs';
13
+ import { useComputeNodeState } from '../hooks';
14
+
15
+ export const ScopeShape = S.extend(
16
+ ComputeShape,
17
+ S.Struct({
18
+ type: S.Literal('scope'),
19
+ }),
20
+ );
21
+
22
+ export type ScopeShape = S.Schema.Type<typeof ScopeShape>;
23
+
24
+ export type CreateScopeProps = CreateShapeProps<ScopeShape>;
25
+
26
+ export const createScope = (props: CreateScopeProps) =>
27
+ createShape<ScopeShape>({
28
+ type: 'scope',
29
+ size: { width: 128, height: 128 },
30
+ classNames: 'rounded-full border-primary-800',
31
+ ...props,
32
+ });
33
+
34
+ export const ScopeComponent = ({ shape }: ShapeComponentProps<ScopeShape>) => {
35
+ const { runtime } = useComputeNodeState(shape);
36
+ const input = runtime.inputs[DEFAULT_INPUT];
37
+ const active = input?.type === 'executed' ? input.value : false;
38
+ const { getAverage } = useAudioStream(active);
39
+
40
+ return (
41
+ <div className='flex w-full justify-center items-center bg-black'>
42
+ <Chaos active={active} getValue={getAverage} options={{ ...shaderPresets.heptapod, zoom: 1.2 }} />
43
+ </div>
44
+ );
45
+ };
46
+
47
+ export const scopeShape: ShapeDef<ScopeShape> = {
48
+ type: 'scope',
49
+ name: 'Scope',
50
+ icon: 'ph--waveform--regular',
51
+ component: ScopeComponent,
52
+ createShape: createScope,
53
+ getAnchors: (shape) => createAnchorMap(shape, { [createAnchorId('input')]: { x: -1, y: 0 } }),
54
+ };
@@ -0,0 +1,57 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React from 'react';
6
+
7
+ import { Surface } from '@dxos/app-framework';
8
+ import { DEFAULT_INPUT } from '@dxos/conductor';
9
+ import { S } from '@dxos/echo-schema';
10
+ import { type ShapeComponentProps, type ShapeDef } from '@dxos/react-ui-canvas-editor';
11
+ import { createAnchorMap } from '@dxos/react-ui-canvas-editor';
12
+
13
+ import { Box, type BoxActionHandler } from './common';
14
+ import { ComputeShape, createAnchorId, createShape, type CreateShapeProps } from './defs';
15
+ import { useComputeNodeState } from '../hooks';
16
+
17
+ export const SurfaceShape = S.extend(
18
+ ComputeShape,
19
+ S.Struct({
20
+ type: S.Literal('surface'),
21
+ }),
22
+ );
23
+
24
+ export type SurfaceShape = S.Schema.Type<typeof SurfaceShape>;
25
+
26
+ export type CreateSurfaceProps = CreateShapeProps<SurfaceShape>;
27
+
28
+ export const createSurface = (props: CreateSurfaceProps) =>
29
+ createShape<SurfaceShape>({ type: 'surface', size: { width: 384, height: 384 }, ...props });
30
+
31
+ export const SurfaceComponent = ({ shape }: ShapeComponentProps<SurfaceShape>) => {
32
+ const { runtime } = useComputeNodeState(shape);
33
+ const input = runtime.inputs[DEFAULT_INPUT];
34
+ const value = input?.type === 'executed' ? input.value : null;
35
+
36
+ const handleAction: BoxActionHandler = (action) => {
37
+ if (action === 'run') {
38
+ runtime.evalNode();
39
+ }
40
+ };
41
+
42
+ return (
43
+ <Box shape={shape} onAction={handleAction}>
44
+ {value !== null && <Surface role='canvas-node' data={{ value }} limit={1} />}
45
+ </Box>
46
+ );
47
+ };
48
+
49
+ export const surfaceShape: ShapeDef<SurfaceShape> = {
50
+ type: 'surface',
51
+ name: 'Surface',
52
+ icon: 'ph--frame-corners--regular',
53
+ component: SurfaceComponent,
54
+ createShape: createSurface,
55
+ getAnchors: (shape) => createAnchorMap(shape, { [createAnchorId('input')]: { x: -1, y: 0 } }),
56
+ resizable: true,
57
+ };
@@ -0,0 +1,53 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React, { useEffect, useState } from 'react';
6
+
7
+ import { DEFAULT_OUTPUT } from '@dxos/conductor';
8
+ import { S } from '@dxos/echo-schema';
9
+ import { Input } from '@dxos/react-ui';
10
+ import { createAnchorMap, type ShapeComponentProps, type ShapeDef } from '@dxos/react-ui-canvas-editor';
11
+
12
+ import { ComputeShape, createAnchorId, createShape, type CreateShapeProps } from './defs';
13
+ import { useComputeNodeState } from '../hooks';
14
+
15
+ export const SwitchShape = S.extend(
16
+ ComputeShape,
17
+ S.Struct({
18
+ type: S.Literal('switch'),
19
+ }),
20
+ );
21
+
22
+ export type SwitchShape = S.Schema.Type<typeof SwitchShape>;
23
+
24
+ export type CreateSwitchProps = CreateShapeProps<SwitchShape>;
25
+
26
+ export const createSwitch = (props: CreateSwitchProps) =>
27
+ createShape<SwitchShape>({ type: 'switch', size: { width: 64, height: 64 }, ...props });
28
+
29
+ // TODO(burdon): Should model as a constant.
30
+ export const SwitchComponent = ({ shape }: ShapeComponentProps<SwitchShape>) => {
31
+ const { runtime } = useComputeNodeState(shape);
32
+ const [value, setValue] = useState(false);
33
+ useEffect(() => {
34
+ runtime.setOutput(DEFAULT_OUTPUT, value);
35
+ }, [value]);
36
+
37
+ return (
38
+ <div className='flex w-full justify-center items-center' onClick={(ev) => ev.stopPropagation()}>
39
+ <Input.Root>
40
+ <Input.Switch checked={value} onCheckedChange={(value) => setValue(value)} />
41
+ </Input.Root>
42
+ </div>
43
+ );
44
+ };
45
+
46
+ export const switchShape: ShapeDef<SwitchShape> = {
47
+ type: 'switch',
48
+ name: 'Switch',
49
+ icon: 'ph--toggle-left--regular',
50
+ component: SwitchComponent,
51
+ createShape: createSwitch,
52
+ getAnchors: (shape) => createAnchorMap(shape, { [createAnchorId('output')]: { x: 1, y: 0 } }),
53
+ };