@dxos/react-ui-canvas-compute 0.13.0 → 0.14.0

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 (244) hide show
  1. package/dist/lib/chunk-types.mjs +142 -0
  2. package/dist/lib/chunk-types.mjs.map +1 -0
  3. package/dist/lib/index.mjs +526 -430
  4. package/dist/lib/index.mjs.map +1 -1
  5. package/dist/lib/types.mjs +2 -0
  6. package/dist/types/src/graph/controller.d.ts +1 -1
  7. package/dist/types/src/graph/controller.d.ts.map +1 -1
  8. package/dist/types/src/hooks/compute-context.d.ts +5 -4
  9. package/dist/types/src/hooks/compute-context.d.ts.map +1 -1
  10. package/dist/types/src/hooks/index.d.ts +0 -1
  11. package/dist/types/src/hooks/index.d.ts.map +1 -1
  12. package/dist/types/src/hooks/useGraphMonitor.d.ts +18 -1
  13. package/dist/types/src/hooks/useGraphMonitor.d.ts.map +1 -1
  14. package/dist/types/src/index.d.ts +1 -1
  15. package/dist/types/src/index.d.ts.map +1 -1
  16. package/dist/types/src/registry.d.ts +5 -8
  17. package/dist/types/src/registry.d.ts.map +1 -1
  18. package/dist/types/src/scene/compute.stories.d.ts.map +1 -1
  19. package/dist/types/src/scene/echo-store.d.ts +1 -1
  20. package/dist/types/src/scene/echo-store.d.ts.map +1 -1
  21. package/dist/types/src/scene/index.d.ts +0 -3
  22. package/dist/types/src/scene/index.d.ts.map +1 -1
  23. package/dist/types/src/scene/projection.d.ts.map +1 -1
  24. package/dist/types/src/scene/scene.d.ts +2 -2
  25. package/dist/types/src/scene/scene.d.ts.map +1 -1
  26. package/dist/types/src/shapes/Append.d.ts +2 -2
  27. package/dist/types/src/shapes/Append.d.ts.map +1 -1
  28. package/dist/types/src/shapes/Array.d.ts +3 -3
  29. package/dist/types/src/shapes/Array.d.ts.map +1 -1
  30. package/dist/types/src/shapes/Audio.d.ts +2 -2
  31. package/dist/types/src/shapes/Audio.d.ts.map +1 -1
  32. package/dist/types/src/shapes/Beacon.d.ts +2 -2
  33. package/dist/types/src/shapes/Beacon.d.ts.map +1 -1
  34. package/dist/types/src/shapes/Boolean.d.ts +4 -52
  35. package/dist/types/src/shapes/Boolean.d.ts.map +1 -1
  36. package/dist/types/src/shapes/Chat.d.ts +3 -3
  37. package/dist/types/src/shapes/Chat.d.ts.map +1 -1
  38. package/dist/types/src/shapes/Constant.d.ts +3 -4
  39. package/dist/types/src/shapes/Constant.d.ts.map +1 -1
  40. package/dist/types/src/shapes/Database.d.ts +2 -2
  41. package/dist/types/src/shapes/Database.d.ts.map +1 -1
  42. package/dist/types/src/shapes/Feed.d.ts +2 -2
  43. package/dist/types/src/shapes/Feed.d.ts.map +1 -1
  44. package/dist/types/src/shapes/Function.d.ts +3 -5
  45. package/dist/types/src/shapes/Function.d.ts.map +1 -1
  46. package/dist/types/src/shapes/Gpt.d.ts +2 -2
  47. package/dist/types/src/shapes/Gpt.d.ts.map +1 -1
  48. package/dist/types/src/shapes/GptRealtime.d.ts +2 -2
  49. package/dist/types/src/shapes/GptRealtime.d.ts.map +1 -1
  50. package/dist/types/src/shapes/Json.d.ts +5 -5
  51. package/dist/types/src/shapes/Json.d.ts.map +1 -1
  52. package/dist/types/src/shapes/Logic.d.ts +5 -5
  53. package/dist/types/src/shapes/Logic.d.ts.map +1 -1
  54. package/dist/types/src/shapes/RNG.d.ts +2 -2
  55. package/dist/types/src/shapes/RNG.d.ts.map +1 -1
  56. package/dist/types/src/shapes/Scope.d.ts +2 -2
  57. package/dist/types/src/shapes/Scope.d.ts.map +1 -1
  58. package/dist/types/src/shapes/Surface.d.ts +2 -2
  59. package/dist/types/src/shapes/Surface.d.ts.map +1 -1
  60. package/dist/types/src/shapes/Switch.d.ts +2 -2
  61. package/dist/types/src/shapes/Switch.d.ts.map +1 -1
  62. package/dist/types/src/shapes/Table.d.ts +2 -2
  63. package/dist/types/src/shapes/Table.d.ts.map +1 -1
  64. package/dist/types/src/shapes/Template.d.ts +2 -2
  65. package/dist/types/src/shapes/Template.d.ts.map +1 -1
  66. package/dist/types/src/shapes/Text.d.ts +2 -2
  67. package/dist/types/src/shapes/Text.d.ts.map +1 -1
  68. package/dist/types/src/shapes/TextToImage.d.ts +2 -2
  69. package/dist/types/src/shapes/TextToImage.d.ts.map +1 -1
  70. package/dist/types/src/shapes/Thread.d.ts +2 -2
  71. package/dist/types/src/shapes/Thread.d.ts.map +1 -1
  72. package/dist/types/src/shapes/Trigger.d.ts +3 -3
  73. package/dist/types/src/shapes/Trigger.d.ts.map +1 -1
  74. package/dist/types/src/shapes/append-def.d.ts +1 -2
  75. package/dist/types/src/shapes/append-def.d.ts.map +1 -1
  76. package/dist/types/src/shapes/array-def.d.ts +2 -3
  77. package/dist/types/src/shapes/array-def.d.ts.map +1 -1
  78. package/dist/types/src/shapes/audio-def.d.ts +1 -2
  79. package/dist/types/src/shapes/audio-def.d.ts.map +1 -1
  80. package/dist/types/src/shapes/beacon-def.d.ts +1 -2
  81. package/dist/types/src/shapes/beacon-def.d.ts.map +1 -1
  82. package/dist/types/src/shapes/chat-def.d.ts +1 -2
  83. package/dist/types/src/shapes/chat-def.d.ts.map +1 -1
  84. package/dist/types/src/shapes/common/Box.d.ts.map +1 -1
  85. package/dist/types/src/shapes/common/FunctionBody.d.ts.map +1 -1
  86. package/dist/types/src/shapes/common/TextBox.d.ts +26 -0
  87. package/dist/types/src/shapes/common/TextBox.d.ts.map +1 -0
  88. package/dist/types/src/shapes/common/index.d.ts +3 -1
  89. package/dist/types/src/shapes/common/index.d.ts.map +1 -1
  90. package/dist/types/src/shapes/common/node-def.d.ts +24 -0
  91. package/dist/types/src/shapes/common/node-def.d.ts.map +1 -0
  92. package/dist/types/src/shapes/common/ports.d.ts +33 -0
  93. package/dist/types/src/shapes/common/ports.d.ts.map +1 -0
  94. package/dist/types/src/shapes/constant-def.d.ts +1 -2
  95. package/dist/types/src/shapes/constant-def.d.ts.map +1 -1
  96. package/dist/types/src/shapes/database-def.d.ts +1 -2
  97. package/dist/types/src/shapes/database-def.d.ts.map +1 -1
  98. package/dist/types/src/shapes/defs.d.ts +7 -2
  99. package/dist/types/src/shapes/defs.d.ts.map +1 -1
  100. package/dist/types/src/shapes/feed-def.d.ts +1 -2
  101. package/dist/types/src/shapes/feed-def.d.ts.map +1 -1
  102. package/dist/types/src/shapes/function-def.d.ts +1 -2
  103. package/dist/types/src/shapes/function-def.d.ts.map +1 -1
  104. package/dist/types/src/shapes/gpt-def.d.ts +1 -2
  105. package/dist/types/src/shapes/gpt-def.d.ts.map +1 -1
  106. package/dist/types/src/shapes/gpt-realtime-def.d.ts +1 -2
  107. package/dist/types/src/shapes/gpt-realtime-def.d.ts.map +1 -1
  108. package/dist/types/src/shapes/json-def.d.ts +2 -3
  109. package/dist/types/src/shapes/json-def.d.ts.map +1 -1
  110. package/dist/types/src/shapes/logic-def.d.ts +2 -3
  111. package/dist/types/src/shapes/logic-def.d.ts.map +1 -1
  112. package/dist/types/src/shapes/ports.test.d.ts +2 -0
  113. package/dist/types/src/shapes/ports.test.d.ts.map +1 -0
  114. package/dist/types/src/shapes/rng-def.d.ts +1 -2
  115. package/dist/types/src/shapes/rng-def.d.ts.map +1 -1
  116. package/dist/types/src/shapes/scope-def.d.ts +1 -2
  117. package/dist/types/src/shapes/scope-def.d.ts.map +1 -1
  118. package/dist/types/src/shapes/surface-def.d.ts +1 -2
  119. package/dist/types/src/shapes/surface-def.d.ts.map +1 -1
  120. package/dist/types/src/shapes/switch-def.d.ts +1 -2
  121. package/dist/types/src/shapes/switch-def.d.ts.map +1 -1
  122. package/dist/types/src/shapes/table-def.d.ts +1 -2
  123. package/dist/types/src/shapes/table-def.d.ts.map +1 -1
  124. package/dist/types/src/shapes/template-def.d.ts +1 -2
  125. package/dist/types/src/shapes/template-def.d.ts.map +1 -1
  126. package/dist/types/src/shapes/text-def.d.ts +1 -2
  127. package/dist/types/src/shapes/text-def.d.ts.map +1 -1
  128. package/dist/types/src/shapes/text-to-image-def.d.ts +1 -2
  129. package/dist/types/src/shapes/text-to-image-def.d.ts.map +1 -1
  130. package/dist/types/src/shapes/thread-def.d.ts +1 -2
  131. package/dist/types/src/shapes/thread-def.d.ts.map +1 -1
  132. package/dist/types/src/shapes/trigger-def.d.ts +1 -2
  133. package/dist/types/src/shapes/trigger-def.d.ts.map +1 -1
  134. package/dist/types/src/testing/circuits.d.ts +1 -1
  135. package/dist/types/src/testing/circuits.d.ts.map +1 -1
  136. package/dist/types/src/types/canvas-board.test.d.ts +2 -0
  137. package/dist/types/src/types/canvas-board.test.d.ts.map +1 -0
  138. package/dist/types/src/types/index.d.ts +4 -0
  139. package/dist/types/src/types/index.d.ts.map +1 -0
  140. package/dist/types/src/types/model.d.ts +10 -0
  141. package/dist/types/src/types/model.d.ts.map +1 -0
  142. package/dist/types/src/types/schema.d.ts +66 -0
  143. package/dist/types/src/types/schema.d.ts.map +1 -0
  144. package/dist/types/src/types/shapes.d.ts +114 -0
  145. package/dist/types/src/types/shapes.d.ts.map +1 -0
  146. package/dist/types/tsconfig.tsbuildinfo +1 -1
  147. package/package.json +43 -35
  148. package/src/graph/controller.ts +1 -1
  149. package/src/hooks/compute-context.ts +7 -4
  150. package/src/hooks/index.ts +0 -1
  151. package/src/hooks/useGraphMonitor.ts +10 -1
  152. package/src/index.ts +1 -1
  153. package/src/playwright/scene.spec.ts +3 -3
  154. package/src/registry.ts +63 -91
  155. package/src/scene/compute.stories.tsx +3 -6
  156. package/src/scene/echo-store.test.ts +18 -7
  157. package/src/scene/echo-store.ts +7 -10
  158. package/src/scene/index.ts +0 -3
  159. package/src/scene/projection.ts +2 -3
  160. package/src/scene/scene.test.ts +4 -4
  161. package/src/scene/scene.ts +6 -4
  162. package/src/schema.test.ts +7 -36
  163. package/src/shapes/Append.tsx +2 -3
  164. package/src/shapes/Array.tsx +3 -4
  165. package/src/shapes/Audio.tsx +2 -2
  166. package/src/shapes/Beacon.tsx +2 -2
  167. package/src/shapes/Boolean.tsx +32 -29
  168. package/src/shapes/Chat.tsx +5 -10
  169. package/src/shapes/Constant.tsx +19 -12
  170. package/src/shapes/Database.tsx +2 -4
  171. package/src/shapes/Feed.tsx +2 -3
  172. package/src/shapes/Function.tsx +4 -10
  173. package/src/shapes/Gpt.tsx +2 -3
  174. package/src/shapes/GptRealtime.tsx +2 -2
  175. package/src/shapes/Json.tsx +5 -6
  176. package/src/shapes/Logic.tsx +5 -6
  177. package/src/shapes/RNG.tsx +2 -2
  178. package/src/shapes/Scope.tsx +2 -2
  179. package/src/shapes/Surface.tsx +9 -6
  180. package/src/shapes/Switch.tsx +10 -12
  181. package/src/shapes/Table.tsx +2 -4
  182. package/src/shapes/Template.tsx +10 -9
  183. package/src/shapes/Text.tsx +2 -3
  184. package/src/shapes/TextToImage.tsx +2 -4
  185. package/src/shapes/Thread.tsx +2 -3
  186. package/src/shapes/Trigger.tsx +3 -4
  187. package/src/shapes/append-def.ts +8 -7
  188. package/src/shapes/array-def.ts +8 -8
  189. package/src/shapes/audio-def.ts +8 -7
  190. package/src/shapes/beacon-def.ts +9 -8
  191. package/src/shapes/chat-def.tsx +8 -8
  192. package/src/shapes/common/Box.tsx +7 -4
  193. package/src/shapes/common/FunctionBody.tsx +13 -26
  194. package/src/shapes/common/TextBox.tsx +137 -0
  195. package/src/shapes/common/index.ts +3 -1
  196. package/src/shapes/common/node-def.tsx +117 -0
  197. package/src/shapes/common/ports.ts +107 -0
  198. package/src/shapes/constant-def.tsx +8 -8
  199. package/src/shapes/database-def.ts +8 -8
  200. package/src/shapes/defs.ts +21 -6
  201. package/src/shapes/feed-def.ts +8 -7
  202. package/src/shapes/function-def.ts +8 -7
  203. package/src/shapes/gpt-def.ts +8 -7
  204. package/src/shapes/gpt-realtime-def.ts +10 -10
  205. package/src/shapes/json-def.ts +15 -13
  206. package/src/shapes/logic-def.ts +14 -11
  207. package/src/shapes/ports.test.ts +23 -0
  208. package/src/shapes/rng-def.ts +8 -7
  209. package/src/shapes/scope-def.ts +8 -7
  210. package/src/shapes/surface-def.ts +8 -8
  211. package/src/shapes/switch-def.ts +8 -7
  212. package/src/shapes/table-def.ts +7 -7
  213. package/src/shapes/template-def.ts +8 -7
  214. package/src/shapes/text-def.ts +8 -8
  215. package/src/shapes/text-to-image-def.ts +8 -8
  216. package/src/shapes/thread-def.ts +8 -7
  217. package/src/shapes/trigger-def.ts +11 -8
  218. package/src/testing/circuits.ts +21 -7
  219. package/src/types/canvas-board.test.ts +84 -0
  220. package/src/types/index.ts +7 -0
  221. package/src/types/model.ts +63 -0
  222. package/src/types/schema.ts +73 -0
  223. package/src/types/shapes.ts +73 -0
  224. package/dist/types/src/compute-layout.d.ts +0 -9
  225. package/dist/types/src/compute-layout.d.ts.map +0 -1
  226. package/dist/types/src/compute.stories.d.ts +0 -58
  227. package/dist/types/src/compute.stories.d.ts.map +0 -1
  228. package/dist/types/src/hooks/useComputeGraphController.d.ts +0 -10
  229. package/dist/types/src/hooks/useComputeGraphController.d.ts.map +0 -1
  230. package/dist/types/src/scene/NodeView.d.ts +0 -11
  231. package/dist/types/src/scene/NodeView.d.ts.map +0 -1
  232. package/dist/types/src/scene/defs.d.ts +0 -5
  233. package/dist/types/src/scene/defs.d.ts.map +0 -1
  234. package/dist/types/src/scene/ports.d.ts +0 -5
  235. package/dist/types/src/scene/ports.d.ts.map +0 -1
  236. package/dist/types/src/shapes/common/function-anchors.d.ts +0 -12
  237. package/dist/types/src/shapes/common/function-anchors.d.ts.map +0 -1
  238. package/src/compute-layout.ts +0 -37
  239. package/src/compute.stories.tsx +0 -302
  240. package/src/hooks/useComputeGraphController.ts +0 -65
  241. package/src/scene/NodeView.tsx +0 -42
  242. package/src/scene/defs.ts +0 -158
  243. package/src/scene/ports.ts +0 -30
  244. package/src/shapes/common/function-anchors.ts +0 -44
@@ -4,12 +4,10 @@
4
4
 
5
5
  import React from 'react';
6
6
 
7
- import { type ShapeComponentProps } from '@dxos/react-ui-canvas-editor';
8
-
9
- import { Box } from './common/index.ts';
7
+ import { Box, type ComputeNodeViewProps } from './common/index.ts';
10
8
  import { type TableShape } from './table-def.ts';
11
9
 
12
- export const TableComponent = ({ shape }: ShapeComponentProps<TableShape>) => {
10
+ export const TableComponent = ({ node: shape }: ComputeNodeViewProps<TableShape>) => {
13
11
  // const items = shape.node.items.value;
14
12
 
15
13
  return <Box shape={shape}></Box>;
@@ -8,24 +8,25 @@ import React, { useRef } from 'react';
8
8
  import { ComputeValueType, getTemplateInputSchema } from '@dxos/conductor';
9
9
  import * as JsonSchema from '@dxos/echo/JsonSchema';
10
10
  import { invariant } from '@dxos/invariant';
11
+
12
+ import { useComputeNodeState } from '../hooks/index.ts';
11
13
  import {
12
- type ShapeComponentProps,
14
+ Box,
15
+ type ComputeNodeViewProps,
13
16
  TextBox,
14
17
  type TextBoxControl,
15
18
  type TextBoxProps,
16
- } from '@dxos/react-ui-canvas-editor';
17
-
18
- import { useComputeNodeState } from '../hooks/index.ts';
19
- import { Box, TypeSelect } from './common/index.ts';
19
+ TypeSelect,
20
+ } from './common/index.ts';
20
21
  import { type TemplateShape } from './template-def.ts';
21
22
 
22
23
  //
23
24
  // Component
24
25
  //
25
26
 
26
- type TextInputComponentProps = ShapeComponentProps<TemplateShape> & TextBoxProps & { title?: string };
27
+ type TextInputComponentProps = ComputeNodeViewProps<TemplateShape> & Pick<TextBoxProps, 'placeholder'>;
27
28
 
28
- const TextInputComponent = ({ shape, title, ...props }: TextInputComponentProps) => {
29
+ const TextInputComponent = ({ node: shape, placeholder }: TextInputComponentProps) => {
29
30
  const { node } = useComputeNodeState(shape);
30
31
  const inputRef = useRef<TextBoxControl>(null);
31
32
 
@@ -53,7 +54,7 @@ const TextInputComponent = ({ shape, title, ...props }: TextInputComponentProps)
53
54
  status={<TypeSelect value={node.valueType ?? 'string'} onValueChange={handleTypeChange} />}
54
55
  >
55
56
  <TextBox
56
- {...props}
57
+ placeholder={placeholder}
57
58
  ref={inputRef}
58
59
  value={node.value}
59
60
  language={node.valueType === 'object' ? 'json' : undefined}
@@ -64,6 +65,6 @@ const TextInputComponent = ({ shape, title, ...props }: TextInputComponentProps)
64
65
  );
65
66
  };
66
67
 
67
- export const TemplateComponent = (props: ShapeComponentProps<TemplateShape>) => (
68
+ export const TemplateComponent = (props: ComputeNodeViewProps<TemplateShape>) => (
68
69
  <TextInputComponent {...props} placeholder={'Prompt'} />
69
70
  );
@@ -5,13 +5,12 @@
5
5
  import React from 'react';
6
6
 
7
7
  import { DEFAULT_INPUT } from '@dxos/conductor';
8
- import { type ShapeComponentProps, TextBox } from '@dxos/react-ui-canvas-editor';
9
8
 
10
9
  import { useComputeNodeState } from '../hooks/index.ts';
11
- import { Box } from './common/index.ts';
10
+ import { Box, type ComputeNodeViewProps, TextBox } from './common/index.ts';
12
11
  import { type TextShape } from './text-def.ts';
13
12
 
14
- export const TextComponent = ({ shape }: ShapeComponentProps<TextShape>) => {
13
+ export const TextComponent = ({ node: shape }: ComputeNodeViewProps<TextShape>) => {
15
14
  const { runtime } = useComputeNodeState(shape);
16
15
  const input = runtime.inputs[DEFAULT_INPUT];
17
16
  const value = input?.type === 'executed' ? input.value : 0;
@@ -4,11 +4,9 @@
4
4
 
5
5
  import React from 'react';
6
6
 
7
- import { type ShapeComponentProps } from '@dxos/react-ui-canvas-editor';
8
-
9
- import { Box } from './common/index.ts';
7
+ import { Box, type ComputeNodeViewProps } from './common/index.ts';
10
8
  import { type TextToImageShape } from './text-to-image-def.ts';
11
9
 
12
- export const TextToImageComponent = ({ shape }: ShapeComponentProps<TextToImageShape>) => {
10
+ export const TextToImageComponent = ({ node: shape }: ComputeNodeViewProps<TextToImageShape>) => {
13
11
  return <Box shape={shape} />;
14
12
  };
@@ -4,15 +4,14 @@
4
4
 
5
5
  import React, { useEffect, useRef } from 'react';
6
6
 
7
- import { type ShapeComponentProps } from '@dxos/react-ui-canvas-editor';
8
7
  import * as ScrollArea from '@dxos/react-ui/ScrollArea';
9
8
  import type * as Util from '@dxos/react-ui/Util';
10
9
  import { mx } from '@dxos/ui-theme';
11
10
 
12
- import { Box } from './common/index.ts';
11
+ import { Box, type ComputeNodeViewProps } from './common/index.ts';
13
12
  import { type ThreadShape } from './thread-def.ts';
14
13
 
15
- export const ThreadComponent = ({ shape }: ShapeComponentProps<ThreadShape>) => {
14
+ export const ThreadComponent = ({ node: shape }: ComputeNodeViewProps<ThreadShape>) => {
16
15
  const items: any[] = [];
17
16
  const scrollRef = useRef<HTMLDivElement>(null);
18
17
  useEffect(() => {
@@ -9,16 +9,15 @@ import { VoidInput } from '@dxos/conductor';
9
9
  import { Obj } from '@dxos/echo';
10
10
  import { useResolveRef } from '@dxos/echo-react';
11
11
  import { useSpaces } from '@dxos/react-client/echo';
12
- import { type ShapeComponentProps } from '@dxos/react-ui-canvas-editor';
13
12
  import * as Select from '@dxos/react-ui/Select';
14
13
 
15
- import { FunctionBody, getHeight } from './common/index.ts';
14
+ import { type ComputeNodeViewProps, FunctionBody, getHeight } from './common/index.ts';
16
15
  import { type TriggerShape } from './trigger-def.ts';
17
16
  import { createTriggerSpec, getOutputSchema } from './trigger-spec.ts';
18
17
 
19
- export type TriggerComponentProps = ShapeComponentProps<TriggerShape>;
18
+ export type TriggerComponentProps = ComputeNodeViewProps<TriggerShape>;
20
19
 
21
- export const TriggerComponent = ({ shape }: TriggerComponentProps) => {
20
+ export const TriggerComponent = ({ node: shape }: TriggerComponentProps) => {
22
21
  const [space] = useSpaces();
23
22
  const functionTrigger = useResolveRef(shape.functionTrigger);
24
23
 
@@ -6,11 +6,10 @@ import * as Schema from 'effect/Schema';
6
6
  import * as Struct from 'effect/Struct';
7
7
 
8
8
  import { AppendInput } from '@dxos/conductor';
9
- import { type ShapeDef } from '@dxos/react-ui-canvas-editor';
10
9
 
11
10
  import { AppendComponent } from './Append.tsx';
12
- import { createFunctionAnchors, getHeight } from './common/index.ts';
13
- import { ComputeShape, type CreateShapeProps, createShape } from './defs.ts';
11
+ import { createFunctionPorts, defineComputeNode, getHeight } from './common/index.ts';
12
+ import { ComputeShape, type CreateShapeProps, createShape, withZ } from './defs.ts';
14
13
 
15
14
  // Kept out of `Append.tsx`: react-refresh only fast-refreshes a module whose
16
15
  // exports are all components, so values exported beside them force a full page reload on every edit.
@@ -32,11 +31,13 @@ export const createAppend = (props: CreateAppendProps) =>
32
31
  ...props,
33
32
  });
34
33
 
35
- export const appendShape: ShapeDef<AppendShape> = {
34
+ export const appendNodeDef = defineComputeNode<AppendShape>({
36
35
  type: 'append',
37
36
  name: 'Append',
38
37
  icon: 'ph--list-plus--regular',
38
+ group: 'Transform',
39
+ schema: withZ(AppendShape),
39
40
  component: AppendComponent,
40
- createShape: createAppend,
41
- getAnchors: (shape) => createFunctionAnchors(shape, AppendInput),
42
- };
41
+ create: createAppend,
42
+ ports: (shape) => createFunctionPorts(shape.size, AppendInput),
43
+ });
@@ -6,11 +6,10 @@ import * as Schema from 'effect/Schema';
6
6
  import * as Struct from 'effect/Struct';
7
7
 
8
8
  import { ReducerInput, ReducerOutput } from '@dxos/conductor';
9
- import { type ShapeDef } from '@dxos/react-ui-canvas-editor';
10
9
 
11
10
  import { ReducerComponent } from './Array.tsx';
12
- import { createFunctionAnchors, getHeight } from './common/index.ts';
13
- import { ComputeShape, type CreateShapeProps, createShape } from './defs.ts';
11
+ import { createFunctionPorts, defineComputeNode, getHeight } from './common/index.ts';
12
+ import { ComputeShape, type CreateShapeProps, createShape, withZ } from './defs.ts';
14
13
 
15
14
  // Kept out of `Array.tsx`: react-refresh only fast-refreshes a module whose
16
15
  // exports are all components, so values exported beside them force a full page reload on every edit.
@@ -34,7 +33,6 @@ export type ReducerShape = Schema.Schema.Type<typeof ReducerShape>;
34
33
  export type CreateReduceProps = CreateShapeProps<ReducerShape> & { reduce?: string };
35
34
 
36
35
  export const createReducer = ({
37
- id,
38
36
  size = { width: 192, height: getHeight(ReducerInput) },
39
37
  ...rest
40
38
  }: CreateReduceProps): ReducerShape =>
@@ -44,11 +42,13 @@ export const createReducer = ({
44
42
  ...rest,
45
43
  });
46
44
 
47
- export const reducerShape: ShapeDef<ReducerShape> = {
45
+ export const reducerNodeDef = defineComputeNode<ReducerShape>({
48
46
  type: 'reducer',
49
47
  name: 'Reducer',
50
48
  icon: 'ph--repeat--regular',
49
+ group: 'Operations',
50
+ schema: withZ(ReducerShape),
51
51
  component: ReducerComponent,
52
- createShape: createReducer,
53
- getAnchors: (shape) => createFunctionAnchors(shape, ReducerInput, ReducerOutput),
54
- };
52
+ create: createReducer,
53
+ ports: (shape) => createFunctionPorts(shape.size, ReducerInput, ReducerOutput),
54
+ });
@@ -5,10 +5,9 @@
5
5
  import * as Schema from 'effect/Schema';
6
6
  import * as Struct from 'effect/Struct';
7
7
 
8
- import { type ShapeDef, createAnchorMap } from '@dxos/react-ui-canvas-editor';
9
-
10
8
  import { AudioComponent } from './Audio.tsx';
11
- import { ComputeShape, type CreateShapeProps, createAnchorId, createShape } from './defs.ts';
9
+ import { createPorts, defineComputeNode } from './common/index.ts';
10
+ import { ComputeShape, type CreateShapeProps, createAnchorId, createShape, withZ } from './defs.ts';
12
11
 
13
12
  // Kept out of `Audio.tsx`: react-refresh only fast-refreshes a module whose
14
13
  // exports are all components, so values exported beside them force a full page reload on every edit.
@@ -26,11 +25,13 @@ export type CreateAudioProps = CreateShapeProps<AudioShape>;
26
25
  export const createAudio = (props: CreateAudioProps) =>
27
26
  createShape<AudioShape>({ type: 'audio', size: { width: 64, height: 64 }, ...props });
28
27
 
29
- export const audioShape: ShapeDef<AudioShape> = {
28
+ export const audioNodeDef = defineComputeNode<AudioShape>({
30
29
  type: 'audio',
31
30
  name: 'Audio',
32
31
  icon: 'ph--microphone--regular',
32
+ group: 'Inputs',
33
+ schema: withZ(AudioShape),
33
34
  component: AudioComponent,
34
- createShape: createAudio,
35
- getAnchors: (shape) => createAnchorMap(shape, { [createAnchorId('output')]: { x: 1, y: 0 } }),
36
- };
35
+ create: createAudio,
36
+ ports: (shape) => createPorts(shape.size, { [createAnchorId('output')]: { x: 1, y: 0 } }),
37
+ });
@@ -5,10 +5,9 @@
5
5
  import * as Schema from 'effect/Schema';
6
6
  import * as Struct from 'effect/Struct';
7
7
 
8
- import { type ShapeDef, createAnchorMap } from '@dxos/react-ui-canvas-editor';
9
-
10
8
  import { BeaconComponent } from './Beacon.tsx';
11
- import { ComputeShape, type CreateShapeProps, createAnchorId, createShape } from './defs.ts';
9
+ import { createPorts, defineComputeNode } from './common/index.ts';
10
+ import { ComputeShape, type CreateShapeProps, createAnchorId, createShape, withZ } from './defs.ts';
12
11
 
13
12
  // Kept out of `Beacon.tsx`: react-refresh only fast-refreshes a module whose
14
13
  // exports are all components, so values exported beside them force a full page reload on every edit.
@@ -26,14 +25,16 @@ export type CreateBeaconProps = CreateShapeProps<BeaconShape>;
26
25
  export const createBeacon = (props: CreateBeaconProps) =>
27
26
  createShape<BeaconShape>({ type: 'beacon', size: { width: 64, height: 64 }, ...props });
28
27
 
29
- export const beaconShape: ShapeDef<BeaconShape> = {
28
+ export const beaconNodeDef = defineComputeNode<BeaconShape>({
30
29
  type: 'beacon',
31
30
  name: 'Beacon',
32
31
  icon: 'ph--sun--regular',
32
+ group: 'Outputs',
33
+ schema: withZ(BeaconShape),
33
34
  component: BeaconComponent,
34
- createShape: createBeacon,
35
- getAnchors: (shape) =>
36
- createAnchorMap(shape, {
35
+ create: createBeacon,
36
+ ports: (shape) =>
37
+ createPorts(shape.size, {
37
38
  [createAnchorId('input')]: { x: -1, y: 0 },
38
39
  }),
39
- };
40
+ });
@@ -6,11 +6,9 @@ import * as Schema from 'effect/Schema';
6
6
  import * as Struct from 'effect/Struct';
7
7
  import React from 'react';
8
8
 
9
- import { type ShapeDef } from '@dxos/react-ui-canvas-editor';
10
- import { createAnchorMap } from '@dxos/react-ui-canvas-editor';
11
-
12
9
  import { TextInputComponent } from './Chat.tsx';
13
- import { ComputeShape, type CreateShapeProps, createAnchorId, createShape } from './defs.ts';
10
+ import { createPorts, defineComputeNode } from './common/index.ts';
11
+ import { ComputeShape, type CreateShapeProps, createAnchorId, createShape, withZ } from './defs.ts';
14
12
 
15
13
  // Kept out of `Chat.tsx`: react-refresh only fast-refreshes a module whose
16
14
  // exports are all components, so values exported beside them force a full page reload on every edit.
@@ -36,12 +34,14 @@ export type CreateChatProps = CreateShapeProps<ChatShape>;
36
34
  export const createChat = (props: CreateChatProps) =>
37
35
  createShape<ChatShape>({ type: 'chat', size: { width: 256, height: 128 }, ...props });
38
36
 
39
- export const chatShape: ShapeDef<ChatShape> = {
37
+ export const chatNodeDef = defineComputeNode<ChatShape>({
40
38
  type: 'chat',
41
39
  name: 'Chat',
42
40
  icon: 'ph--textbox--regular',
41
+ group: 'Inputs',
42
+ schema: withZ(ChatShape),
43
43
  component: (props) => <TextInputComponent {...props} title={'Prompt'} placeholder={'Message'} />,
44
- createShape: createChat,
45
- getAnchors: (shape) => createAnchorMap(shape, { [createAnchorId('output')]: { x: 1, y: 0 } }),
44
+ create: createChat,
45
+ ports: (shape) => createPorts(shape.size, { [createAnchorId('output')]: { x: 1, y: 0 } }),
46
46
  resizable: true,
47
- };
47
+ });
@@ -11,7 +11,7 @@ import * as Icon from '@dxos/react-ui/Icon';
11
11
  import type * as Util from '@dxos/react-ui/Util';
12
12
  import { mx } from '@dxos/ui-theme';
13
13
 
14
- import { useComputeContext } from '../../hooks/compute-context.ts';
14
+ import { useComputeContext, useComputeNodeDef } from '../../hooks/compute-context.ts';
15
15
  import { type ComputeShape } from '../defs.ts';
16
16
 
17
17
  export type BoxActionHandler = (action: 'open' | 'close') => void;
@@ -29,9 +29,12 @@ export type BoxProps = PropsWithChildren<
29
29
  export const Box = forwardRef<HTMLDivElement, BoxProps>(
30
30
  ({ children, classNames, shape, title, status, open, onAction }, forwardedRef) => {
31
31
  invariant(shape.type);
32
- // The chrome comes from the host's registry, whichever surface the shape is mounted in.
33
- const { controller, registry, debug = false } = useComputeContext();
34
- const { icon, name, openable } = registry?.getShapeDef(shape.type) ?? { icon: 'ph--circle-dashed--regular' };
32
+ // The chrome comes from the node registry the scene renders with.
33
+ const { controller, debug = false } = useComputeContext();
34
+ const def = useComputeNodeDef();
35
+ const icon = def?.icon ?? 'ph--circle-dashed--regular';
36
+ const name = def?.name;
37
+ const openable = def?.openable;
35
38
 
36
39
  // Running a node propagates to everything downstream of it, which is what the button means; a shape
37
40
  // with no compute node behind it has nothing to run, so it does not get one.
@@ -3,15 +3,15 @@
3
3
  //
4
4
 
5
5
  import type * as Schema from 'effect/Schema';
6
- import React, { type JSX, useRef, useState } from 'react';
6
+ import React, { type JSX, useState } from 'react';
7
7
 
8
8
  import { VoidInput, VoidOutput } from '@dxos/conductor';
9
- import { getParentShapeElement, rowHeight } from '@dxos/react-ui-canvas-editor';
9
+ import { mx } from '@dxos/ui-theme';
10
10
 
11
11
  import { useComputeContext } from '../../hooks/compute-context.ts';
12
12
  import { Box, type BoxProps } from '../common/index.ts';
13
13
  import { type ComputeShape, getProperties } from '../defs.ts';
14
- import { bodyPadding } from './function-anchors.ts';
14
+ import { rowHeight } from './ports.ts';
15
15
 
16
16
  const expandedHeight = 200;
17
17
 
@@ -32,23 +32,13 @@ export const FunctionBody = ({
32
32
  outputSchema = VoidOutput,
33
33
  ...props
34
34
  }: FunctionBodyProps) => {
35
- // Opening grows the shape: through the host's `resize` when it offers one (the scene engine, where size
36
- // is model state), else by stretching the editor's frame element as the canvas editor always did.
35
+ // Opening grows the shape through the host's `resize`, since its size is model state.
37
36
  const { resize } = useComputeContext();
38
- const rootRef = useRef<HTMLDivElement>(null);
39
37
  const [open, setOpen] = useState(false);
40
38
 
41
39
  const handleAction: BoxProps['onAction'] = (action) => {
42
40
  const opening = action === 'open';
43
- if (resize) {
44
- resize(shape.id, opening ? expandedHeight : -expandedHeight);
45
- } else if (rootRef.current) {
46
- const element = getParentShapeElement(rootRef.current, shape.id);
47
- if (element) {
48
- // The layout height is already in canvas units, whatever the zoom.
49
- element.style.height = opening ? `${element.offsetHeight + expandedHeight}px` : '';
50
- }
51
- }
41
+ resize?.(shape.id, opening ? expandedHeight : -expandedHeight);
52
42
  setOpen(opening);
53
43
  };
54
44
 
@@ -59,7 +49,6 @@ export const FunctionBody = ({
59
49
 
60
50
  return (
61
51
  <Box
62
- ref={rootRef}
63
52
  shape={shape}
64
53
  title={name}
65
54
  classNames='divide-y divide-separator-subtle'
@@ -67,28 +56,26 @@ export const FunctionBody = ({
67
56
  onAction={handleAction}
68
57
  {...props}
69
58
  >
70
- <div
71
- className={`grid grid-cols-${columnCount} items-center`}
72
- style={{ paddingTop: bodyPadding, paddingBottom: bodyPadding }}
73
- >
59
+ {/* Each column's rows are centred in the body, as the ports beside them are (`createFunctionPorts`). */}
60
+ <div className={mx(`grid grid-cols-${columnCount}`, !open && 'grow')}>
74
61
  {(inputs?.length ?? 0) > 0 && (
75
- <div className='flex flex-col'>
62
+ <div className='flex flex-col justify-center'>
76
63
  {inputs?.map(({ name }) => (
77
- <div key={name} className='px-2 truncate text-sm font-mono items-center' style={{ height: rowHeight }}>
78
- {name}
64
+ <div key={name} className='flex items-center px-2 text-sm font-mono' style={{ height: rowHeight }}>
65
+ <span className='truncate'>{name}</span>
79
66
  </div>
80
67
  ))}
81
68
  </div>
82
69
  )}
83
70
  {(outputs?.length ?? 0) > 0 && (
84
- <div className='flex flex-col'>
71
+ <div className='flex flex-col justify-center'>
85
72
  {outputs?.map(({ name }) => (
86
73
  <div
87
74
  key={name}
88
- className='px-2 truncate text-sm font-mono items-center text-right'
75
+ className='flex items-center justify-end px-2 text-sm font-mono'
89
76
  style={{ height: rowHeight }}
90
77
  >
91
- {name}
78
+ <span className='truncate'>{name}</span>
92
79
  </div>
93
80
  ))}
94
81
  </div>
@@ -0,0 +1,137 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { json } from '@codemirror/lang-json';
6
+ import { Prec } from '@codemirror/state';
7
+ import { EditorView, keymap } from '@codemirror/view';
8
+ import React, { forwardRef, useEffect, useImperativeHandle, useRef } from 'react';
9
+
10
+ import { useTextEditor } from '@dxos/react-ui-editor';
11
+ import * as Hooks from '@dxos/react-ui/Hooks';
12
+ import type * as Util from '@dxos/react-ui/Util';
13
+ import {
14
+ type BasicExtensionsOptions,
15
+ createBasicExtensions,
16
+ createMarkdownExtensions,
17
+ createThemeExtensions,
18
+ decorateMarkdown,
19
+ } from '@dxos/ui-editor';
20
+ import { mx } from '@dxos/ui-theme';
21
+
22
+ // An always-editable field, since the engine's `TextPart` edits only an opened part and focuses on mount.
23
+
24
+ export interface TextBoxControl {
25
+ setText(text: string): void;
26
+ focus(): void;
27
+ }
28
+
29
+ export type TextBoxProps = Util.ThemedClassName<
30
+ {
31
+ value?: string;
32
+ centered?: boolean;
33
+ onBlur?: (value: string) => void;
34
+ onEnter?: (value: string) => void;
35
+ onCancel?: () => void;
36
+ language?: 'json' | 'markdown';
37
+ } & Pick<BasicExtensionsOptions, 'placeholder'>
38
+ >;
39
+
40
+ export const TextBox = forwardRef<TextBoxControl, TextBoxProps>(
41
+ ({ classNames, value = '', centered, onEnter, onCancel, language, ...rest }, forwardedRef) => {
42
+ const themeMode = Hooks.useThemeMode();
43
+ const modified = useRef(false);
44
+ const doc = useRef(value);
45
+ useEffect(() => {
46
+ modified.current = false;
47
+ doc.current = value;
48
+ }, [value]);
49
+
50
+ const { parentRef, view, focusAttributes } = useTextEditor(() => {
51
+ return {
52
+ id: 'text',
53
+ initialValue: value,
54
+ extensions: [
55
+ createBasicExtensions({ lineWrapping: !centered, ...rest }),
56
+ ...(language === 'json'
57
+ ? [json()]
58
+ : language === 'markdown'
59
+ ? [createMarkdownExtensions(), decorateMarkdown()]
60
+ : []),
61
+ createThemeExtensions({
62
+ themeMode,
63
+ syntaxHighlighting: !!language,
64
+ slots: {
65
+ editor: { className: 'h-full w-full [&>.cm-scroller]:scrollbar-none p-2' },
66
+ content: { className: mx(centered && 'text-center') },
67
+ },
68
+ }),
69
+ // Detect changes.
70
+ EditorView.updateListener.of((update) => {
71
+ if (update.docChanged) {
72
+ modified.current = doc.current !== update.state.doc.toString();
73
+ }
74
+ }),
75
+ // TODO(burdon): Only fire if modified.
76
+ EditorView.focusChangeEffect.of((state, focusing) => {
77
+ if (!focusing && modified.current) {
78
+ onEnter?.(state.doc.toString());
79
+ }
80
+
81
+ return null;
82
+ }),
83
+ Prec.highest(
84
+ keymap.of([
85
+ {
86
+ key: 'Enter',
87
+ preventDefault: true,
88
+ run: (view) => {
89
+ onEnter?.(view.state.doc.toString());
90
+ modified.current = false;
91
+ return true;
92
+ },
93
+ },
94
+ {
95
+ key: 'Shift-Enter',
96
+ run: (view) => {
97
+ // The new line is an edit like any other, so leaving the field still commits it.
98
+ view.dispatch(view.state.replaceSelection('\n'));
99
+ return true;
100
+ },
101
+ },
102
+ {
103
+ key: 'Escape',
104
+ run: () => {
105
+ onCancel?.();
106
+ modified.current = false;
107
+ return true;
108
+ },
109
+ },
110
+ ]),
111
+ ),
112
+ ],
113
+ };
114
+ }, [value, language]);
115
+
116
+ // External control.
117
+ useImperativeHandle(
118
+ forwardedRef,
119
+ () => ({
120
+ setText: (text: string) => {
121
+ view?.dispatch({ changes: { from: 0, to: view.state.doc.length, insert: text } });
122
+ },
123
+ focus: () => {
124
+ view?.focus();
125
+ },
126
+ }),
127
+ [view],
128
+ );
129
+
130
+ // Scroll to bottom.
131
+ useEffect(() => {
132
+ view?.dispatch({ selection: { anchor: view.state.doc.length } });
133
+ }, [view]);
134
+
135
+ return <div ref={parentRef} {...focusAttributes} className={mx('dx-fill overflow-hidden', classNames)} />;
136
+ },
137
+ );
@@ -3,8 +3,10 @@
3
3
  //
4
4
 
5
5
  export * from './box-defs.ts';
6
- export * from './function-anchors.ts';
6
+ export * from './node-def.tsx';
7
+ export * from './ports.ts';
7
8
 
8
9
  export * from './Box.tsx';
9
10
  export * from './FunctionBody.tsx';
11
+ export * from './TextBox.tsx';
10
12
  export * from './TypeSelect.tsx';