@dxos/react-ui-editor 0.3.11-main.fbbdc2a → 0.3.11-main.fc97a54

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 (202) hide show
  1. package/dist/lib/browser/index.mjs +2904 -1394
  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 +16 -14
  5. package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
  6. package/dist/types/src/components/TextEditor/TextEditor.d.ts +20 -17
  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 -6
  9. package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
  10. package/dist/types/src/components/TextEditor/automerge.stories.d.ts.map +1 -1
  11. package/dist/types/src/components/TextEditor/hooks.stories.d.ts +23 -0
  12. package/dist/types/src/components/TextEditor/hooks.stories.d.ts.map +1 -0
  13. package/dist/types/src/components/Toolbar/Toolbar.d.ts +29 -0
  14. package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -0
  15. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +25 -0
  16. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -0
  17. package/dist/types/src/components/Toolbar/index.d.ts +2 -0
  18. package/dist/types/src/components/Toolbar/index.d.ts.map +1 -0
  19. package/dist/types/src/components/index.d.ts +1 -0
  20. package/dist/types/src/components/index.d.ts.map +1 -1
  21. package/dist/types/src/extensions/autocomplete.d.ts.map +1 -1
  22. package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -1
  23. package/dist/types/src/extensions/automerge/automerge.spec.d.ts +2 -0
  24. package/dist/types/src/extensions/automerge/automerge.spec.d.ts.map +1 -0
  25. package/dist/types/src/extensions/automerge/automerge.test.d.ts +2 -0
  26. package/dist/types/src/extensions/automerge/automerge.test.d.ts.map +1 -0
  27. package/dist/types/src/extensions/automerge/cursor.d.ts +1 -1
  28. package/dist/types/src/extensions/automerge/cursor.d.ts.map +1 -1
  29. package/dist/types/src/extensions/automerge/defs.d.ts +9 -11
  30. package/dist/types/src/extensions/automerge/defs.d.ts.map +1 -1
  31. package/dist/types/src/extensions/automerge/semaphore.d.ts +8 -12
  32. package/dist/types/src/extensions/automerge/semaphore.d.ts.map +1 -1
  33. package/dist/types/src/extensions/automerge/update-automerge.d.ts +2 -2
  34. package/dist/types/src/extensions/automerge/update-automerge.d.ts.map +1 -1
  35. package/dist/types/src/extensions/awareness.d.ts +2 -2
  36. package/dist/types/src/extensions/awareness.d.ts.map +1 -1
  37. package/dist/types/src/extensions/basic.d.ts +4 -5
  38. package/dist/types/src/extensions/basic.d.ts.map +1 -1
  39. package/dist/types/src/extensions/comments.d.ts +41 -20
  40. package/dist/types/src/extensions/comments.d.ts.map +1 -1
  41. package/dist/types/src/{util → extensions}/cursor.d.ts +10 -2
  42. package/dist/types/src/extensions/cursor.d.ts.map +1 -0
  43. package/dist/types/src/extensions/index.d.ts +2 -8
  44. package/dist/types/src/extensions/index.d.ts.map +1 -1
  45. package/dist/types/src/extensions/markdown/bundle.d.ts +3 -6
  46. package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
  47. package/dist/types/src/extensions/markdown/code.d.ts.map +1 -0
  48. package/dist/types/src/extensions/markdown/formatting.d.ts +58 -0
  49. package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -0
  50. package/dist/types/src/extensions/markdown/formatting.test.d.ts +3 -0
  51. package/dist/types/src/extensions/markdown/formatting.test.d.ts.map +1 -0
  52. package/dist/types/src/extensions/markdown/heading.d.ts +6 -0
  53. package/dist/types/src/extensions/markdown/heading.d.ts.map +1 -0
  54. package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -1
  55. package/dist/types/src/extensions/markdown/hr.d.ts.map +1 -0
  56. package/dist/types/src/extensions/markdown/image.d.ts.map +1 -0
  57. package/dist/types/src/extensions/markdown/index.d.ts +8 -0
  58. package/dist/types/src/extensions/markdown/index.d.ts.map +1 -1
  59. package/dist/types/src/extensions/markdown/link.d.ts.map +1 -0
  60. package/dist/types/src/extensions/markdown/table.d.ts.map +1 -0
  61. package/dist/types/src/extensions/markdown/tasklist.d.ts.map +1 -0
  62. package/dist/types/src/extensions/mention.d.ts.map +1 -1
  63. package/dist/types/src/extensions/outliner.d.ts +4 -0
  64. package/dist/types/src/extensions/outliner.d.ts.map +1 -0
  65. package/dist/types/src/hooks/awareness-provider.d.ts +7 -4
  66. package/dist/types/src/hooks/awareness-provider.d.ts.map +1 -1
  67. package/dist/types/src/hooks/defs.d.ts +25 -0
  68. package/dist/types/src/hooks/defs.d.ts.map +1 -0
  69. package/dist/types/src/hooks/index.d.ts +4 -2
  70. package/dist/types/src/hooks/index.d.ts.map +1 -1
  71. package/dist/types/src/hooks/useActionHandler.d.ts +4 -0
  72. package/dist/types/src/hooks/useActionHandler.d.ts.map +1 -0
  73. package/dist/types/src/hooks/useEditorView.d.ts +17 -0
  74. package/dist/types/src/hooks/useEditorView.d.ts.map +1 -0
  75. package/dist/types/src/hooks/useTextEditor.d.ts +39 -0
  76. package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -0
  77. package/dist/types/src/hooks/useTextModel.d.ts +14 -32
  78. package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
  79. package/dist/types/src/index.d.ts +3 -0
  80. package/dist/types/src/index.d.ts.map +1 -1
  81. package/dist/types/src/styles/markdown.d.ts +2 -2
  82. package/dist/types/src/styles/markdown.d.ts.map +1 -1
  83. package/dist/types/src/styles/tokens.d.ts +1 -0
  84. package/dist/types/src/styles/tokens.d.ts.map +1 -1
  85. package/dist/types/src/themes/default.d.ts.map +1 -1
  86. package/dist/types/src/util.d.ts +7 -0
  87. package/dist/types/src/util.d.ts.map +1 -0
  88. package/package.json +48 -37
  89. package/src/components/TextEditor/MarkdownEditor.stories.tsx +85 -92
  90. package/src/components/TextEditor/TextEditor.stories.tsx +12 -46
  91. package/src/components/TextEditor/TextEditor.tsx +135 -95
  92. package/src/components/TextEditor/automerge.stories.tsx +1 -2
  93. package/src/components/TextEditor/hooks.stories.tsx +111 -0
  94. package/src/components/Toolbar/Toolbar.stories.tsx +102 -0
  95. package/src/components/Toolbar/Toolbar.tsx +264 -0
  96. package/src/components/Toolbar/index.ts +5 -0
  97. package/src/components/index.ts +1 -0
  98. package/src/extensions/autocomplete.ts +23 -19
  99. package/src/extensions/automerge/automerge.spec.tsx +76 -0
  100. package/src/extensions/automerge/automerge.test.ts +13 -0
  101. package/src/extensions/automerge/automerge.ts +55 -46
  102. package/src/extensions/automerge/cursor.ts +5 -4
  103. package/src/extensions/automerge/defs.ts +13 -34
  104. package/src/extensions/automerge/semaphore.ts +33 -32
  105. package/src/extensions/automerge/update-automerge.ts +14 -8
  106. package/src/extensions/automerge/update-codemirror.ts +5 -5
  107. package/src/extensions/awareness.ts +46 -49
  108. package/src/extensions/basic.ts +17 -10
  109. package/src/extensions/blast.ts +4 -1
  110. package/src/extensions/comments.ts +332 -267
  111. package/src/extensions/cursor.ts +50 -0
  112. package/src/extensions/index.ts +2 -8
  113. package/src/extensions/markdown/bundle.ts +23 -28
  114. package/src/extensions/markdown/code.ts +150 -0
  115. package/src/extensions/markdown/formatting.test.ts +482 -0
  116. package/src/extensions/markdown/formatting.ts +1237 -0
  117. package/src/extensions/markdown/heading.ts +59 -0
  118. package/src/extensions/markdown/highlight.ts +11 -26
  119. package/src/extensions/markdown/hr.ts +71 -0
  120. package/src/extensions/markdown/image.ts +87 -0
  121. package/src/extensions/markdown/index.ts +8 -0
  122. package/src/extensions/{link.ts → markdown/link.ts} +90 -83
  123. package/src/extensions/{table.ts → markdown/table.ts} +10 -4
  124. package/src/extensions/markdown/tasklist.ts +110 -0
  125. package/src/extensions/mention.ts +9 -2
  126. package/src/extensions/outliner.ts +12 -0
  127. package/src/hooks/awareness-provider.ts +24 -20
  128. package/src/hooks/defs.ts +42 -0
  129. package/src/hooks/index.ts +5 -2
  130. package/src/hooks/useActionHandler.ts +93 -0
  131. package/src/hooks/useEditorView.ts +29 -0
  132. package/src/hooks/useTextEditor.ts +153 -0
  133. package/src/hooks/useTextModel.ts +67 -60
  134. package/src/index.ts +3 -0
  135. package/src/styles/markdown.ts +9 -12
  136. package/src/styles/tokens.ts +3 -0
  137. package/src/themes/default.ts +59 -83
  138. package/src/util.ts +41 -0
  139. package/dist/types/src/components/TextEditor/codemirror.stories.d.ts +0 -12
  140. package/dist/types/src/components/TextEditor/codemirror.stories.d.ts.map +0 -1
  141. package/dist/types/src/components/TextEditor/yjs.stories.d.ts +0 -12
  142. package/dist/types/src/components/TextEditor/yjs.stories.d.ts.map +0 -1
  143. package/dist/types/src/extensions/code.d.ts.map +0 -1
  144. package/dist/types/src/extensions/hr.d.ts.map +0 -1
  145. package/dist/types/src/extensions/image.d.ts.map +0 -1
  146. package/dist/types/src/extensions/link.d.ts.map +0 -1
  147. package/dist/types/src/extensions/mermaid.d.ts +0 -3
  148. package/dist/types/src/extensions/mermaid.d.ts.map +0 -1
  149. package/dist/types/src/extensions/table.d.ts.map +0 -1
  150. package/dist/types/src/extensions/tasklist.d.ts.map +0 -1
  151. package/dist/types/src/extensions/yjs/cursor.d.ts +0 -4
  152. package/dist/types/src/extensions/yjs/cursor.d.ts.map +0 -1
  153. package/dist/types/src/extensions/yjs/index.d.ts +0 -2
  154. package/dist/types/src/extensions/yjs/index.d.ts.map +0 -1
  155. package/dist/types/src/extensions/yjs/yjs.d.ts +0 -4
  156. package/dist/types/src/extensions/yjs/yjs.d.ts.map +0 -1
  157. package/dist/types/src/extensions/yjs/yjs.test.d.ts +0 -2
  158. package/dist/types/src/extensions/yjs/yjs.test.d.ts.map +0 -1
  159. package/dist/types/src/hooks/automerge.d.ts +0 -3
  160. package/dist/types/src/hooks/automerge.d.ts.map +0 -1
  161. package/dist/types/src/hooks/yjs.d.ts +0 -27
  162. package/dist/types/src/hooks/yjs.d.ts.map +0 -1
  163. package/dist/types/src/testing/index.d.ts +0 -3
  164. package/dist/types/src/testing/index.d.ts.map +0 -1
  165. package/dist/types/src/testing/proto/gen/schema.d.ts +0 -15
  166. package/dist/types/src/testing/proto/gen/schema.d.ts.map +0 -1
  167. package/dist/types/src/testing/proto/index.d.ts +0 -2
  168. package/dist/types/src/testing/proto/index.d.ts.map +0 -1
  169. package/dist/types/src/testing/replicator.d.ts +0 -45
  170. package/dist/types/src/testing/replicator.d.ts.map +0 -1
  171. package/dist/types/src/util/cursor.d.ts.map +0 -1
  172. package/dist/types/src/util/index.d.ts +0 -3
  173. package/dist/types/src/util/index.d.ts.map +0 -1
  174. package/dist/types/src/util/util.d.ts +0 -5
  175. package/dist/types/src/util/util.d.ts.map +0 -1
  176. package/src/components/TextEditor/codemirror.stories.ts +0 -115
  177. package/src/components/TextEditor/yjs.stories.tsx +0 -56
  178. package/src/extensions/code.ts +0 -99
  179. package/src/extensions/hr.ts +0 -74
  180. package/src/extensions/image.ts +0 -69
  181. package/src/extensions/mermaid.ts +0 -11
  182. package/src/extensions/tasklist.ts +0 -121
  183. package/src/extensions/yjs/cursor.ts +0 -21
  184. package/src/extensions/yjs/index.ts +0 -5
  185. package/src/extensions/yjs/yjs.test.ts +0 -35
  186. package/src/extensions/yjs/yjs.ts +0 -16
  187. package/src/hooks/automerge.ts +0 -52
  188. package/src/hooks/yjs.ts +0 -178
  189. package/src/testing/index.ts +0 -6
  190. package/src/testing/proto/gen/schema.ts +0 -49
  191. package/src/testing/proto/index.ts +0 -5
  192. package/src/testing/proto/schema.proto +0 -15
  193. package/src/testing/replicator.ts +0 -184
  194. package/src/util/cursor.ts +0 -29
  195. package/src/util/index.ts +0 -6
  196. package/src/util/util.ts +0 -18
  197. /package/dist/types/src/extensions/{code.d.ts → markdown/code.d.ts} +0 -0
  198. /package/dist/types/src/extensions/{hr.d.ts → markdown/hr.d.ts} +0 -0
  199. /package/dist/types/src/extensions/{image.d.ts → markdown/image.d.ts} +0 -0
  200. /package/dist/types/src/extensions/{link.d.ts → markdown/link.d.ts} +0 -0
  201. /package/dist/types/src/extensions/{table.d.ts → markdown/table.d.ts} +0 -0
  202. /package/dist/types/src/extensions/{tasklist.d.ts → markdown/tasklist.d.ts} +0 -0
@@ -2,58 +2,19 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { StateField, type Extension } from '@codemirror/state';
6
- import { useEffect, useState } from 'react';
7
- import type * as YP from 'y-protocols/awareness';
5
+ import get from 'lodash.get';
6
+ import { type Dispatch, type SetStateAction, useEffect, useState } from 'react';
8
7
 
9
- import { isAutomergeObject, type DocAccessor, type Space, type TextObject } from '@dxos/react-client/echo';
8
+ import { generateName } from '@dxos/display-name';
9
+ import { type AutomergeTextCompat, getRawDoc } from '@dxos/echo-schema';
10
+ import { invariant } from '@dxos/invariant';
11
+ import { isAutomergeObject, type Space, type TextObject } from '@dxos/react-client/echo';
10
12
  import { type Identity } from '@dxos/react-client/halo';
11
- import type { YText, YXmlFragment } from '@dxos/text-model';
12
13
 
13
- import { createAutomergeModel } from './automerge';
14
- import { createYjsModel } from './yjs';
15
-
16
- // TODO(burdon): Factor out defs.
17
-
18
- /**
19
- * State field makes the model available to other extensions.
20
- */
21
- export const modelState = StateField.define<EditorModel | undefined>({
22
- create: () => undefined,
23
- update: (model) => model,
24
- });
25
-
26
- export type Range = {
27
- from: number;
28
- to: number;
29
- };
30
-
31
- export type CommentRange = {
32
- id: string;
33
- cursor: string;
34
- };
35
-
36
- // TODO(wittjosiah): Factor out to common package? @dxos/react-client?
37
- export type EditorModel = {
38
- id: string;
39
- text: () => string;
40
- extension?: Extension;
41
-
42
- // TODO(burdon): Remove.
43
- content: string | YText | YXmlFragment | DocAccessor;
44
- /**
45
- * @deprecated Use CursorConverter.
46
- */
47
- getCursorFromRange?: (value: Range) => string;
48
- getRangeFromCursor?: (cursor: string) => Range | undefined;
49
- // TODO(burdon): Move into extension.
50
- awareness?: YP.Awareness;
51
- // TODO(burdon): Remove.
52
- peer?: {
53
- id: string;
54
- name?: string;
55
- };
56
- };
14
+ import { SpaceAwarenessProvider } from './awareness-provider';
15
+ import { type EditorModel, modelState } from './defs';
16
+ import { automerge, awareness } from '../extensions';
17
+ import { cursorColor } from '../styles';
57
18
 
58
19
  // TODO(burdon): Remove space/identity dependency. Define interface for the framework re content and presence.
59
20
  export type UseTextModelProps = {
@@ -62,22 +23,68 @@ export type UseTextModelProps = {
62
23
  text?: TextObject;
63
24
  };
64
25
 
65
- // TODO(burdon): Remove YJS/Automerge deps (from UI component -- create abstraction; incl. all ECHO/Space deps).
66
- // TODO(wittjosiah): Factor out to common package? @dxos/react-client?
67
26
  export const useTextModel = (props: UseTextModelProps): EditorModel | undefined => {
68
27
  const { identity, space, text } = props;
69
- const [model, setModel] = useState<EditorModel | undefined>(() => createModel(props));
28
+ const [model, setModel] = useState<EditorModel | undefined>();
70
29
  useEffect(() => setModel(createModel(props)), [identity, space, text]);
71
30
  return model;
72
31
  };
73
32
 
74
- const createModel = (props: UseTextModelProps) => {
75
- const { text } = props;
76
- if (isAutomergeObject(text)) {
77
- return createAutomergeModel(props);
78
- } else if (text?.doc) {
79
- return createYjsModel(props);
80
- } else {
81
- return undefined;
33
+ /**
34
+ * For use primarily in stories & tests so the dependence on TextObject can be avoided.
35
+ * @param id
36
+ * @param defaultContent
37
+ */
38
+ export const useInMemoryTextModel = ({
39
+ id,
40
+ defaultContent,
41
+ }: {
42
+ id: string;
43
+ defaultContent?: string;
44
+ }): EditorModel & { setContent: Dispatch<SetStateAction<string>> } => {
45
+ const [content, setContent] = useState(defaultContent ?? '');
46
+ return { id, content, setContent, text: () => content };
47
+ };
48
+
49
+ const createModel = ({ space, identity, text }: UseTextModelProps) => {
50
+ invariant(isAutomergeObject(text));
51
+ const obj = text as any as AutomergeTextCompat;
52
+ const doc = getRawDoc(obj, [obj.field]);
53
+
54
+ const awarenessProvider =
55
+ space &&
56
+ new SpaceAwarenessProvider({
57
+ space,
58
+ channel: `automerge.awareness.${obj.id}`,
59
+ info: {
60
+ displayName: identity ? identity.profile?.displayName ?? generateName(identity.identityKey.toHex()) : undefined,
61
+ color: cursorColor.color,
62
+ lightColor: cursorColor.light,
63
+ },
64
+ peerId: identity?.identityKey.toHex() ?? 'Anonymous',
65
+ });
66
+
67
+ const extensions = [
68
+ //
69
+ modelState.init(() => model),
70
+ automerge({ handle: doc.handle, path: doc.path }),
71
+ ];
72
+ if (awarenessProvider) {
73
+ extensions.push(awareness(awarenessProvider));
82
74
  }
75
+
76
+ const model: EditorModel = {
77
+ id: obj.id,
78
+ content: doc,
79
+ text: () => get(doc.handle.docSync(), doc.path),
80
+ extension: extensions,
81
+ peer: identity
82
+ ? {
83
+ id: identity.identityKey.toHex(),
84
+ name: identity.profile?.displayName,
85
+ }
86
+ : undefined,
87
+ };
88
+
89
+ return model;
83
90
  };
package/src/index.ts CHANGED
@@ -5,8 +5,11 @@
5
5
  export { TextKind } from '@dxos/protocols/proto/dxos/echo/model/text';
6
6
  export { Doc, YText, YXmlFragment } from '@dxos/text-model';
7
7
  export { type Extension } from '@codemirror/state';
8
+ export { type EditorView, keymap } from '@codemirror/view';
8
9
 
9
10
  export * from './components';
10
11
  export * from './extensions';
11
12
  export * from './hooks';
13
+ export { getToken } from './styles';
12
14
  export * from './themes';
15
+ export * from './util';
@@ -8,18 +8,17 @@ export type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
8
8
 
9
9
  // TODO(burdon): Better way to align vertically than negative margin? Font-specific?
10
10
  // https://tailwindcss.com/docs/font-weight
11
- export const headings: Record<HeadingLevel, string[]> = {
12
- 1: ['mbs-4 mbe-2 font-medium text-inherit no-underline text-4xl', '-ml-[10px]'],
13
- 2: ['mbs-4 mbe-2 font-medium text-inherit no-underline text-3xl', '-ml-[8px]'],
14
- 3: ['mbs-4 mbe-2 font-medium text-inherit no-underline text-2xl', '-ml-[7px]'],
15
- 4: ['mbs-4 mbe-2 font-medium text-inherit no-underline text-xl', '-ml-[6px]'],
16
- 5: ['mbs-4 mbe-2 font-medium text-inherit no-underline text-lg', '-ml-[5px]'],
17
- 6: ['mbs-4 mbe-2 font-medium text-inherit no-underline', '-ml-[4px]'],
11
+ export const headings: Record<HeadingLevel, string> = {
12
+ 1: 'mbs-4 mbe-2 font-medium text-inherit no-underline text-4xl',
13
+ 2: 'mbs-4 mbe-2 font-medium text-inherit no-underline text-3xl',
14
+ 3: 'mbs-4 mbe-2 font-medium text-inherit no-underline text-2xl',
15
+ 4: 'mbs-4 mbe-2 font-medium text-inherit no-underline text-xl',
16
+ 5: 'mbs-4 mbe-2 font-medium text-inherit no-underline text-lg',
17
+ 6: 'mbs-4 mbe-2 font-medium text-inherit no-underline',
18
18
  };
19
19
 
20
- export const heading = (level: HeadingLevel, readonly?: boolean) => {
21
- const [style, offset] = headings[level];
22
- return mx(style, readonly && offset);
20
+ export const heading = (level: HeadingLevel) => {
21
+ return headings[level];
23
22
  };
24
23
 
25
24
  export const text = 'text-neutral-800 dark:text-neutral-200';
@@ -39,10 +38,8 @@ export const codeBlock = 'mlb-2 font-mono bg-neutral-500/10 p-3 rounded';
39
38
 
40
39
  export const inlineUrl = mx(code, 'px-1');
41
40
 
42
- // TODO(burdon): Replace with widget.
43
41
  export const blockquote = mx('pl-1 mr-1 border-is-4 border-primary-500/70 dark:border-primary-500/30', light);
44
42
 
45
- // TODO(burdon): Replace with widget.
46
43
  export const horizontalRule =
47
44
  'flex mlb-4 border-b text-neutral-100 dark:text-neutral-900 border-neutral-200 dark:border-neutral-800';
48
45
 
@@ -2,6 +2,7 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
+ import get from 'lodash.get';
5
6
  import type { StyleSpec } from 'style-mod';
6
7
 
7
8
  import { tailwindConfig, type TailwindConfig } from '@dxos/react-ui-theme';
@@ -12,3 +13,5 @@ export type ThemeStyles = {
12
13
 
13
14
  // TODO(thure): Why export the whole theme? Can this be done differently?
14
15
  export const tokens: TailwindConfig['theme'] = tailwindConfig({}).theme;
16
+
17
+ export const getToken = (path: string, defaultValue: any = undefined) => get(tokens, path, defaultValue);
@@ -6,8 +6,8 @@ import get from 'lodash.get';
6
6
 
7
7
  import { type ThemeStyles, tokens } from '../styles';
8
8
 
9
- // TODO(burdon): Can we erase All of the default CM styles?
10
- // TODO(burdon): Theme styles seem to be added multiple times?
9
+ // TODO(burdon): Can we use @apply and import css file?
10
+ // https://tailwindcss.com/docs/reusing-styles#extracting-classes-with-apply?
11
11
 
12
12
  /**
13
13
  * Minimal styles.
@@ -49,22 +49,24 @@ export const defaultTheme: ThemeStyles = {
49
49
  '&.cm-focused': {
50
50
  outline: 'none',
51
51
  },
52
- '& .cm-scroller': {
53
- overflow: 'visible',
52
+
53
+ '.cm-scroller': {
54
+ // overflow: 'visible',
54
55
  fontFamily: get(tokens, 'fontFamily.mono', []).join(','),
56
+ lineHeight: 1.4,
55
57
  },
56
58
 
57
- '& .cm-content': {
59
+ '.cm-content': {
58
60
  padding: 0,
59
61
  // NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
60
62
  fontSize: '16px',
61
63
  },
62
64
  '&light .cm-content': {
63
- color: get(tokens, 'extend.colors.neutral.900', 'black'),
65
+ color: get(tokens, 'extend.semanticColors.base.fg.light', 'black'),
64
66
  caretColor: 'black',
65
67
  },
66
68
  '&dark .cm-content': {
67
- color: get(tokens, 'extend.colors.neutral.100', 'white'),
69
+ color: get(tokens, 'extend.semanticColors.base.fg.dark', 'white'),
68
70
  caretColor: 'white',
69
71
  },
70
72
 
@@ -77,18 +79,21 @@ export const defaultTheme: ThemeStyles = {
77
79
  '&dark .cm-cursor, &dark .cm-dropCursor': {
78
80
  borderLeft: '2px solid white',
79
81
  },
80
- '& .cm-placeholder': {
81
- fontWeight: 100,
82
+ '&light .cm-placeholder': {
83
+ color: get(tokens, 'extend.semanticColors.description.light', 'rgba(0,0,0,.2)'),
84
+ },
85
+ '&dark .cm-placeholder': {
86
+ color: get(tokens, 'extend.semanticColors.description.dark', 'rgba(255,255,255,.2)'),
82
87
  },
83
88
 
84
89
  //
85
90
  // line
86
91
  //
87
- '& .cm-line': {
92
+ '.cm-line': {
88
93
  paddingInline: 0,
89
94
  },
90
- '& .cm-activeLine': {
91
- background: 'inherit',
95
+ '.cm-activeLine': {
96
+ background: 'transparent',
92
97
  },
93
98
 
94
99
  //
@@ -119,40 +124,10 @@ export const defaultTheme: ThemeStyles = {
119
124
  backgroundColor: get(tokens, 'extend.colors.yellow.700'),
120
125
  },
121
126
 
122
- //
123
- // collaboration
124
- // TODO(burdon): Review classnames (YJS dependent?) Note: e2e tests depend on this class.
125
- //
126
-
127
- '&light .cm-ySelection, &light .cm-yLineSelection': {
128
- mixBlendMode: 'multiply',
129
- },
130
- '&dark .cm-ySelection, &dark .cm-yLineSelection': {
131
- mixBlendMode: 'screen',
132
- },
133
-
134
- '& .cm-ySelectionInfo': {
135
- padding: '2px 4px',
136
- marginBlockStart: '-4px',
137
- },
138
- '& .cm-ySelection, & .cm-selectionMatch': {
139
- paddingBlockStart: '.15em',
140
- paddingBlockEnd: '.15em',
141
- },
142
- '& .cm-ySelectionCaret': {
143
- display: 'inline-block',
144
- insetBlockStart: '.1em',
145
- blockSize: '1.4em',
146
- verticalAlign: 'top',
147
- },
148
- '& .cm-yLineSelection': {
149
- margin: 0,
150
- },
151
-
152
127
  //
153
128
  // link
154
129
  //
155
- '& .cm-link': {
130
+ '.cm-link': {
156
131
  color: get(tokens, 'extend.colors.primary.500'),
157
132
  textDecorationLine: 'underline',
158
133
  textDecorationThickness: '1px',
@@ -164,75 +139,74 @@ export const defaultTheme: ThemeStyles = {
164
139
  //
165
140
  // tooltip
166
141
  //
167
- '& .cm-tooltip': {
142
+ '.cm-tooltip': {
168
143
  border: 'none',
169
144
  },
170
- '& .cm-tooltip-below': {},
145
+ '.cm-tooltip-below': {},
171
146
 
172
147
  //
173
148
  // autocomplete
174
149
  //
175
- '& .cm-tooltip-autocomplete': {
150
+ '.cm-tooltip-autocomplete': {
176
151
  marginTop: '4px',
177
152
  marginLeft: '-3px',
178
153
  },
179
- '& .cm-tooltip-autocomplete ul li': {},
180
- '& .cm-tooltip-autocomplete ul li[aria-selected]': {},
181
- '& .cm-completionIcon': {
154
+ '.cm-tooltip-autocomplete ul li': {},
155
+ '.cm-tooltip-autocomplete ul li[aria-selected]': {},
156
+ '.cm-completionIcon': {
182
157
  display: 'none',
183
158
  },
184
- '& .cm-completionLabel': {
159
+ '.cm-completionLabel': {
185
160
  fontFamily: get(tokens, 'fontFamily.body', []).join(','),
186
161
  },
187
- '& .cm-completionMatchedText': {
162
+ '.cm-completionMatchedText': {
188
163
  textDecoration: 'none',
189
164
  },
190
165
 
191
- //
192
- // widgets
193
- //
194
- '& .cm-widgetBuffer': {
195
- display: 'none',
196
- height: 0,
197
- },
198
-
199
166
  //
200
167
  // table
201
168
  //
202
- '& .cm-table *': {
169
+ '.cm-table *': {
203
170
  fontFamily: `${get(tokens, 'fontFamily.mono', []).join(',')} !important`,
204
171
  textDecoration: 'none !important',
205
172
  },
206
- '& .cm-table-head': {
173
+ '.cm-table-head': {
207
174
  padding: '2px 16px 2px 0px',
208
175
  borderBottom: `1px solid ${get(tokens, 'extend.colors.neutral.500')}`,
209
176
  fontWeight: 100,
210
177
  textAlign: 'left',
211
178
  color: get(tokens, 'extend.colors.neutral.500'),
212
179
  },
213
- '& .cm-table-cell': {
180
+ '.cm-table-cell': {
214
181
  padding: '2px 16px 2px 0px',
215
182
  },
216
183
 
217
184
  //
218
185
  // image
219
186
  //
220
- '& .cm-image': {
221
- margin: '0.5rem 0',
187
+ '.cm-image': {
188
+ display: 'block',
189
+ height: '0',
190
+ },
191
+ '.cm-image.cm-loaded-image': {
192
+ height: 'auto',
193
+ borderTop: '0.5rem solid transparent',
194
+ borderBottom: '0.5rem solid transparent',
222
195
  },
223
196
 
224
197
  //
225
198
  // font size
226
- // 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.
199
+ // TODO(thure): This appears to be the best or only way to set selection caret heights,
200
+ // but it's far more verbose than it needs to be.
227
201
  //
228
- ...Object.keys(get(tokens, 'extend.fontSize', {})).reduce((acc: Record<string, any>, fontSize) => {
229
- const height = get(tokens, ['extend', 'fontSize', fontSize, 1, 'lineHeight']);
230
-
231
- acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = { height };
232
- acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = { height };
233
- acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = { height };
234
- return acc;
235
- }, {}),
202
+ // ...Object.keys(get(tokens, 'extend.fontSize', {})).reduce((acc: Record<string, any>, fontSize) => {
203
+ // const height = get(tokens, ['extend', 'fontSize', fontSize, 1, 'lineHeight']);
204
+ //
205
+ // acc[`& .text-${fontSize} + .cm-ySelectionCaret`] = { height };
206
+ // acc[`& .text-${fontSize} + .cm-ySelection + .cm-ySelectionCaret`] = { height };
207
+ // acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = { height };
208
+ // return acc;
209
+ // }, {}),
236
210
 
237
211
  /**
238
212
  * Panels
@@ -250,14 +224,14 @@ export const defaultTheme: ThemeStyles = {
250
224
  * </div>
251
225
  * </div
252
226
  */
253
- '& .cm-panels': {
227
+ '.cm-panels': {
254
228
  border: `1px solid ${get(tokens, 'extend.colors.neutral.200')}`,
255
229
  },
256
- '& .cm-panel': {
230
+ '.cm-panel': {
257
231
  background: get(tokens, 'extend.colors.neutral.50'),
258
232
  fontFamily: get(tokens, 'fontFamily.body', []).join(','),
259
233
  },
260
- '& .cm-button': {
234
+ '.cm-button': {
261
235
  margin: '4px',
262
236
  fontFamily: get(tokens, 'fontFamily.body', []).join(','),
263
237
  background: get(tokens, 'extend.colors.neutral.100'),
@@ -271,32 +245,34 @@ export const defaultTheme: ThemeStyles = {
271
245
  backgroundImage: 'none',
272
246
  },
273
247
  },
274
- '& .cm-panel input[type=checkbox]': {
248
+ '.cm-panel input[type=checkbox]': {
275
249
  marginRight: '0.4rem !important',
276
250
  },
277
251
  };
278
252
 
279
253
  export const textTheme: ThemeStyles = {
280
- '& .cm-scroller': {
254
+ '.cm-scroller': {
281
255
  fontFamily: get(tokens, 'fontFamily.body', []).join(','),
282
256
  },
283
- '& .cm-placeholder': {
257
+ '.cm-placeholder': {
284
258
  fontFamily: get(tokens, 'fontFamily.body', []).join(','),
285
259
  },
286
260
  };
287
261
 
288
262
  export const markdownTheme: ThemeStyles = {
289
- // NOTE: Must leave base font family as is (i.e., monospace) due to fenced code blocks.
290
- '& .cm-placeholder': {
263
+ '.cm-scroller': {
264
+ fontFamily: get(tokens, 'fontFamily.body', []).join(','),
265
+ },
266
+ '.cm-placeholder': {
291
267
  fontFamily: get(tokens, 'fontFamily.body', []).join(','),
292
268
  },
293
269
  };
294
270
 
295
271
  export const codeTheme: ThemeStyles = {
296
- '& .cm-scroller': {
272
+ '.cm-scroller': {
297
273
  fontFamily: get(tokens, 'fontFamily.mono', []).join(','),
298
274
  },
299
- '& .cm-placeholder': {
275
+ '.cm-placeholder': {
300
276
  fontFamily: get(tokens, 'fontFamily.mono', []).join(','),
301
277
  },
302
278
  };
package/src/util.ts ADDED
@@ -0,0 +1,41 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import type { Transaction } from '@codemirror/state';
6
+
7
+ import { log } from '@dxos/log';
8
+
9
+ /**
10
+ * CodeMirror callbacks swallow errors so wrap handlers.
11
+ */
12
+ // TODO(burdon): EditorView.exceptionSink should catch errors.
13
+ export const callbackWrapper = <T extends Function>(fn: T): T =>
14
+ ((...args: any[]) => {
15
+ try {
16
+ return fn(...args);
17
+ } catch (err) {
18
+ log.catch(err);
19
+ }
20
+ }) as unknown as T;
21
+
22
+ export const logChanges = (trs: readonly Transaction[]) => {
23
+ const changes = trs
24
+ .flatMap((tr) => {
25
+ if (tr.changes.empty) {
26
+ return undefined;
27
+ }
28
+
29
+ const changes: any[] = [];
30
+ tr.changes.iterChanges((fromA, toA, fromB, toB, inserted) =>
31
+ changes.push(JSON.stringify({ fromA, toA, fromB, toB, inserted: inserted.toString() })),
32
+ );
33
+
34
+ return changes;
35
+ })
36
+ .filter(Boolean);
37
+
38
+ if (changes.length) {
39
+ console.log('changes', changes);
40
+ }
41
+ };
@@ -1,12 +0,0 @@
1
- import { type StoryObj } from '@storybook/html';
2
- import { Client, type PublicKey } from '@dxos/react-client';
3
- declare const _default: {
4
- title: string;
5
- };
6
- export default _default;
7
- export declare const Default: StoryObj<{
8
- id: number;
9
- client: Client;
10
- spaceKey: PublicKey;
11
- }>;
12
- //# sourceMappingURL=codemirror.stories.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"codemirror.stories.d.ts","sourceRoot":"","sources":["../../../../../src/components/TextEditor/codemirror.stories.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAMhD,OAAO,EAAE,MAAM,EAAE,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;;;;AAU5D,wBAEE;AAqEF,eAAO,MAAM,OAAO,EAAE,QAAQ,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,SAAS,CAAA;CAAE,CAoBjF,CAAC"}
@@ -1,12 +0,0 @@
1
- import '@dxosTheme';
2
- import React from 'react';
3
- declare const _default: {
4
- title: string;
5
- component: React.ForwardRefExoticComponent<import("./TextEditor").TextEditorProps & React.RefAttributes<import("./TextEditor").TextEditorRef>>;
6
- decorators: import("@storybook/react").Decorator[];
7
- };
8
- export default _default;
9
- export declare const Default: {
10
- render: () => JSX.Element;
11
- };
12
- //# sourceMappingURL=yjs.stories.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"yjs.stories.d.ts","sourceRoot":"","sources":["../../../../../src/components/TextEditor/yjs.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,YAAY,CAAC;AAEpB,OAAO,KAAmB,MAAM,OAAO,CAAC;;;;;;AAWxC,wBAIE;AA+BF,eAAO,MAAM,OAAO;;CAGnB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"code.d.ts","sourceRoot":"","sources":["../../../../src/extensions/code.ts"],"names":[],"mappings":"AAuDA,eAAO,MAAM,IAAI,+CA2ChB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"hr.d.ts","sourceRoot":"","sources":["../../../../src/extensions/hr.ts"],"names":[],"mappings":"AAmDA,eAAO,MAAM,EAAE,+CAsBd,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../../../src/extensions/image.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,KAAK,SAAS,EAKf,MAAM,mBAAmB,CAAC;AAG3B,MAAM,MAAM,YAAY,GAAG,EAAE,CAAC;AAE9B,eAAO,MAAM,KAAK,aAAa,YAAY,KAAQ,SAMlD,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../../../src/extensions/link.ts"],"names":[],"mappings":"AAMA,OAAO,EAEL,KAAK,SAAS,EAKf,MAAM,mBAAmB,CAAC;AAW3B,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/C,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,IAAI,aAAa,WAAW,KAAQ,SAyDhD,CAAC"}
@@ -1,3 +0,0 @@
1
- import { type Extension } from '@codemirror/state';
2
- export declare const mermaid: () => Extension;
3
- //# sourceMappingURL=mermaid.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"mermaid.d.ts","sourceRoot":"","sources":["../../../../src/extensions/mermaid.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAInD,eAAO,MAAM,OAAO,QAAO,SAE1B,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../../../src/extensions/table.ts"],"names":[],"mappings":"AAKA,OAAO,EAAoB,KAAK,QAAQ,EAAmB,UAAU,EAAoB,MAAM,mBAAmB,CAAC;AASnH,MAAM,MAAM,YAAY,GAAG,EAAE,CAAC;AAE9B;;;GAGG;AACH,eAAO,MAAM,KAAK,aAAa,YAAY,8BAM1C,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"tasklist.d.ts","sourceRoot":"","sources":["../../../../src/extensions/tasklist.ts"],"names":[],"mappings":"AA+DA,MAAM,MAAM,eAAe,GAAG,EAAE,CAAC;AAEjC,eAAO,MAAM,QAAQ,aAAa,eAAe,4CAuDhD,CAAC"}
@@ -1,4 +0,0 @@
1
- import * as Y from 'yjs';
2
- import { type CursorConverter } from '../../util';
3
- export declare const cursorConverter: (text: Y.Text) => CursorConverter;
4
- //# sourceMappingURL=cursor.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../../../../src/extensions/yjs/cursor.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAIzB,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,eAAO,MAAM,eAAe,SAAU,MAAM,KAAG,eAU7C,CAAC"}
@@ -1,2 +0,0 @@
1
- export * from './yjs';
2
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/extensions/yjs/index.ts"],"names":[],"mappings":"AAIA,cAAc,OAAO,CAAC"}
@@ -1,4 +0,0 @@
1
- import type * as YP from 'y-protocols/awareness';
2
- import type { YText } from '@dxos/text-model';
3
- export declare const yjs: (content: YText, awareness?: YP.Awareness) => import("@codemirror/state").Extension[];
4
- //# sourceMappingURL=yjs.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"yjs.d.ts","sourceRoot":"","sources":["../../../../../src/extensions/yjs/yjs.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAK9C,eAAO,MAAM,GAAG,YAAa,KAAK,cAAc,GAAG,SAAS,4CAG3D,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=yjs.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"yjs.test.d.ts","sourceRoot":"","sources":["../../../../../src/extensions/yjs/yjs.test.ts"],"names":[],"mappings":""}
@@ -1,3 +0,0 @@
1
- import { type EditorModel, type UseTextModelProps } from './useTextModel';
2
- export declare const createAutomergeModel: ({ space, identity, text }: UseTextModelProps) => EditorModel;
3
- //# sourceMappingURL=automerge.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"automerge.d.ts","sourceRoot":"","sources":["../../../../src/hooks/automerge.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,WAAW,EAAc,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAItF,eAAO,MAAM,oBAAoB,8BAA+B,iBAAiB,KAAG,WAqCnF,CAAC"}