@dxos/react-ui-editor 0.3.10 → 0.3.11-main.00a28cb

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 (222) hide show
  1. package/dist/lib/browser/index.mjs +1724 -1105
  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 +24 -13
  5. package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
  6. package/dist/types/src/components/TextEditor/TextEditor.d.ts +15 -19
  7. package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
  8. package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +6 -3
  9. package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
  10. package/dist/types/src/{hooks/automerge → components/TextEditor}/automerge.stories.d.ts +6 -2
  11. package/dist/types/src/components/TextEditor/automerge.stories.d.ts.map +1 -0
  12. package/dist/types/src/components/TextEditor/codemirror.stories.d.ts.map +1 -1
  13. package/dist/types/src/components/TextEditor/comments.stories.d.ts +26 -0
  14. package/dist/types/src/components/TextEditor/comments.stories.d.ts.map +1 -0
  15. package/dist/types/src/components/TextEditor/index.d.ts +0 -2
  16. package/dist/types/src/components/TextEditor/index.d.ts.map +1 -1
  17. package/dist/types/src/{hooks/yjs → components/TextEditor}/yjs.stories.d.ts +1 -1
  18. package/dist/types/src/components/TextEditor/yjs.stories.d.ts.map +1 -0
  19. package/dist/types/src/extensions/autocomplete.d.ts.map +1 -0
  20. package/dist/types/src/extensions/automerge/automerge.d.ts +9 -0
  21. package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -0
  22. package/dist/types/src/extensions/automerge/cursor.d.ts +5 -0
  23. package/dist/types/src/extensions/automerge/cursor.d.ts.map +1 -0
  24. package/dist/types/src/extensions/automerge/defs.d.ts +26 -0
  25. package/dist/types/src/extensions/automerge/defs.d.ts.map +1 -0
  26. package/dist/types/src/extensions/automerge/index.d.ts +3 -0
  27. package/dist/types/src/extensions/automerge/index.d.ts.map +1 -0
  28. package/dist/types/src/extensions/automerge/semaphore.d.ts +14 -0
  29. package/dist/types/src/extensions/automerge/semaphore.d.ts.map +1 -0
  30. package/dist/types/src/extensions/automerge/update-automerge.d.ts +5 -0
  31. package/dist/types/src/extensions/automerge/update-automerge.d.ts.map +1 -0
  32. package/dist/types/src/extensions/automerge/update-codemirror.d.ts +5 -0
  33. package/dist/types/src/extensions/automerge/update-codemirror.d.ts.map +1 -0
  34. package/dist/types/src/extensions/awareness.d.ts +46 -0
  35. package/dist/types/src/extensions/awareness.d.ts.map +1 -0
  36. package/dist/types/src/extensions/basic.d.ts.map +1 -0
  37. package/dist/types/src/extensions/blast.d.ts.map +1 -0
  38. package/dist/types/src/extensions/code.d.ts.map +1 -0
  39. package/dist/types/src/extensions/comments.d.ts +59 -0
  40. package/dist/types/src/extensions/comments.d.ts.map +1 -0
  41. package/dist/types/src/extensions/cursor.d.ts +25 -0
  42. package/dist/types/src/extensions/cursor.d.ts.map +1 -0
  43. package/dist/types/src/extensions/hr.d.ts +2 -0
  44. package/dist/types/src/extensions/hr.d.ts.map +1 -0
  45. package/dist/types/src/extensions/image.d.ts.map +1 -0
  46. package/dist/types/src/{components/TextEditor/extensions → extensions}/index.d.ts +7 -3
  47. package/dist/types/src/extensions/index.d.ts.map +1 -0
  48. package/dist/types/src/{components/TextEditor/extensions → extensions}/link.d.ts +1 -0
  49. package/dist/types/src/extensions/link.d.ts.map +1 -0
  50. package/dist/types/src/extensions/listener.d.ts +10 -0
  51. package/dist/types/src/extensions/listener.d.ts.map +1 -0
  52. package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -0
  53. package/dist/types/src/{components/TextEditor/extensions → extensions}/markdown/highlight.d.ts +0 -1
  54. package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -0
  55. package/dist/types/src/extensions/markdown/index.d.ts.map +1 -0
  56. package/dist/types/src/extensions/mention.d.ts.map +1 -0
  57. package/dist/types/src/extensions/outliner.d.ts +4 -0
  58. package/dist/types/src/extensions/outliner.d.ts.map +1 -0
  59. package/dist/types/src/extensions/table.d.ts.map +1 -0
  60. package/dist/types/src/extensions/tasklist.d.ts +7 -0
  61. package/dist/types/src/extensions/tasklist.d.ts.map +1 -0
  62. package/dist/types/src/{components/TextEditor/extensions/demo.d.ts → extensions/typewriter.d.ts} +2 -3
  63. package/dist/types/src/extensions/typewriter.d.ts.map +1 -0
  64. package/dist/types/src/extensions/yjs/cursor.d.ts +4 -0
  65. package/dist/types/src/extensions/yjs/cursor.d.ts.map +1 -0
  66. package/dist/types/src/extensions/yjs/index.d.ts +2 -0
  67. package/dist/types/src/extensions/yjs/index.d.ts.map +1 -0
  68. package/dist/types/src/extensions/yjs/yjs.d.ts +4 -0
  69. package/dist/types/src/extensions/yjs/yjs.d.ts.map +1 -0
  70. package/dist/types/src/extensions/yjs/yjs.test.d.ts +2 -0
  71. package/dist/types/src/extensions/yjs/yjs.test.d.ts.map +1 -0
  72. package/dist/types/src/hooks/automerge.d.ts +3 -0
  73. package/dist/types/src/hooks/automerge.d.ts.map +1 -0
  74. package/dist/types/src/hooks/awareness-provider.d.ts +28 -0
  75. package/dist/types/src/hooks/awareness-provider.d.ts.map +1 -0
  76. package/dist/types/src/hooks/index.d.ts +3 -1
  77. package/dist/types/src/hooks/index.d.ts.map +1 -1
  78. package/dist/types/src/hooks/useTextModel.d.ts +15 -11
  79. package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
  80. package/dist/types/src/hooks/{yjs/space-provider.d.ts → yjs.d.ts} +8 -8
  81. package/dist/types/src/hooks/yjs.d.ts.map +1 -0
  82. package/dist/types/src/index.d.ts +6 -0
  83. package/dist/types/src/index.d.ts.map +1 -1
  84. package/dist/types/src/styles/cursors.d.ts.map +1 -0
  85. package/dist/types/src/styles/index.d.ts +1 -0
  86. package/dist/types/src/styles/index.d.ts.map +1 -1
  87. package/dist/types/src/styles/markdown.d.ts.map +1 -1
  88. package/dist/types/src/styles/tokens.d.ts +1 -0
  89. package/dist/types/src/styles/tokens.d.ts.map +1 -1
  90. package/dist/types/src/testing/replicator.d.ts +2 -2
  91. package/dist/types/src/testing/replicator.d.ts.map +1 -1
  92. package/dist/types/src/{components/TextEditor/themes → themes}/default.d.ts +5 -13
  93. package/dist/types/src/themes/default.d.ts.map +1 -0
  94. package/dist/types/src/themes/index.d.ts.map +1 -0
  95. package/dist/types/src/util.d.ts +5 -0
  96. package/dist/types/src/util.d.ts.map +1 -0
  97. package/package.json +28 -22
  98. package/src/components/TextEditor/MarkdownEditor.stories.tsx +150 -87
  99. package/src/components/TextEditor/TextEditor.stories.tsx +14 -35
  100. package/src/components/TextEditor/TextEditor.tsx +87 -79
  101. package/src/{hooks/automerge → components/TextEditor}/automerge.stories.tsx +67 -8
  102. package/src/components/TextEditor/codemirror.stories.ts +3 -2
  103. package/src/components/TextEditor/comments.stories.tsx +355 -0
  104. package/src/components/TextEditor/index.ts +0 -3
  105. package/src/{hooks/yjs → components/TextEditor}/yjs.stories.tsx +1 -1
  106. package/src/{components/TextEditor/extensions → extensions}/autocomplete.ts +18 -17
  107. package/src/extensions/automerge/automerge.ts +92 -0
  108. package/src/extensions/automerge/cursor.ts +52 -0
  109. package/src/extensions/automerge/defs.ts +66 -0
  110. package/src/extensions/automerge/index.ts +6 -0
  111. package/src/{hooks/automerge/PatchSemaphore.ts → extensions/automerge/semaphore.ts} +26 -25
  112. package/src/{hooks/automerge/translation/codemirror-to-automerge.ts → extensions/automerge/update-automerge.ts} +6 -7
  113. package/src/{hooks/automerge/translation/automerge-to-codemirror.ts → extensions/automerge/update-codemirror.ts} +14 -11
  114. package/src/extensions/awareness.ts +310 -0
  115. package/src/extensions/code.ts +104 -0
  116. package/src/extensions/comments.ts +408 -0
  117. package/src/extensions/cursor.ts +46 -0
  118. package/src/extensions/hr.ts +72 -0
  119. package/src/extensions/image.ts +87 -0
  120. package/src/{components/TextEditor/extensions → extensions}/index.ts +7 -3
  121. package/src/{components/TextEditor/extensions → extensions}/link.ts +116 -62
  122. package/src/extensions/listener.ts +35 -0
  123. package/src/{components/TextEditor/extensions → extensions}/markdown/highlight.ts +4 -16
  124. package/src/extensions/outliner.ts +12 -0
  125. package/src/{components/TextEditor/extensions → extensions}/table.ts +23 -4
  126. package/src/extensions/tasklist.ts +96 -0
  127. package/src/{components/TextEditor/extensions/demo.ts → extensions/typewriter.ts} +2 -3
  128. package/src/extensions/yjs/cursor.ts +22 -0
  129. package/src/extensions/yjs/index.ts +5 -0
  130. package/src/extensions/yjs/yjs.test.ts +35 -0
  131. package/src/extensions/yjs/yjs.ts +16 -0
  132. package/src/hooks/automerge.ts +52 -0
  133. package/src/hooks/awareness-provider.ts +120 -0
  134. package/src/hooks/index.ts +4 -1
  135. package/src/hooks/useTextModel.ts +40 -79
  136. package/src/hooks/{yjs/space-provider.ts → yjs.ts} +49 -19
  137. package/src/index.ts +6 -0
  138. package/src/styles/index.ts +1 -0
  139. package/src/styles/markdown.ts +0 -2
  140. package/src/styles/tokens.ts +3 -0
  141. package/src/testing/replicator.ts +10 -16
  142. package/src/themes/default.ts +275 -0
  143. package/src/util.ts +18 -0
  144. package/dist/types/src/components/TextEditor/extensions/autocomplete.d.ts.map +0 -1
  145. package/dist/types/src/components/TextEditor/extensions/basic.d.ts.map +0 -1
  146. package/dist/types/src/components/TextEditor/extensions/blast.d.ts.map +0 -1
  147. package/dist/types/src/components/TextEditor/extensions/code.d.ts.map +0 -1
  148. package/dist/types/src/components/TextEditor/extensions/comments.d.ts +0 -18
  149. package/dist/types/src/components/TextEditor/extensions/comments.d.ts.map +0 -1
  150. package/dist/types/src/components/TextEditor/extensions/demo.d.ts.map +0 -1
  151. package/dist/types/src/components/TextEditor/extensions/experimental.d.ts +0 -10
  152. package/dist/types/src/components/TextEditor/extensions/experimental.d.ts.map +0 -1
  153. package/dist/types/src/components/TextEditor/extensions/highlight.d.ts +0 -24
  154. package/dist/types/src/components/TextEditor/extensions/highlight.d.ts.map +0 -1
  155. package/dist/types/src/components/TextEditor/extensions/image.d.ts.map +0 -1
  156. package/dist/types/src/components/TextEditor/extensions/index.d.ts.map +0 -1
  157. package/dist/types/src/components/TextEditor/extensions/link.d.ts.map +0 -1
  158. package/dist/types/src/components/TextEditor/extensions/listener.d.ts +0 -9
  159. package/dist/types/src/components/TextEditor/extensions/listener.d.ts.map +0 -1
  160. package/dist/types/src/components/TextEditor/extensions/markdown/bundle.d.ts.map +0 -1
  161. package/dist/types/src/components/TextEditor/extensions/markdown/highlight.d.ts.map +0 -1
  162. package/dist/types/src/components/TextEditor/extensions/markdown/index.d.ts.map +0 -1
  163. package/dist/types/src/components/TextEditor/extensions/mention.d.ts.map +0 -1
  164. package/dist/types/src/components/TextEditor/extensions/table.d.ts.map +0 -1
  165. package/dist/types/src/components/TextEditor/extensions/tasklist.d.ts +0 -3
  166. package/dist/types/src/components/TextEditor/extensions/tasklist.d.ts.map +0 -1
  167. package/dist/types/src/components/TextEditor/extensions/tooltip.d.ts +0 -12
  168. package/dist/types/src/components/TextEditor/extensions/tooltip.d.ts.map +0 -1
  169. package/dist/types/src/components/TextEditor/themes/default.d.ts.map +0 -1
  170. package/dist/types/src/components/TextEditor/themes/index.d.ts.map +0 -1
  171. package/dist/types/src/hooks/automerge/PatchSemaphore.d.ts +0 -19
  172. package/dist/types/src/hooks/automerge/PatchSemaphore.d.ts.map +0 -1
  173. package/dist/types/src/hooks/automerge/automerge.stories.d.ts.map +0 -1
  174. package/dist/types/src/hooks/automerge/handle.d.ts +0 -9
  175. package/dist/types/src/hooks/automerge/handle.d.ts.map +0 -1
  176. package/dist/types/src/hooks/automerge/index.d.ts +0 -3
  177. package/dist/types/src/hooks/automerge/index.d.ts.map +0 -1
  178. package/dist/types/src/hooks/automerge/plugin.d.ts +0 -26
  179. package/dist/types/src/hooks/automerge/plugin.d.ts.map +0 -1
  180. package/dist/types/src/hooks/automerge/translation/automerge-to-codemirror.d.ts +0 -5
  181. package/dist/types/src/hooks/automerge/translation/automerge-to-codemirror.d.ts.map +0 -1
  182. package/dist/types/src/hooks/automerge/translation/codemirror-to-automerge.d.ts +0 -6
  183. package/dist/types/src/hooks/automerge/translation/codemirror-to-automerge.d.ts.map +0 -1
  184. package/dist/types/src/hooks/automerge/translation/index.d.ts +0 -3
  185. package/dist/types/src/hooks/automerge/translation/index.d.ts.map +0 -1
  186. package/dist/types/src/hooks/yjs/cursors.d.ts.map +0 -1
  187. package/dist/types/src/hooks/yjs/index.d.ts +0 -3
  188. package/dist/types/src/hooks/yjs/index.d.ts.map +0 -1
  189. package/dist/types/src/hooks/yjs/space-provider.d.ts.map +0 -1
  190. package/dist/types/src/hooks/yjs/yjs.stories.d.ts.map +0 -1
  191. package/src/components/TextEditor/extensions/code.ts +0 -99
  192. package/src/components/TextEditor/extensions/comments.ts +0 -173
  193. package/src/components/TextEditor/extensions/experimental.tsx +0 -114
  194. package/src/components/TextEditor/extensions/highlight.ts +0 -128
  195. package/src/components/TextEditor/extensions/image.ts +0 -67
  196. package/src/components/TextEditor/extensions/listener.ts +0 -23
  197. package/src/components/TextEditor/extensions/tasklist.ts +0 -121
  198. package/src/components/TextEditor/extensions/tooltip.tsx +0 -61
  199. package/src/components/TextEditor/themes/default.ts +0 -279
  200. package/src/hooks/automerge/handle.ts +0 -14
  201. package/src/hooks/automerge/index.ts +0 -6
  202. package/src/hooks/automerge/plugin.ts +0 -134
  203. package/src/hooks/automerge/translation/index.ts +0 -6
  204. package/src/hooks/yjs/index.ts +0 -6
  205. /package/dist/types/src/{components/TextEditor/extensions → extensions}/autocomplete.d.ts +0 -0
  206. /package/dist/types/src/{components/TextEditor/extensions → extensions}/basic.d.ts +0 -0
  207. /package/dist/types/src/{components/TextEditor/extensions → extensions}/blast.d.ts +0 -0
  208. /package/dist/types/src/{components/TextEditor/extensions → extensions}/code.d.ts +0 -0
  209. /package/dist/types/src/{components/TextEditor/extensions → extensions}/image.d.ts +0 -0
  210. /package/dist/types/src/{components/TextEditor/extensions → extensions}/markdown/bundle.d.ts +0 -0
  211. /package/dist/types/src/{components/TextEditor/extensions → extensions}/markdown/index.d.ts +0 -0
  212. /package/dist/types/src/{components/TextEditor/extensions → extensions}/mention.d.ts +0 -0
  213. /package/dist/types/src/{components/TextEditor/extensions → extensions}/table.d.ts +0 -0
  214. /package/dist/types/src/{hooks/yjs → styles}/cursors.d.ts +0 -0
  215. /package/dist/types/src/{components/TextEditor/themes → themes}/index.d.ts +0 -0
  216. /package/src/{components/TextEditor/extensions → extensions}/basic.ts +0 -0
  217. /package/src/{components/TextEditor/extensions → extensions}/blast.ts +0 -0
  218. /package/src/{components/TextEditor/extensions → extensions}/markdown/bundle.ts +0 -0
  219. /package/src/{components/TextEditor/extensions → extensions}/markdown/index.ts +0 -0
  220. /package/src/{components/TextEditor/extensions → extensions}/mention.ts +0 -0
  221. /package/src/{hooks/yjs → styles}/cursors.ts +0 -0
  222. /package/src/{components/TextEditor/themes → themes}/index.ts +0 -0
@@ -1,121 +0,0 @@
1
- //
2
- // Copyright 2023 DXOS.org
3
- //
4
-
5
- import {
6
- EditorView,
7
- Decoration,
8
- WidgetType,
9
- MatchDecorator,
10
- ViewPlugin,
11
- type DecorationSet,
12
- type ViewUpdate,
13
- } from '@codemirror/view';
14
-
15
- // TODO(burdon): Reconcile with theme.
16
- const styles = EditorView.baseTheme({
17
- '& .cm-task-item': {
18
- paddingLeft: '4px',
19
- paddingRight: '8px',
20
- },
21
- });
22
-
23
- class CheckboxWidget extends WidgetType {
24
- constructor(
25
- private readonly _pos: number,
26
- private _checked: boolean,
27
- private readonly _indent: number,
28
- private readonly _onCheck?: (check: boolean) => void,
29
- ) {
30
- super();
31
- }
32
-
33
- override eq(other: CheckboxWidget) {
34
- return this._pos === other._pos && this._checked === other._checked && this._indent === other._indent;
35
- }
36
-
37
- toDOM(view: EditorView) {
38
- const wrap = document.createElement('span');
39
- wrap.className = 'cm-task-item';
40
- wrap.setAttribute('aria-hidden', 'true');
41
- wrap.style.setProperty('margin-left', this._indent * 24 + 'px');
42
-
43
- const input = wrap.appendChild(document.createElement('input'));
44
- input.type = 'checkbox';
45
- input.checked = this._checked;
46
- if (!this._onCheck) {
47
- input.setAttribute('disabled', 'true');
48
- }
49
- if (this._onCheck) {
50
- input.onchange = (event: Event) => {
51
- this._onCheck?.((event.target as any).checked);
52
- return true;
53
- };
54
- }
55
-
56
- return wrap;
57
- }
58
-
59
- override ignoreEvent() {
60
- return false;
61
- }
62
- }
63
-
64
- export type TasklistOptions = {};
65
-
66
- export const tasklist = (options: TasklistOptions = {}) => {
67
- // TODO(burdon): Matcher isn't as precise as syntax tree.
68
- // Allows for indents to be greater than AST would allow.
69
- const taskMatcher = new MatchDecorator({
70
- regexp: /^(\s*)- \[([ xX])\]\s/g,
71
- decoration: (match, view, pos) => {
72
- const indent = Math.floor(match[1].length / 2);
73
- const checked = match[2] === 'x' || match[2] === 'X';
74
- return Decoration.replace({
75
- widget: new CheckboxWidget(
76
- pos,
77
- checked,
78
- indent,
79
- view.state.readOnly
80
- ? undefined
81
- : (checked) => {
82
- const idx = pos + match[0].indexOf('[') + 1;
83
- view.dispatch({
84
- changes: {
85
- from: idx,
86
- to: idx + 1,
87
- insert: checked ? 'x' : ' ',
88
- },
89
- // TODO(burdon): Restore cursor position? More useful to move to end of line (can indent).
90
- selection: {
91
- anchor: idx + 3,
92
- },
93
- });
94
- },
95
- ),
96
- });
97
- },
98
- });
99
-
100
- const tasks = ViewPlugin.fromClass(
101
- class {
102
- tasks: DecorationSet;
103
- constructor(view: EditorView) {
104
- this.tasks = taskMatcher.createDeco(view);
105
- }
106
-
107
- update(update: ViewUpdate) {
108
- this.tasks = taskMatcher.updateDeco(update, this.tasks);
109
- }
110
- },
111
- {
112
- decorations: (value) => value.tasks,
113
- provide: (plugin) =>
114
- EditorView.atomicRanges.of((view) => {
115
- return view.plugin(plugin)?.tasks || Decoration.none;
116
- }),
117
- },
118
- );
119
-
120
- return [tasks, styles];
121
- };
@@ -1,61 +0,0 @@
1
- //
2
- // Copyright 2023 DXOS.org
3
- //
4
-
5
- import { type Extension } from '@codemirror/state';
6
- import { hoverTooltip } from '@codemirror/view';
7
-
8
- import { tooltipContent } from '@dxos/react-ui-theme';
9
-
10
- const markdownLinkRegexp = /\[([^\]]+)]\(([^)]+)\)/;
11
-
12
- export type TooltipOptions = {
13
- onHover: (el: Element, url: string) => void;
14
- regexp?: RegExp;
15
- };
16
-
17
- /**
18
- * https://codemirror.net/examples/tooltip
19
- * https://codemirror.net/docs/ref/#view.hoverTooltip
20
- * https://github.com/codemirror/view/blob/main/src/tooltip.ts
21
- */
22
- export const tooltip = ({ onHover, regexp = markdownLinkRegexp }: TooltipOptions): Extension =>
23
- hoverTooltip((view, pos) => {
24
- const { from, text } = view.state.doc.lineAt(pos);
25
- const p = pos - from;
26
-
27
- let idx = 0;
28
- let match;
29
- do {
30
- match = text.substring(idx).match(regexp);
31
- if (!match) {
32
- match = undefined;
33
- break;
34
- }
35
-
36
- idx = text.indexOf(match[0]);
37
- if (p >= idx && p < idx + match[0].length) {
38
- break;
39
- }
40
-
41
- idx += match[0].length;
42
- } while (true);
43
-
44
- if (!match) {
45
- return null;
46
- }
47
-
48
- const [, , url] = match ?? [];
49
-
50
- return {
51
- pos: idx + from,
52
- end: idx + from + match[0].length,
53
- above: true,
54
- create: () => {
55
- const el = document.createElement('div');
56
- el.className = tooltipContent({}, 'pli-2 plb-1');
57
- onHover(el, url);
58
- return { dom: el, offset: { x: 0, y: 12 } };
59
- },
60
- };
61
- });
@@ -1,279 +0,0 @@
1
- //
2
- // Copyright 2023 DXOS.org
3
- //
4
-
5
- import get from 'lodash.get';
6
- import { type StyleSpec } from 'style-mod';
7
-
8
- import { tokens } from '../../../styles';
9
-
10
- /**
11
- * Minimal styles.
12
- * https://codemirror.net/examples/styling
13
- *
14
- * Examples:
15
- * - https://github.com/codemirror/view/blob/main/src/theme.ts
16
- * - https://github.com/codemirror/theme-one-dark/blob/main/src/one-dark.ts
17
- *
18
- * NOTE: Use one of '&', '&light', and '&dark' prefix to scope instance.
19
- * NOTE: `light` and `dark` selectors are preprocessed by CodeMirror and can only be in the base theme.
20
- */
21
- export const defaultTheme: {
22
- [selector: string]: StyleSpec;
23
- } = {
24
- //
25
- // Main layout:
26
- // <div class=".cm-editor .cm-focused">
27
- // <div class=".cm-scroller">
28
- // <div class=".cm-content" role="textbox" contenteditable="true">
29
- // <div class=".cm-line" />
30
- // </div>
31
- // </div>
32
- // </div>
33
- //
34
- '&': {},
35
- '&.cm-focused': {
36
- outline: 'none',
37
- },
38
- '& .cm-scroller': {
39
- overflow: 'visible',
40
- fontFamily: get(tokens, 'fontFamily.mono', []).join(','),
41
- },
42
- '& .cm-content': {
43
- padding: 0,
44
- // Base font size (otherwise defined by HTML tag, which might be different for storybook).
45
- fontSize: '16px',
46
- },
47
- '&light .cm-content': {
48
- color: get(tokens, 'extend.colors.neutral.900', 'black'),
49
- caretColor: 'black',
50
- },
51
- '&dark .cm-content': {
52
- color: get(tokens, 'extend.colors.neutral.100', 'white'),
53
- caretColor: 'white',
54
- },
55
-
56
- //
57
- // Cursor
58
- //
59
- '&light .cm-cursor, &light .cm-dropCursor': {
60
- borderLeft: '2px solid black',
61
- },
62
- '&dark .cm-cursor, &dark .cm-dropCursor': {
63
- borderLeft: '2px solid white',
64
- },
65
- '& .cm-placeholder': {
66
- fontWeight: 100,
67
- },
68
-
69
- //
70
- // line
71
- //
72
- '& .cm-line': {
73
- paddingInline: 0,
74
- },
75
- '& .cm-line *': {},
76
- '& .cm-activeLine': {
77
- backgroundColor: 'transparent',
78
- },
79
-
80
- //
81
- // selection
82
- //
83
-
84
- '&light .cm-selectionBackground, &light.cm-focused .cm-selectionBackground': {
85
- background: get(tokens, 'extend.colors.primary.150', '#00ffff'),
86
- },
87
- '&dark .cm-selectionBackground, &dark.cm-focused .cm-selectionBackground': {
88
- background: get(tokens, 'extend.colors.primary.850', '#00ffff'),
89
- },
90
- '&light .cm-selectionMatch': {
91
- background: get(tokens, 'extend.colors.primary.250', '#00ffff') + '44',
92
- },
93
- '&dark .cm-selectionMatch': {
94
- background: get(tokens, 'extend.colors.primary.600', '#00ffff') + '44',
95
- },
96
-
97
- //
98
- // collaboration
99
- // TODO(burdon): Review classnames (YJS dependent?)
100
- //
101
-
102
- '&light .cm-ySelection, &light .cm-yLineSelection': {
103
- mixBlendMode: 'multiply',
104
- },
105
- '&dark .cm-ySelection, &dark .cm-yLineSelection': {
106
- mixBlendMode: 'screen',
107
- },
108
-
109
- '& .cm-ySelectionInfo': {
110
- padding: '2px 4px',
111
- marginBlockStart: '-4px',
112
- },
113
- '& .cm-ySelection, & .cm-selectionMatch': {
114
- paddingBlockStart: '.15em',
115
- paddingBlockEnd: '.15em',
116
- },
117
- '& .cm-ySelectionCaret': {
118
- display: 'inline-block',
119
- insetBlockStart: '.1em',
120
- blockSize: '1.4em',
121
- verticalAlign: 'top',
122
- },
123
- '& .cm-yLineSelection': {
124
- margin: 0,
125
- },
126
-
127
- //
128
- // link
129
- //
130
- '& .cm-link': {
131
- color: get(tokens, 'extend.colors.primary.500'),
132
- textDecorationLine: 'underline',
133
- textDecorationThickness: '1px',
134
- textUnderlineOffset: '2px',
135
- borderRadius: '.125rem',
136
- fontFamily: get(tokens, 'fontFamily.body', []).join(','),
137
- },
138
-
139
- //
140
- // tooltip
141
- //
142
- '& .cm-tooltip': {
143
- border: 'none',
144
- },
145
- '& .cm-tooltip-below': {},
146
-
147
- //
148
- // autocomplete
149
- //
150
- '& .cm-tooltip-autocomplete': {
151
- marginTop: '4px',
152
- marginLeft: '-3px',
153
- },
154
- '& .cm-tooltip-autocomplete ul li': {},
155
- '& .cm-tooltip-autocomplete ul li[aria-selected]': {},
156
- '& .cm-completionIcon': {
157
- display: 'none',
158
- },
159
- '& .cm-completionLabel': {
160
- fontFamily: get(tokens, 'fontFamily.body', []).join(','),
161
- },
162
- '& .cm-completionMatchedText': {
163
- textDecoration: 'none',
164
- },
165
-
166
- //
167
- // widgets
168
- //
169
- '& .cm-widgetBuffer': {
170
- display: 'none',
171
- height: 0,
172
- },
173
-
174
- //
175
- // table
176
- //
177
- '& .cm-table *': {
178
- fontFamily: `${get(tokens, 'fontFamily.mono', []).join(',')} !important`,
179
- textDecoration: 'none !important',
180
- },
181
- '& .cm-table-head': {
182
- padding: '2px 16px 2px 0px',
183
- borderBottom: `1px solid ${get(tokens, 'extend.colors.neutral.500')}`,
184
- fontWeight: 100,
185
- textAlign: 'left',
186
- color: get(tokens, 'extend.colors.neutral.500'),
187
- },
188
- '& .cm-table-cell': {
189
- padding: '2px 16px 2px 0px',
190
- },
191
-
192
- //
193
- // image
194
- //
195
- '& .cm-image': {
196
- margin: '0.5rem 0',
197
- },
198
-
199
- //
200
- // font size
201
- // TODO(thure): This appears to be the best or only way to set selection caret heights, but it's far more verbose than it needs to be.
202
- //
203
- ...Object.keys(get(tokens, 'extend.fontSize', {})).reduce((acc: Record<string, any>, fontSize) => {
204
- const height = get(tokens, ['extend', 'fontSize', fontSize, 1, 'lineHeight']);
205
-
206
- acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = { height };
207
- acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = { height };
208
- acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = { height };
209
- return acc;
210
- }, {}),
211
-
212
- /**
213
- * Panels
214
- * https://github.com/codemirror/search/blob/main/src/search.ts#L745
215
- *
216
- * Find/replace panel.
217
- * <div class="cm-announced">...</div>
218
- * <div class="cm-scroller">...</div>
219
- * <div class="cm-panels cm-panels-bottom">
220
- * <div class="cm-search cm-panel">
221
- * <input class="cm-textfield" />
222
- * <button class="cm-button">...</button>
223
- * <label><input type="checkbox" />...</label>
224
- * </div>
225
- * </div
226
- */
227
- '& .cm-panels': {
228
- border: `1px solid ${get(tokens, 'extend.colors.neutral.200')}`,
229
- borderBottom: 'none',
230
- },
231
- '& .cm-panel': {
232
- background: get(tokens, 'extend.colors.neutral.50'),
233
- fontFamily: get(tokens, 'fontFamily.body', []).join(','),
234
- },
235
- '& .cm-button': {
236
- margin: '4px',
237
- fontFamily: get(tokens, 'fontFamily.body', []).join(','),
238
- background: get(tokens, 'extend.colors.neutral.100'),
239
- border: 'none',
240
- },
241
-
242
- '& .cm-searchMatch': {
243
- backgroundColor: get(tokens, 'extend.colors.yellow.100'),
244
- },
245
- '& .cm-searchMatch.cm-searchMatch-selected': {
246
- backgroundColor: get(tokens, 'extend.colors.primary.100'),
247
- },
248
- };
249
-
250
- export const textTheme: {
251
- [selector: string]: StyleSpec;
252
- } = {
253
- '& .cm-scroller': {
254
- fontFamily: get(tokens, 'fontFamily.body', []).join(','),
255
- },
256
- '& .cm-placeholder': {
257
- fontFamily: get(tokens, 'fontFamily.body', []).join(','),
258
- },
259
- };
260
-
261
- export const markdownTheme: {
262
- [selector: string]: StyleSpec;
263
- } = {
264
- // NOTE: Must leave base font family as is (i.e., monospace) due to fenced code blocks.
265
- '& .cm-placeholder': {
266
- fontFamily: get(tokens, 'fontFamily.body', []).join(','),
267
- },
268
- };
269
-
270
- export const codeTheme: {
271
- [selector: string]: StyleSpec;
272
- } = {
273
- '& .cm-scroller': {
274
- fontFamily: get(tokens, 'fontFamily.mono', []).join(','),
275
- },
276
- '& .cm-placeholder': {
277
- fontFamily: get(tokens, 'fontFamily.mono', []).join(','),
278
- },
279
- };
@@ -1,14 +0,0 @@
1
- //
2
- // Copyright 2023 DXOS.org
3
- //
4
-
5
- import type * as A from '@dxos/automerge/automerge';
6
-
7
- export type IDocHandle<T = any> = {
8
- docSync(): A.Doc<T> | undefined;
9
- change(callback: A.ChangeFn<T>, options?: A.ChangeOptions<T>): void;
10
- changeAt(heads: A.Heads, callback: A.ChangeFn<T>, options?: A.ChangeOptions<T>): string[] | undefined;
11
-
12
- addListener(event: 'change', listener: () => void): void;
13
- removeListener(event: 'change', listener: () => void): void;
14
- };
@@ -1,6 +0,0 @@
1
- //
2
- // Copyright 2023 DXOS.org
3
- //
4
-
5
- export { type IDocHandle } from './handle';
6
- export { automergePlugin, type AutomergePlugin } from './plugin';
@@ -1,134 +0,0 @@
1
- //
2
- // Copyright 2023 DXOS.org
3
- //
4
-
5
- import {
6
- Annotation,
7
- type EditorState,
8
- type Extension,
9
- Facet,
10
- StateEffect,
11
- StateField,
12
- type Transaction,
13
- type TransactionSpec,
14
- } from '@codemirror/state';
15
- import { ViewPlugin, type EditorView, type PluginValue, type ViewUpdate } from '@codemirror/view';
16
-
17
- import * as automerge from '@dxos/automerge/automerge';
18
- import { type Heads, type Prop } from '@dxos/automerge/automerge';
19
-
20
- import { PatchSemaphore } from './PatchSemaphore';
21
- import { type IDocHandle } from './handle';
22
-
23
- export type Value = {
24
- lastHeads: Heads;
25
- path: Prop[];
26
- unreconciledTransactions: Transaction[];
27
- };
28
-
29
- type UpdateHeads = {
30
- newHeads: Heads;
31
- };
32
-
33
- export const effectType = StateEffect.define<UpdateHeads>({});
34
-
35
- export const updateHeads = (newHeads: Heads): StateEffect<UpdateHeads> => effectType.of({ newHeads });
36
-
37
- export const getLastHeads = (state: EditorState, field: Field): Heads => state.field(field).lastHeads;
38
-
39
- export const getPath = (state: EditorState, field: Field): Prop[] => state.field(field).path;
40
-
41
- export type Field = StateField<Value>;
42
-
43
- const semaphoreFacet = Facet.define<PatchSemaphore, PatchSemaphore>({
44
- combine: (values) => values.at(-1)!, // Take last.
45
- });
46
-
47
- export type AutomergePlugin = {
48
- extension: Extension;
49
- };
50
-
51
- export const automergePlugin = (handle: IDocHandle, path: Prop[]): AutomergePlugin => {
52
- const stateField: StateField<Value> = StateField.define({
53
- create: () => ({
54
- lastHeads: automerge.getHeads(handle.docSync()!),
55
- unreconciledTransactions: [],
56
- path: path.slice(),
57
- }),
58
- update: (value: Value, tr: Transaction) => {
59
- const result: Value = {
60
- lastHeads: value.lastHeads,
61
- unreconciledTransactions: value.unreconciledTransactions.slice(),
62
- path: path.slice(),
63
- };
64
- let clearUnreconciled = false;
65
- for (const effect of tr.effects) {
66
- if (effect.is(effectType)) {
67
- result.lastHeads = effect.value.newHeads;
68
- clearUnreconciled = true;
69
- }
70
- }
71
- if (clearUnreconciled) {
72
- result.unreconciledTransactions = [];
73
- } else {
74
- if (!isReconcileTx(tr)) {
75
- result.unreconciledTransactions.push(tr);
76
- }
77
- }
78
- return result;
79
- },
80
- });
81
-
82
- const semaphore = new PatchSemaphore(stateField);
83
-
84
- const viewPlugin = ViewPlugin.fromClass(
85
- class AutomergeCodemirrorViewPlugin implements PluginValue {
86
- private _view: EditorView;
87
-
88
- constructor(view: EditorView) {
89
- this._view = view;
90
- handle.addListener('change', this._handleChange);
91
- }
92
-
93
- update(update: ViewUpdate) {
94
- if (update.transactions.length > 0 && update.transactions.some((t) => !isReconcileTx(t))) {
95
- queueMicrotask(() => {
96
- this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
97
- });
98
- }
99
- }
100
-
101
- destroy() {
102
- handle.addListener('change', this._handleChange);
103
- }
104
-
105
- private _handleChange = () => {
106
- this._view.state.facet(semaphoreFacet).reconcile(handle, this._view);
107
- };
108
- },
109
- );
110
-
111
- return {
112
- extension: [stateField, semaphoreFacet.of(semaphore), viewPlugin],
113
- };
114
- };
115
-
116
- export const reconcileAnnotationType = Annotation.define<unknown>();
117
-
118
- export const isReconcileTx = (tr: Transaction): boolean => !!tr.annotation(reconcileAnnotationType);
119
-
120
- export const makeReconcile = (tr: TransactionSpec) => {
121
- if (tr.annotations != null) {
122
- if (tr.annotations instanceof Array) {
123
- tr.annotations = [...tr.annotations, reconcileAnnotationType.of({})];
124
- } else {
125
- tr.annotations = [tr.annotations, reconcileAnnotationType.of({})];
126
- }
127
- } else {
128
- tr.annotations = [reconcileAnnotationType.of({})];
129
- }
130
- // return {
131
- // ...tr,
132
- // annotations: reconcileAnnotationType.of({})
133
- // }
134
- };
@@ -1,6 +0,0 @@
1
- //
2
- // Copyright 2023 DXOS.org
3
- //
4
-
5
- export * from './automerge-to-codemirror';
6
- export * from './codemirror-to-automerge';
@@ -1,6 +0,0 @@
1
- //
2
- // Copyright 2023 DXOS.org
3
- //
4
-
5
- export * from './cursors';
6
- export * from './space-provider';
File without changes