@dxos/react-ui-canvas-compute 0.7.5-labs.8a82073 → 0.7.5-labs.c0e040f

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.
@@ -10,7 +10,7 @@ import { invariant } from '@dxos/invariant';
10
10
  import { DXN } from '@dxos/keys';
11
11
  import { getSpace } from '@dxos/react-client/echo';
12
12
  import { type GraphMonitor, type CanvasGraphModel, type Connection } from '@dxos/react-ui-canvas-editor';
13
- import { nonNullable } from '@dxos/util';
13
+ import { isNonNullable } from '@dxos/util';
14
14
 
15
15
  import { createComputeNode, isValidComputeNode } from '../graph';
16
16
  import { type ComputeShape, type TriggerShape } from '../shapes';
@@ -79,7 +79,7 @@ export const useGraphMonitor = (model?: ComputeGraphModel): GraphMonitor<Compute
79
79
  return model.edges.find((computeEdge) => computeEdge.input === input && computeEdge.output === output)
80
80
  ?.id;
81
81
  })
82
- .filter(nonNullable);
82
+ .filter(isNonNullable);
83
83
 
84
84
  model.removeNodes(nodeIds);
85
85
  model.removeEdges(edgeIds);
@@ -2,14 +2,24 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import React from 'react';
5
+ import React, { useCallback, useRef } from 'react';
6
6
 
7
7
  import { AnyOutput, FunctionInput } from '@dxos/conductor';
8
- import { S } from '@dxos/echo-schema';
9
- import { type ShapeComponentProps, type ShapeDef } from '@dxos/react-ui-canvas-editor';
8
+ import { getSnapshot, S } from '@dxos/echo-schema';
9
+ import { FunctionType, ScriptType } from '@dxos/functions';
10
+ import { useClient } from '@dxos/react-client';
11
+ import { Filter, makeRef, parseId } from '@dxos/react-client/echo';
12
+ import {
13
+ TextBox,
14
+ type TextBoxControl,
15
+ type TextBoxProps,
16
+ type ShapeComponentProps,
17
+ type ShapeDef,
18
+ } from '@dxos/react-ui-canvas-editor';
10
19
 
11
- import { createFunctionAnchors, FunctionBody, getHeight } from './common';
20
+ import { Box, createFunctionAnchors } from './common';
12
21
  import { ComputeShape, createShape, type CreateShapeProps } from './defs';
22
+ import { useComputeNodeState } from '../hooks';
13
23
 
14
24
  export const FunctionShape = S.extend(
15
25
  ComputeShape,
@@ -23,18 +33,82 @@ export type FunctionShape = S.Schema.Type<typeof FunctionShape>;
23
33
  export type CreateFunctionProps = CreateShapeProps<FunctionShape>;
24
34
 
25
35
  export const createFunction = (props: CreateFunctionProps) =>
26
- createShape<FunctionShape>({ type: 'function', size: { width: 192, height: getHeight(FunctionInput) }, ...props });
36
+ createShape<FunctionShape>({ type: 'function', size: { width: 256, height: 192 }, ...props });
27
37
 
28
- export const FunctionComponent = ({ shape }: ShapeComponentProps<FunctionShape>) => {
29
- return <FunctionBody shape={shape} inputSchema={FunctionInput} outputSchema={AnyOutput} />;
38
+ //
39
+ // Component
40
+ //
41
+
42
+ type TextInputComponentProps = ShapeComponentProps<FunctionShape> & TextBoxProps & { title?: string };
43
+
44
+ const TextInputComponent = ({ shape, title, ...props }: TextInputComponentProps) => {
45
+ const client = useClient();
46
+ const { node, runtime } = useComputeNodeState(shape);
47
+ const inputRef = useRef<TextBoxControl>(null);
48
+
49
+ const handleEnter = useCallback(
50
+ async (text: string) => {
51
+ const value = text.trim();
52
+ const { spaceId, objectId } = parseId(value);
53
+ if (!spaceId || !objectId) {
54
+ return;
55
+ }
56
+
57
+ const space = client.spaces.get(spaceId);
58
+ const object = space?.db.getObjectById(objectId);
59
+ if (!space || !(object instanceof ScriptType)) {
60
+ return;
61
+ }
62
+
63
+ const {
64
+ objects: [fn],
65
+ } = await space.db.query(Filter.schema(FunctionType, { source: object })).run();
66
+ if (!fn) {
67
+ return;
68
+ }
69
+
70
+ node.value = value;
71
+ node.function = makeRef(fn);
72
+ node.inputSchema = getSnapshot(fn.inputSchema);
73
+ node.outputSchema = getSnapshot(fn.outputSchema);
74
+ },
75
+ [client, node],
76
+ );
77
+
78
+ const handleAction = useCallback(
79
+ (action: 'run' | 'open' | 'close') => {
80
+ if (action !== 'run') {
81
+ return;
82
+ }
83
+
84
+ runtime.evalNode();
85
+ },
86
+ [runtime],
87
+ );
88
+
89
+ return (
90
+ <Box shape={shape} title='Function' onAction={handleAction}>
91
+ <TextBox
92
+ {...props}
93
+ ref={inputRef}
94
+ value={node.value}
95
+ language={node.valueType === 'object' ? 'json' : undefined}
96
+ onBlur={handleEnter}
97
+ onEnter={handleEnter}
98
+ />
99
+ </Box>
100
+ );
30
101
  };
31
102
 
103
+ //
104
+ // Defs
105
+ //
106
+
32
107
  export const functionShape: ShapeDef<FunctionShape> = {
33
108
  type: 'function',
34
109
  name: 'Function',
35
110
  icon: 'ph--function--regular',
36
- component: FunctionComponent,
111
+ component: TextInputComponent,
37
112
  createShape: createFunction,
38
- // TODO(burdon): Get dynamic schema.
39
113
  getAnchors: (shape) => createFunctionAnchors(shape, FunctionInput, AnyOutput),
40
114
  };
@@ -24,6 +24,7 @@ export type FunctionBodyProps = {
24
24
  outputSchema?: S.Schema.Any;
25
25
  } & Pick<BoxProps, 'status'>;
26
26
 
27
+ // TODO(wittjosiah): Rename, not used for functions.
27
28
  export const FunctionBody = ({
28
29
  shape,
29
30
  name,