@dxos/plugin-markdown 0.8.2-main.fbd8ed0 → 0.8.2-staging.4d6ad0f

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 (171) hide show
  1. package/dist/lib/browser/{MarkdownContainer-KKWICAKV.mjs → MarkdownContainer-NNE5SMES.mjs} +299 -262
  2. package/dist/lib/browser/MarkdownContainer-NNE5SMES.mjs.map +7 -0
  3. package/dist/lib/browser/MarkdownPreview-YW5CS3ID.mjs +87 -0
  4. package/dist/lib/{node-esm/MarkdownPreview-KYWRMBRM.mjs.map → browser/MarkdownPreview-YW5CS3ID.mjs.map} +1 -1
  5. package/dist/lib/browser/anchor-sort-VS4OZVPP.mjs +32 -0
  6. package/dist/lib/browser/anchor-sort-VS4OZVPP.mjs.map +7 -0
  7. package/dist/lib/browser/{app-graph-serializer-MPJQUYTQ.mjs → app-graph-serializer-V6RLEHVY.mjs} +3 -3
  8. package/dist/lib/browser/{artifact-definition-DAF3YCVL.mjs → artifact-definition-5NAODQLG.mjs} +61 -14
  9. package/dist/lib/browser/artifact-definition-5NAODQLG.mjs.map +7 -0
  10. package/dist/lib/browser/{chunk-S42YXFZ7.mjs → chunk-77NGW7EO.mjs} +5 -6
  11. package/dist/lib/browser/chunk-77NGW7EO.mjs.map +7 -0
  12. package/dist/lib/browser/{chunk-TUCSFCS5.mjs → chunk-C5RABVIX.mjs} +2 -2
  13. package/dist/lib/browser/{chunk-XP2ZPCLI.mjs → chunk-ECSM56YC.mjs} +15 -22
  14. package/dist/lib/browser/chunk-ECSM56YC.mjs.map +7 -0
  15. package/dist/lib/browser/{chunk-NAGMSX77.mjs → chunk-QVJETNGS.mjs} +2 -2
  16. package/dist/lib/{node-esm/chunk-ETXPC5VP.mjs.map → browser/chunk-QVJETNGS.mjs.map} +1 -1
  17. package/dist/lib/browser/chunk-Z7VSZKOO.mjs +20 -0
  18. package/dist/lib/browser/chunk-Z7VSZKOO.mjs.map +7 -0
  19. package/dist/lib/browser/index.mjs +29 -17
  20. package/dist/lib/browser/index.mjs.map +3 -3
  21. package/dist/lib/browser/intent-resolver-4GDYST4Y.mjs +65 -0
  22. package/dist/lib/browser/intent-resolver-4GDYST4Y.mjs.map +7 -0
  23. package/dist/lib/browser/meta.json +1 -1
  24. package/dist/lib/browser/{react-surface-EMQV3GVI.mjs → react-surface-LDVROHXZ.mjs} +75 -62
  25. package/dist/lib/browser/react-surface-LDVROHXZ.mjs.map +7 -0
  26. package/dist/lib/browser/{settings-GPB6WOIU.mjs → settings-W5CK4PXP.mjs} +2 -2
  27. package/dist/lib/browser/{state-XTP5IP3W.mjs → state-KI6PJ6DT.mjs} +2 -2
  28. package/dist/lib/browser/types/index.mjs +1 -1
  29. package/dist/lib/node/{MarkdownContainer-LBI6ZESS.cjs → MarkdownContainer-LFCR2YMB.cjs} +304 -267
  30. package/dist/lib/node/MarkdownContainer-LFCR2YMB.cjs.map +7 -0
  31. package/dist/lib/node/MarkdownPreview-G34HSQEB.cjs +110 -0
  32. package/dist/lib/node/{MarkdownPreview-O3BR4PZW.cjs.map → MarkdownPreview-G34HSQEB.cjs.map} +1 -1
  33. package/dist/lib/node/{thread-NWBGBGOR.cjs → anchor-sort-NHVF23EU.cjs} +15 -20
  34. package/dist/lib/node/anchor-sort-NHVF23EU.cjs.map +7 -0
  35. package/dist/lib/node/{app-graph-serializer-Z7UJYSSL.cjs → app-graph-serializer-CLALIYN3.cjs} +9 -9
  36. package/dist/lib/node/{artifact-definition-UIZSL2AL.cjs → artifact-definition-VEAHK7BX.cjs} +65 -19
  37. package/dist/lib/node/artifact-definition-VEAHK7BX.cjs.map +7 -0
  38. package/dist/lib/node/{chunk-AJHB57YQ.cjs → chunk-3KDAJADP.cjs} +15 -15
  39. package/dist/lib/node/chunk-3KDAJADP.cjs.map +7 -0
  40. package/dist/lib/node/{chunk-BWRBWEKN.cjs → chunk-G7RBJX22.cjs} +8 -9
  41. package/dist/lib/node/chunk-G7RBJX22.cjs.map +7 -0
  42. package/dist/lib/node/{chunk-DZXTXSXX.cjs → chunk-IFYSBQE5.cjs} +5 -5
  43. package/dist/lib/node/{chunk-DZXTXSXX.cjs.map → chunk-IFYSBQE5.cjs.map} +1 -1
  44. package/dist/lib/node/{chunk-EO5H4OZJ.cjs → chunk-RQS4KBMG.cjs} +13 -20
  45. package/dist/lib/node/chunk-RQS4KBMG.cjs.map +7 -0
  46. package/dist/lib/node/{chunk-4525YF72.cjs → chunk-ZDTL47I7.cjs} +6 -6
  47. package/dist/lib/node/index.cjs +41 -29
  48. package/dist/lib/node/index.cjs.map +3 -3
  49. package/dist/lib/node/intent-resolver-AUZVK3NZ.cjs +78 -0
  50. package/dist/lib/node/intent-resolver-AUZVK3NZ.cjs.map +7 -0
  51. package/dist/lib/node/meta.json +1 -1
  52. package/dist/lib/node/{react-surface-REHX3ABQ.cjs → react-surface-QM65PGDI.cjs} +84 -71
  53. package/dist/lib/node/react-surface-QM65PGDI.cjs.map +7 -0
  54. package/dist/lib/node/{settings-SF6JDJG6.cjs → settings-IRKU3WPM.cjs} +6 -6
  55. package/dist/lib/node/{state-K4IPZTRO.cjs → state-KKDRAG7X.cjs} +6 -6
  56. package/dist/lib/node/types/index.cjs +7 -7
  57. package/dist/lib/node/types/index.cjs.map +1 -1
  58. package/dist/lib/node-esm/{MarkdownContainer-62XZY5EP.mjs → MarkdownContainer-HUOBFKZR.mjs} +299 -262
  59. package/dist/lib/node-esm/MarkdownContainer-HUOBFKZR.mjs.map +7 -0
  60. package/dist/lib/node-esm/MarkdownPreview-TCV7BI32.mjs +88 -0
  61. package/dist/lib/{browser/MarkdownPreview-FVSYVJGN.mjs.map → node-esm/MarkdownPreview-TCV7BI32.mjs.map} +1 -1
  62. package/dist/lib/node-esm/anchor-sort-G2HLCYFK.mjs +33 -0
  63. package/dist/lib/node-esm/anchor-sort-G2HLCYFK.mjs.map +7 -0
  64. package/dist/lib/node-esm/{app-graph-serializer-DDMFMNYI.mjs → app-graph-serializer-C3RNTQGM.mjs} +3 -3
  65. package/dist/lib/node-esm/{artifact-definition-ER3446S7.mjs → artifact-definition-7TIJW2CO.mjs} +61 -14
  66. package/dist/lib/node-esm/artifact-definition-7TIJW2CO.mjs.map +7 -0
  67. package/dist/lib/node-esm/{chunk-T5Z5BIOF.mjs → chunk-4444OQSA.mjs} +10 -10
  68. package/dist/lib/node-esm/chunk-4444OQSA.mjs.map +7 -0
  69. package/dist/lib/node-esm/{chunk-PDD5B7EO.mjs → chunk-6RPARLIK.mjs} +5 -6
  70. package/dist/lib/node-esm/chunk-6RPARLIK.mjs.map +7 -0
  71. package/dist/lib/node-esm/{chunk-ETXPC5VP.mjs → chunk-JXXDCSMW.mjs} +2 -2
  72. package/dist/lib/{browser/chunk-NAGMSX77.mjs.map → node-esm/chunk-JXXDCSMW.mjs.map} +1 -1
  73. package/dist/lib/node-esm/{chunk-66XM3JMR.mjs → chunk-NCMPVEXO.mjs} +15 -22
  74. package/dist/lib/node-esm/chunk-NCMPVEXO.mjs.map +7 -0
  75. package/dist/lib/node-esm/{chunk-CXTVDT5U.mjs → chunk-TCFJNUAE.mjs} +2 -2
  76. package/dist/lib/node-esm/index.mjs +29 -17
  77. package/dist/lib/node-esm/index.mjs.map +3 -3
  78. package/dist/lib/node-esm/intent-resolver-FTNXUNI2.mjs +66 -0
  79. package/dist/lib/node-esm/intent-resolver-FTNXUNI2.mjs.map +7 -0
  80. package/dist/lib/node-esm/meta.json +1 -1
  81. package/dist/lib/node-esm/{react-surface-FA7JYF2A.mjs → react-surface-5QZ76RZA.mjs} +75 -62
  82. package/dist/lib/node-esm/react-surface-5QZ76RZA.mjs.map +7 -0
  83. package/dist/lib/node-esm/{settings-2DT2C4RA.mjs → settings-MK7D7LHQ.mjs} +2 -2
  84. package/dist/lib/node-esm/{state-7VFYPF6Z.mjs → state-LLGVRYKL.mjs} +2 -2
  85. package/dist/lib/node-esm/types/index.mjs +1 -1
  86. package/dist/types/src/MarkdownPlugin.d.ts.map +1 -1
  87. package/dist/types/src/capabilities/anchor-sort.d.ts +6 -0
  88. package/dist/types/src/capabilities/anchor-sort.d.ts.map +1 -0
  89. package/dist/types/src/capabilities/artifact-definition.d.ts.map +1 -1
  90. package/dist/types/src/capabilities/index.d.ts +4 -4
  91. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  92. package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
  93. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  94. package/dist/types/src/components/MarkdownContainer.d.ts +3 -1
  95. package/dist/types/src/components/MarkdownContainer.d.ts.map +1 -1
  96. package/dist/types/src/components/MarkdownEditor/MarkdownEditor.d.ts +3 -3
  97. package/dist/types/src/components/MarkdownEditor/MarkdownEditor.d.ts.map +1 -1
  98. package/dist/types/src/components/MarkdownPreview/MarkdownPreview.stories.d.ts +0 -104
  99. package/dist/types/src/components/MarkdownPreview/MarkdownPreview.stories.d.ts.map +1 -1
  100. package/dist/types/src/components/Suggestions.stories.d.ts.map +1 -1
  101. package/dist/types/src/components/index.d.ts +1 -1
  102. package/dist/types/src/components/index.d.ts.map +1 -1
  103. package/dist/types/src/extensions.d.ts +4 -1
  104. package/dist/types/src/extensions.d.ts.map +1 -1
  105. package/dist/types/src/types/schema.d.ts +1 -314
  106. package/dist/types/src/types/schema.d.ts.map +1 -1
  107. package/dist/types/src/types/types.d.ts +7 -109
  108. package/dist/types/src/types/types.d.ts.map +1 -1
  109. package/package.json +47 -40
  110. package/src/MarkdownPlugin.tsx +17 -7
  111. package/src/capabilities/anchor-sort.ts +30 -0
  112. package/src/capabilities/artifact-definition.ts +43 -7
  113. package/src/capabilities/index.ts +1 -1
  114. package/src/capabilities/intent-resolver.ts +23 -28
  115. package/src/capabilities/react-surface.tsx +7 -0
  116. package/src/components/MarkdownContainer.tsx +16 -3
  117. package/src/components/MarkdownEditor/MarkdownEditor.tsx +8 -29
  118. package/src/components/MarkdownPreview/MarkdownPreview.stories.tsx +0 -1
  119. package/src/components/Suggestions.stories.tsx +40 -15
  120. package/src/components/Toolbar.stories.tsx +2 -2
  121. package/src/extensions.tsx +40 -11
  122. package/src/types/schema.ts +7 -13
  123. package/src/util.tsx +2 -2
  124. package/dist/lib/browser/MarkdownContainer-KKWICAKV.mjs.map +0 -7
  125. package/dist/lib/browser/MarkdownPreview-FVSYVJGN.mjs +0 -81
  126. package/dist/lib/browser/artifact-definition-DAF3YCVL.mjs.map +0 -7
  127. package/dist/lib/browser/chunk-JJY5LKZS.mjs +0 -20
  128. package/dist/lib/browser/chunk-JJY5LKZS.mjs.map +0 -7
  129. package/dist/lib/browser/chunk-S42YXFZ7.mjs.map +0 -7
  130. package/dist/lib/browser/chunk-XP2ZPCLI.mjs.map +0 -7
  131. package/dist/lib/browser/intent-resolver-PVKVTAFF.mjs +0 -81
  132. package/dist/lib/browser/intent-resolver-PVKVTAFF.mjs.map +0 -7
  133. package/dist/lib/browser/react-surface-EMQV3GVI.mjs.map +0 -7
  134. package/dist/lib/browser/thread-KW43PJ53.mjs +0 -37
  135. package/dist/lib/browser/thread-KW43PJ53.mjs.map +0 -7
  136. package/dist/lib/node/MarkdownContainer-LBI6ZESS.cjs.map +0 -7
  137. package/dist/lib/node/MarkdownPreview-O3BR4PZW.cjs +0 -104
  138. package/dist/lib/node/artifact-definition-UIZSL2AL.cjs.map +0 -7
  139. package/dist/lib/node/chunk-AJHB57YQ.cjs.map +0 -7
  140. package/dist/lib/node/chunk-BWRBWEKN.cjs.map +0 -7
  141. package/dist/lib/node/chunk-EO5H4OZJ.cjs.map +0 -7
  142. package/dist/lib/node/intent-resolver-ND7PSRJX.cjs +0 -94
  143. package/dist/lib/node/intent-resolver-ND7PSRJX.cjs.map +0 -7
  144. package/dist/lib/node/react-surface-REHX3ABQ.cjs.map +0 -7
  145. package/dist/lib/node/thread-NWBGBGOR.cjs.map +0 -7
  146. package/dist/lib/node-esm/MarkdownContainer-62XZY5EP.mjs.map +0 -7
  147. package/dist/lib/node-esm/MarkdownPreview-KYWRMBRM.mjs +0 -82
  148. package/dist/lib/node-esm/artifact-definition-ER3446S7.mjs.map +0 -7
  149. package/dist/lib/node-esm/chunk-66XM3JMR.mjs.map +0 -7
  150. package/dist/lib/node-esm/chunk-PDD5B7EO.mjs.map +0 -7
  151. package/dist/lib/node-esm/chunk-T5Z5BIOF.mjs.map +0 -7
  152. package/dist/lib/node-esm/intent-resolver-5BF5PLSN.mjs +0 -82
  153. package/dist/lib/node-esm/intent-resolver-5BF5PLSN.mjs.map +0 -7
  154. package/dist/lib/node-esm/react-surface-FA7JYF2A.mjs.map +0 -7
  155. package/dist/lib/node-esm/thread-D2E6W44K.mjs +0 -38
  156. package/dist/lib/node-esm/thread-D2E6W44K.mjs.map +0 -7
  157. package/dist/types/src/capabilities/thread.d.ts +0 -6
  158. package/dist/types/src/capabilities/thread.d.ts.map +0 -1
  159. package/src/capabilities/thread.ts +0 -35
  160. /package/dist/lib/browser/{app-graph-serializer-MPJQUYTQ.mjs.map → app-graph-serializer-V6RLEHVY.mjs.map} +0 -0
  161. /package/dist/lib/browser/{chunk-TUCSFCS5.mjs.map → chunk-C5RABVIX.mjs.map} +0 -0
  162. /package/dist/lib/browser/{settings-GPB6WOIU.mjs.map → settings-W5CK4PXP.mjs.map} +0 -0
  163. /package/dist/lib/browser/{state-XTP5IP3W.mjs.map → state-KI6PJ6DT.mjs.map} +0 -0
  164. /package/dist/lib/node/{app-graph-serializer-Z7UJYSSL.cjs.map → app-graph-serializer-CLALIYN3.cjs.map} +0 -0
  165. /package/dist/lib/node/{chunk-4525YF72.cjs.map → chunk-ZDTL47I7.cjs.map} +0 -0
  166. /package/dist/lib/node/{settings-SF6JDJG6.cjs.map → settings-IRKU3WPM.cjs.map} +0 -0
  167. /package/dist/lib/node/{state-K4IPZTRO.cjs.map → state-KKDRAG7X.cjs.map} +0 -0
  168. /package/dist/lib/node-esm/{app-graph-serializer-DDMFMNYI.mjs.map → app-graph-serializer-C3RNTQGM.mjs.map} +0 -0
  169. /package/dist/lib/node-esm/{chunk-CXTVDT5U.mjs.map → chunk-TCFJNUAE.mjs.map} +0 -0
  170. /package/dist/lib/node-esm/{settings-2DT2C4RA.mjs.map → settings-MK7D7LHQ.mjs.map} +0 -0
  171. /package/dist/lib/node-esm/{state-7VFYPF6Z.mjs.map → state-LLGVRYKL.mjs.map} +0 -0
@@ -2,11 +2,13 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
+ import { Rx } from '@effect-rx/rx-react';
5
6
  import React, { useEffect, useMemo } from 'react';
6
7
 
7
- import { Capabilities, useCapabilities } from '@dxos/app-framework';
8
+ import { Capabilities, useAppGraph, useCapabilities } from '@dxos/app-framework';
8
9
  import { isInstanceOf } from '@dxos/echo-schema';
9
10
  import { fullyQualifiedId, getSpace } from '@dxos/react-client/echo';
11
+ import { type SelectionManager } from '@dxos/react-ui-attention';
10
12
  import { DataType } from '@dxos/schema';
11
13
 
12
14
  import { MarkdownEditor, type MarkdownEditorProps } from './MarkdownEditor';
@@ -21,6 +23,7 @@ export type MarkdownContainerProps = Pick<
21
23
  id: string;
22
24
  object: DocumentType | DataType.Text | any;
23
25
  settings: MarkdownSettingsProps;
26
+ selectionManager?: SelectionManager;
24
27
  };
25
28
 
26
29
  // TODO(burdon): Factor out difference for ECHO and non-ECHO objects; i.e., single component.
@@ -29,6 +32,7 @@ const MarkdownContainer = ({
29
32
  role,
30
33
  object,
31
34
  settings,
35
+ selectionManager,
32
36
  viewMode,
33
37
  editorStateStore,
34
38
  onViewModeChange,
@@ -36,7 +40,7 @@ const MarkdownContainer = ({
36
40
  const scrollPastEnd = role === 'article';
37
41
  const doc = isInstanceOf(DocumentType, object) ? object : undefined;
38
42
  const text = isInstanceOf(DataType.Text, object) ? object : undefined;
39
- const extensions = useExtensions({ document: doc, text, id, settings, viewMode, editorStateStore });
43
+ const extensions = useExtensions({ document: doc, text, id, settings, selectionManager, viewMode, editorStateStore });
40
44
 
41
45
  if (doc) {
42
46
  return (
@@ -60,7 +64,6 @@ const MarkdownContainer = ({
60
64
  extensions={extensions}
61
65
  viewMode={viewMode}
62
66
  toolbar={settings.toolbar}
63
- comment={false}
64
67
  inputMode={settings.editorInputMode}
65
68
  scrollPastEnd={scrollPastEnd}
66
69
  onViewModeChange={onViewModeChange}
@@ -115,12 +118,22 @@ export const DocumentEditor = ({ id, document: doc, settings, viewMode, ...props
115
118
  return async (file: File) => upload!(file, space);
116
119
  }, [space, upload]);
117
120
 
121
+ const { graph } = useAppGraph();
122
+ const customActions = useMemo(() => {
123
+ return Rx.make((get) => {
124
+ const actions = get(graph.actions(id));
125
+ const nodes = actions.filter((action) => action.properties.disposition === 'toolbar');
126
+ return { nodes, edges: nodes.map((node) => ({ source: 'root', target: node.id })) };
127
+ });
128
+ }, [graph]);
129
+
118
130
  return (
119
131
  <MarkdownEditor
120
132
  id={id}
121
133
  initialValue={doc.content?.target?.content}
122
134
  viewMode={viewMode}
123
135
  toolbar={settings.toolbar}
136
+ customActions={customActions}
124
137
  inputMode={settings.editorInputMode}
125
138
  onFileUpload={handleFileUpload}
126
139
  {...props}
@@ -6,9 +6,8 @@ import { type EditorView } from '@codemirror/view';
6
6
  import React, { useMemo, useEffect, useCallback } from 'react';
7
7
  import { useDropzone } from 'react-dropzone';
8
8
 
9
- import { createIntent, type FileInfo, useIntentDispatcher } from '@dxos/app-framework';
9
+ import { type FileInfo } from '@dxos/app-framework';
10
10
  import { invariant } from '@dxos/invariant';
11
- import { ATTENDABLE_PATH_SEPARATOR, DeckAction } from '@dxos/plugin-deck/types';
12
11
  import { useThemeContext, useTranslation } from '@dxos/react-ui';
13
12
  import {
14
13
  type DNDOptions,
@@ -22,16 +21,15 @@ import {
22
21
  createMarkdownExtensions,
23
22
  createThemeExtensions,
24
23
  dropFile,
25
- editorContent,
24
+ editorSlots,
26
25
  editorGutter,
27
26
  processEditorPayload,
28
27
  stackItemContentEditorClassNames,
29
- useCommentState,
30
- useCommentClickListener,
31
28
  useFormattingState,
32
29
  useTextEditor,
33
30
  useEditorToolbarState,
34
31
  addLink,
32
+ type EditorToolbarActionGraphProps,
35
33
  } from '@dxos/react-ui-editor';
36
34
  import { StackItem } from '@dxos/react-ui-stack';
37
35
  import { isNotFalsy, isNonNullable } from '@dxos/util';
@@ -46,8 +44,8 @@ export type MarkdownEditorProps = {
46
44
  inputMode?: EditorInputMode;
47
45
  scrollPastEnd?: boolean;
48
46
  toolbar?: boolean;
47
+ customActions?: EditorToolbarActionGraphProps['customActions'];
49
48
  // TODO(wittjosiah): Generalize custom toolbar actions (e.g. comment, upload, etc.)
50
- comment?: boolean;
51
49
  viewMode?: EditorViewMode;
52
50
  editorStateStore?: EditorStateStore;
53
51
  onViewModeChange?: (id: string, mode: EditorViewMode) => void;
@@ -69,7 +67,7 @@ export const MarkdownEditor = ({
69
67
  extensionProviders,
70
68
  scrollPastEnd,
71
69
  toolbar,
72
- comment = true,
70
+ customActions,
73
71
  viewMode,
74
72
  editorStateStore,
75
73
  onFileUpload,
@@ -77,7 +75,6 @@ export const MarkdownEditor = ({
77
75
  }: MarkdownEditorProps) => {
78
76
  const { t } = useTranslation(MARKDOWN_PLUGIN);
79
77
  const { themeMode } = useThemeContext();
80
- const { dispatchPromise: dispatch } = useIntentDispatcher();
81
78
  const toolbarState = useEditorToolbarState({ viewMode });
82
79
  const formattingObserver = useFormattingState(toolbarState);
83
80
 
@@ -91,18 +88,6 @@ export const MarkdownEditor = ({
91
88
  [extensionProviders],
92
89
  );
93
90
 
94
- // TODO(Zan): Factor out to thread plugin.
95
- const commentObserver = useCommentState(toolbarState);
96
- const onCommentClick = useCallback(async () => {
97
- await dispatch(
98
- createIntent(DeckAction.ChangeCompanion, {
99
- primary: id,
100
- companion: `${id}${ATTENDABLE_PATH_SEPARATOR}comments`,
101
- }),
102
- );
103
- }, [dispatch]);
104
- const commentClickObserver = useCommentClickListener(onCommentClick);
105
-
106
91
  // TODO(wittjosiah): Factor out to file uploader plugin.
107
92
  // Drag files.
108
93
  const handleDrop: DNDOptions['onDrop'] = async (view, { files }) => {
@@ -122,19 +107,13 @@ export const MarkdownEditor = ({
122
107
  initialValue,
123
108
  extensions: [
124
109
  formattingObserver,
125
- comment && commentObserver,
126
- comment && commentClickObserver,
127
110
  createBasicExtensions({
128
111
  readOnly: viewMode === 'readonly',
129
112
  placeholder: t('editor placeholder'),
130
113
  scrollPastEnd: role === 'section' ? false : scrollPastEnd,
131
114
  }),
132
115
  createMarkdownExtensions({ themeMode }),
133
- createThemeExtensions({
134
- themeMode,
135
- syntaxHighlighting: true,
136
- slots: { content: { className: editorContent } },
137
- }),
116
+ createThemeExtensions({ themeMode, syntaxHighlighting: true, slots: editorSlots }),
138
117
  editorGutter,
139
118
  role !== 'section' && onFileUpload && dropFile({ onDrop: handleDrop }),
140
119
  providerExtensions,
@@ -149,7 +128,7 @@ export const MarkdownEditor = ({
149
128
  moveToEndOfLine: true,
150
129
  }),
151
130
  }),
152
- [id, formattingObserver, comment, viewMode, themeMode, extensions, providerExtensions],
131
+ [id, formattingObserver, viewMode, themeMode, extensions, providerExtensions],
153
132
  );
154
133
 
155
134
  useTest(editorView);
@@ -206,8 +185,8 @@ export const MarkdownEditor = ({
206
185
  attendableId={id}
207
186
  role={role}
208
187
  state={toolbarState}
188
+ customActions={customActions}
209
189
  getView={getView}
210
- comment={comment}
211
190
  image={handleImageUpload}
212
191
  viewMode={handleViewModeChange}
213
192
  />
@@ -61,7 +61,6 @@ const data = (() => {
61
61
  content: faker.lorem.paragraphs(3),
62
62
  }),
63
63
  ),
64
- threads: [],
65
64
  });
66
65
 
67
66
  return { document };
@@ -5,9 +5,10 @@
5
5
  import '@dxos-theme';
6
6
 
7
7
  import { type Meta } from '@storybook/react';
8
- import { Schema, SchemaAST } from 'effect';
8
+ import { Match, Option, pipe, Schema } from 'effect';
9
9
  import React, { type FC, useEffect, useMemo, useState } from 'react';
10
10
 
11
+ import { Message } from '@dxos/ai';
11
12
  import {
12
13
  Capabilities,
13
14
  CollaborationActions,
@@ -19,7 +20,6 @@ import {
19
20
  useIntentDispatcher,
20
21
  } from '@dxos/app-framework';
21
22
  import { withPluginManager } from '@dxos/app-framework/testing';
22
- import { Message } from '@dxos/artifact';
23
23
  import { Type } from '@dxos/echo';
24
24
  import { create, createQueueDxn, type Expando } from '@dxos/echo-schema';
25
25
  import { invariant } from '@dxos/invariant';
@@ -31,9 +31,9 @@ import { SpacePlugin } from '@dxos/plugin-space';
31
31
  import { StorybookLayoutPlugin } from '@dxos/plugin-storybook-layout';
32
32
  import { ThemePlugin } from '@dxos/plugin-theme';
33
33
  import { faker } from '@dxos/random';
34
- import { useQueue, useSpace } from '@dxos/react-client/echo';
34
+ import { createDocAccessor, fullyQualifiedId, toCursorRange, useQueue, useSpace } from '@dxos/react-client/echo';
35
35
  import { IconButton, Toolbar } from '@dxos/react-ui';
36
- import { command, useTextEditor } from '@dxos/react-ui-editor';
36
+ import { command, type EditorSelection, type Range, useTextEditor } from '@dxos/react-ui-editor';
37
37
  import { StackItem } from '@dxos/react-ui-stack';
38
38
  import { defaultTx } from '@dxos/react-ui-theme';
39
39
  import { withLayout } from '@dxos/storybook-utils';
@@ -49,15 +49,15 @@ faker.seed(1);
49
49
 
50
50
  const TestItem = Schema.Struct({
51
51
  title: Schema.String.annotations({
52
- [SchemaAST.TitleAnnotationId]: 'Title',
53
- [SchemaAST.DescriptionAnnotationId]: 'Product title',
52
+ title: 'Title',
53
+ description: 'Product title',
54
54
  }),
55
55
  description: Schema.String.annotations({
56
- [SchemaAST.TitleAnnotationId]: 'Description',
57
- [SchemaAST.DescriptionAnnotationId]: 'Product description',
56
+ title: 'Description',
57
+ description: 'Product description',
58
58
  }),
59
59
  }).pipe(
60
- Type.def({
60
+ Type.Obj({
61
61
  typename: 'dxos.org/type/Test',
62
62
  version: '0.1.0',
63
63
  }),
@@ -66,28 +66,39 @@ const TestItem = Schema.Struct({
66
66
  const TestChat: FC<{ doc: DocumentType; content: string }> = ({ doc, content }) => {
67
67
  const { dispatchPromise: dispatch } = useIntentDispatcher();
68
68
  const { parentRef } = useTextEditor({ initialValue: content });
69
+ const { editorState } = useCapability(MarkdownCapabilities.State);
69
70
 
70
71
  const space = useSpace();
71
72
  const queueDxn = useMemo(() => space && createQueueDxn(space.id), [space]);
72
73
  const queue = useQueue<Message>(queueDxn);
73
74
 
74
- const handleInsert = () => {
75
+ const handleInsert = async () => {
75
76
  invariant(space);
76
77
  invariant(queue);
77
78
  queue.append([create(Message, { role: 'assistant', content: [{ type: 'text', text: 'Hello' }] })]);
78
- const message = queue.items[queue.items.length - 1];
79
+ const message = queue.objects.at(-1);
80
+ invariant(message);
81
+
82
+ const text = await doc.content.load();
83
+ const accessor = createDocAccessor(text, ['content']);
84
+ const cursor = pipe(
85
+ editorState.getState(fullyQualifiedId(doc))?.selection,
86
+ Option.fromNullable,
87
+ Option.map(selectionToRange),
88
+ Option.map((range) => toCursorRange(accessor, range.from, range.to)),
89
+ Option.getOrUndefined,
90
+ );
79
91
 
80
92
  // {
81
93
  // const ref = refFromDXN(new DXN(DXN.kind.QUEUE, [...queue.dxn.parts, message.id]));
82
-
83
94
  // const message = deref(ref);
84
95
  // }
85
96
 
86
97
  void dispatch(
87
98
  createIntent(CollaborationActions.InsertContent, {
88
- spaceId: space.id,
89
- target: makeRef(doc as any as Expando), // TODO(burdon): Comomon base type.
99
+ target: doc as any as Expando, // TODO(burdon): Common base type.
90
100
  object: refFromDXN(new DXN(DXN.kind.QUEUE, [...queue.dxn.parts, message.id])),
101
+ at: cursor,
91
102
  label: 'Proposal',
92
103
  }),
93
104
  );
@@ -107,6 +118,7 @@ const DefaultStory = ({ document, chat }: { document: string; chat: string }) =>
107
118
  const space = useSpace();
108
119
  const [doc, setDoc] = useState<DocumentType>();
109
120
  const settings = useCapability(Capabilities.SettingsStore).getStore<MarkdownSettingsProps>(MARKDOWN_PLUGIN)!.value;
121
+ const { editorState } = useCapability(MarkdownCapabilities.State);
110
122
 
111
123
  useEffect(() => {
112
124
  if (!space) {
@@ -135,7 +147,7 @@ const DefaultStory = ({ document, chat }: { document: string; chat: string }) =>
135
147
 
136
148
  return (
137
149
  <>
138
- <MarkdownContainer id={doc.id} object={doc} settings={settings} />
150
+ <MarkdownContainer id={doc.id} object={doc} settings={settings} editorStateStore={editorState} />
139
151
  <TestChat doc={doc} content={chat} />
140
152
  </>
141
153
  );
@@ -189,3 +201,16 @@ export const Default: Story = {
189
201
  ].join('\n'),
190
202
  },
191
203
  };
204
+
205
+ // TODO(wittjosiah): Factor out.
206
+ const selectionToRange = Match.type<EditorSelection>().pipe(
207
+ Match.when(
208
+ ({ head, anchor }) => (head ? head > anchor : false),
209
+ ({ head, anchor }) => ({ from: anchor, to: head! }) as Range,
210
+ ),
211
+ Match.when(
212
+ ({ head, anchor }) => (head ? head < anchor : false),
213
+ ({ head, anchor }) => ({ from: head!, to: anchor }) as Range,
214
+ ),
215
+ Match.orElse(({ anchor }) => ({ from: anchor, to: anchor }) as Range),
216
+ );
@@ -22,7 +22,7 @@ import {
22
22
  createMarkdownExtensions,
23
23
  createThemeExtensions,
24
24
  decorateMarkdown,
25
- editorContent,
25
+ editorSlots,
26
26
  formattingKeymap,
27
27
  translations,
28
28
  useComments,
@@ -49,7 +49,7 @@ const DefaultStory: FC<{ content?: string }> = ({ content = '' }) => {
49
49
  formattingObserver,
50
50
  createBasicExtensions({ readOnly: toolbarState.viewMode === 'readonly' }),
51
51
  createMarkdownExtensions({ themeMode }),
52
- createThemeExtensions({ themeMode, syntaxHighlighting: true, slots: { editor: { className: editorContent } } }),
52
+ createThemeExtensions({ themeMode, syntaxHighlighting: true, slots: editorSlots }),
53
53
  createDataExtensions({ id: text.id, text: createDocAccessor(text, ['content']) }),
54
54
  comments({
55
55
  onCreate: ({ cursor }) => {
@@ -16,6 +16,7 @@ import { invariant } from '@dxos/invariant';
16
16
  import { createDocAccessor, fullyQualifiedId, getSpace, type QueryResult } from '@dxos/react-client/echo';
17
17
  import { useIdentity } from '@dxos/react-client/halo';
18
18
  import { Icon, ThemeProvider } from '@dxos/react-ui';
19
+ import { type SelectionManager } from '@dxos/react-ui-attention';
19
20
  import {
20
21
  type AutocompleteResult,
21
22
  type EditorStateStore,
@@ -33,6 +34,9 @@ import {
33
34
  selectionState,
34
35
  typewriter,
35
36
  type RenderCallback,
37
+ EditorView,
38
+ documentId,
39
+ Cursor,
36
40
  } from '@dxos/react-ui-editor';
37
41
  import { defaultTx } from '@dxos/react-ui-theme';
38
42
  import { type DataType } from '@dxos/schema';
@@ -49,6 +53,7 @@ type ExtensionsOptions = {
49
53
  dispatch?: PromiseIntentDispatcher;
50
54
  query?: QueryResult<DocumentType>;
51
55
  settings: MarkdownSettingsProps;
56
+ selectionManager?: SelectionManager;
52
57
  viewMode?: EditorViewMode;
53
58
  editorStateStore?: EditorStateStore;
54
59
  };
@@ -59,6 +64,7 @@ export const useExtensions = ({
59
64
  id,
60
65
  text,
61
66
  settings,
67
+ selectionManager,
62
68
  viewMode,
63
69
  editorStateStore,
64
70
  }: ExtensionsOptions): Extension[] => {
@@ -77,6 +83,7 @@ export const useExtensions = ({
77
83
  id,
78
84
  text,
79
85
  settings,
86
+ selectionManager,
80
87
  viewMode,
81
88
  dispatch,
82
89
  // query,
@@ -93,6 +100,7 @@ export const useExtensions = ({
93
100
  settings.numberedHeadings,
94
101
  settings.debug,
95
102
  settings.typewriter,
103
+ selectionManager,
96
104
  ],
97
105
  );
98
106
 
@@ -101,18 +109,20 @@ export const useExtensions = ({
101
109
  //
102
110
  // External extensions from other plugins.
103
111
  //
104
- const pluginExtensions = useMemo<Extension[] | undefined>(
105
- () =>
106
- extensionProviders.flat().reduce((acc: Extension[], provider) => {
107
- const extension = typeof provider === 'function' ? provider({ document }) : provider;
108
- if (extension) {
109
- acc.push(extension);
110
- }
112
+ const pluginExtensions = useMemo<Extension[] | undefined>(() => {
113
+ if (!document) {
114
+ return [];
115
+ }
111
116
 
112
- return acc;
113
- }, []),
114
- [extensionProviders, document],
115
- );
117
+ extensionProviders.flat().reduce((acc: Extension[], provider) => {
118
+ const extension = typeof provider === 'function' ? provider({ document }) : provider;
119
+ if (extension) {
120
+ acc.push(extension);
121
+ }
122
+
123
+ return acc;
124
+ }, []);
125
+ }, [extensionProviders, document]);
116
126
 
117
127
  //
118
128
  // Basic plugins.
@@ -156,10 +166,12 @@ const createBaseExtensions = ({
156
166
  id,
157
167
  dispatch,
158
168
  settings,
169
+ selectionManager,
159
170
  query,
160
171
  viewMode,
161
172
  }: ExtensionsOptions): Extension[] => {
162
173
  const extensions: Extension[] = [
174
+ selectionManager && selectionChange(selectionManager),
163
175
  settings.editorInputMode && InputModeExtensions[settings.editorInputMode],
164
176
  settings.folding && folding(),
165
177
  ].filter(isNotFalsy);
@@ -230,6 +242,23 @@ const createBaseExtensions = ({
230
242
  return extensions;
231
243
  };
232
244
 
245
+ export const selectionChange = (selectionManager: SelectionManager) => {
246
+ return EditorView.updateListener.of((update) => {
247
+ if (update.selectionSet) {
248
+ const id = update.state.facet(documentId);
249
+ const cursorConverter = update.state.facet(Cursor.converter);
250
+ const selection = update.state.selection;
251
+ const ranges = selection.ranges
252
+ .map((range) => ({
253
+ from: cursorConverter.toCursor(range.from),
254
+ to: cursorConverter.toCursor(range.to),
255
+ }))
256
+ .filter(({ from, to }) => to > from);
257
+ selectionManager.updateMultiRange(id, ranges);
258
+ }
259
+ });
260
+ };
261
+
233
262
  // TODO(burdon): Factor out styles.
234
263
  const style = {
235
264
  hover: 'rounded-sm text-primary-500 hover:text-primary-600 dark:text-primary-500 hover:dark:text-primary-400',
@@ -4,25 +4,19 @@
4
4
 
5
5
  import { Schema } from 'effect';
6
6
 
7
- import { Type } from '@dxos/echo';
8
- import { Expando, LabelAnnotationId, Ref } from '@dxos/echo-schema';
9
- import { makeRef, live } from '@dxos/live-object';
10
- import { ThreadType } from '@dxos/plugin-space/types';
7
+ import { Type, Ref } from '@dxos/echo';
8
+ import { LabelAnnotation } from '@dxos/echo-schema';
9
+ import { live } from '@dxos/live-object';
11
10
  import { DataType } from '@dxos/schema';
12
11
 
13
12
  export const DocumentSchema = Schema.Struct({
14
13
  name: Schema.optional(Schema.String),
15
14
  fallbackName: Schema.optional(Schema.String),
16
- content: Ref(DataType.Text),
17
- threads: Schema.mutable(Schema.Array(Ref(ThreadType))),
18
- assistantChatQueue: Schema.optional(Ref(Expando)),
19
- }).annotations({
20
- // TODO(dmaretskyi): `Schema.Struct(...).pipe(defaultLabel(['name', 'fallbackName']))` for type-safe annotations.
21
- [LabelAnnotationId]: ['name', 'fallbackName'],
22
- });
15
+ content: Type.Ref(DataType.Text),
16
+ }).pipe(LabelAnnotation.set(['name', 'fallbackName']));
23
17
 
24
18
  export const DocumentType = DocumentSchema.pipe(
25
- Type.def({
19
+ Type.Obj({
26
20
  typename: 'dxos.org/type/Document',
27
21
  version: '0.1.0',
28
22
  }),
@@ -31,7 +25,7 @@ export type DocumentType = Schema.Schema.Type<typeof DocumentType>;
31
25
 
32
26
  // TODO(burdon): Replace when defaults are supported.
33
27
  export const createDocument = ({ name, content }: { name: string; content: string }) =>
34
- live(DocumentType, { name, content: makeRef(live(DataType.Text, { content })), threads: [] });
28
+ live(DocumentType, { name, content: Ref.make(live(DataType.Text, { content })) });
35
29
 
36
30
  /**
37
31
  * Checks if an object conforms to the interface needed to render an editor.
package/src/util.tsx CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  import { debounce } from '@dxos/async';
6
6
  import { type TypedObjectSerializer } from '@dxos/plugin-space/types';
7
- import { live, createObject, isEchoObject, loadObjectReferences, makeRef } from '@dxos/react-client/echo';
7
+ import { live, createObject, isEchoObject, loadObjectReferences, Ref } from '@dxos/react-client/echo';
8
8
  import { DataType } from '@dxos/schema';
9
9
 
10
10
  import { DocumentType, type MarkdownProperties } from './types';
@@ -42,7 +42,7 @@ export const serializer: TypedObjectSerializer<DocumentType> = {
42
42
  deserialize: async ({ content: serialized }) => {
43
43
  const { name, fallbackName, content } = JSON.parse(serialized);
44
44
  return createObject(
45
- live(DocumentType, { name, fallbackName, content: makeRef(live(DataType.Text, { content })), threads: [] }),
45
+ live(DocumentType, { name, fallbackName, content: Ref.make(live(DataType.Text, { content })) }),
46
46
  );
47
47
  },
48
48
  };
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/components/MarkdownContainer.tsx", "../../../src/components/MarkdownEditor/MarkdownEditor.tsx", "../../../src/hooks/useSelectCurrentThread.tsx", "../../../src/extensions.tsx"],
4
- "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport React, { useEffect, useMemo } from 'react';\n\nimport { Capabilities, useCapabilities } from '@dxos/app-framework';\nimport { isInstanceOf } from '@dxos/echo-schema';\nimport { fullyQualifiedId, getSpace } from '@dxos/react-client/echo';\nimport { DataType } from '@dxos/schema';\n\nimport { MarkdownEditor, type MarkdownEditorProps } from './MarkdownEditor';\nimport { useExtensions } from '../extensions';\nimport { DocumentType, type MarkdownSettingsProps } from '../types';\nimport { getFallbackName } from '../util';\n\nexport type MarkdownContainerProps = Pick<\n MarkdownEditorProps,\n 'role' | 'extensionProviders' | 'viewMode' | 'editorStateStore' | 'onViewModeChange'\n> & {\n id: string;\n object: DocumentType | DataType.Text | any;\n settings: MarkdownSettingsProps;\n};\n\n// TODO(burdon): Factor out difference for ECHO and non-ECHO objects; i.e., single component.\nconst MarkdownContainer = ({\n id,\n role,\n object,\n settings,\n viewMode,\n editorStateStore,\n onViewModeChange,\n}: MarkdownContainerProps) => {\n const scrollPastEnd = role === 'article';\n const doc = isInstanceOf(DocumentType, object) ? object : undefined;\n const text = isInstanceOf(DataType.Text, object) ? object : undefined;\n const extensions = useExtensions({ document: doc, text, id, settings, viewMode, editorStateStore });\n\n if (doc) {\n return (\n <DocumentEditor\n id={fullyQualifiedId(object)}\n role={role}\n document={doc}\n extensions={extensions}\n viewMode={viewMode}\n settings={settings}\n scrollPastEnd={scrollPastEnd}\n onViewModeChange={onViewModeChange}\n />\n );\n } else if (text) {\n return (\n <MarkdownEditor\n id={id}\n role={role}\n initialValue={text.content}\n extensions={extensions}\n viewMode={viewMode}\n toolbar={settings.toolbar}\n comment={false}\n inputMode={settings.editorInputMode}\n scrollPastEnd={scrollPastEnd}\n onViewModeChange={onViewModeChange}\n />\n );\n } else {\n // TODO(burdon): Normalize with above.\n return (\n <MarkdownEditor\n id={id}\n role={role}\n initialValue={object.text}\n extensions={extensions}\n viewMode={viewMode}\n toolbar={settings.toolbar}\n inputMode={settings.editorInputMode}\n scrollPastEnd={scrollPastEnd}\n onViewModeChange={onViewModeChange}\n />\n );\n }\n};\n\ntype DocumentEditorProps = Omit<MarkdownContainerProps, 'object' | 'extensionProviders' | 'editorStateStore'> &\n Pick<MarkdownEditorProps, 'id' | 'scrollPastEnd' | 'extensions'> & {\n document: DocumentType;\n };\n\nexport const DocumentEditor = ({ id, document: doc, settings, viewMode, ...props }: DocumentEditorProps) => {\n const space = getSpace(doc);\n\n // Migrate gradually to `fallbackName`.\n useEffect(() => {\n if (typeof doc.fallbackName === 'string') {\n return;\n }\n\n const fallbackName = doc.content?.target?.content ? getFallbackName(doc.content.target.content) : undefined;\n if (fallbackName) {\n doc.fallbackName = fallbackName;\n }\n }, [doc, doc.content]);\n\n // File dragging.\n const [upload] = useCapabilities(Capabilities.FileUploader);\n const handleFileUpload = useMemo(() => {\n if (space === undefined || upload === undefined) {\n return undefined;\n }\n\n // TODO(burdon): Re-order props: space, file.\n return async (file: File) => upload!(file, space);\n }, [space, upload]);\n\n return (\n <MarkdownEditor\n id={id}\n initialValue={doc.content?.target?.content}\n viewMode={viewMode}\n toolbar={settings.toolbar}\n inputMode={settings.editorInputMode}\n onFileUpload={handleFileUpload}\n {...props}\n />\n );\n};\n\nexport default MarkdownContainer;\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type EditorView } from '@codemirror/view';\nimport React, { useMemo, useEffect, useCallback } from 'react';\nimport { useDropzone } from 'react-dropzone';\n\nimport { createIntent, type FileInfo, useIntentDispatcher } from '@dxos/app-framework';\nimport { invariant } from '@dxos/invariant';\nimport { ATTENDABLE_PATH_SEPARATOR, DeckAction } from '@dxos/plugin-deck/types';\nimport { useThemeContext, useTranslation } from '@dxos/react-ui';\nimport {\n type DNDOptions,\n type EditorViewMode,\n type EditorInputMode,\n type EditorSelectionState,\n type EditorStateStore,\n EditorToolbar,\n type UseTextEditorProps,\n createBasicExtensions,\n createMarkdownExtensions,\n createThemeExtensions,\n dropFile,\n editorContent,\n editorGutter,\n processEditorPayload,\n stackItemContentEditorClassNames,\n useCommentState,\n useCommentClickListener,\n useFormattingState,\n useTextEditor,\n useEditorToolbarState,\n addLink,\n} from '@dxos/react-ui-editor';\nimport { StackItem } from '@dxos/react-ui-stack';\nimport { isNotFalsy, isNonNullable } from '@dxos/util';\n\nimport { useSelectCurrentThread } from '../../hooks';\nimport { MARKDOWN_PLUGIN } from '../../meta';\nimport { type MarkdownPluginState } from '../../types';\n\nexport type MarkdownEditorProps = {\n id: string;\n role?: string;\n inputMode?: EditorInputMode;\n scrollPastEnd?: boolean;\n toolbar?: boolean;\n // TODO(wittjosiah): Generalize custom toolbar actions (e.g. comment, upload, etc.)\n comment?: boolean;\n viewMode?: EditorViewMode;\n editorStateStore?: EditorStateStore;\n onViewModeChange?: (id: string, mode: EditorViewMode) => void;\n onFileUpload?: (file: File) => Promise<FileInfo | undefined>;\n} & Pick<UseTextEditorProps, 'initialValue' | 'extensions'> &\n Partial<Pick<MarkdownPluginState, 'extensionProviders'>>;\n\n/**\n * Base markdown editor component.\n *\n * This component provides all the features of the markdown editor that do no depend on ECHO.\n * This allows it to be used as a common editor for markdown content on arbitrary backends (e.g. files).\n */\nexport const MarkdownEditor = ({\n id,\n role = 'article',\n initialValue,\n extensions,\n extensionProviders,\n scrollPastEnd,\n toolbar,\n comment = true,\n viewMode,\n editorStateStore,\n onFileUpload,\n onViewModeChange,\n}: MarkdownEditorProps) => {\n const { t } = useTranslation(MARKDOWN_PLUGIN);\n const { themeMode } = useThemeContext();\n const { dispatchPromise: dispatch } = useIntentDispatcher();\n const toolbarState = useEditorToolbarState({ viewMode });\n const formattingObserver = useFormattingState(toolbarState);\n\n // Restore last selection and scroll point.\n const { scrollTo, selection } = useMemo<EditorSelectionState>(() => editorStateStore?.getState(id) ?? {}, [id]);\n\n // Extensions from other plugins.\n // TODO(burdon): Reconcile with DocumentEditor.useExtensions.\n const providerExtensions = useMemo(\n () => extensionProviders?.flatMap((provider) => provider({})).filter(isNonNullable),\n [extensionProviders],\n );\n\n // TODO(Zan): Factor out to thread plugin.\n const commentObserver = useCommentState(toolbarState);\n const onCommentClick = useCallback(async () => {\n await dispatch(\n createIntent(DeckAction.ChangeCompanion, {\n primary: id,\n companion: `${id}${ATTENDABLE_PATH_SEPARATOR}comments`,\n }),\n );\n }, [dispatch]);\n const commentClickObserver = useCommentClickListener(onCommentClick);\n\n // TODO(wittjosiah): Factor out to file uploader plugin.\n // Drag files.\n const handleDrop: DNDOptions['onDrop'] = async (view, { files }) => {\n const file = files[0];\n const info = file && onFileUpload ? await onFileUpload(file) : undefined;\n if (info) {\n processEditorPayload(view, { type: 'image', data: info.url });\n }\n };\n\n const {\n parentRef,\n view: editorView,\n focusAttributes,\n } = useTextEditor(\n () => ({\n initialValue,\n extensions: [\n formattingObserver,\n comment && commentObserver,\n comment && commentClickObserver,\n createBasicExtensions({\n readOnly: viewMode === 'readonly',\n placeholder: t('editor placeholder'),\n scrollPastEnd: role === 'section' ? false : scrollPastEnd,\n }),\n createMarkdownExtensions({ themeMode }),\n createThemeExtensions({\n themeMode,\n syntaxHighlighting: true,\n slots: { content: { className: editorContent } },\n }),\n editorGutter,\n role !== 'section' && onFileUpload && dropFile({ onDrop: handleDrop }),\n providerExtensions,\n extensions,\n ].filter(isNotFalsy),\n ...(role !== 'section' && {\n id,\n scrollTo,\n selection,\n // TODO(wittjosiah): Autofocus based on layout is racy.\n // autoFocus: layoutPlugin?.provides.layout ? layoutPlugin?.provides.layout.scrollIntoView === id : true,\n moveToEndOfLine: true,\n }),\n }),\n [id, formattingObserver, comment, viewMode, themeMode, extensions, providerExtensions],\n );\n\n useTest(editorView);\n useSelectCurrentThread(editorView, id);\n\n // https://react-dropzone.js.org/#src\n const { acceptedFiles, getInputProps, open } = useDropzone({\n multiple: false,\n noDrag: true,\n accept: {\n 'image/*': ['.jpg', '.jpeg', '.png', '.gif'],\n },\n });\n\n useEffect(() => {\n if (editorView && onFileUpload && acceptedFiles.length) {\n requestAnimationFrame(async () => {\n // NOTE: Clone file since react-dropzone patches in a non-standard `path` property, which confuses IPFS.\n const f = acceptedFiles[0];\n const file = new File([f], f.name, {\n type: f.type,\n lastModified: f.lastModified,\n });\n\n const info = await onFileUpload(file);\n if (info) {\n addLink({ url: info.url, image: true })(editorView);\n }\n });\n }\n }, [acceptedFiles, editorView, onFileUpload]);\n\n const getView = useCallback(() => {\n invariant(editorView);\n return editorView;\n }, [editorView]);\n\n const handleViewModeChange = useCallback(\n (mode: EditorViewMode) => onViewModeChange?.(id, mode),\n [id, onViewModeChange],\n );\n\n const handleImageUpload = useCallback(() => {\n if (onFileUpload) {\n open();\n }\n }, [onFileUpload]);\n\n return (\n <StackItem.Content toolbar={!!toolbar}>\n {toolbar && (\n <>\n <EditorToolbar\n attendableId={id}\n role={role}\n state={toolbarState}\n getView={getView}\n comment={comment}\n image={handleImageUpload}\n viewMode={handleViewModeChange}\n />\n <input {...getInputProps()} />\n </>\n )}\n <div\n role='none'\n ref={parentRef}\n data-testid='composer.markdownRoot'\n data-toolbar={toolbar ? 'enabled' : 'disabled'}\n className={stackItemContentEditorClassNames(role)}\n data-popover-collision-boundary={true}\n {...focusAttributes}\n />\n </StackItem.Content>\n );\n};\n\n// Expose editor view for playwright tests.\n// TODO(wittjosiah): Find a better way to expose this or find a way to limit it to test runs.\nconst useTest = (view?: EditorView) => {\n useEffect(() => {\n const composer = (window as any).composer;\n if (composer) {\n composer.editorView = view;\n }\n }, [view]);\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { EditorView } from '@codemirror/view';\nimport { Schema } from 'effect';\nimport { useMemo } from 'react';\n\nimport { createResolver, LayoutAction, useIntentResolver } from '@dxos/app-framework';\nimport { invariant } from '@dxos/invariant';\nimport { Cursor, setSelection } from '@dxos/react-ui-editor';\n\nimport { MARKDOWN_PLUGIN } from '../meta';\n\n/**\n * Handle scrolling and selection of the current thread in a markdown editor.\n */\nexport const useSelectCurrentThread = (editorView: EditorView | undefined, documentId: string) => {\n const scrollIntoViewResolver = useMemo(\n () =>\n createResolver({\n intent: LayoutAction.UpdateLayout,\n position: 'hoist',\n filter: (data): data is { part: 'current'; subject: string; options: { cursor: string } } => {\n if (!Schema.is(LayoutAction.ScrollIntoView.fields.input)(data)) {\n return false;\n }\n\n return !!editorView && data.subject === documentId && !!data.options?.cursor;\n },\n resolve: ({ options: { cursor } }) => {\n invariant(editorView, 'Editor view is not defined.');\n const range = Cursor.getRangeFromCursor(editorView.state, cursor!);\n if (range) {\n const selection = editorView.state.selection.main.from !== range.from ? { anchor: range.from } : undefined;\n const effects = [\n // NOTE: This does not use the DOM scrollIntoView function.\n EditorView.scrollIntoView(range.from, { y: 'start', yMargin: 96 }),\n ];\n if (selection) {\n // Update the editor selection to get bi-directional highlighting.\n effects.push(setSelection.of({ current: documentId }));\n }\n\n editorView.dispatch({\n effects,\n selection: selection ? { anchor: range.from } : undefined,\n });\n }\n },\n }),\n [documentId, editorView],\n );\n\n useIntentResolver(MARKDOWN_PLUGIN, scrollIntoViewResolver);\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport React, { type AnchorHTMLAttributes, type ReactNode, useMemo } from 'react';\nimport { createRoot } from 'react-dom/client';\n\nimport {\n createIntent,\n LayoutAction,\n type PromiseIntentDispatcher,\n useCapabilities,\n useIntentDispatcher,\n} from '@dxos/app-framework';\nimport { invariant } from '@dxos/invariant';\nimport { createDocAccessor, fullyQualifiedId, getSpace, type QueryResult } from '@dxos/react-client/echo';\nimport { useIdentity } from '@dxos/react-client/halo';\nimport { Icon, ThemeProvider } from '@dxos/react-ui';\nimport {\n type AutocompleteResult,\n type EditorStateStore,\n type EditorViewMode,\n type Extension,\n InputModeExtensions,\n createDataExtensions,\n autocomplete,\n decorateMarkdown,\n folding,\n formattingKeymap,\n linkTooltip,\n listener,\n preview,\n selectionState,\n typewriter,\n type RenderCallback,\n} from '@dxos/react-ui-editor';\nimport { defaultTx } from '@dxos/react-ui-theme';\nimport { type DataType } from '@dxos/schema';\nimport { isNotFalsy } from '@dxos/util';\n\nimport { MarkdownCapabilities } from './capabilities';\nimport { type DocumentType, type MarkdownSettingsProps } from './types';\nimport { setFallbackName } from './util';\n\ntype ExtensionsOptions = {\n document?: DocumentType;\n id?: string;\n text?: DataType.Text;\n dispatch?: PromiseIntentDispatcher;\n query?: QueryResult<DocumentType>;\n settings: MarkdownSettingsProps;\n viewMode?: EditorViewMode;\n editorStateStore?: EditorStateStore;\n};\n\n// TODO(burdon): Merge with createBaseExtensions below.\nexport const useExtensions = ({\n document,\n id,\n text,\n settings,\n viewMode,\n editorStateStore,\n}: ExtensionsOptions): Extension[] => {\n const { dispatchPromise: dispatch } = useIntentDispatcher();\n const identity = useIdentity();\n const space = getSpace(document) ?? getSpace(text);\n\n // TODO(wittjosiah): Autocomplete is not working and this query is causing performance issues.\n // TODO(burdon): Unsubscribe.\n // const query = space?.db.query(Filter.type(DocumentType));\n // query?.subscribe();\n const baseExtensions = useMemo(\n () =>\n createBaseExtensions({\n document,\n id,\n text,\n settings,\n viewMode,\n dispatch,\n // query,\n }),\n [\n document,\n id,\n text,\n viewMode,\n dispatch,\n settings,\n settings.editorInputMode,\n settings.folding,\n settings.numberedHeadings,\n settings.debug,\n settings.typewriter,\n ],\n );\n\n const extensionProviders = useCapabilities(MarkdownCapabilities.Extensions);\n\n //\n // External extensions from other plugins.\n //\n const pluginExtensions = useMemo<Extension[] | undefined>(\n () =>\n extensionProviders.flat().reduce((acc: Extension[], provider) => {\n const extension = typeof provider === 'function' ? provider({ document }) : provider;\n if (extension) {\n acc.push(extension);\n }\n\n return acc;\n }, []),\n [extensionProviders, document],\n );\n\n //\n // Basic plugins.\n //\n return useMemo<Extension[]>(\n () =>\n [\n // NOTE: Data extensions must be first so that automerge is updated before other extensions compute their state.\n document &&\n createDataExtensions({\n id: document.id,\n text: document.content.target && createDocAccessor(document.content.target, ['content']),\n space,\n identity,\n }),\n text &&\n id &&\n createDataExtensions({\n id,\n text: createDocAccessor(text, ['content']),\n space,\n identity,\n }),\n selectionState(editorStateStore),\n document &&\n listener({\n onChange: (text) => setFallbackName(document, text),\n }),\n baseExtensions,\n pluginExtensions,\n ].filter(isNotFalsy),\n [baseExtensions, pluginExtensions, document, document?.content?.target, text, id, space, identity],\n );\n};\n\n/**\n * Create extension instances for editor.\n */\nconst createBaseExtensions = ({\n document,\n id,\n dispatch,\n settings,\n query,\n viewMode,\n}: ExtensionsOptions): Extension[] => {\n const extensions: Extension[] = [\n settings.editorInputMode && InputModeExtensions[settings.editorInputMode],\n settings.folding && folding(),\n ].filter(isNotFalsy);\n\n //\n // Markdown\n //\n if (viewMode !== 'source') {\n extensions.push(\n ...[\n formattingKeymap(),\n decorateMarkdown({\n selectionChangeDelay: 100,\n numberedHeadings: settings.numberedHeadings ? { from: 2 } : undefined,\n // TODO(wittjosiah): For internal links, consider ignoring the link text and rendering the label of the object being linked to.\n renderLinkButton:\n dispatch && (document || id)\n ? createLinkRenderer((id: string) => {\n void dispatch(\n createIntent(LayoutAction.Open, {\n part: 'main',\n subject: [id],\n options: {\n pivotId: document ? fullyQualifiedId(document) : id,\n },\n }),\n );\n })\n : undefined,\n }),\n linkTooltip(renderLinkTooltip),\n preview(),\n ],\n );\n }\n\n //\n // Autocomplete object links.\n //\n if (query) {\n extensions.push(\n autocomplete({\n onSearch: (text: string) => {\n // TODO(burdon): Specify filter (e.g., stack).\n return query.objects\n .map<AutocompleteResult | undefined>((object) =>\n object.name?.length && object.id !== document?.id\n ? {\n label: object.name,\n // TODO(burdon): Factor out URL builder.\n apply: `[${object.name}](/${fullyQualifiedId(object)})`,\n }\n : undefined,\n )\n .filter(isNotFalsy);\n },\n }),\n );\n }\n\n if (settings.debug) {\n const items = settings.typewriter?.split(/[,\\n]/) ?? '';\n if (items) {\n extensions.push(typewriter({ items }));\n }\n }\n\n return extensions;\n};\n\n// TODO(burdon): Factor out styles.\nconst style = {\n hover: 'rounded-sm text-primary-500 hover:text-primary-600 dark:text-primary-500 hover:dark:text-primary-400',\n icon: 'inline-block leading-none mis-1 cursor-pointer',\n};\n\nconst createLinkRenderer =\n (onSelectObject: (id: string) => void): RenderCallback<{ url: string }> =>\n (el, { url }) => {\n // TODO(burdon): Formalize/document internal link format.\n const isInternal =\n url.startsWith('/') ||\n // TODO(wittjosiah): This should probably be parsed out on paste?\n url.startsWith(window.location.origin);\n\n const options: AnchorHTMLAttributes<any> = isInternal\n ? {\n onClick: () => {\n const qualifiedId = url.split('/').at(-1);\n invariant(qualifiedId, 'Invalid link format.');\n onSelectObject(qualifiedId);\n },\n }\n : {\n href: url,\n rel: 'noreferrer',\n target: '_blank',\n };\n\n renderRoot(\n el,\n <a {...options} className={style.hover}>\n <Icon\n icon={isInternal ? 'ph--arrow-square-down--bold' : 'ph--arrow-square-out--bold'}\n size={4}\n classNames={style.icon}\n />\n </a>,\n );\n };\n\nconst renderLinkTooltip: RenderCallback<{ url: string }> = (el, { url }) => {\n const web = new URL(url);\n renderRoot(\n el,\n <a href={url} rel='noreferrer' target='_blank' className={style.hover}>\n {web.origin}\n <Icon icon='ph--arrow-square-out--bold' size={4} classNames={style.icon} />\n </a>,\n );\n};\n\n// TODO(burdon): Remove react rendering; use DOM directly.\nexport const renderRoot = <T extends Element>(root: T, node: ReactNode): T => {\n createRoot(root).render(<ThemeProvider tx={defaultTx}>{node}</ThemeProvider>);\n return root;\n};\n"],
5
- "mappings": "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",
6
- "names": ["React", "useEffect", "useMemo", "Capabilities", "useCapabilities", "isInstanceOf", "fullyQualifiedId", "getSpace", "DataType", "React", "useMemo", "useEffect", "useCallback", "useDropzone", "createIntent", "useIntentDispatcher", "invariant", "ATTENDABLE_PATH_SEPARATOR", "DeckAction", "useThemeContext", "useTranslation", "EditorToolbar", "createBasicExtensions", "createMarkdownExtensions", "createThemeExtensions", "dropFile", "editorContent", "editorGutter", "processEditorPayload", "stackItemContentEditorClassNames", "useCommentState", "useCommentClickListener", "useFormattingState", "useTextEditor", "useEditorToolbarState", "addLink", "StackItem", "isNotFalsy", "isNonNullable", "EditorView", "Schema", "useMemo", "createResolver", "LayoutAction", "useIntentResolver", "invariant", "Cursor", "setSelection", "useSelectCurrentThread", "editorView", "documentId", "scrollIntoViewResolver", "useMemo", "createResolver", "intent", "LayoutAction", "UpdateLayout", "position", "filter", "data", "Schema", "is", "ScrollIntoView", "fields", "input", "subject", "options", "cursor", "resolve", "invariant", "range", "Cursor", "getRangeFromCursor", "state", "selection", "main", "from", "anchor", "undefined", "effects", "EditorView", "scrollIntoView", "y", "yMargin", "push", "setSelection", "of", "current", "dispatch", "useIntentResolver", "MARKDOWN_PLUGIN", "MarkdownEditor", "id", "role", "initialValue", "extensions", "extensionProviders", "scrollPastEnd", "toolbar", "comment", "viewMode", "editorStateStore", "onFileUpload", "onViewModeChange", "t", "useTranslation", "MARKDOWN_PLUGIN", "themeMode", "useThemeContext", "dispatchPromise", "dispatch", "useIntentDispatcher", "toolbarState", "useEditorToolbarState", "formattingObserver", "useFormattingState", "scrollTo", "selection", "useMemo", "getState", "providerExtensions", "flatMap", "provider", "filter", "isNonNullable", "commentObserver", "useCommentState", "onCommentClick", "useCallback", "createIntent", "DeckAction", "ChangeCompanion", "primary", "companion", "ATTENDABLE_PATH_SEPARATOR", "commentClickObserver", "useCommentClickListener", "handleDrop", "view", "files", "file", "info", "undefined", "processEditorPayload", "type", "data", "url", "parentRef", "editorView", "focusAttributes", "useTextEditor", "createBasicExtensions", "readOnly", "placeholder", "createMarkdownExtensions", "createThemeExtensions", "syntaxHighlighting", "slots", "content", "className", "editorContent", "editorGutter", "dropFile", "onDrop", "isNotFalsy", "moveToEndOfLine", "useTest", "useSelectCurrentThread", "acceptedFiles", "getInputProps", "open", "useDropzone", "multiple", "noDrag", "accept", "useEffect", "length", "requestAnimationFrame", "f", "File", "name", "lastModified", "addLink", "image", "getView", "invariant", "handleViewModeChange", "mode", "handleImageUpload", "StackItem", "Content", "EditorToolbar", "attendableId", "state", "input", "div", "ref", "data-testid", "data-toolbar", "stackItemContentEditorClassNames", "data-popover-collision-boundary", "composer", "window", "React", "useMemo", "createRoot", "createIntent", "LayoutAction", "useCapabilities", "useIntentDispatcher", "invariant", "createDocAccessor", "fullyQualifiedId", "getSpace", "useIdentity", "Icon", "ThemeProvider", "InputModeExtensions", "createDataExtensions", "autocomplete", "decorateMarkdown", "folding", "formattingKeymap", "linkTooltip", "listener", "preview", "selectionState", "typewriter", "defaultTx", "isNotFalsy", "useExtensions", "document", "id", "text", "settings", "viewMode", "editorStateStore", "dispatchPromise", "dispatch", "useIntentDispatcher", "identity", "useIdentity", "space", "getSpace", "baseExtensions", "useMemo", "createBaseExtensions", "editorInputMode", "folding", "numberedHeadings", "debug", "typewriter", "extensionProviders", "useCapabilities", "MarkdownCapabilities", "Extensions", "pluginExtensions", "flat", "reduce", "acc", "provider", "extension", "push", "createDataExtensions", "content", "target", "createDocAccessor", "selectionState", "listener", "onChange", "setFallbackName", "filter", "isNotFalsy", "query", "extensions", "InputModeExtensions", "formattingKeymap", "decorateMarkdown", "selectionChangeDelay", "from", "undefined", "renderLinkButton", "createLinkRenderer", "createIntent", "LayoutAction", "Open", "part", "subject", "options", "pivotId", "fullyQualifiedId", "linkTooltip", "renderLinkTooltip", "preview", "autocomplete", "onSearch", "objects", "map", "object", "name", "length", "label", "apply", "items", "split", "style", "hover", "icon", "onSelectObject", "el", "url", "isInternal", "startsWith", "window", "location", "origin", "onClick", "qualifiedId", "at", "invariant", "href", "rel", "renderRoot", "React", "a", "className", "Icon", "size", "classNames", "web", "URL", "root", "node", "createRoot", "render", "ThemeProvider", "tx", "defaultTx", "MarkdownContainer", "id", "role", "object", "settings", "viewMode", "editorStateStore", "onViewModeChange", "scrollPastEnd", "doc", "isInstanceOf", "DocumentType", "undefined", "text", "DataType", "Text", "extensions", "useExtensions", "document", "React", "DocumentEditor", "fullyQualifiedId", "MarkdownEditor", "initialValue", "content", "toolbar", "comment", "inputMode", "editorInputMode", "props", "space", "getSpace", "useEffect", "fallbackName", "target", "getFallbackName", "upload", "useCapabilities", "Capabilities", "FileUploader", "handleFileUpload", "useMemo", "file", "onFileUpload"]
7
- }