@dxos/plugin-script 0.6.12-staging.e11e696 → 0.6.12

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 (179) hide show
  1. package/dist/lib/browser/{ScriptContainer-AGDWRBHJ.mjs → ScriptEditor-5Y3EROG3.mjs} +106 -258
  2. package/dist/lib/browser/ScriptEditor-5Y3EROG3.mjs.map +7 -0
  3. package/dist/lib/browser/TypescriptEditor-GPE72Y6I.mjs +9 -0
  4. package/dist/lib/browser/{chunk-G6FWCTGT.mjs → chunk-DL5XQRQM.mjs} +5 -7
  5. package/dist/lib/browser/chunk-DL5XQRQM.mjs.map +7 -0
  6. package/dist/lib/browser/{chunk-MDX7ACIK.mjs → chunk-JBACGDOJ.mjs} +6 -3
  7. package/dist/lib/browser/chunk-JBACGDOJ.mjs.map +7 -0
  8. package/dist/lib/browser/chunk-MRGOT5RF.mjs +78 -0
  9. package/dist/lib/browser/chunk-MRGOT5RF.mjs.map +7 -0
  10. package/dist/lib/browser/{chunk-CAEANETO.mjs → chunk-O4LWBX6A.mjs} +2 -2
  11. package/dist/lib/browser/{chunk-CAEANETO.mjs.map → chunk-O4LWBX6A.mjs.map} +2 -2
  12. package/dist/lib/browser/{chunk-G6H56WFS.mjs → chunk-RHEZ5LUU.mjs} +2 -51
  13. package/dist/lib/browser/{chunk-G6H56WFS.mjs.map → chunk-RHEZ5LUU.mjs.map} +4 -4
  14. package/dist/lib/browser/edge/index.mjs +1 -3
  15. package/dist/lib/browser/index.mjs +62 -80
  16. package/dist/lib/browser/index.mjs.map +4 -4
  17. package/dist/lib/browser/meta.json +1 -1
  18. package/dist/lib/browser/meta.mjs +1 -1
  19. package/dist/lib/browser/types/index.mjs +2 -2
  20. package/dist/lib/node/ScriptEditor-YCUQFWQM.cjs +526 -0
  21. package/dist/lib/node/ScriptEditor-YCUQFWQM.cjs.map +7 -0
  22. package/dist/lib/node/{chunk-OJ77BZRH.cjs → TypescriptEditor-M3WWFIP2.cjs} +8 -19
  23. package/dist/lib/node/TypescriptEditor-M3WWFIP2.cjs.map +7 -0
  24. package/dist/lib/node/{chunk-ACLCRWDB.cjs → chunk-4GTXIELQ.cjs} +6 -44
  25. package/dist/lib/node/chunk-4GTXIELQ.cjs.map +7 -0
  26. package/dist/lib/node/chunk-4VMNBXWU.cjs +54 -0
  27. package/dist/lib/node/chunk-4VMNBXWU.cjs.map +7 -0
  28. package/dist/lib/node/{chunk-2PZKJXNP.cjs → chunk-5RBVXKXT.cjs} +6 -6
  29. package/dist/lib/node/{chunk-2PZKJXNP.cjs.map → chunk-5RBVXKXT.cjs.map} +2 -2
  30. package/dist/lib/node/chunk-IMLDKD5Y.cjs +111 -0
  31. package/dist/lib/node/chunk-IMLDKD5Y.cjs.map +7 -0
  32. package/dist/lib/node/{chunk-UZ3ZXEBF.cjs → chunk-PFH3ROEH.cjs} +8 -11
  33. package/dist/lib/node/chunk-PFH3ROEH.cjs.map +7 -0
  34. package/dist/lib/node/edge/index.cjs +8 -10
  35. package/dist/lib/node/edge/index.cjs.map +2 -2
  36. package/dist/lib/node/index.cjs +82 -95
  37. package/dist/lib/node/index.cjs.map +4 -4
  38. package/dist/lib/node/meta.cjs +3 -3
  39. package/dist/lib/node/meta.cjs.map +1 -1
  40. package/dist/lib/node/meta.json +1 -1
  41. package/dist/lib/node/types/index.cjs +5 -5
  42. package/dist/lib/node/types/index.cjs.map +1 -1
  43. package/dist/types/src/ScriptPlugin.d.ts.map +1 -1
  44. package/dist/types/src/components/DebugPanel.d.ts.map +1 -0
  45. package/dist/types/src/components/{FrameContainer → ScriptBlock/FrameContainer}/FrameContainer.d.ts +1 -1
  46. package/dist/types/src/components/ScriptBlock/FrameContainer/FrameContainer.d.ts.map +1 -0
  47. package/dist/types/src/components/ScriptBlock/FrameContainer/frame.d.ts.map +1 -0
  48. package/dist/types/src/components/ScriptBlock/FrameContainer/index.d.ts.map +1 -0
  49. package/dist/types/src/components/ScriptBlock/ScriptBlock.d.ts +3 -1
  50. package/dist/types/src/components/ScriptBlock/ScriptBlock.d.ts.map +1 -1
  51. package/dist/types/src/components/ScriptBlock/ScriptBlock.stories.d.ts +1 -1
  52. package/dist/types/src/components/ScriptBlock/ScriptBlock.stories.d.ts.map +1 -1
  53. package/dist/types/src/components/ScriptBlock/Splitter/Splitter.d.ts +15 -0
  54. package/dist/types/src/components/ScriptBlock/Splitter/Splitter.d.ts.map +1 -0
  55. package/dist/types/src/components/ScriptBlock/Splitter/Splitter.stories.d.ts +13 -0
  56. package/dist/types/src/components/ScriptBlock/Splitter/Splitter.stories.d.ts.map +1 -0
  57. package/dist/types/src/components/ScriptBlock/Splitter/index.d.ts +2 -0
  58. package/dist/types/src/components/ScriptBlock/Splitter/index.d.ts.map +1 -0
  59. package/dist/types/src/components/ScriptEditor.d.ts +5 -4
  60. package/dist/types/src/components/ScriptEditor.d.ts.map +1 -1
  61. package/dist/types/src/components/Toolbar.d.ts +13 -0
  62. package/dist/types/src/components/Toolbar.d.ts.map +1 -0
  63. package/dist/types/src/components/Toolbar.stories.d.ts +14 -0
  64. package/dist/types/src/components/Toolbar.stories.d.ts.map +1 -0
  65. package/dist/types/src/components/{TypescriptEditor/TypescriptEditor.d.ts → TypescriptEditor.d.ts} +2 -1
  66. package/dist/types/src/components/TypescriptEditor.d.ts.map +1 -0
  67. package/dist/types/src/components/TypescriptEditor.stories.d.ts +10 -0
  68. package/dist/types/src/components/TypescriptEditor.stories.d.ts.map +1 -0
  69. package/dist/types/src/components/index.d.ts +2 -2
  70. package/dist/types/src/components/index.d.ts.map +1 -1
  71. package/dist/types/src/edge/functions.d.ts +0 -1
  72. package/dist/types/src/edge/functions.d.ts.map +1 -1
  73. package/dist/types/src/meta.d.ts +4 -1
  74. package/dist/types/src/meta.d.ts.map +1 -1
  75. package/dist/types/src/translations.d.ts +0 -2
  76. package/dist/types/src/translations.d.ts.map +1 -1
  77. package/dist/types/src/types/script.d.ts +4 -4
  78. package/dist/types/src/types/types.d.ts +3 -4
  79. package/dist/types/src/types/types.d.ts.map +1 -1
  80. package/package.json +55 -61
  81. package/src/ScriptPlugin.tsx +38 -22
  82. package/src/bundler/bundler.test.ts +2 -12
  83. package/src/components/{DebugPanel/DebugPanel.tsx → DebugPanel.tsx} +41 -48
  84. package/src/components/{FrameContainer → ScriptBlock/FrameContainer}/FrameContainer.tsx +1 -1
  85. package/src/components/ScriptBlock/ScriptBlock.stories.tsx +3 -4
  86. package/src/components/ScriptBlock/ScriptBlock.tsx +36 -10
  87. package/src/components/ScriptBlock/Splitter/Splitter.stories.tsx +37 -0
  88. package/src/components/ScriptBlock/Splitter/Splitter.tsx +52 -0
  89. package/src/components/{Toolbar → ScriptBlock/Splitter}/index.ts +1 -1
  90. package/src/components/ScriptEditor.tsx +46 -47
  91. package/src/components/{Toolbar/Toolbar.stories.tsx → Toolbar.stories.tsx} +1 -10
  92. package/src/components/Toolbar.tsx +147 -0
  93. package/src/components/{TypescriptEditor/TypescriptEditor.stories.tsx → TypescriptEditor.stories.tsx} +28 -7
  94. package/src/components/{TypescriptEditor/TypescriptEditor.tsx → TypescriptEditor.tsx} +3 -1
  95. package/src/components/index.ts +2 -3
  96. package/src/edge/functions.ts +0 -1
  97. package/src/meta.tsx +6 -2
  98. package/src/translations.ts +0 -2
  99. package/src/types/types.ts +5 -9
  100. package/dist/lib/browser/ScriptContainer-AGDWRBHJ.mjs.map +0 -7
  101. package/dist/lib/browser/chunk-G6FWCTGT.mjs.map +0 -7
  102. package/dist/lib/browser/chunk-MDX7ACIK.mjs.map +0 -7
  103. package/dist/lib/node/ScriptContainer-5R3NWYKS.cjs +0 -668
  104. package/dist/lib/node/ScriptContainer-5R3NWYKS.cjs.map +0 -7
  105. package/dist/lib/node/chunk-ACLCRWDB.cjs.map +0 -7
  106. package/dist/lib/node/chunk-OJ77BZRH.cjs.map +0 -7
  107. package/dist/lib/node/chunk-UZ3ZXEBF.cjs.map +0 -7
  108. package/dist/lib/node-esm/ScriptContainer-ZY2XG3GH.mjs +0 -666
  109. package/dist/lib/node-esm/ScriptContainer-ZY2XG3GH.mjs.map +0 -7
  110. package/dist/lib/node-esm/chunk-2NX3HWPM.mjs +0 -245
  111. package/dist/lib/node-esm/chunk-2NX3HWPM.mjs.map +0 -7
  112. package/dist/lib/node-esm/chunk-7BZDZF7Z.mjs +0 -47
  113. package/dist/lib/node-esm/chunk-7BZDZF7Z.mjs.map +0 -7
  114. package/dist/lib/node-esm/chunk-LDLNTVAK.mjs +0 -280
  115. package/dist/lib/node-esm/chunk-LDLNTVAK.mjs.map +0 -7
  116. package/dist/lib/node-esm/chunk-TZ3Z4SII.mjs +0 -20
  117. package/dist/lib/node-esm/chunk-TZ3Z4SII.mjs.map +0 -7
  118. package/dist/lib/node-esm/edge/index.mjs +0 -22
  119. package/dist/lib/node-esm/index.mjs +0 -310
  120. package/dist/lib/node-esm/index.mjs.map +0 -7
  121. package/dist/lib/node-esm/meta.json +0 -1
  122. package/dist/lib/node-esm/meta.mjs +0 -10
  123. package/dist/lib/node-esm/meta.mjs.map +0 -7
  124. package/dist/lib/node-esm/types/index.mjs +0 -13
  125. package/dist/lib/node-esm/types/index.mjs.map +0 -7
  126. package/dist/types/src/components/DebugPanel/DebugPanel.d.ts.map +0 -1
  127. package/dist/types/src/components/DebugPanel/index.d.ts +0 -2
  128. package/dist/types/src/components/DebugPanel/index.d.ts.map +0 -1
  129. package/dist/types/src/components/FrameContainer/FrameContainer.d.ts.map +0 -1
  130. package/dist/types/src/components/FrameContainer/frame.d.ts.map +0 -1
  131. package/dist/types/src/components/FrameContainer/index.d.ts.map +0 -1
  132. package/dist/types/src/components/ScriptContainer.d.ts +0 -5
  133. package/dist/types/src/components/ScriptContainer.d.ts.map +0 -1
  134. package/dist/types/src/components/ScriptSettings/ScriptSettings.d.ts +0 -6
  135. package/dist/types/src/components/ScriptSettings/ScriptSettings.d.ts.map +0 -1
  136. package/dist/types/src/components/ScriptSettings/index.d.ts +0 -2
  137. package/dist/types/src/components/ScriptSettings/index.d.ts.map +0 -1
  138. package/dist/types/src/components/Toolbar/Toolbar.d.ts +0 -23
  139. package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +0 -1
  140. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +0 -17
  141. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +0 -1
  142. package/dist/types/src/components/Toolbar/index.d.ts +0 -2
  143. package/dist/types/src/components/Toolbar/index.d.ts.map +0 -1
  144. package/dist/types/src/components/TypescriptEditor/TypescriptEditor.d.ts.map +0 -1
  145. package/dist/types/src/components/TypescriptEditor/TypescriptEditor.stories.d.ts +0 -10
  146. package/dist/types/src/components/TypescriptEditor/TypescriptEditor.stories.d.ts.map +0 -1
  147. package/dist/types/src/components/TypescriptEditor/index.d.ts +0 -2
  148. package/dist/types/src/components/TypescriptEditor/index.d.ts.map +0 -1
  149. package/dist/types/src/templates/chat.d.ts +0 -6
  150. package/dist/types/src/templates/chat.d.ts.map +0 -1
  151. package/dist/types/src/templates/chess.d.ts +0 -6
  152. package/dist/types/src/templates/chess.d.ts.map +0 -1
  153. package/dist/types/src/templates/echo.d.ts +0 -6
  154. package/dist/types/src/templates/echo.d.ts.map +0 -1
  155. package/dist/types/src/templates/email.d.ts +0 -6
  156. package/dist/types/src/templates/email.d.ts.map +0 -1
  157. package/dist/types/src/templates/forex.d.ts +0 -6
  158. package/dist/types/src/templates/forex.d.ts.map +0 -1
  159. package/dist/types/src/templates.d.ts +0 -8
  160. package/dist/types/src/templates.d.ts.map +0 -1
  161. package/src/components/DebugPanel/index.ts +0 -5
  162. package/src/components/ScriptContainer.tsx +0 -22
  163. package/src/components/ScriptSettings/ScriptSettings.tsx +0 -47
  164. package/src/components/ScriptSettings/index.ts +0 -5
  165. package/src/components/Toolbar/Toolbar.tsx +0 -180
  166. package/src/components/TypescriptEditor/index.ts +0 -5
  167. package/src/templates/chat.ts +0 -102
  168. package/src/templates/chess.ts +0 -41
  169. package/src/templates/echo.ts +0 -15
  170. package/src/templates/email.ts +0 -38
  171. package/src/templates/forex.ts +0 -21
  172. package/src/templates.ts +0 -54
  173. /package/dist/lib/{node-esm/edge/index.mjs.map → browser/TypescriptEditor-GPE72Y6I.mjs.map} +0 -0
  174. /package/dist/types/src/components/{DebugPanel/DebugPanel.d.ts → DebugPanel.d.ts} +0 -0
  175. /package/dist/types/src/components/{FrameContainer → ScriptBlock/FrameContainer}/frame.d.ts +0 -0
  176. /package/dist/types/src/components/{FrameContainer → ScriptBlock/FrameContainer}/index.d.ts +0 -0
  177. /package/src/components/{FrameContainer → ScriptBlock/FrameContainer}/frame.html +0 -0
  178. /package/src/components/{FrameContainer → ScriptBlock/FrameContainer}/frame.tsx +0 -0
  179. /package/src/components/{FrameContainer → ScriptBlock/FrameContainer}/index.ts +0 -0
@@ -2,6 +2,7 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
+ import { Code, type IconProps } from '@phosphor-icons/react';
5
6
  // @ts-ignore
6
7
  import wasmUrl from 'esbuild-wasm/esbuild.wasm?url';
7
8
  import React from 'react';
@@ -16,9 +17,8 @@ import { loadObjectReferences } from '@dxos/react-client/echo';
16
17
 
17
18
  import { initializeBundler } from './bundler';
18
19
  import { Compiler } from './compiler';
19
- import { ScriptContainer, ScriptSettings } from './components';
20
+ import { ScriptEditor } from './components';
20
21
  import meta, { SCRIPT_PLUGIN } from './meta';
21
- import { templates } from './templates';
22
22
  import translations from './translations';
23
23
  import { FunctionType, ScriptType } from './types';
24
24
  import { ScriptAction, type ScriptPluginProvides } from './types';
@@ -45,12 +45,12 @@ export const ScriptPlugin = (): PluginDefinition<ScriptPluginProvides> => {
45
45
  await initializeBundler({ wasmUrl });
46
46
  },
47
47
  provides: {
48
- settings: {},
49
48
  metadata: {
50
49
  records: {
51
50
  [ScriptType.typename]: {
52
51
  placeholder: ['object title placeholder', { ns: SCRIPT_PLUGIN }],
53
- icon: 'ph--code--regular',
52
+ icon: (props: IconProps) => <Code {...props} />,
53
+ iconSymbol: 'ph--code--regular',
54
54
  // TODO(wittjosiah): Move out of metadata.
55
55
  loadReferences: (script: ScriptType) => loadObjectReferences(script, (script) => [script.source]),
56
56
  },
@@ -60,12 +60,6 @@ export const ScriptPlugin = (): PluginDefinition<ScriptPluginProvides> => {
60
60
  echo: {
61
61
  schema: [ScriptType, FunctionType],
62
62
  },
63
- space: {
64
- onSpaceCreate: {
65
- label: ['create object label', { ns: SCRIPT_PLUGIN }],
66
- action: ScriptAction.CREATE,
67
- },
68
- },
69
63
  graph: {
70
64
  builder: (plugins) => {
71
65
  const client = resolvePlugin(plugins, parseClientPlugin)?.provides.client;
@@ -99,7 +93,8 @@ export const ScriptPlugin = (): PluginDefinition<ScriptPluginProvides> => {
99
93
  },
100
94
  properties: {
101
95
  label: ['create object label', { ns: SCRIPT_PLUGIN }],
102
- icon: 'ph--code--regular',
96
+ icon: (props: IconProps) => <Code {...props} />,
97
+ iconSymbol: 'ph--code--regular',
103
98
  testId: 'scriptPlugin.createObject',
104
99
  },
105
100
  },
@@ -108,19 +103,29 @@ export const ScriptPlugin = (): PluginDefinition<ScriptPluginProvides> => {
108
103
  });
109
104
  },
110
105
  },
106
+ stack: {
107
+ creators: [
108
+ {
109
+ id: 'create-stack-section-script',
110
+ testId: 'scriptPlugin.createSection',
111
+ type: ['plugin name', { ns: SCRIPT_PLUGIN }],
112
+ label: ['create stack section label', { ns: SCRIPT_PLUGIN }],
113
+ icon: (props: any) => <Code {...props} />,
114
+ intent: {
115
+ plugin: SCRIPT_PLUGIN,
116
+ action: ScriptAction.CREATE,
117
+ },
118
+ },
119
+ ],
120
+ },
111
121
  surface: {
112
122
  component: ({ data, role }) => {
113
- switch (role) {
114
- case 'settings': {
115
- return data.plugin === meta.id ? <ScriptSettings settings={{}} /> : null;
116
- }
123
+ if (role && !['article', 'section'].includes(role)) {
124
+ return null;
125
+ }
117
126
 
118
- case 'article': {
119
- if (data.object instanceof ScriptType) {
120
- return <ScriptContainer script={data.object} env={compiler.environment} />;
121
- }
122
- break;
123
- }
127
+ if (data.object instanceof ScriptType) {
128
+ return <ScriptEditor env={compiler.environment} script={data.object} role={role} />;
124
129
  }
125
130
 
126
131
  return null;
@@ -130,7 +135,7 @@ export const ScriptPlugin = (): PluginDefinition<ScriptPluginProvides> => {
130
135
  resolver: (intent) => {
131
136
  switch (intent.action) {
132
137
  case ScriptAction.CREATE: {
133
- return { data: create(ScriptType, { source: create(TextType, { content: templates[0].source }) }) };
138
+ return { data: create(ScriptType, { source: create(TextType, { content: example }) }) };
134
139
  }
135
140
  }
136
141
  },
@@ -138,3 +143,14 @@ export const ScriptPlugin = (): PluginDefinition<ScriptPluginProvides> => {
138
143
  },
139
144
  };
140
145
  };
146
+
147
+ // TODO(burdon): Import.
148
+ const example = [
149
+ 'export default async ({ ',
150
+ ' event: { data: { request } },',
151
+ ' context: { space, ai } ',
152
+ '}: any) => {',
153
+ " return new Response('Hello DXOS!');",
154
+ '};',
155
+ '',
156
+ ].join('\n');
@@ -2,21 +2,11 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- // @ts-ignore
6
- import wasmUrl from 'esbuild-wasm/esbuild.wasm?url';
7
- import { beforeAll, describe, expect, test } from 'vitest';
5
+ import { describe, expect, test } from 'vitest';
8
6
 
9
- import { isNode } from '@dxos/util';
10
-
11
- import { Bundler, initializeBundler } from './bundler';
7
+ import { Bundler } from './bundler';
12
8
 
13
9
  describe('Bundler', () => {
14
- beforeAll(async () => {
15
- if (!isNode()) {
16
- await initializeBundler({ wasmUrl });
17
- }
18
- });
19
-
20
10
  test('Basic', async () => {
21
11
  const bundler = new Bundler({ platform: 'node', sandboxedModules: [], remoteModules: {} });
22
12
  const result = await bundler.bundle('const x = 100'); // TODO(burdon): Test import.
@@ -18,7 +18,7 @@ import {
18
18
  import { SyntaxHighlighter } from '@dxos/react-ui-syntax-highlighter';
19
19
  import { mx } from '@dxos/react-ui-theme';
20
20
 
21
- import { SCRIPT_PLUGIN } from '../../meta';
21
+ import { SCRIPT_PLUGIN } from '../meta';
22
22
 
23
23
  type State = 'pending' | 'responding';
24
24
 
@@ -47,7 +47,7 @@ export const DebugPanel = ({ classNames, functionUrl, binding: _binding, onBindi
47
47
  const [result, setResult] = useState('');
48
48
  const [state, setState] = useState<State | null>(null);
49
49
 
50
- // TODO(burdon): Persistent history -- at least for session (non-space ECHO data?)
50
+ // TODO(burdon): Persistent history (non-space ECHO data?)
51
51
  const [history, setHistory] = useState<Message[]>([]);
52
52
 
53
53
  const scrollerRef = useRef<HTMLDivElement>(null);
@@ -215,62 +215,55 @@ export const DebugPanel = ({ classNames, functionUrl, binding: _binding, onBindi
215
215
  );
216
216
  };
217
217
 
218
+ const RobotAvatar = () => (
219
+ <Avatar.Root size={6} variant='circle'>
220
+ <Avatar.Frame>
221
+ <Avatar.Icon icon='ph--robot--regular' />
222
+ </Avatar.Frame>
223
+ </Avatar.Root>
224
+ );
225
+
226
+ const MessageItem = ({ classNames, message }: ThemedClassName<{ message: Message }>) => {
227
+ const { text, data, error } = message;
228
+ if (error) {
229
+ return <span className={mx(classNames, 'whitespace-pre text-error')}>{String(error)}</span>;
230
+ } else if (data) {
231
+ return (
232
+ <SyntaxHighlighter language='json' className={mx('text-xs', classNames)}>
233
+ {JSON.stringify(data, null, 2)}
234
+ </SyntaxHighlighter>
235
+ );
236
+ }
237
+
238
+ return <span className={mx(classNames)}>{text || '\u00D8'}</span>;
239
+ };
240
+
218
241
  // TODO(burdon): Replace with thread?
219
242
  // TODO(burdon): Button to delete individual messages.
220
- // TODO(burdon): Button to edit/re-run question.
243
+ // TODO(burdon): Button to re-run question.
221
244
  const MessageThread = ({ state, result, history }: { state: State | null; result: string; history: Message[] }) => {
222
245
  return (
223
246
  <>
224
247
  {history.map((message, i) => (
225
- <div key={i} className='grid grid-cols-[3rem_1fr_3rem]'>
226
- <div className='p-1'>{message.type === 'response' && <RobotAvatar />}</div>
227
- <div className='overflow-auto'>
228
- <MessageItem message={message} />
248
+ <div key={i} className='grid grid-cols-[3rem_1fr]'>
249
+ <div>{message.type === 'response' && <RobotAvatar />}</div>
250
+ <div className={mx('flex', message.type === 'request' && 'justify-end')}>
251
+ <MessageItem
252
+ classNames={[message.type === 'request' && 'p-1 px-2 rounded-lg bg-hoverSurface']}
253
+ message={message}
254
+ />
229
255
  </div>
230
256
  </div>
231
257
  ))}
232
- {result?.length > 0 && (
233
- <div className='grid grid-cols-[3rem_1fr_3rem]'>
234
- <div className='p-1'>
235
- {(state === 'pending' && <Icon icon='ph--spinner--regular' size={6} classNames='animate-spin' />) || (
236
- <Icon icon='ph--robot--regular' size={6} classNames='animate-[pulse_1s_ease-in-out_infinite]' />
237
- )}
238
- </div>
239
- <div className='overflow-auto'>
240
- <MessageItem message={{ type: 'response', text: result }} />
241
- </div>
258
+ <div className='grid grid-cols-[3rem_1fr]'>
259
+ <div>
260
+ {(state === 'pending' && <Icon icon='ph--spinner--regular' size={6} classNames='animate-spin-slow' />) ||
261
+ (result.length > 0 && <RobotAvatar />)}
242
262
  </div>
243
- )}
244
- </>
245
- );
246
- };
247
-
248
- const MessageItem = ({ classNames, message }: ThemedClassName<{ message: Message }>) => {
249
- const { type, text, data, error } = message;
250
- const wrapper = 'p-1 px-2 rounded-lg bg-hoverSurface overflow-auto';
251
- return (
252
- <div className={mx('flex', type === 'request' ? 'ml-[8rem] justify-end' : 'mr-[8rem]', classNames)}>
253
- {error && <div className={mx(wrapper, 'whitespace-pre text-error')}>{String(error)}</div>}
254
-
255
- {text !== undefined && (
256
- <div className={mx(wrapper, type === 'request' && 'bg-primary-400 dark:bg-primary-600')}>
257
- {text || '\u00D8'}
263
+ <div>
264
+ <span>{result}</span>
258
265
  </div>
259
- )}
260
-
261
- {data && (
262
- <SyntaxHighlighter language='json' className={mx(wrapper, 'px-8 py-2 text-xs')}>
263
- {JSON.stringify(data, null, 2)}
264
- </SyntaxHighlighter>
265
- )}
266
- </div>
266
+ </div>
267
+ </>
267
268
  );
268
269
  };
269
-
270
- const RobotAvatar = () => (
271
- <Avatar.Root size={6} variant='circle'>
272
- <Avatar.Frame>
273
- <Avatar.Icon icon='ph--robot--regular' />
274
- </Avatar.Frame>
275
- </Avatar.Root>
276
- );
@@ -11,7 +11,7 @@ import { baseSurface, mx } from '@dxos/react-ui-theme';
11
11
  import { createProtoRpcPeer } from '@dxos/rpc';
12
12
  import { createIFramePort } from '@dxos/rpc-tunnel';
13
13
 
14
- import { type BundlerResult } from '../../bundler';
14
+ import { type BundlerResult } from '../../../bundler';
15
15
 
16
16
  export type FrameContainerProps = {
17
17
  containerUrl: string;
@@ -3,7 +3,6 @@
3
3
  //
4
4
 
5
5
  import '@dxos-theme';
6
-
7
6
  import React, { useEffect, useMemo } from 'react';
8
7
 
9
8
  import { createSpaceObjectGenerator, TestSchemaType } from '@dxos/echo-generator';
@@ -13,10 +12,10 @@ import { create, createEchoObject, useSpaces } from '@dxos/react-client/echo';
13
12
  import { withClientProvider } from '@dxos/react-client/testing';
14
13
  import { withLayout, withTheme } from '@dxos/storybook-utils';
15
14
 
15
+ // @ts-ignore
16
+ import mainUrl from './FrameContainer/frame?url';
16
17
  import { ScriptBlock } from './ScriptBlock';
17
18
  import { ScriptType } from '../../types';
18
- // @ts-ignore
19
- import mainUrl from '../FrameContainer/frame?url';
20
19
 
21
20
  const code = [
22
21
  "import { Filter, useQuery, useSpaces} from '@dxos/react-client/echo';",
@@ -65,7 +64,7 @@ const Story = () => {
65
64
  export default {
66
65
  title: 'plugin-script/ScriptBlock',
67
66
  component: ScriptBlock,
68
- decorators: [withClientProvider({ createSpace: true }), withTheme, withLayout({ fullscreen: true, tooltips: true })],
67
+ decorators: [withTheme, withLayout({ fullscreen: true, tooltips: true }), withClientProvider({ createSpace: true })],
69
68
  render: Story,
70
69
  };
71
70
 
@@ -2,17 +2,19 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
+ import { Check, Play, Warning } from '@phosphor-icons/react';
5
6
  // @ts-ignore
6
7
  import wasmUrl from 'esbuild-wasm/esbuild.wasm?url';
7
8
  import React, { useCallback, useEffect, useMemo, useState } from 'react';
8
9
 
9
10
  import { createDocAccessor, DocAccessor } from '@dxos/react-client/echo';
10
- import { DensityProvider, Toolbar, Button, Icon } from '@dxos/react-ui';
11
- import { mx } from '@dxos/react-ui-theme';
11
+ import { DensityProvider, Toolbar, Button } from '@dxos/react-ui';
12
+ import { mx, getSize } from '@dxos/react-ui-theme';
12
13
 
14
+ import { FrameContainer } from './FrameContainer';
15
+ import { Splitter, SplitterSelector, type View } from './Splitter';
13
16
  import { Bundler, type BundlerResult, initializeBundler } from '../../bundler';
14
17
  import { type ScriptType } from '../../types';
15
- import { FrameContainer } from '../FrameContainer';
16
18
  import { ScriptEditor } from '../ScriptEditor';
17
19
 
18
20
  // Keep in sync with packages/apps/composer-app/script-frame/main.tsx .
@@ -27,6 +29,7 @@ const PROVIDED_MODULES = [
27
29
 
28
30
  export type ScriptBlockProps = {
29
31
  script: ScriptType;
32
+ view?: View;
30
33
  hideSelector?: boolean;
31
34
  classes?: {
32
35
  root?: string;
@@ -41,8 +44,17 @@ export type ScriptBlockProps = {
41
44
  * @deprecated
42
45
  */
43
46
  // TODO(burdon): Cache compiled results in context.
44
- export const ScriptBlock = ({ script, hideSelector, classes, containerUrl }: ScriptBlockProps) => {
47
+ export const ScriptBlock = ({
48
+ script,
49
+ view: controlledView,
50
+ hideSelector,
51
+ classes,
52
+ containerUrl,
53
+ }: ScriptBlockProps) => {
45
54
  const source = useMemo(() => script.source && createDocAccessor(script.source, ['content']), [script.source]);
55
+ const [view, setView] = useState<View>(controlledView ?? 'editor');
56
+ useEffect(() => handleSetView(controlledView ?? 'editor'), [controlledView]);
57
+
46
58
  const [result, setResult] = useState<BundlerResult>();
47
59
  const bundler = useMemo(
48
60
  () => new Bundler({ platform: 'browser', sandboxedModules: PROVIDED_MODULES, remoteModules: {} }),
@@ -66,6 +78,16 @@ export const ScriptBlock = ({ script, hideSelector, classes, containerUrl }: Scr
66
78
  return () => clearTimeout(t);
67
79
  }, [source]);
68
80
 
81
+ const handleSetView = useCallback(
82
+ (view: View) => {
83
+ setView(view);
84
+ if (!result && view !== 'editor') {
85
+ void handleExec(false);
86
+ }
87
+ },
88
+ [result],
89
+ );
90
+
69
91
  const handleExec = useCallback(
70
92
  async (auto = true) => {
71
93
  if (!source) {
@@ -73,8 +95,11 @@ export const ScriptBlock = ({ script, hideSelector, classes, containerUrl }: Scr
73
95
  }
74
96
  const result = await bundler.bundle(DocAccessor.getValue(source));
75
97
  setResult(result);
98
+ if (auto && view === 'editor') {
99
+ setView('preview');
100
+ }
76
101
  },
77
- [source],
102
+ [source, view],
78
103
  );
79
104
 
80
105
  return (
@@ -82,28 +107,29 @@ export const ScriptBlock = ({ script, hideSelector, classes, containerUrl }: Scr
82
107
  {!hideSelector && (
83
108
  <DensityProvider density='fine'>
84
109
  <Toolbar.Root classNames={mx('mb-2', classes?.toolbar)}>
110
+ <SplitterSelector view={view} onChange={handleSetView} />
85
111
  <div className='grow' />
86
112
  {result?.bundle && !result?.error && (
87
113
  <div title={String(result.error)}>
88
- <Icon icon='ph--check--regular' size={5} classNames='text-green-500' />
114
+ <Check className={mx(getSize(5), 'text-green-500')} />
89
115
  </div>
90
116
  )}
91
117
  {result?.error && (
92
118
  <div title={String(result.error)}>
93
- <Icon icon='ph--warning--regular' size={5} classNames='text-orange-500' />
119
+ <Warning className={mx(getSize(5), 'text-orange-500')} />
94
120
  </div>
95
121
  )}
96
122
  <Button variant='ghost' onClick={() => handleExec()}>
97
- <Icon icon='ph--play--regular' size={5} />
123
+ <Play className={getSize(5)} />
98
124
  </Button>
99
125
  </Toolbar.Root>
100
126
  </DensityProvider>
101
127
  )}
102
128
 
103
- <div className='flex'>
129
+ <Splitter view={view}>
104
130
  <ScriptEditor script={script} />
105
131
  {result && <FrameContainer key={script.id} result={result} containerUrl={containerUrl} />}
106
- </div>
132
+ </Splitter>
107
133
  </div>
108
134
  );
109
135
  };
@@ -0,0 +1,37 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import '@dxos-theme';
6
+
7
+ import React, { useState } from 'react';
8
+
9
+ import { DensityProvider } from '@dxos/react-ui';
10
+
11
+ import { Splitter, SplitterSelector, type View } from './Splitter';
12
+
13
+ const Story = () => {
14
+ const [view, setView] = useState<View>();
15
+ return (
16
+ <div>
17
+ <DensityProvider density='fine'>
18
+ <SplitterSelector view={view} onChange={setView} />
19
+ </DensityProvider>
20
+ <Splitter view={view}>
21
+ <div>1</div>
22
+ <div>2</div>
23
+ </Splitter>
24
+ </div>
25
+ );
26
+ };
27
+
28
+ export default {
29
+ title: 'plugin-script/Splitter',
30
+ component: Splitter,
31
+ render: Story,
32
+ parameters: {
33
+ layout: 'fullscreen',
34
+ },
35
+ };
36
+
37
+ export const Default = {};
@@ -0,0 +1,52 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { Code, SquareSplitHorizontal, Eye } from '@phosphor-icons/react';
6
+ import React, { type ReactNode } from 'react';
7
+
8
+ import { ToggleGroup, ToggleGroupItem, Toolbar } from '@dxos/react-ui';
9
+ import { getSize, mx } from '@dxos/react-ui-theme';
10
+
11
+ export type View = 'editor' | 'preview' | 'split';
12
+
13
+ export type SplitterProps = {
14
+ view?: View;
15
+ className?: string;
16
+ children?: ReactNode[];
17
+ };
18
+
19
+ // TODO(burdon): Surfaces?
20
+ export const Splitter = ({ view = 'split', className, children = [] }: SplitterProps) => {
21
+ const [left, right] = children;
22
+ return (
23
+ <div className={mx('flex overflow-hidden grow', className)}>
24
+ {left && view !== 'preview' && <div className='flex flex-1 shrink-0 overflow-hidden'>{left}</div>}
25
+ {right && view !== 'editor' && <div className='flex flex-1 shrink-0 overflow-hidden'>{right}</div>}
26
+ </div>
27
+ );
28
+ };
29
+
30
+ export type SplitterSelectorProps = {
31
+ view?: View;
32
+ onChange?: (view: View) => void;
33
+ className?: string;
34
+ };
35
+
36
+ export const SplitterSelector = ({ view, onChange, className }: SplitterSelectorProps) => {
37
+ return (
38
+ <Toolbar.Root classNames={className}>
39
+ <ToggleGroup type='single' value={view} onValueChange={(value) => onChange?.(value as View)}>
40
+ <ToggleGroupItem value='editor'>
41
+ <Code className={getSize(5)} />
42
+ </ToggleGroupItem>
43
+ <ToggleGroupItem value='split'>
44
+ <SquareSplitHorizontal className={getSize(5)} />
45
+ </ToggleGroupItem>
46
+ <ToggleGroupItem value='preview'>
47
+ <Eye className={getSize(5)} />
48
+ </ToggleGroupItem>
49
+ </ToggleGroup>
50
+ </Toolbar.Root>
51
+ );
52
+ };
@@ -2,4 +2,4 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- export * from './Toolbar';
5
+ export * from './Splitter';