@dxos/react-ui-editor 0.6.12-main.15a606f → 0.6.12-main.568932b

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 (105) hide show
  1. package/dist/lib/browser/chunk-AZWYO7TE.mjs +148 -0
  2. package/dist/lib/browser/chunk-AZWYO7TE.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +152 -269
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/state/index.mjs +17 -0
  7. package/dist/lib/browser/state/index.mjs.map +7 -0
  8. package/dist/lib/node/chunk-5RSKGJRI.cjs +169 -0
  9. package/dist/lib/node/chunk-5RSKGJRI.cjs.map +7 -0
  10. package/dist/lib/node/index.cjs +5480 -0
  11. package/dist/lib/node/index.cjs.map +7 -0
  12. package/dist/lib/node/meta.json +1 -0
  13. package/dist/lib/node/state/index.cjs +39 -0
  14. package/dist/lib/node/state/index.cjs.map +7 -0
  15. package/dist/lib/node-esm/chunk-RCIWLRIY.mjs +150 -0
  16. package/dist/lib/node-esm/chunk-RCIWLRIY.mjs.map +7 -0
  17. package/dist/lib/node-esm/index.mjs +5472 -0
  18. package/dist/lib/node-esm/index.mjs.map +7 -0
  19. package/dist/lib/node-esm/meta.json +1 -0
  20. package/dist/lib/node-esm/state/index.mjs +18 -0
  21. package/dist/lib/node-esm/state/index.mjs.map +7 -0
  22. package/dist/types/src/TextEditor.stories.d.ts +3 -0
  23. package/dist/types/src/TextEditor.stories.d.ts.map +1 -1
  24. package/dist/types/src/extensions/autocomplete.d.ts +2 -1
  25. package/dist/types/src/extensions/autocomplete.d.ts.map +1 -1
  26. package/dist/types/src/extensions/automerge/cursor.d.ts +1 -1
  27. package/dist/types/src/extensions/automerge/cursor.d.ts.map +1 -1
  28. package/dist/types/src/extensions/awareness/awareness.d.ts +2 -2
  29. package/dist/types/src/extensions/awareness/awareness.d.ts.map +1 -1
  30. package/dist/types/src/extensions/command/state.d.ts +2 -2
  31. package/dist/types/src/extensions/command/state.d.ts.map +1 -1
  32. package/dist/types/src/extensions/comments.d.ts +1 -1
  33. package/dist/types/src/extensions/comments.d.ts.map +1 -1
  34. package/dist/types/src/extensions/debug.d.ts +2 -2
  35. package/dist/types/src/extensions/debug.d.ts.map +1 -1
  36. package/dist/types/src/extensions/folding.d.ts.map +1 -1
  37. package/dist/types/src/extensions/index.d.ts +0 -4
  38. package/dist/types/src/extensions/index.d.ts.map +1 -1
  39. package/dist/types/src/extensions/markdown/decorate.d.ts.map +1 -1
  40. package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -1
  41. package/dist/types/src/extensions/markdown/link.d.ts +1 -1
  42. package/dist/types/src/extensions/markdown/link.d.ts.map +1 -1
  43. package/dist/types/src/extensions/markdown/styles.d.ts.map +1 -1
  44. package/dist/types/src/extensions/modes.d.ts +3 -3
  45. package/dist/types/src/extensions/modes.d.ts.map +1 -1
  46. package/dist/types/src/extensions/util/overlap.d.ts +1 -1
  47. package/dist/types/src/extensions/util/overlap.d.ts.map +1 -1
  48. package/dist/types/src/extensions/util/react.d.ts +1 -1
  49. package/dist/types/src/extensions/util/react.d.ts.map +1 -1
  50. package/dist/types/src/hooks/useTextEditor.d.ts +1 -1
  51. package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -1
  52. package/dist/types/src/index.d.ts +1 -0
  53. package/dist/types/src/index.d.ts.map +1 -1
  54. package/dist/types/src/{extensions → state}/cursor.d.ts +2 -2
  55. package/dist/types/src/state/cursor.d.ts.map +1 -0
  56. package/dist/types/src/state/doc.d.ts +5 -0
  57. package/dist/types/src/state/doc.d.ts.map +1 -0
  58. package/dist/types/src/state/index.d.ts +6 -0
  59. package/dist/types/src/state/index.d.ts.map +1 -0
  60. package/dist/types/src/state/state.d.ts.map +1 -0
  61. package/dist/types/src/state/types.d.ts.map +1 -0
  62. package/dist/types/src/state/util.d.ts +3 -0
  63. package/dist/types/src/state/util.d.ts.map +1 -0
  64. package/dist/types/src/styles/markdown.d.ts +1 -2
  65. package/dist/types/src/styles/markdown.d.ts.map +1 -1
  66. package/dist/types/src/styles/theme.d.ts.map +1 -1
  67. package/package.json +45 -33
  68. package/src/TextEditor.stories.tsx +9 -5
  69. package/src/extensions/annotations.ts +1 -1
  70. package/src/extensions/autocomplete.ts +9 -8
  71. package/src/extensions/automerge/automerge.stories.tsx +1 -1
  72. package/src/extensions/automerge/automerge.ts +1 -1
  73. package/src/extensions/automerge/cursor.ts +1 -1
  74. package/src/extensions/awareness/awareness.ts +3 -5
  75. package/src/extensions/command/state.ts +3 -4
  76. package/src/extensions/comments.ts +37 -43
  77. package/src/extensions/debug.ts +2 -2
  78. package/src/extensions/folding.tsx +4 -2
  79. package/src/extensions/index.ts +0 -4
  80. package/src/extensions/markdown/decorate.ts +49 -6
  81. package/src/extensions/markdown/highlight.ts +0 -5
  82. package/src/extensions/markdown/link.ts +3 -2
  83. package/src/extensions/markdown/styles.ts +10 -0
  84. package/src/extensions/markdown/table.ts +3 -3
  85. package/src/extensions/modes.ts +6 -5
  86. package/src/extensions/util/overlap.ts +1 -1
  87. package/src/extensions/util/react.tsx +5 -1
  88. package/src/hooks/useTextEditor.ts +3 -2
  89. package/src/index.ts +1 -0
  90. package/src/{extensions → state}/cursor.ts +3 -6
  91. package/src/state/doc.ts +10 -0
  92. package/src/state/index.ts +11 -0
  93. package/src/{extensions → state}/state.ts +1 -0
  94. package/src/state/util.ts +13 -0
  95. package/src/styles/markdown.ts +1 -3
  96. package/src/styles/theme.ts +2 -0
  97. package/dist/types/src/extensions/cursor.d.ts.map +0 -1
  98. package/dist/types/src/extensions/doc.d.ts +0 -6
  99. package/dist/types/src/extensions/doc.d.ts.map +0 -1
  100. package/dist/types/src/extensions/state.d.ts.map +0 -1
  101. package/dist/types/src/extensions/types.d.ts.map +0 -1
  102. package/src/extensions/doc.ts +0 -17
  103. /package/dist/types/src/{extensions → state}/state.d.ts +0 -0
  104. /package/dist/types/src/{extensions → state}/types.d.ts +0 -0
  105. /package/src/{extensions → state}/types.ts +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/react-ui-editor",
3
- "version": "0.6.12-main.15a606f",
3
+ "version": "0.6.12-main.568932b",
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",
@@ -9,7 +9,19 @@
9
9
  "exports": {
10
10
  ".": {
11
11
  "browser": "./dist/lib/browser/index.mjs",
12
+ "node": {
13
+ "require": "./dist/lib/node/index.cjs",
14
+ "default": "./dist/lib/node-esm/index.mjs"
15
+ },
12
16
  "types": "./dist/types/src/index.d.ts"
17
+ },
18
+ "./state": {
19
+ "browser": "./dist/lib/browser/state/index.mjs",
20
+ "node": {
21
+ "require": "./dist/lib/node/state/index.cjs",
22
+ "default": "./dist/lib/node-esm/state/index.mjs"
23
+ },
24
+ "types": "./dist/types/src/state/index.d.ts"
13
25
  }
14
26
  },
15
27
  "types": "dist/types/src/index.d.ts",
@@ -21,24 +33,24 @@
21
33
  "src"
22
34
  ],
23
35
  "dependencies": {
24
- "@codemirror/autocomplete": "^6.18.0",
25
- "@codemirror/commands": "^6.6.0",
36
+ "@codemirror/autocomplete": "^6.18.1",
37
+ "@codemirror/commands": "^6.6.2",
26
38
  "@codemirror/lang-javascript": "^6.2.2",
27
- "@codemirror/lang-markdown": "^6.2.5",
28
- "@codemirror/language": "^6.10.2",
39
+ "@codemirror/lang-markdown": "^6.3.0",
40
+ "@codemirror/language": "^6.10.3",
29
41
  "@codemirror/language-data": "^6.5.1",
30
- "@codemirror/lint": "^6.8.1",
42
+ "@codemirror/lint": "^6.8.2",
31
43
  "@codemirror/search": "^6.5.6",
32
44
  "@codemirror/state": "^6.4.1",
33
45
  "@codemirror/theme-one-dark": "^6.1.2",
34
- "@codemirror/view": "^6.29.1",
46
+ "@codemirror/view": "^6.34.1",
35
47
  "@fluentui/react-tabster": "^9.19.0",
36
- "@lezer/common": "^1.2.1",
48
+ "@lezer/common": "^1.2.2",
37
49
  "@lezer/generator": "^1.7.1",
38
- "@lezer/highlight": "^1.2.0",
39
- "@lezer/markdown": "^1.3.0",
50
+ "@lezer/highlight": "^1.2.1",
51
+ "@lezer/markdown": "^1.3.1",
40
52
  "@radix-ui/react-context": "^1.0.0",
41
- "@replit/codemirror-vim": "^6.0.14",
53
+ "@replit/codemirror-vim": "^6.2.1",
42
54
  "@replit/codemirror-vscode-keymap": "^6.0.2",
43
55
  "codemirror": "^6.0.1",
44
56
  "lib0": "^0.2.65",
@@ -48,19 +60,19 @@
48
60
  "lodash.sortby": "^4.7.0",
49
61
  "react-dropzone": "^14.2.3",
50
62
  "style-mod": "^4.1.0",
51
- "@dxos/async": "0.6.12-main.15a606f",
52
- "@dxos/context": "0.6.12-main.15a606f",
53
- "@dxos/debug": "0.6.12-main.15a606f",
54
- "@dxos/automerge": "0.6.12-main.15a606f",
55
- "@dxos/display-name": "0.6.12-main.15a606f",
56
- "@dxos/log": "0.6.12-main.15a606f",
57
- "@dxos/echo-schema": "0.6.12-main.15a606f",
58
- "@dxos/invariant": "0.6.12-main.15a606f",
59
- "@dxos/protocols": "0.6.12-main.15a606f",
60
- "@dxos/react-ui-theme": "0.6.12-main.15a606f",
61
- "@dxos/react-hooks": "0.6.12-main.15a606f",
62
- "@dxos/util": "0.6.12-main.15a606f",
63
- "@dxos/react-ui": "0.6.12-main.15a606f"
63
+ "@dxos/async": "0.6.12-main.568932b",
64
+ "@dxos/automerge": "0.6.12-main.568932b",
65
+ "@dxos/debug": "0.6.12-main.568932b",
66
+ "@dxos/context": "0.6.12-main.568932b",
67
+ "@dxos/display-name": "0.6.12-main.568932b",
68
+ "@dxos/invariant": "0.6.12-main.568932b",
69
+ "@dxos/echo-schema": "0.6.12-main.568932b",
70
+ "@dxos/log": "0.6.12-main.568932b",
71
+ "@dxos/protocols": "0.6.12-main.568932b",
72
+ "@dxos/react-hooks": "0.6.12-main.568932b",
73
+ "@dxos/react-ui-theme": "0.6.12-main.568932b",
74
+ "@dxos/react-ui": "0.6.12-main.568932b",
75
+ "@dxos/util": "0.6.12-main.568932b"
64
76
  },
65
77
  "devDependencies": {
66
78
  "@phosphor-icons/react": "^2.1.5",
@@ -88,20 +100,20 @@
88
100
  "vite": "5.4.7",
89
101
  "vite-plugin-top-level-await": "^1.4.1",
90
102
  "vite-plugin-wasm": "^3.3.0",
91
- "@dxos/automerge": "0.6.12-main.15a606f",
92
- "@dxos/config": "0.6.12-main.15a606f",
93
- "@dxos/echo-signals": "0.6.12-main.15a606f",
94
- "@dxos/keyboard": "0.6.12-main.15a606f",
95
- "@dxos/random": "0.6.12-main.15a606f",
96
- "@dxos/react-client": "0.6.12-main.15a606f",
97
- "@dxos/storybook-utils": "0.6.12-main.15a606f",
98
- "@dxos/react-ui": "0.6.12-main.15a606f"
103
+ "@dxos/automerge": "0.6.12-main.568932b",
104
+ "@dxos/config": "0.6.12-main.568932b",
105
+ "@dxos/echo-signals": "0.6.12-main.568932b",
106
+ "@dxos/keyboard": "0.6.12-main.568932b",
107
+ "@dxos/random": "0.6.12-main.568932b",
108
+ "@dxos/react-client": "0.6.12-main.568932b",
109
+ "@dxos/storybook-utils": "0.6.12-main.568932b",
110
+ "@dxos/react-ui": "0.6.12-main.568932b"
99
111
  },
100
112
  "peerDependencies": {
101
113
  "@phosphor-icons/react": "^2.1.5",
102
114
  "react": "~18.2.0",
103
115
  "react-dom": "~18.2.0",
104
- "@dxos/react-client": "0.6.12-main.15a606f"
116
+ "@dxos/react-client": "0.6.12-main.568932b"
105
117
  },
106
118
  "publishConfig": {
107
119
  "access": "public"
@@ -47,18 +47,16 @@ import {
47
47
  linkTooltip,
48
48
  listener,
49
49
  mention,
50
- state,
51
50
  table,
52
51
  typewriter,
53
52
  type CommandAction,
54
- type Comment,
55
53
  type CommentsOptions,
56
- type EditorSelectionState,
57
54
  debugTree,
58
55
  type DebugNode,
59
56
  } from './extensions';
60
57
  import { renderRoot } from './extensions/util';
61
58
  import { useTextEditor, type UseTextEditorProps } from './hooks';
59
+ import { type Comment, type EditorSelectionState, state } from './state';
62
60
  import translations from './translations';
63
61
 
64
62
  faker.seed(101);
@@ -165,8 +163,8 @@ const content = {
165
163
  '> This is a long wrapping block quote. Neque reiciendis ullam quae error labore sit, at, et, nulla, aut at nostrum omnis quas nostrum, at consectetur vitae eos asperiores non omnis ullam in beatae at vitae deserunt asperiores sapiente.',
166
164
  '',
167
165
  '> This is ...',
168
- '> ... a multi-line ...',
169
- '> block quote.',
166
+ '... a multi-line ...',
167
+ 'block quote.',
170
168
  '',
171
169
  ),
172
170
 
@@ -453,6 +451,12 @@ export const ScrollTo = {
453
451
  // Markdown
454
452
  //
455
453
 
454
+ export const Blockquote = {
455
+ render: () => (
456
+ <Story text={str('> Blockquote', 'continuation', content.footer)} extensions={decorateMarkdown()} debug='raw' />
457
+ ),
458
+ };
459
+
456
460
  export const Headings = {
457
461
  render: () => <Story text={headings} extensions={decorateMarkdown({ numberedHeadings: { from: 2, to: 4 } })} />,
458
462
  };
@@ -7,7 +7,7 @@ import { Decoration, EditorView } from '@codemirror/view';
7
7
 
8
8
  import { isNotFalsy } from '@dxos/util';
9
9
 
10
- import { Cursor } from './cursor';
10
+ import { Cursor } from '../state';
11
11
 
12
12
  type Annotation = {
13
13
  cursor: string;
@@ -2,10 +2,6 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- // https://codemirror.net/examples/autocompletion
6
- // https://codemirror.net/docs/ref/#autocomplete.autocompletion
7
- // https://codemirror.net/docs/ref/#autocomplete.Completion
8
-
9
5
  import {
10
6
  autocompletion,
11
7
  completionKeymap,
@@ -15,6 +11,7 @@ import {
15
11
  type CompletionResult,
16
12
  } from '@codemirror/autocomplete';
17
13
  import { markdownLanguage } from '@codemirror/lang-markdown';
14
+ import { type Extension } from '@codemirror/state';
18
15
  import { keymap } from '@codemirror/view';
19
16
 
20
17
  export type AutocompleteResult = Completion;
@@ -25,11 +22,15 @@ export type AutocompleteOptions = {
25
22
  onSearch?: (text: string) => Completion[];
26
23
  };
27
24
 
25
+ // https://codemirror.net/examples/autocompletion
26
+ // https://codemirror.net/docs/ref/#autocomplete.autocompletion
27
+ // https://codemirror.net/docs/ref/#autocomplete.Completion
28
+
28
29
  /**
29
30
  * Autocomplete extension.
30
31
  */
31
- export const autocomplete = ({ activateOnTyping, override, onSearch }: AutocompleteOptions = {}) => {
32
- const extentions = [
32
+ export const autocomplete = ({ activateOnTyping, override, onSearch }: AutocompleteOptions = {}): Extension => {
33
+ const extensions: Extension[] = [
33
34
  // https://codemirror.net/docs/ref/#view.keymap
34
35
  // https://discuss.codemirror.net/t/how-can-i-replace-the-default-autocompletion-keymap-v6/3322
35
36
  // TODO(burdon): Set custom keymap.
@@ -50,7 +51,7 @@ export const autocomplete = ({ activateOnTyping, override, onSearch }: Autocompl
50
51
  ];
51
52
 
52
53
  if (onSearch) {
53
- extentions.push(
54
+ extensions.push(
54
55
  // TODO(burdon): Optional decoration via addToOptions
55
56
  markdownLanguage.data.of({
56
57
  autocomplete: (context: CompletionContext): CompletionResult | null => {
@@ -68,5 +69,5 @@ export const autocomplete = ({ activateOnTyping, override, onSearch }: Autocompl
68
69
  );
69
70
  }
70
71
 
71
- return extentions;
72
+ return extensions;
72
73
  };
@@ -129,7 +129,7 @@ export const WithEcho = {
129
129
  count={2}
130
130
  component={EchoStory}
131
131
  createSpace
132
- onCreateSpace={async (space) => {
132
+ onSpaceCreated={async ({ space }) => {
133
133
  space.db.add(
134
134
  create({
135
135
  type: 'test',
@@ -13,7 +13,7 @@ import { type DocAccessor } from '@dxos/react-client/echo';
13
13
  import { cursorConverter } from './cursor';
14
14
  import { updateHeadsEffect, isReconcile, type State } from './defs';
15
15
  import { Syncer } from './sync';
16
- import { Cursor } from '../cursor';
16
+ import { Cursor } from '../../state';
17
17
 
18
18
  export const automerge = (accessor: DocAccessor): Extension => {
19
19
  const syncState = StateField.define<State>({
@@ -5,7 +5,7 @@
5
5
  import { log } from '@dxos/log';
6
6
  import { type DocAccessor, fromCursor, toCursor } from '@dxos/react-client/echo';
7
7
 
8
- import { type CursorConverter } from '../cursor';
8
+ import { type CursorConverter } from '../../state';
9
9
 
10
10
  export const cursorConverter = (accessor: DocAccessor): CursorConverter => ({
11
11
  toCursor: (pos, assoc) => {
@@ -2,7 +2,7 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { Annotation, Facet, type Extension, RangeSet, type Range } from '@codemirror/state';
5
+ import { Annotation, type Extension, RangeSet, type Range } from '@codemirror/state';
6
6
  import {
7
7
  Decoration,
8
8
  type DecorationSet,
@@ -16,7 +16,7 @@ import {
16
16
  import { Event } from '@dxos/async';
17
17
  import { Context } from '@dxos/context';
18
18
 
19
- import { Cursor, type CursorConverter } from '../cursor';
19
+ import { singleValueFacet, Cursor, type CursorConverter } from '../../state';
20
20
 
21
21
  export interface AwarenessProvider {
22
22
  remoteStateChange: Event<void>;
@@ -38,9 +38,7 @@ const dummyProvider: AwarenessProvider = {
38
38
  update: () => {},
39
39
  };
40
40
 
41
- export const awarenessProvider = Facet.define<AwarenessProvider, AwarenessProvider>({
42
- combine: (providers) => providers[0] ?? dummyProvider,
43
- });
41
+ export const awarenessProvider = singleValueFacet<AwarenessProvider>(dummyProvider);
44
42
 
45
43
  // TODO(dmaretskyi): Specify the users that actually changed. Currently, we recalculate positions for every user.
46
44
  const RemoteSelectionChangedAnnotation = Annotation.define();
@@ -2,7 +2,7 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { Facet, StateEffect, StateField } from '@codemirror/state';
5
+ import { StateEffect, StateField } from '@codemirror/state';
6
6
  import {
7
7
  type Command,
8
8
  type EditorView,
@@ -13,14 +13,13 @@ import {
13
13
  } from '@codemirror/view';
14
14
 
15
15
  import { type CommandOptions } from './command';
16
+ import { singleValueFacet } from '../../state';
16
17
 
17
18
  type CommandState = {
18
19
  tooltip?: Tooltip | null;
19
20
  };
20
21
 
21
- export const commandConfig = Facet.define<CommandOptions, Required<CommandOptions>>({
22
- combine: (providers) => providers[0],
23
- });
22
+ export const commandConfig = singleValueFacet<CommandOptions>();
24
23
 
25
24
  export const commandState = StateField.define<CommandState>({
26
25
  create: () => ({}),
@@ -5,7 +5,6 @@
5
5
  import { invertedEffects } from '@codemirror/commands';
6
6
  import {
7
7
  type Extension,
8
- Facet,
9
8
  StateEffect,
10
9
  StateField,
11
10
  type Text,
@@ -29,18 +28,15 @@ import { debounce, type UnsubscribeCallback } from '@dxos/async';
29
28
  import { log } from '@dxos/log';
30
29
  import { nonNullable } from '@dxos/util';
31
30
 
32
- import { Cursor } from './cursor';
33
- import { type Comment, type Range } from './types';
34
31
  import { overlap } from './util';
32
+ import { Cursor, documentId, singleValueFacet } from '../state';
33
+ import { type Comment, type Range } from '../state';
35
34
  import { callbackWrapper } from '../util';
36
35
 
37
36
  //
38
37
  // State management.
39
38
  //
40
39
 
41
- // TODO(wittjosiah): Factor out, not comments-specific.
42
- const documentId = Facet.define<string | undefined, string | undefined>({ combine: (values) => values[0] });
43
-
44
40
  type CommentState = {
45
41
  comment: Comment;
46
42
  range: Range;
@@ -369,7 +365,7 @@ export type CommentsOptions = {
369
365
  onHover?: (el: Element, shortcut: string) => void;
370
366
  };
371
367
 
372
- const optionsFacet = Facet.define<CommentsOptions, CommentsOptions>({ combine: (providers) => providers[0] });
368
+ const optionsFacet = singleValueFacet<CommentsOptions>();
373
369
 
374
370
  /**
375
371
  * Comment threads.
@@ -389,7 +385,7 @@ export const comments = (options: CommentsOptions = {}): Extension => {
389
385
 
390
386
  return [
391
387
  optionsFacet.of(options),
392
- documentId.of(options.id),
388
+ options.id ? documentId.of(options.id) : undefined,
393
389
  commentsState,
394
390
  commentsDecorations,
395
391
  handleCommentClick,
@@ -398,45 +394,43 @@ export const comments = (options: CommentsOptions = {}): Extension => {
398
394
  //
399
395
  // Keymap.
400
396
  //
401
- options.onCreate
402
- ? keymap.of([
403
- {
404
- key: shortcut,
405
- run: callbackWrapper(createComment),
406
- },
407
- ])
408
- : [],
397
+ options.onCreate &&
398
+ keymap.of([
399
+ {
400
+ key: shortcut,
401
+ run: callbackWrapper(createComment),
402
+ },
403
+ ]),
409
404
 
410
405
  //
411
406
  // Hover tooltip (for key shortcut hints, etc.)
412
407
  // TODO(burdon): Factor out to generic hints extension for current selection/line.
413
408
  //
414
- options.onHover
415
- ? hoverTooltip(
416
- (view, pos) => {
417
- const selection = view.state.selection.main;
418
- if (selection && pos >= selection.from && pos <= selection.to) {
419
- return {
420
- pos: selection.from,
421
- end: selection.to,
422
- above: true,
423
- create: () => {
424
- const el = document.createElement('div');
425
- options.onHover!(el, shortcut);
426
- return { dom: el, offset: { x: 0, y: 8 } };
427
- },
428
- };
429
- }
409
+ options.onHover &&
410
+ hoverTooltip(
411
+ (view, pos) => {
412
+ const selection = view.state.selection.main;
413
+ if (selection && pos >= selection.from && pos <= selection.to) {
414
+ return {
415
+ pos: selection.from,
416
+ end: selection.to,
417
+ above: true,
418
+ create: () => {
419
+ const el = document.createElement('div');
420
+ options.onHover!(el, shortcut);
421
+ return { dom: el, offset: { x: 0, y: 8 } };
422
+ },
423
+ };
424
+ }
430
425
 
431
- return null;
432
- },
433
- {
434
- // TODO(burdon): Hide on change triggered immediately?
435
- // hideOnChange: true,
436
- hoverTime: 1_000,
437
- },
438
- )
439
- : [],
426
+ return null;
427
+ },
428
+ {
429
+ // TODO(burdon): Hide on change triggered immediately?
430
+ // hideOnChange: true,
431
+ hoverTime: 1_000,
432
+ },
433
+ ),
440
434
 
441
435
  //
442
436
  // Track deleted ranges and update ranges for decorations.
@@ -511,8 +505,8 @@ export const comments = (options: CommentsOptions = {}): Extension => {
511
505
  }
512
506
  }),
513
507
 
514
- options.onUpdate ? trackPastedComments(options.onUpdate) : [],
515
- ];
508
+ options.onUpdate && trackPastedComments(options.onUpdate),
509
+ ].filter(nonNullable);
516
510
  };
517
511
 
518
512
  //
@@ -3,10 +3,10 @@
3
3
  //
4
4
 
5
5
  import { syntaxTree } from '@codemirror/language';
6
- import { type EditorState, type RangeSet, StateField, type Transaction } from '@codemirror/state';
6
+ import { type EditorState, type Extension, type RangeSet, StateField, type Transaction } from '@codemirror/state';
7
7
 
8
8
  // eslint-disable-next-line no-console
9
- export const debugNodeLogger = (log: (...args: any[]) => void = console.log) => {
9
+ export const debugNodeLogger = (log: (...args: any[]) => void = console.log): Extension => {
10
10
  const logTokens = (state: EditorState) => syntaxTree(state).iterate({ enter: (node) => log(node.type) });
11
11
  return StateField.define<any>({
12
12
  create: (state) => logTokens(state),
@@ -17,7 +17,7 @@ export type FoldingOptions = {};
17
17
  /**
18
18
  * https://codemirror.net/examples/gutter
19
19
  */
20
- // TODO(burdon): Remember folding state.
20
+ // TODO(burdon): Remember folding state (to state).
21
21
  export const folding = (_props: FoldingOptions = {}): Extension => [
22
22
  codeFolding({
23
23
  placeholderDOM: () => {
@@ -26,8 +26,10 @@ export const folding = (_props: FoldingOptions = {}): Extension => [
26
26
  }),
27
27
  foldGutter({
28
28
  markerDOM: (open) => {
29
+ // TODO(burdon): Use sprite directly.
30
+ const el = createElement('div', { className: 'flex h-full items-center' });
29
31
  return renderRoot(
30
- createElement('div', { className: 'flex h-full items-center' }),
32
+ el,
31
33
  <Icon icon='ph--caret-right--regular' classNames={[getSize(3), 'mx-3 cursor-pointer', open && 'rotate-90']} />,
32
34
  );
33
35
  },
@@ -9,9 +9,7 @@ export * from './awareness';
9
9
  export * from './blast';
10
10
  export * from './command';
11
11
  export * from './comments';
12
- export * from './cursor';
13
12
  export * from './debug';
14
- export * from './doc';
15
13
  export * from './dnd';
16
14
  export * from './factories';
17
15
  export * from './folding';
@@ -19,6 +17,4 @@ export * from './listener';
19
17
  export * from './markdown';
20
18
  export * from './mention';
21
19
  export * from './modes';
22
- export * from './state';
23
- export * from './types';
24
20
  export * from './typewriter';
@@ -45,7 +45,7 @@ class HorizontalRuleWidget extends WidgetType {
45
45
  class LinkButton extends WidgetType {
46
46
  constructor(
47
47
  private readonly url: string,
48
- private readonly render: (el: Element, url: string) => void,
48
+ private readonly render: (el: HTMLElement, url: string) => void,
49
49
  ) {
50
50
  super();
51
51
  }
@@ -54,6 +54,7 @@ class LinkButton extends WidgetType {
54
54
  return this.url === other.url;
55
55
  }
56
56
 
57
+ // TODO(burdon): Create icon and link directly without react?
57
58
  override toDOM(view: EditorView) {
58
59
  const el = document.createElement('span');
59
60
  this.render(el, this.url);
@@ -127,6 +128,7 @@ class TextWidget extends WidgetType {
127
128
  }
128
129
 
129
130
  const hide = Decoration.replace({});
131
+ const blockQuote = Decoration.line({ class: mx('cm-blockquote') });
130
132
  const fencedCodeLine = Decoration.line({ class: mx('cm-code cm-codeblock-line') });
131
133
  const fencedCodeLineFirst = Decoration.line({ class: mx('cm-code cm-codeblock-line', 'cm-codeblock-first') });
132
134
  const fencedCodeLineLast = Decoration.line({ class: mx('cm-code cm-codeblock-line', 'cm-codeblock-last') });
@@ -199,7 +201,7 @@ const buildDecorations = (view: EditorView, options: DecorateOptions, focus: boo
199
201
  return listLevels[listLevels.length - 1];
200
202
  };
201
203
 
202
- // const count = 0;
204
+ // let count = 0;
203
205
  const enterNode = (node: SyntaxNodeRef) => {
204
206
  // console.log(`[${count++}]`, { node: node.name, from: node.from, to: node.to });
205
207
  switch (node.name) {
@@ -329,7 +331,36 @@ const buildDecorations = (view: EditorView, options: DecorateOptions, focus: boo
329
331
  break;
330
332
  }
331
333
 
334
+ //
335
+ // Blockquote > QuoteMark > Paragraph
336
+ //
337
+
338
+ case 'Blockquote': {
339
+ const editing = editingRange(state, node, focus);
340
+ const quoteMark = node.node.getChild('QuoteMark');
341
+ const paragraph = node.node.getChild('Paragraph');
342
+ if (!editing && quoteMark && paragraph) {
343
+ atomicDeco.add(quoteMark.from, paragraph.from, hide);
344
+ }
345
+
346
+ for (const block of view.viewportLineBlocks) {
347
+ if (block.to < node.from) {
348
+ continue;
349
+ }
350
+ if (block.from > node.to) {
351
+ break;
352
+ }
353
+
354
+ deco.add(block.from, block.from, blockQuote);
355
+ }
356
+
357
+ break;
358
+ }
359
+
360
+ //
332
361
  // CommentBlock
362
+ //
363
+
333
364
  case 'CommentBlock': {
334
365
  const editing = editingRange(state, node, focus);
335
366
  for (const block of view.viewportLineBlocks) {
@@ -339,21 +370,27 @@ const buildDecorations = (view: EditorView, options: DecorateOptions, focus: boo
339
370
  if (block.from > node.to) {
340
371
  break;
341
372
  }
342
- const first = block.from <= node.from;
343
- const last = block.to >= node.to && /^(\s>)*-->$/.test(state.doc.sliceString(block.from, block.to));
373
+
374
+ const isFirst = block.from <= node.from;
375
+ const isLast = block.to >= node.to && /^(\s>)*-->$/.test(state.doc.sliceString(block.from, block.to));
376
+
344
377
  deco.add(
345
378
  block.from,
346
379
  block.from,
347
- first ? commentBlockLineFirst : last ? commentBlockLineLast : commentBlockLine,
380
+ isFirst ? commentBlockLineFirst : isLast ? commentBlockLineLast : commentBlockLine,
348
381
  );
349
- if (!editing && (first || last)) {
382
+
383
+ if (!editing && (isFirst || isLast)) {
350
384
  atomicDeco.add(block.from, block.to, hide);
351
385
  }
352
386
  }
353
387
  break;
354
388
  }
355
389
 
390
+ //
356
391
  // FencedCode > CodeMark > [CodeInfo] > CodeText > CodeMark
392
+ //
393
+
357
394
  case 'FencedCode': {
358
395
  for (const block of view.viewportLineBlocks) {
359
396
  if (block.to < node.from) {
@@ -375,7 +412,10 @@ const buildDecorations = (view: EditorView, options: DecorateOptions, focus: boo
375
412
  return false;
376
413
  }
377
414
 
415
+ //
378
416
  // Link > [LinkMark, URL]
417
+ //
418
+
379
419
  case 'Link': {
380
420
  const marks = node.node.getChildren('LinkMark');
381
421
  const urlNode = node.node.getChild('URL');
@@ -412,7 +452,10 @@ const buildDecorations = (view: EditorView, options: DecorateOptions, focus: boo
412
452
  break;
413
453
  }
414
454
 
455
+ //
415
456
  // HR
457
+ //
458
+
416
459
  case 'HorizontalRule': {
417
460
  if (!editingRange(state, node, focus)) {
418
461
  deco.add(node.from, node.to, horizontalRule);
@@ -168,11 +168,6 @@ export const markdownHighlightStyle = (_options: HighlightOptions = {}) => {
168
168
  class: theme.code,
169
169
  },
170
170
 
171
- {
172
- tag: [markdownTags.QuoteMark],
173
- class: theme.blockquote,
174
- },
175
-
176
171
  {
177
172
  tag: [markdownTags.TableCell],
178
173
  class: 'font-mono',
@@ -9,8 +9,8 @@ import { type SyntaxNode } from '@lezer/common';
9
9
 
10
10
  import { tooltipContent } from '@dxos/react-ui-theme';
11
11
 
12
- export const linkTooltip = (render: (el: Element, url: string) => void) =>
13
- hoverTooltip((view, pos, side) => {
12
+ export const linkTooltip = (render: (el: HTMLElement, url: string) => void) => {
13
+ return hoverTooltip((view, pos, side) => {
14
14
  const syntax = syntaxTree(view.state).resolveInner(pos, side);
15
15
  let link = null;
16
16
  for (let i = 0, node: SyntaxNode | null = syntax; !link && node && i < 5; node = node.parent, i++) {
@@ -35,3 +35,4 @@ export const linkTooltip = (render: (el: Element, url: string) => void) =>
35
35
  },
36
36
  };
37
37
  });
38
+ };