@dxos/react-ui-editor 0.3.10-main.90b298e → 0.3.10-main.92d1f2c

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 (65) hide show
  1. package/dist/lib/browser/index.mjs +897 -293
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts +19 -1
  5. package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
  6. package/dist/types/src/components/TextEditor/TextEditor.d.ts +2 -1
  7. package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
  8. package/dist/types/src/components/TextEditor/extensions/autocomplete.d.ts.map +1 -1
  9. package/dist/types/src/components/TextEditor/extensions/basic.d.ts +2 -1
  10. package/dist/types/src/components/TextEditor/extensions/basic.d.ts.map +1 -1
  11. package/dist/types/src/components/TextEditor/extensions/blast.d.ts +25 -0
  12. package/dist/types/src/components/TextEditor/extensions/blast.d.ts.map +1 -0
  13. package/dist/types/src/components/TextEditor/extensions/comments.d.ts +1 -1
  14. package/dist/types/src/components/TextEditor/extensions/comments.d.ts.map +1 -1
  15. package/dist/types/src/components/TextEditor/extensions/demo.d.ts +2 -1
  16. package/dist/types/src/components/TextEditor/extensions/demo.d.ts.map +1 -1
  17. package/dist/types/src/components/TextEditor/extensions/experimental.d.ts +1 -1
  18. package/dist/types/src/components/TextEditor/extensions/experimental.d.ts.map +1 -1
  19. package/dist/types/src/components/TextEditor/extensions/image.d.ts +4 -0
  20. package/dist/types/src/components/TextEditor/extensions/image.d.ts.map +1 -0
  21. package/dist/types/src/components/TextEditor/extensions/index.d.ts +4 -0
  22. package/dist/types/src/components/TextEditor/extensions/index.d.ts.map +1 -1
  23. package/dist/types/src/components/TextEditor/extensions/link.d.ts.map +1 -1
  24. package/dist/types/src/components/TextEditor/extensions/listener.d.ts.map +1 -1
  25. package/dist/types/src/components/TextEditor/extensions/markdown/bundle.d.ts +2 -1
  26. package/dist/types/src/components/TextEditor/extensions/markdown/bundle.d.ts.map +1 -1
  27. package/dist/types/src/components/TextEditor/extensions/markdown/highlight.d.ts +9 -3
  28. package/dist/types/src/components/TextEditor/extensions/markdown/highlight.d.ts.map +1 -1
  29. package/dist/types/src/components/TextEditor/extensions/mention.d.ts +6 -0
  30. package/dist/types/src/components/TextEditor/extensions/mention.d.ts.map +1 -0
  31. package/dist/types/src/components/TextEditor/extensions/table.d.ts +8 -0
  32. package/dist/types/src/components/TextEditor/extensions/table.d.ts.map +1 -0
  33. package/dist/types/src/components/TextEditor/extensions/tasklist.d.ts +2 -1
  34. package/dist/types/src/components/TextEditor/extensions/tasklist.d.ts.map +1 -1
  35. package/dist/types/src/components/TextEditor/themes/default.d.ts +5 -0
  36. package/dist/types/src/components/TextEditor/themes/default.d.ts.map +1 -1
  37. package/dist/types/src/hooks/automerge/automerge.stories.d.ts +8 -1
  38. package/dist/types/src/hooks/automerge/automerge.stories.d.ts.map +1 -1
  39. package/dist/types/src/{components/TextEditor → hooks/yjs}/yjs.stories.d.ts +1 -1
  40. package/dist/types/src/hooks/yjs/yjs.stories.d.ts.map +1 -0
  41. package/dist/types/src/styles/markdown.d.ts +3 -2
  42. package/dist/types/src/styles/markdown.d.ts.map +1 -1
  43. package/package.json +20 -20
  44. package/src/components/TextEditor/MarkdownEditor.stories.tsx +102 -27
  45. package/src/components/TextEditor/TextEditor.tsx +13 -23
  46. package/src/components/TextEditor/extensions/autocomplete.ts +5 -20
  47. package/src/components/TextEditor/extensions/basic.ts +2 -1
  48. package/src/components/TextEditor/extensions/blast.ts +387 -0
  49. package/src/components/TextEditor/extensions/comments.ts +21 -39
  50. package/src/components/TextEditor/extensions/demo.ts +4 -1
  51. package/src/components/TextEditor/extensions/experimental.tsx +14 -35
  52. package/src/components/TextEditor/extensions/image.ts +67 -0
  53. package/src/components/TextEditor/extensions/index.ts +4 -0
  54. package/src/components/TextEditor/extensions/link.ts +17 -25
  55. package/src/components/TextEditor/extensions/listener.ts +3 -3
  56. package/src/components/TextEditor/extensions/markdown/bundle.ts +30 -19
  57. package/src/components/TextEditor/extensions/markdown/highlight.ts +147 -108
  58. package/src/components/TextEditor/extensions/mention.ts +31 -0
  59. package/src/components/TextEditor/extensions/table.ts +122 -0
  60. package/src/components/TextEditor/extensions/tasklist.ts +41 -27
  61. package/src/components/TextEditor/themes/default.ts +54 -2
  62. package/src/hooks/automerge/automerge.stories.tsx +3 -2
  63. package/src/{components/TextEditor → hooks/yjs}/yjs.stories.tsx +1 -1
  64. package/src/styles/markdown.ts +14 -8
  65. package/dist/types/src/components/TextEditor/yjs.stories.d.ts.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/react-ui-editor",
3
- "version": "0.3.10-main.90b298e",
3
+ "version": "0.3.10-main.92d1f2c",
4
4
  "description": "Document editing experience within a DXOS shell.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -36,19 +36,19 @@
36
36
  "y-codemirror.next": "^0.3.2",
37
37
  "y-protocols": "^1.0.5",
38
38
  "yjs": "^13.6.10",
39
- "@dxos/automerge": "0.3.10-main.90b298e",
40
- "@dxos/async": "0.3.10-main.90b298e",
41
- "@dxos/display-name": "0.3.10-main.90b298e",
42
- "@dxos/debug": "0.3.10-main.90b298e",
43
- "@dxos/echo-schema": "0.3.10-main.90b298e",
44
- "@dxos/invariant": "0.3.10-main.90b298e",
45
- "@dxos/react-async": "0.3.10-main.90b298e",
46
- "@dxos/log": "0.3.10-main.90b298e",
47
- "@dxos/protocols": "0.3.10-main.90b298e",
48
- "@dxos/react-ui": "0.3.10-main.90b298e",
49
- "@dxos/react-ui-theme": "0.3.10-main.90b298e",
50
- "@dxos/text-model": "0.3.10-main.90b298e",
51
- "@dxos/util": "0.3.10-main.90b298e"
39
+ "@dxos/async": "0.3.10-main.92d1f2c",
40
+ "@dxos/debug": "0.3.10-main.92d1f2c",
41
+ "@dxos/echo-schema": "0.3.10-main.92d1f2c",
42
+ "@dxos/invariant": "0.3.10-main.92d1f2c",
43
+ "@dxos/log": "0.3.10-main.92d1f2c",
44
+ "@dxos/automerge": "0.3.10-main.92d1f2c",
45
+ "@dxos/display-name": "0.3.10-main.92d1f2c",
46
+ "@dxos/protocols": "0.3.10-main.92d1f2c",
47
+ "@dxos/react-async": "0.3.10-main.92d1f2c",
48
+ "@dxos/react-ui-theme": "0.3.10-main.92d1f2c",
49
+ "@dxos/react-ui": "0.3.10-main.92d1f2c",
50
+ "@dxos/text-model": "0.3.10-main.92d1f2c",
51
+ "@dxos/util": "0.3.10-main.92d1f2c"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@automerge/automerge-repo-network-broadcastchannel": "^1.0.19",
@@ -61,17 +61,17 @@
61
61
  "@types/react-dom": "^18.0.6",
62
62
  "react": "^18.2.0",
63
63
  "react-dom": "^18.2.0",
64
- "@dxos/config": "0.3.10-main.90b298e",
65
- "@dxos/react-client": "0.3.10-main.90b298e",
66
- "@dxos/echo-typegen": "0.3.10-main.90b298e",
67
- "@dxos/storybook-utils": "0.3.10-main.90b298e",
68
- "@dxos/react-ui": "0.3.10-main.90b298e"
64
+ "@dxos/config": "0.3.10-main.92d1f2c",
65
+ "@dxos/echo-typegen": "0.3.10-main.92d1f2c",
66
+ "@dxos/react-ui": "0.3.10-main.92d1f2c",
67
+ "@dxos/react-client": "0.3.10-main.92d1f2c",
68
+ "@dxos/storybook-utils": "0.3.10-main.92d1f2c"
69
69
  },
70
70
  "peerDependencies": {
71
71
  "@phosphor-icons/react": "^2.0.5",
72
72
  "react": "^18.2.0",
73
73
  "react-dom": "^18.2.0",
74
- "@dxos/react-client": "0.3.10-main.90b298e"
74
+ "@dxos/react-client": "0.3.10-main.92d1f2c"
75
75
  },
76
76
  "publishConfig": {
77
77
  "access": "public"
@@ -3,9 +3,11 @@
3
3
  //
4
4
 
5
5
  import '@dxosTheme';
6
+
6
7
  import { EditorView } from '@codemirror/view';
7
8
  import { faker } from '@faker-js/faker';
8
9
  import { ArrowSquareOut } from '@phosphor-icons/react';
10
+ import defaultsDeep from 'lodash.defaultsdeep';
9
11
  import React, { StrictMode, useRef, useState } from 'react';
10
12
  import { createRoot } from 'react-dom/client';
11
13
 
@@ -24,18 +26,19 @@ import {
24
26
  type TooltipOptions,
25
27
  type LinkOptions,
26
28
  comments,
29
+ table,
30
+ image,
31
+ mention,
32
+ blast,
33
+ demo,
34
+ defaultOptions,
27
35
  } from './extensions';
28
36
  import { useTextModel } from '../../hooks';
29
37
 
30
- // TODO(burdon): Read-only render mode (presentation).
31
- // TODO(burdon): Slides.
32
- // TODO(burdon): Autocomplete.
33
- // TODO(burdon): Block quote.
34
- // TODO(burdon): Images.
35
- // TODO(burdon): Tables.
36
-
37
38
  const str = (...lines: string[]) => lines.join('\n');
38
39
 
40
+ const num = () => faker.number.int({ min: 0, max: 9999 }).toLocaleString();
41
+
39
42
  // prettier-ignore
40
43
  const text = {
41
44
  tasks: str(
@@ -77,6 +80,7 @@ const text = {
77
80
  ' const x = 100;',
78
81
  ' return () => <div>Test</div>;',
79
82
  '};',
83
+ '',
80
84
  '```'
81
85
  ),
82
86
 
@@ -89,11 +93,24 @@ const text = {
89
93
  '',
90
94
  ),
91
95
 
96
+ table: str(
97
+ '# Table',
98
+ '',
99
+ `| ${faker.lorem.word()} | ${faker.lorem.word()} | ${faker.lorem.word()} |`,
100
+ '|---|---|---|',
101
+ `| ${num()} | ${num()} | ${num()} |`,
102
+ `| ${num()} | ${num()} | ${num()} |`,
103
+ `| ${num()} | ${num()} | ${num()} |`,
104
+ '', // TODO(burdon): Possible GFM parsing bug if no newline?
105
+ ),
106
+
107
+ image: str('# Image', '', '![dxos](https://pbs.twimg.com/profile_banners/1268328127673044992/1684766689/1500x500)'),
108
+
92
109
  headings: str(
93
110
  ...[1, 2, 3, 4, 5, 6].map((level) => ['#'.repeat(level) + ` Heading ${level}`, faker.lorem.sentences(), '']).flat(),
94
111
  ),
95
112
 
96
- paragraphs: str(...faker.helpers.multiple(() => [faker.lorem.paragraph(), ''], { count: 3 }).flat())
113
+ paragraphs: str(...faker.helpers.multiple(() => [faker.lorem.paragraph(), ''], { count: 3 }).flat()),
97
114
  };
98
115
 
99
116
  const document = str(
@@ -103,9 +120,7 @@ const document = str(
103
120
  '',
104
121
  'This is all about https://dxos.org and related technologies.',
105
122
  '',
106
- 'This this is **bold**, __underlined__, _italic_, and `f(INLINE)`.',
107
- '',
108
- '__NOTE__: Fenced code uses the base font.',
123
+ 'This this is **bold**, ~~strikethrough~~, _italic_, and `f(INLINE)`.',
109
124
  '',
110
125
  '---',
111
126
  text.links,
@@ -119,6 +134,11 @@ const document = str(
119
134
  text.code,
120
135
  '---',
121
136
  text.headings,
137
+ '---',
138
+ text.table,
139
+ '---',
140
+ text.image,
141
+ '',
122
142
  );
123
143
 
124
144
  const links = [
@@ -158,7 +178,7 @@ const Story = ({
158
178
  text,
159
179
  automerge,
160
180
  ...props
161
- }: { text?: string; automerge?: boolean } & Pick<TextEditorProps, 'extensions' | 'slots'>) => {
181
+ }: { text?: string; automerge?: boolean } & Pick<TextEditorProps, 'readonly' | 'extensions' | 'slots'>) => {
162
182
  const ref = useRef<TextEditorRef>(null);
163
183
  const [item] = useState({ text: new TextObject(text, undefined, undefined, { useAutomergeBackend: automerge }) });
164
184
  const model = useTextModel({ text: item.text });
@@ -185,20 +205,23 @@ export default {
185
205
  render: Story,
186
206
  };
187
207
 
208
+ const extensions = [
209
+ link({ onRender }),
210
+ tooltip({ onHover }),
211
+ tasklist(),
212
+ table(),
213
+ image(),
214
+ autocomplete({
215
+ onSearch: (text) => links.filter(({ label }) => label.toLowerCase().includes(text.toLowerCase())),
216
+ }),
217
+ ];
218
+
188
219
  export const Default = {
189
- render: () => (
190
- <Story
191
- text={document}
192
- extensions={[
193
- link({ onRender }),
194
- tooltip({ onHover }),
195
- tasklist(),
196
- autocomplete({
197
- onSearch: (text) => links.filter(({ label }) => label.toLowerCase().includes(text.toLowerCase())),
198
- }),
199
- ]}
200
- />
201
- ),
220
+ render: () => <Story text={document} extensions={extensions} />,
221
+ };
222
+
223
+ export const Readonly = {
224
+ render: () => <Story text={document} extensions={extensions} readonly />,
202
225
  };
203
226
 
204
227
  export const Simple = {
@@ -206,11 +229,19 @@ export const Simple = {
206
229
  };
207
230
 
208
231
  export const Tooltips = {
209
- render: () => <Story text={text.links} extensions={[tooltip({ onHover })]} />,
232
+ render: () => <Story text={str(text.links, '')} extensions={[tooltip({ onHover })]} />,
210
233
  };
211
234
 
212
235
  export const Links = {
213
- render: () => <Story text={text.links} extensions={[link({ onRender })]} />,
236
+ render: () => <Story text={str(text.links, '')} extensions={[link({ onRender })]} />,
237
+ };
238
+
239
+ export const Table = {
240
+ render: () => <Story text={str(text.table, '')} extensions={[table()]} />,
241
+ };
242
+
243
+ export const Image = {
244
+ render: () => <Story text={str(text.image, '', '')} readonly extensions={[image()]} />,
214
245
  };
215
246
 
216
247
  export const TaskList = {
@@ -243,6 +274,21 @@ export const Autocomplete = {
243
274
  ),
244
275
  };
245
276
 
277
+ const names = ['adam', 'alice', 'alison', 'bob', 'carol', 'charlie', 'sayuri', 'shoko'];
278
+
279
+ export const Mention = {
280
+ render: () => (
281
+ <Story
282
+ text={str('# Mention', '', '', '', '', '', '')}
283
+ extensions={[
284
+ mention({
285
+ onSearch: (text) => names.filter((name) => name.toLowerCase().startsWith(text.toLowerCase())),
286
+ }),
287
+ ]}
288
+ />
289
+ ),
290
+ };
291
+
246
292
  const mark = () => `[^${PublicKey.random().toHex()}]`;
247
293
  export const Comments = {
248
294
  render: () => (
@@ -273,3 +319,32 @@ export const Diagnostics = {
273
319
  />
274
320
  ),
275
321
  };
322
+
323
+ export const Demo = {
324
+ render: () => <Story text={text.paragraphs} extensions={[demo()]} />,
325
+ };
326
+
327
+ export const Blast = {
328
+ render: () => (
329
+ <Story
330
+ text={str(text.paragraphs, text.code, text.paragraphs)}
331
+ extensions={[
332
+ demo({
333
+ items: localStorage.getItem('dxos.composer.extension.demo')?.split(','),
334
+ }),
335
+ blast(
336
+ defaultsDeep(
337
+ {
338
+ effect: 2,
339
+ particleGravity: 0.2,
340
+ particleShrinkRate: 0.995,
341
+ color: () => [faker.number.int({ min: 100, max: 200 }), 0, 0],
342
+ // color: () => [faker.number.int(256), faker.number.int(256), faker.number.int(256)],
343
+ },
344
+ defaultOptions,
345
+ ),
346
+ ),
347
+ ]}
348
+ />
349
+ ),
350
+ };
@@ -21,7 +21,7 @@ import { generateName } from '@dxos/display-name';
21
21
  import { useThemeContext } from '@dxos/react-ui';
22
22
  import { getColorForValue, inputSurface, mx } from '@dxos/react-ui-theme';
23
23
 
24
- import { basicBundle, demo, markdownBundle } from './extensions';
24
+ import { basicBundle, markdownBundle } from './extensions';
25
25
  import { defaultTheme, markdownTheme, textTheme } from './themes';
26
26
  import { type EditorModel } from '../../hooks';
27
27
  import { type ThemeStyles } from '../../styles';
@@ -56,9 +56,10 @@ export type TextEditorSlots = {
56
56
 
57
57
  export type TextEditorProps = {
58
58
  model: EditorModel;
59
+ readonly?: boolean;
60
+ editorMode?: EditorMode;
59
61
  extensions?: Extension[];
60
62
  slots?: TextEditorSlots;
61
- editorMode?: EditorMode;
62
63
  };
63
64
 
64
65
  /**
@@ -66,7 +67,7 @@ export type TextEditorProps = {
66
67
  * NOTE: Rather than adding properties, try to create extensions that can be reused.
67
68
  */
68
69
  export const BaseTextEditor = forwardRef<TextEditorRef, TextEditorProps>(
69
- ({ model, extensions = [], slots = defaultSlots, editorMode }, forwardedRef) => {
70
+ ({ model, readonly, editorMode, extensions = [], slots = defaultSlots }, forwardedRef) => {
70
71
  const { themeMode } = useThemeContext();
71
72
  const tabsterDOMAttribute = useFocusableGroup({ tabBehavior: 'limited' });
72
73
 
@@ -95,6 +96,8 @@ export const BaseTextEditor = forwardRef<TextEditorRef, TextEditorProps>(
95
96
  const state = EditorState.create({
96
97
  doc: model.text(),
97
98
  extensions: [
99
+ readonly && EditorState.readOnly.of(readonly),
100
+
98
101
  // TODO(burdon): Factor out VIM mode?
99
102
  editorMode === 'vim' && vim(),
100
103
 
@@ -124,7 +127,7 @@ export const BaseTextEditor = forwardRef<TextEditorRef, TextEditorProps>(
124
127
  setView(undefined);
125
128
  setState(undefined);
126
129
  };
127
- }, [root, model, themeMode, editorMode]);
130
+ }, [root, model, themeMode, readonly, editorMode]);
128
131
 
129
132
  const handleKeyUp = useCallback(
130
133
  (event: KeyboardEvent) => {
@@ -157,25 +160,15 @@ export const BaseTextEditor = forwardRef<TextEditorRef, TextEditorProps>(
157
160
  },
158
161
  );
159
162
 
160
- // TODO(burdon): Allow plugins to set extensions (factory).
161
- const maybeDebug = (): Extension => {
162
- // TODO(burdon): Parse JSON script format (with key bindings?)
163
- const items = localStorage.getItem('dxos.composer.demo');
164
- if (items) {
165
- return demo({ items: items.split(',') });
166
- }
167
-
168
- return [];
169
- };
170
-
171
163
  export const TextEditor = forwardRef<TextEditorRef, TextEditorProps>(
172
- ({ extensions = [], slots: _slots, ...props }, forwardedRef) => {
164
+ ({ readonly, extensions = [], slots: _slots, ...props }, forwardedRef) => {
173
165
  const { themeMode } = useThemeContext();
174
166
  const slots = defaultsDeep({}, _slots, defaultTextSlots);
175
167
  return (
176
168
  <BaseTextEditor
177
169
  ref={forwardedRef}
178
- extensions={[basicBundle({ themeMode, placeholder: slots?.editor?.placeholder }), maybeDebug(), ...extensions]}
170
+ readonly={readonly}
171
+ extensions={[basicBundle({ readonly, themeMode, placeholder: slots?.editor?.placeholder }), ...extensions]}
179
172
  slots={slots}
180
173
  {...props}
181
174
  />
@@ -184,17 +177,14 @@ export const TextEditor = forwardRef<TextEditorRef, TextEditorProps>(
184
177
  );
185
178
 
186
179
  export const MarkdownEditor = forwardRef<TextEditorRef, TextEditorProps>(
187
- ({ extensions = [], slots: _slots, ...props }, forwardedRef) => {
180
+ ({ readonly, extensions = [], slots: _slots, ...props }, forwardedRef) => {
188
181
  const { themeMode } = useThemeContext();
189
182
  const slots = defaultsDeep({}, _slots, defaultMarkdownSlots);
190
183
  return (
191
184
  <BaseTextEditor
192
185
  ref={forwardedRef}
193
- extensions={[
194
- markdownBundle({ themeMode, placeholder: slots?.editor?.placeholder }),
195
- maybeDebug(),
196
- ...extensions,
197
- ]}
186
+ readonly={readonly}
187
+ extensions={[markdownBundle({ readonly, themeMode, placeholder: slots?.editor?.placeholder }), ...extensions]}
198
188
  slots={slots}
199
189
  {...props}
200
190
  />
@@ -2,23 +2,15 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- // TODO(burdon): Automcomplete: https://codemirror.net/5/doc/manual.html#addon_runmode
6
- // TODO(burdon): Modes: parallel parsing and decoration (e.g., associated with language).
7
- // TODO(burdon): Add-on: runmode: run lexer over content (with rendering codemirror).
8
- // https://codemirror.net/5/doc/manual.html#addon_runmode
9
- // TODO(burdon): Add-on: dialog.
10
- // TODO(burdon): Comments: https://codemirror.net/5/doc/manual.html#setBookmark
11
- // TODO(burdon): Split view: https://codemirror.net/examples/split
12
-
13
5
  // https://codemirror.net/examples/autocompletion
14
6
  // https://codemirror.net/docs/ref/#autocomplete.autocompletion
15
7
  // https://codemirror.net/docs/ref/#autocomplete.Completion
16
8
 
17
9
  import {
18
10
  autocompletion,
11
+ completionKeymap,
19
12
  type Completion,
20
13
  type CompletionContext,
21
- completionKeymap,
22
14
  type CompletionResult,
23
15
  } from '@codemirror/autocomplete';
24
16
  import { keymap } from '@codemirror/view';
@@ -51,21 +43,14 @@ export const autocomplete = ({ onSearch }: AutocompleteOptions) => {
51
43
  // TODO(burdon): Optional decoration via addToOptions
52
44
  override: [
53
45
  (context: CompletionContext): CompletionResult | null => {
54
- const word = context.matchBefore(/\w*/);
55
- if (!word || (word.from === word.to && !context.explicit)) {
46
+ const match = context.matchBefore(/\w*/);
47
+ if (!match || (match.from === match.to && !context.explicit)) {
56
48
  return null;
57
49
  }
58
50
 
59
- // TODO(burdon): Option to convert to links?
60
51
  return {
61
- from: word.from,
62
- options: onSearch(word.text.toLowerCase()),
63
- // options: [
64
- // { label: 'apple', type: 'keyword' },
65
- // { label: 'amazon', type: 'keyword' },
66
- // { label: 'hello', type: 'variable', info: '(World)' },
67
- // { label: 'magic', type: 'text', apply: '⠁⭒*.✩.*⭒⠁', detail: 'macro' },
68
- // ],
52
+ from: match.from,
53
+ options: onSearch(match.text.toLowerCase()),
69
54
  };
70
55
  },
71
56
  ],
@@ -11,11 +11,12 @@ import { EditorView, placeholder } from '@codemirror/view';
11
11
  import type { ThemeMode } from '@dxos/react-ui';
12
12
 
13
13
  export type BasicBundleOptions = {
14
+ readonly?: boolean;
14
15
  themeMode?: ThemeMode;
15
16
  placeholder?: string;
16
17
  };
17
18
 
18
- export const basicBundle = ({ themeMode, placeholder: _placeholder }: BasicBundleOptions): Extension[] =>
19
+ export const basicBundle = ({ readonly, themeMode, placeholder: _placeholder }: BasicBundleOptions): Extension[] =>
19
20
  [
20
21
  // TODO(burdon): Compare with minimalSetup.
21
22
  // https://codemirror.net/docs/ref/#codemirror.minimalSetup