@dxos/plugin-markdown 0.8.2-main.f081794 → 0.8.2-main.fbd8ed0

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 (192) hide show
  1. package/dist/lib/browser/{MarkdownContainer-MH6MMKA5.mjs → MarkdownContainer-KKWICAKV.mjs} +49 -63
  2. package/dist/lib/browser/MarkdownContainer-KKWICAKV.mjs.map +7 -0
  3. package/dist/lib/browser/MarkdownPreview-FVSYVJGN.mjs +81 -0
  4. package/dist/lib/browser/MarkdownPreview-FVSYVJGN.mjs.map +7 -0
  5. package/dist/lib/browser/{app-graph-serializer-BF7WSE3D.mjs → app-graph-serializer-MPJQUYTQ.mjs} +5 -6
  6. package/dist/lib/browser/app-graph-serializer-MPJQUYTQ.mjs.map +7 -0
  7. package/dist/lib/browser/{artifact-definition-XTVOUMMI.mjs → artifact-definition-DAF3YCVL.mjs} +10 -9
  8. package/dist/lib/browser/artifact-definition-DAF3YCVL.mjs.map +7 -0
  9. package/dist/lib/browser/chunk-JJY5LKZS.mjs +20 -0
  10. package/dist/lib/browser/chunk-JJY5LKZS.mjs.map +7 -0
  11. package/dist/lib/browser/{chunk-V54HDI7B.mjs → chunk-S42YXFZ7.mjs} +9 -22
  12. package/dist/lib/browser/chunk-S42YXFZ7.mjs.map +7 -0
  13. package/dist/lib/browser/{chunk-2DKQKSBR.mjs → chunk-TUCSFCS5.mjs} +6 -5
  14. package/dist/lib/browser/chunk-TUCSFCS5.mjs.map +7 -0
  15. package/dist/lib/browser/chunk-XP2ZPCLI.mjs +87 -0
  16. package/dist/lib/browser/chunk-XP2ZPCLI.mjs.map +7 -0
  17. package/dist/lib/browser/index.mjs +10 -6
  18. package/dist/lib/browser/index.mjs.map +3 -3
  19. package/dist/lib/browser/{intent-resolver-H37L3DBD.mjs → intent-resolver-PVKVTAFF.mjs} +9 -14
  20. package/dist/lib/browser/intent-resolver-PVKVTAFF.mjs.map +7 -0
  21. package/dist/lib/browser/meta.json +1 -1
  22. package/dist/lib/browser/{react-surface-RONTBOZZ.mjs → react-surface-EMQV3GVI.mjs} +18 -7
  23. package/dist/lib/browser/react-surface-EMQV3GVI.mjs.map +7 -0
  24. package/dist/lib/browser/{settings-EQSDBX6O.mjs → settings-GPB6WOIU.mjs} +2 -2
  25. package/dist/lib/browser/{state-AIN4J7N5.mjs → state-XTP5IP3W.mjs} +2 -2
  26. package/dist/lib/browser/state-XTP5IP3W.mjs.map +7 -0
  27. package/dist/lib/browser/{thread-MFKBUVCB.mjs → thread-KW43PJ53.mjs} +2 -2
  28. package/dist/lib/browser/types/index.mjs +1 -1
  29. package/dist/lib/node/{MarkdownContainer-PCHMSPTC.cjs → MarkdownContainer-LBI6ZESS.cjs} +53 -67
  30. package/dist/lib/node/MarkdownContainer-LBI6ZESS.cjs.map +7 -0
  31. package/dist/lib/node/MarkdownPreview-O3BR4PZW.cjs +104 -0
  32. package/dist/lib/node/MarkdownPreview-O3BR4PZW.cjs.map +7 -0
  33. package/dist/lib/node/{app-graph-serializer-UVT5EAWW.cjs → app-graph-serializer-Z7UJYSSL.cjs} +10 -11
  34. package/dist/lib/node/app-graph-serializer-Z7UJYSSL.cjs.map +7 -0
  35. package/dist/lib/node/{artifact-definition-ADEN2KD6.cjs → artifact-definition-UIZSL2AL.cjs} +15 -14
  36. package/dist/lib/node/artifact-definition-UIZSL2AL.cjs.map +7 -0
  37. package/dist/lib/node/{chunk-6ERKWMAU.cjs → chunk-4525YF72.cjs} +9 -8
  38. package/dist/lib/node/chunk-4525YF72.cjs.map +7 -0
  39. package/dist/lib/node/chunk-AJHB57YQ.cjs +58 -0
  40. package/dist/lib/node/chunk-AJHB57YQ.cjs.map +7 -0
  41. package/dist/lib/node/{chunk-5XQ27MNY.cjs → chunk-BWRBWEKN.cjs} +12 -39
  42. package/dist/lib/node/chunk-BWRBWEKN.cjs.map +7 -0
  43. package/dist/lib/node/{chunk-YHL4JSA6.cjs → chunk-EO5H4OZJ.cjs} +35 -32
  44. package/dist/lib/node/chunk-EO5H4OZJ.cjs.map +7 -0
  45. package/dist/lib/node/index.cjs +24 -21
  46. package/dist/lib/node/index.cjs.map +3 -3
  47. package/dist/lib/node/{intent-resolver-NX5QNRYF.cjs → intent-resolver-ND7PSRJX.cjs} +14 -19
  48. package/dist/lib/node/intent-resolver-ND7PSRJX.cjs.map +7 -0
  49. package/dist/lib/node/meta.json +1 -1
  50. package/dist/lib/node/{react-surface-26PWFBBV.cjs → react-surface-REHX3ABQ.cjs} +21 -10
  51. package/dist/lib/node/react-surface-REHX3ABQ.cjs.map +7 -0
  52. package/dist/lib/node/{settings-2JXASSLU.cjs → settings-SF6JDJG6.cjs} +6 -6
  53. package/dist/lib/node/{state-PC7IVXFP.cjs → state-K4IPZTRO.cjs} +5 -5
  54. package/dist/lib/node/state-K4IPZTRO.cjs.map +7 -0
  55. package/dist/lib/node/{thread-MXEGV6HS.cjs → thread-NWBGBGOR.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-ERQH4SXI.mjs → MarkdownContainer-62XZY5EP.mjs} +49 -63
  59. package/dist/lib/node-esm/MarkdownContainer-62XZY5EP.mjs.map +7 -0
  60. package/dist/lib/node-esm/MarkdownPreview-KYWRMBRM.mjs +82 -0
  61. package/dist/lib/node-esm/MarkdownPreview-KYWRMBRM.mjs.map +7 -0
  62. package/dist/lib/node-esm/{app-graph-serializer-LPRG2PFZ.mjs → app-graph-serializer-DDMFMNYI.mjs} +5 -6
  63. package/dist/lib/node-esm/app-graph-serializer-DDMFMNYI.mjs.map +7 -0
  64. package/dist/lib/node-esm/{artifact-definition-KTS5M2FW.mjs → artifact-definition-ER3446S7.mjs} +10 -9
  65. package/dist/lib/node-esm/artifact-definition-ER3446S7.mjs.map +7 -0
  66. package/dist/lib/node-esm/chunk-66XM3JMR.mjs +88 -0
  67. package/dist/lib/node-esm/chunk-66XM3JMR.mjs.map +7 -0
  68. package/dist/lib/node-esm/{chunk-IZUCQ5P5.mjs → chunk-CXTVDT5U.mjs} +6 -5
  69. package/dist/lib/node-esm/chunk-CXTVDT5U.mjs.map +7 -0
  70. package/dist/lib/node-esm/{chunk-USLC246I.mjs → chunk-PDD5B7EO.mjs} +9 -22
  71. package/dist/lib/node-esm/chunk-PDD5B7EO.mjs.map +7 -0
  72. package/dist/lib/node-esm/chunk-T5Z5BIOF.mjs +22 -0
  73. package/dist/lib/node-esm/chunk-T5Z5BIOF.mjs.map +7 -0
  74. package/dist/lib/node-esm/index.mjs +10 -6
  75. package/dist/lib/node-esm/index.mjs.map +3 -3
  76. package/dist/lib/node-esm/{intent-resolver-XES4ZCA6.mjs → intent-resolver-5BF5PLSN.mjs} +9 -14
  77. package/dist/lib/node-esm/intent-resolver-5BF5PLSN.mjs.map +7 -0
  78. package/dist/lib/node-esm/meta.json +1 -1
  79. package/dist/lib/node-esm/{react-surface-ZEJSYIRX.mjs → react-surface-FA7JYF2A.mjs} +18 -7
  80. package/dist/lib/node-esm/react-surface-FA7JYF2A.mjs.map +7 -0
  81. package/dist/lib/node-esm/{settings-67RVIH3N.mjs → settings-2DT2C4RA.mjs} +2 -2
  82. package/dist/lib/node-esm/{state-PNOPM4TS.mjs → state-7VFYPF6Z.mjs} +2 -2
  83. package/dist/lib/node-esm/state-7VFYPF6Z.mjs.map +7 -0
  84. package/dist/lib/node-esm/{thread-5U4KSBED.mjs → thread-D2E6W44K.mjs} +2 -2
  85. package/dist/lib/node-esm/types/index.mjs +1 -1
  86. package/dist/types/src/capabilities/app-graph-serializer.d.ts +2 -2
  87. package/dist/types/src/capabilities/app-graph-serializer.d.ts.map +1 -1
  88. package/dist/types/src/capabilities/artifact-definition.d.ts.map +1 -1
  89. package/dist/types/src/capabilities/index.d.ts +3 -3
  90. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  91. package/dist/types/src/capabilities/intent-resolver.d.ts +2 -2
  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/capabilities/state.d.ts +2 -2
  95. package/dist/types/src/capabilities/state.d.ts.map +1 -1
  96. package/dist/types/src/components/MarkdownContainer.d.ts +2 -2
  97. package/dist/types/src/components/MarkdownContainer.d.ts.map +1 -1
  98. package/dist/types/src/components/{MarkdownEditor.d.ts → MarkdownEditor/MarkdownEditor.d.ts} +1 -16
  99. package/dist/types/src/components/MarkdownEditor/MarkdownEditor.d.ts.map +1 -0
  100. package/dist/types/src/components/MarkdownEditor/MarkdownEditor.stories.d.ts.map +1 -0
  101. package/dist/types/src/components/MarkdownEditor/index.d.ts +2 -0
  102. package/dist/types/src/components/MarkdownEditor/index.d.ts.map +1 -0
  103. package/dist/types/src/components/MarkdownPreview/MarkdownPreview.d.ts +6 -0
  104. package/dist/types/src/components/MarkdownPreview/MarkdownPreview.d.ts.map +1 -0
  105. package/dist/types/src/components/MarkdownPreview/MarkdownPreview.stories.d.ts +127 -0
  106. package/dist/types/src/components/MarkdownPreview/MarkdownPreview.stories.d.ts.map +1 -0
  107. package/dist/types/src/components/MarkdownPreview/index.d.ts +4 -0
  108. package/dist/types/src/components/MarkdownPreview/index.d.ts.map +1 -0
  109. package/dist/types/src/components/{MarkdownSettings.d.ts → MarkdownSettings/MarkdownSettings.d.ts} +1 -1
  110. package/dist/types/src/components/MarkdownSettings/MarkdownSettings.d.ts.map +1 -0
  111. package/dist/types/src/components/MarkdownSettings/index.d.ts +2 -0
  112. package/dist/types/src/components/MarkdownSettings/index.d.ts.map +1 -0
  113. package/dist/types/src/components/Suggestions.stories.d.ts.map +1 -1
  114. package/dist/types/src/components/Toolbar.stories.d.ts.map +1 -1
  115. package/dist/types/src/components/index.d.ts +1 -0
  116. package/dist/types/src/components/index.d.ts.map +1 -1
  117. package/dist/types/src/extensions.d.ts +4 -4
  118. package/dist/types/src/extensions.d.ts.map +1 -1
  119. package/dist/types/src/hooks/useSelectCurrentThread.d.ts.map +1 -1
  120. package/dist/types/src/translations.d.ts +4 -42
  121. package/dist/types/src/translations.d.ts.map +1 -1
  122. package/dist/types/src/types/schema.d.ts +323 -190
  123. package/dist/types/src/types/schema.d.ts.map +1 -1
  124. package/dist/types/src/types/types.d.ts +139 -85
  125. package/dist/types/src/types/types.d.ts.map +1 -1
  126. package/dist/types/src/util.d.ts +1 -0
  127. package/dist/types/src/util.d.ts.map +1 -1
  128. package/dist/types/tsconfig.tsbuildinfo +1 -1
  129. package/package.json +40 -37
  130. package/src/MarkdownPlugin.tsx +2 -2
  131. package/src/capabilities/app-graph-serializer.ts +4 -5
  132. package/src/capabilities/artifact-definition.ts +6 -4
  133. package/src/capabilities/intent-resolver.ts +10 -10
  134. package/src/capabilities/react-surface.tsx +13 -5
  135. package/src/capabilities/state.ts +3 -3
  136. package/src/components/MarkdownContainer.tsx +3 -4
  137. package/src/components/{MarkdownEditor.stories.tsx → MarkdownEditor/MarkdownEditor.stories.tsx} +2 -2
  138. package/src/components/{MarkdownEditor.tsx → MarkdownEditor/MarkdownEditor.tsx} +25 -45
  139. package/src/components/MarkdownEditor/index.ts +5 -0
  140. package/src/components/MarkdownPreview/MarkdownPreview.stories.tsx +74 -0
  141. package/src/components/MarkdownPreview/MarkdownPreview.tsx +85 -0
  142. package/src/components/MarkdownPreview/index.ts +9 -0
  143. package/src/components/{MarkdownSettings.tsx → MarkdownSettings/MarkdownSettings.tsx} +2 -2
  144. package/src/components/MarkdownSettings/index.ts +5 -0
  145. package/src/components/Suggestions.stories.tsx +23 -14
  146. package/src/components/Toolbar.stories.tsx +14 -14
  147. package/src/components/index.ts +1 -0
  148. package/src/extensions.tsx +5 -5
  149. package/src/hooks/useSelectCurrentThread.tsx +2 -2
  150. package/src/translations.ts +3 -3
  151. package/src/types/schema.ts +20 -12
  152. package/src/types/types.ts +23 -21
  153. package/src/util.tsx +7 -3
  154. package/dist/lib/browser/MarkdownContainer-MH6MMKA5.mjs.map +0 -7
  155. package/dist/lib/browser/app-graph-serializer-BF7WSE3D.mjs.map +0 -7
  156. package/dist/lib/browser/artifact-definition-XTVOUMMI.mjs.map +0 -7
  157. package/dist/lib/browser/chunk-2DKQKSBR.mjs.map +0 -7
  158. package/dist/lib/browser/chunk-GVOEHF7E.mjs +0 -84
  159. package/dist/lib/browser/chunk-GVOEHF7E.mjs.map +0 -7
  160. package/dist/lib/browser/chunk-V54HDI7B.mjs.map +0 -7
  161. package/dist/lib/browser/intent-resolver-H37L3DBD.mjs.map +0 -7
  162. package/dist/lib/browser/react-surface-RONTBOZZ.mjs.map +0 -7
  163. package/dist/lib/browser/state-AIN4J7N5.mjs.map +0 -7
  164. package/dist/lib/node/MarkdownContainer-PCHMSPTC.cjs.map +0 -7
  165. package/dist/lib/node/app-graph-serializer-UVT5EAWW.cjs.map +0 -7
  166. package/dist/lib/node/artifact-definition-ADEN2KD6.cjs.map +0 -7
  167. package/dist/lib/node/chunk-5XQ27MNY.cjs.map +0 -7
  168. package/dist/lib/node/chunk-6ERKWMAU.cjs.map +0 -7
  169. package/dist/lib/node/chunk-YHL4JSA6.cjs.map +0 -7
  170. package/dist/lib/node/intent-resolver-NX5QNRYF.cjs.map +0 -7
  171. package/dist/lib/node/react-surface-26PWFBBV.cjs.map +0 -7
  172. package/dist/lib/node/state-PC7IVXFP.cjs.map +0 -7
  173. package/dist/lib/node-esm/MarkdownContainer-ERQH4SXI.mjs.map +0 -7
  174. package/dist/lib/node-esm/app-graph-serializer-LPRG2PFZ.mjs.map +0 -7
  175. package/dist/lib/node-esm/artifact-definition-KTS5M2FW.mjs.map +0 -7
  176. package/dist/lib/node-esm/chunk-IZUCQ5P5.mjs.map +0 -7
  177. package/dist/lib/node-esm/chunk-NUZHKZSZ.mjs +0 -85
  178. package/dist/lib/node-esm/chunk-NUZHKZSZ.mjs.map +0 -7
  179. package/dist/lib/node-esm/chunk-USLC246I.mjs.map +0 -7
  180. package/dist/lib/node-esm/intent-resolver-XES4ZCA6.mjs.map +0 -7
  181. package/dist/lib/node-esm/react-surface-ZEJSYIRX.mjs.map +0 -7
  182. package/dist/lib/node-esm/state-PNOPM4TS.mjs.map +0 -7
  183. package/dist/types/src/components/MarkdownEditor.d.ts.map +0 -1
  184. package/dist/types/src/components/MarkdownEditor.stories.d.ts.map +0 -1
  185. package/dist/types/src/components/MarkdownSettings.d.ts.map +0 -1
  186. /package/dist/lib/browser/{settings-EQSDBX6O.mjs.map → settings-GPB6WOIU.mjs.map} +0 -0
  187. /package/dist/lib/browser/{thread-MFKBUVCB.mjs.map → thread-KW43PJ53.mjs.map} +0 -0
  188. /package/dist/lib/node/{settings-2JXASSLU.cjs.map → settings-SF6JDJG6.cjs.map} +0 -0
  189. /package/dist/lib/node/{thread-MXEGV6HS.cjs.map → thread-NWBGBGOR.cjs.map} +0 -0
  190. /package/dist/lib/node-esm/{settings-67RVIH3N.mjs.map → settings-2DT2C4RA.mjs.map} +0 -0
  191. /package/dist/lib/node-esm/{thread-5U4KSBED.mjs.map → thread-D2E6W44K.mjs.map} +0 -0
  192. /package/dist/types/src/components/{MarkdownEditor.stories.d.ts → MarkdownEditor/MarkdownEditor.stories.d.ts} +0 -0
@@ -7,7 +7,7 @@ import React, { useEffect, useMemo } from 'react';
7
7
  import { Capabilities, useCapabilities } from '@dxos/app-framework';
8
8
  import { isInstanceOf } from '@dxos/echo-schema';
9
9
  import { fullyQualifiedId, getSpace } from '@dxos/react-client/echo';
10
- import { TextType } from '@dxos/schema';
10
+ import { DataType } from '@dxos/schema';
11
11
 
12
12
  import { MarkdownEditor, type MarkdownEditorProps } from './MarkdownEditor';
13
13
  import { useExtensions } from '../extensions';
@@ -19,11 +19,10 @@ export type MarkdownContainerProps = Pick<
19
19
  'role' | 'extensionProviders' | 'viewMode' | 'editorStateStore' | 'onViewModeChange'
20
20
  > & {
21
21
  id: string;
22
- object: DocumentType | TextType | any;
22
+ object: DocumentType | DataType.Text | any;
23
23
  settings: MarkdownSettingsProps;
24
24
  };
25
25
 
26
- // TODO(burdon): Move toolbar here.
27
26
  // TODO(burdon): Factor out difference for ECHO and non-ECHO objects; i.e., single component.
28
27
  const MarkdownContainer = ({
29
28
  id,
@@ -36,7 +35,7 @@ const MarkdownContainer = ({
36
35
  }: MarkdownContainerProps) => {
37
36
  const scrollPastEnd = role === 'article';
38
37
  const doc = isInstanceOf(DocumentType, object) ? object : undefined;
39
- const text = isInstanceOf(TextType, object) ? object : undefined;
38
+ const text = isInstanceOf(DataType.Text, object) ? object : undefined;
40
39
  const extensions = useExtensions({ document: doc, text, id, settings, viewMode, editorStateStore });
41
40
 
42
41
  if (doc) {
@@ -15,7 +15,7 @@ import { automerge, translations as editorTranslations } from '@dxos/react-ui-ed
15
15
  import { withLayout, withTheme } from '@dxos/storybook-utils';
16
16
 
17
17
  import { MarkdownEditor, type MarkdownEditorProps } from './MarkdownEditor';
18
- import translations from '../translations';
18
+ import translations from '../../translations';
19
19
 
20
20
  const content = Array.from({ length: 100 }, (_, i) => `Line ${i + 1}`).join('\n');
21
21
 
@@ -36,7 +36,7 @@ const meta: Meta<typeof MarkdownEditor> = {
36
36
  render: DefaultStory,
37
37
  decorators: [
38
38
  withTheme,
39
- withLayout({ tooltips: true, fullscreen: true }),
39
+ withLayout({ fullscreen: true }),
40
40
  withAttention,
41
41
  withPluginManager({ plugins: [IntentPlugin()] }),
42
42
  ],
@@ -2,17 +2,16 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { openSearchPanel } from '@codemirror/search';
6
5
  import { type EditorView } from '@codemirror/view';
7
6
  import React, { useMemo, useEffect, useCallback } from 'react';
8
7
  import { useDropzone } from 'react-dropzone';
9
8
 
10
9
  import { createIntent, type FileInfo, useIntentDispatcher } from '@dxos/app-framework';
10
+ import { invariant } from '@dxos/invariant';
11
11
  import { ATTENDABLE_PATH_SEPARATOR, DeckAction } from '@dxos/plugin-deck/types';
12
12
  import { useThemeContext, useTranslation } from '@dxos/react-ui';
13
13
  import {
14
14
  type DNDOptions,
15
- type EditorAction,
16
15
  type EditorViewMode,
17
16
  type EditorInputMode,
18
17
  type EditorSelectionState,
@@ -20,7 +19,6 @@ import {
20
19
  EditorToolbar,
21
20
  type UseTextEditorProps,
22
21
  createBasicExtensions,
23
- createEditorAction,
24
22
  createMarkdownExtensions,
25
23
  createThemeExtensions,
26
24
  dropFile,
@@ -28,19 +26,19 @@ import {
28
26
  editorGutter,
29
27
  processEditorPayload,
30
28
  stackItemContentEditorClassNames,
31
- useActionHandler,
32
29
  useCommentState,
33
30
  useCommentClickListener,
34
31
  useFormattingState,
35
32
  useTextEditor,
36
33
  useEditorToolbarState,
34
+ addLink,
37
35
  } from '@dxos/react-ui-editor';
38
36
  import { StackItem } from '@dxos/react-ui-stack';
39
37
  import { isNotFalsy, isNonNullable } from '@dxos/util';
40
38
 
41
- import { useSelectCurrentThread } from '../hooks';
42
- import { MARKDOWN_PLUGIN } from '../meta';
43
- import { type MarkdownPluginState } from '../types';
39
+ import { useSelectCurrentThread } from '../../hooks';
40
+ import { MARKDOWN_PLUGIN } from '../../meta';
41
+ import { type MarkdownPluginState } from '../../types';
44
42
 
45
43
  export type MarkdownEditorProps = {
46
44
  id: string;
@@ -178,49 +176,40 @@ export const MarkdownEditor = ({
178
176
 
179
177
  const info = await onFileUpload(file);
180
178
  if (info) {
181
- processEditorPayload(editorView, { type: 'image', data: info.url });
179
+ addLink({ url: info.url, image: true })(editorView);
182
180
  }
183
181
  });
184
182
  }
185
- }, [acceptedFiles, editorView]);
183
+ }, [acceptedFiles, editorView, onFileUpload]);
186
184
 
187
- // Toolbar handler.
188
- const handleToolbarAction = useActionHandler(editorView);
189
- const handleAction = useCallback(
190
- (action: EditorAction) => {
191
- switch (action.properties.type) {
192
- case 'search': {
193
- if (editorView) {
194
- openSearchPanel(editorView);
195
- }
196
- return;
197
- }
198
- case 'view-mode': {
199
- onViewModeChange?.(id, action.properties.data);
200
- return;
201
- }
202
- case 'image': {
203
- open();
204
- return;
205
- }
206
- }
185
+ const getView = useCallback(() => {
186
+ invariant(editorView);
187
+ return editorView;
188
+ }, [editorView]);
207
189
 
208
- handleToolbarAction?.(action);
209
- },
210
- [editorView, onViewModeChange, open],
190
+ const handleViewModeChange = useCallback(
191
+ (mode: EditorViewMode) => onViewModeChange?.(id, mode),
192
+ [id, onViewModeChange],
211
193
  );
212
194
 
195
+ const handleImageUpload = useCallback(() => {
196
+ if (onFileUpload) {
197
+ open();
198
+ }
199
+ }, [onFileUpload]);
200
+
213
201
  return (
214
- <StackItem.Content toolbar={!!toolbar} classNames='is-full min-bs-0'>
202
+ <StackItem.Content toolbar={!!toolbar}>
215
203
  {toolbar && (
216
204
  <>
217
205
  <EditorToolbar
218
206
  attendableId={id}
219
207
  role={role}
220
208
  state={toolbarState}
209
+ getView={getView}
221
210
  comment={comment}
222
- customActions={onFileUpload ? createUploadAction : undefined}
223
- onAction={handleAction}
211
+ image={handleImageUpload}
212
+ viewMode={handleViewModeChange}
224
213
  />
225
214
  <input {...getInputProps()} />
226
215
  </>
@@ -231,6 +220,7 @@ export const MarkdownEditor = ({
231
220
  data-testid='composer.markdownRoot'
232
221
  data-toolbar={toolbar ? 'enabled' : 'disabled'}
233
222
  className={stackItemContentEditorClassNames(role)}
223
+ data-popover-collision-boundary={true}
234
224
  {...focusAttributes}
235
225
  />
236
226
  </StackItem.Content>
@@ -247,13 +237,3 @@ const useTest = (view?: EditorView) => {
247
237
  }
248
238
  }, [view]);
249
239
  };
250
-
251
- export const createUploadAction = () => ({
252
- nodes: [
253
- createEditorAction({ type: 'image', testId: 'editor.toolbar.image' }, 'ph--image-square--regular', [
254
- 'upload image label',
255
- { ns: MARKDOWN_PLUGIN },
256
- ]),
257
- ],
258
- edges: [{ source: 'root', target: 'image' }],
259
- });
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ export * from './MarkdownEditor';
@@ -0,0 +1,74 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import '@dxos-theme';
6
+
7
+ import { type Meta } from '@storybook/react';
8
+ import React from 'react';
9
+
10
+ import { IntentPlugin } from '@dxos/app-framework';
11
+ import { withPluginManager } from '@dxos/app-framework/testing';
12
+ import { create } from '@dxos/echo-schema';
13
+ import { DocumentType } from '@dxos/plugin-markdown/types';
14
+ import { faker } from '@dxos/random';
15
+ import { makeRef } from '@dxos/react-client/echo';
16
+ import { Icon, Popover } from '@dxos/react-ui';
17
+ import { DataType } from '@dxos/schema';
18
+ import { withTheme, withLayout } from '@dxos/storybook-utils';
19
+
20
+ import { MarkdownPreview } from './MarkdownPreview';
21
+ import translations from '../../translations';
22
+
23
+ faker.seed(1234);
24
+
25
+ const meta: Meta<typeof MarkdownPreview> = {
26
+ title: 'plugins/plugin-markdown/MarkdownPreview',
27
+ component: MarkdownPreview,
28
+ render: ({ subject }) => {
29
+ return (
30
+ <Popover.Root open>
31
+ <Popover.Content>
32
+ <MarkdownPreview subject={subject} role='popover' />
33
+ <Popover.Arrow />
34
+ </Popover.Content>
35
+ <Popover.Trigger>
36
+ <Icon icon='ph--text-aa--regular' size={5} />
37
+ </Popover.Trigger>
38
+ </Popover.Root>
39
+ );
40
+ },
41
+ decorators: [
42
+ withPluginManager({
43
+ plugins: [IntentPlugin()],
44
+ }),
45
+ withTheme,
46
+ withLayout(),
47
+ ],
48
+ parameters: {
49
+ layout: 'centered',
50
+ translations,
51
+ },
52
+ };
53
+
54
+ export default meta;
55
+
56
+ const data = (() => {
57
+ const document = create(DocumentType, {
58
+ name: faker.lorem.words(3),
59
+ content: makeRef(
60
+ create(DataType.Text, {
61
+ content: faker.lorem.paragraphs(3),
62
+ }),
63
+ ),
64
+ threads: [],
65
+ });
66
+
67
+ return { document };
68
+ })();
69
+
70
+ export const Default = {
71
+ args: {
72
+ subject: create(DocumentType, data.document),
73
+ },
74
+ };
@@ -0,0 +1,85 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { pipe } from 'effect';
6
+ import React, { useCallback } from 'react';
7
+
8
+ import { chain, createIntent, LayoutAction, useIntentDispatcher } from '@dxos/app-framework';
9
+ import { isInstanceOf } from '@dxos/echo-schema';
10
+ import {
11
+ type PreviewProps,
12
+ defaultCard,
13
+ kanbanCardWithoutPoster,
14
+ popoverCard,
15
+ previewTitle,
16
+ previewProse,
17
+ previewChrome,
18
+ } from '@dxos/plugin-preview';
19
+ import { fullyQualifiedId } from '@dxos/react-client/echo';
20
+ import { Button, Icon, useTranslation } from '@dxos/react-ui';
21
+ import { mx } from '@dxos/react-ui-theme';
22
+ import { DataType } from '@dxos/schema';
23
+
24
+ import { MARKDOWN_PLUGIN } from '../../meta';
25
+ import { DocumentType } from '../../types';
26
+ import { getAbstract, getFallbackName } from '../../util';
27
+
28
+ // TODO(burdon): Factor out.
29
+ const getTitle = (subject: DocumentType | DataType.Text, fallback: string) => {
30
+ if (isInstanceOf(DocumentType, subject)) {
31
+ return subject.name ?? subject.fallbackName ?? getFallbackName(subject.content?.target?.content ?? fallback);
32
+ } else if (isInstanceOf(DataType.Text, subject)) {
33
+ return getFallbackName(subject.content);
34
+ }
35
+ };
36
+
37
+ // TODO(burdon): Factor out.
38
+ const getSnippet = (subject: DocumentType | DataType.Text, fallback: string) => {
39
+ if (isInstanceOf(DocumentType, subject)) {
40
+ return getAbstract(subject.content?.target?.content ?? fallback);
41
+ } else if (isInstanceOf(DataType.Text, subject)) {
42
+ return getAbstract(subject.content);
43
+ }
44
+ };
45
+
46
+ export const MarkdownPreview = ({ classNames, subject, role }: PreviewProps<DocumentType | DataType.Text>) => {
47
+ const { dispatchPromise: dispatch } = useIntentDispatcher();
48
+ const { t } = useTranslation(MARKDOWN_PLUGIN);
49
+ const snippet = getSnippet(subject, t('fallback abstract'));
50
+
51
+ // TODO(wittjosiah): Factor out so this component isn't dependent on the app framework.
52
+ const handleNavigate = useCallback(
53
+ () =>
54
+ dispatch(
55
+ pipe(
56
+ createIntent(LayoutAction.UpdatePopover, {
57
+ part: 'popover',
58
+ subject: null,
59
+ options: { state: false, anchorId: '' },
60
+ }),
61
+ chain(LayoutAction.Open, { part: 'main', subject: [fullyQualifiedId(subject)] }),
62
+ ),
63
+ ),
64
+ [dispatch, subject],
65
+ );
66
+
67
+ return (
68
+ <div
69
+ role='none'
70
+ className={mx(
71
+ role === 'popover' ? popoverCard : role === 'card--kanban' ? kanbanCardWithoutPoster : defaultCard,
72
+ classNames,
73
+ )}
74
+ >
75
+ <h2 className={mx(previewTitle, previewProse)}>{getTitle(subject, t('fallback title'))}</h2>
76
+ {snippet && <p className={mx(previewProse, 'line-clamp-3 break-words col-span-2')}>{snippet}</p>}
77
+ <div role='none' className={previewChrome}>
78
+ <Button onClick={handleNavigate}>
79
+ <span className='grow'>{t('navigate to document label')}</span>
80
+ <Icon icon='ph--arrow-right--regular' />
81
+ </Button>
82
+ </div>
83
+ </div>
84
+ );
85
+ };
@@ -0,0 +1,9 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { MarkdownPreview } from './MarkdownPreview';
6
+
7
+ export * from './MarkdownPreview';
8
+
9
+ export default MarkdownPreview;
@@ -8,8 +8,8 @@ import { Input, Select, useTranslation } from '@dxos/react-ui';
8
8
  import { type EditorInputMode, EditorInputModes, type EditorViewMode, EditorViewModes } from '@dxos/react-ui-editor';
9
9
  import { DeprecatedFormContainer, DeprecatedFormInput } from '@dxos/react-ui-form';
10
10
 
11
- import { MARKDOWN_PLUGIN } from '../meta';
12
- import { type MarkdownSettingsProps } from '../types';
11
+ import { MARKDOWN_PLUGIN } from '../../meta';
12
+ import { type MarkdownSettingsProps } from '../../types';
13
13
 
14
14
  export const MarkdownSettings = ({ settings }: { settings: MarkdownSettingsProps }) => {
15
15
  const { t } = useTranslation(MARKDOWN_PLUGIN);
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ export * from './MarkdownSettings';
@@ -5,6 +5,7 @@
5
5
  import '@dxos-theme';
6
6
 
7
7
  import { type Meta } from '@storybook/react';
8
+ import { Schema, SchemaAST } from 'effect';
8
9
  import React, { type FC, useEffect, useMemo, useState } from 'react';
9
10
 
10
11
  import {
@@ -19,16 +20,18 @@ import {
19
20
  } from '@dxos/app-framework';
20
21
  import { withPluginManager } from '@dxos/app-framework/testing';
21
22
  import { Message } from '@dxos/artifact';
22
- import { S, AST, create, type Expando, EchoObject } from '@dxos/echo-schema';
23
+ import { Type } from '@dxos/echo';
24
+ import { create, createQueueDxn, type Expando } from '@dxos/echo-schema';
23
25
  import { invariant } from '@dxos/invariant';
24
26
  import { DXN } from '@dxos/keys';
25
27
  import { live, makeRef, refFromDXN } from '@dxos/live-object';
26
28
  import { ClientPlugin } from '@dxos/plugin-client';
29
+ import { PreviewPlugin } from '@dxos/plugin-preview';
27
30
  import { SpacePlugin } from '@dxos/plugin-space';
28
31
  import { StorybookLayoutPlugin } from '@dxos/plugin-storybook-layout';
29
32
  import { ThemePlugin } from '@dxos/plugin-theme';
30
33
  import { faker } from '@dxos/random';
31
- import { randomQueueDxn, useQueue, useSpace } from '@dxos/react-client/echo';
34
+ import { useQueue, useSpace } from '@dxos/react-client/echo';
32
35
  import { IconButton, Toolbar } from '@dxos/react-ui';
33
36
  import { command, useTextEditor } from '@dxos/react-ui-editor';
34
37
  import { StackItem } from '@dxos/react-ui-stack';
@@ -44,23 +47,28 @@ import { createDocument, DocumentType, type MarkdownSettingsProps } from '../typ
44
47
 
45
48
  faker.seed(1);
46
49
 
47
- const TestItem = S.Struct({
48
- title: S.String.annotations({
49
- [AST.TitleAnnotationId]: 'Title',
50
- [AST.DescriptionAnnotationId]: 'Product title',
50
+ const TestItem = Schema.Struct({
51
+ title: Schema.String.annotations({
52
+ [SchemaAST.TitleAnnotationId]: 'Title',
53
+ [SchemaAST.DescriptionAnnotationId]: 'Product title',
51
54
  }),
52
- description: S.String.annotations({
53
- [AST.TitleAnnotationId]: 'Description',
54
- [AST.DescriptionAnnotationId]: 'Product description',
55
+ description: Schema.String.annotations({
56
+ [SchemaAST.TitleAnnotationId]: 'Description',
57
+ [SchemaAST.DescriptionAnnotationId]: 'Product description',
55
58
  }),
56
- }).pipe(EchoObject({ typename: 'dxos.org/type/Test', version: '0.1.0' }));
59
+ }).pipe(
60
+ Type.def({
61
+ typename: 'dxos.org/type/Test',
62
+ version: '0.1.0',
63
+ }),
64
+ );
57
65
 
58
66
  const TestChat: FC<{ doc: DocumentType; content: string }> = ({ doc, content }) => {
59
67
  const { dispatchPromise: dispatch } = useIntentDispatcher();
60
68
  const { parentRef } = useTextEditor({ initialValue: content });
61
69
 
62
70
  const space = useSpace();
63
- const queueDxn = useMemo(() => space && randomQueueDxn(space.id), [space]);
71
+ const queueDxn = useMemo(() => space && createQueueDxn(space.id), [space]);
64
72
  const queue = useQueue<Message>(queueDxn);
65
73
 
66
74
  const handleInsert = () => {
@@ -86,8 +94,8 @@ const TestChat: FC<{ doc: DocumentType; content: string }> = ({ doc, content })
86
94
  };
87
95
 
88
96
  return (
89
- <StackItem.Content toolbar classNames='w-full'>
90
- <Toolbar.Root classNames='border-be border-separator'>
97
+ <StackItem.Content toolbar>
98
+ <Toolbar.Root>
91
99
  <IconButton icon='ph--plus--regular' disabled={!queue} label='Insert' onClick={handleInsert} />
92
100
  </Toolbar.Root>
93
101
  <div ref={parentRef} className='p-4' />
@@ -151,10 +159,11 @@ const meta: Meta<typeof DefaultStory> = {
151
159
  SettingsPlugin(),
152
160
  IntentPlugin(),
153
161
  MarkdownPlugin(),
162
+ PreviewPlugin(),
154
163
  ],
155
164
  capabilities: [contributes(MarkdownCapabilities.Extensions, [() => command()])],
156
165
  }),
157
- withLayout({ tooltips: true, fullscreen: true, classNames: 'grid grid-cols-2' }),
166
+ withLayout({ fullscreen: true, classNames: 'grid grid-cols-2' }),
158
167
  ],
159
168
  parameters: {
160
169
  translations,
@@ -5,8 +5,9 @@
5
5
  import '@dxos-theme';
6
6
 
7
7
  import { type Meta } from '@storybook/react';
8
- import React, { type FC, useState } from 'react';
8
+ import React, { type FC, useCallback, useState } from 'react';
9
9
 
10
+ import { invariant } from '@dxos/invariant';
10
11
  import { PublicKey } from '@dxos/keys';
11
12
  import { live } from '@dxos/live-object';
12
13
  import { faker } from '@dxos/random';
@@ -14,7 +15,6 @@ import { createDocAccessor, createObject } from '@dxos/react-client/echo';
14
15
  import { useThemeContext } from '@dxos/react-ui';
15
16
  import {
16
17
  EditorToolbar,
17
- type EditorAction,
18
18
  type Comment,
19
19
  comments,
20
20
  createBasicExtensions,
@@ -25,20 +25,20 @@ import {
25
25
  editorContent,
26
26
  formattingKeymap,
27
27
  translations,
28
- useActionHandler,
29
28
  useComments,
30
29
  useFormattingState,
31
30
  useTextEditor,
32
31
  useEditorToolbarState,
32
+ type EditorViewMode,
33
33
  } from '@dxos/react-ui-editor';
34
- import { TextType } from '@dxos/schema';
34
+ import { DataType } from '@dxos/schema';
35
35
  import { withLayout, withTheme } from '@dxos/storybook-utils';
36
36
 
37
37
  faker.seed(101);
38
38
 
39
39
  const DefaultStory: FC<{ content?: string }> = ({ content = '' }) => {
40
40
  const { themeMode } = useThemeContext();
41
- const [text] = useState(createObject(live(TextType, { content })));
41
+ const [text] = useState(createObject(live(DataType.Text, { content })));
42
42
  const toolbarState = useEditorToolbarState({ viewMode: 'preview' });
43
43
  const formattingObserver = useFormattingState(toolbarState);
44
44
  const { parentRef, view } = useTextEditor(() => {
@@ -64,21 +64,21 @@ const DefaultStory: FC<{ content?: string }> = ({ content = '' }) => {
64
64
  };
65
65
  }, [text, formattingObserver, toolbarState.viewMode, themeMode]);
66
66
 
67
- const handleToolbarAction = useActionHandler(view);
68
- const handleAction = (action: EditorAction) => {
69
- if (action.type === 'view-mode') {
70
- toolbarState.viewMode = action.properties.data;
71
- } else {
72
- handleToolbarAction?.(action);
73
- }
67
+ const handleViewModeChange = (viewMode: EditorViewMode) => {
68
+ toolbarState.viewMode = viewMode;
74
69
  };
75
70
 
71
+ const getView = useCallback(() => {
72
+ invariant(view);
73
+ return view;
74
+ }, [view]);
75
+
76
76
  const [_comments, setComments] = useState<Comment[]>([]);
77
77
  useComments(view, text.id, _comments);
78
78
 
79
79
  return (
80
80
  <div role='none' className='flex flex-col'>
81
- <EditorToolbar onAction={handleAction} state={toolbarState ?? {}} />
81
+ <EditorToolbar state={toolbarState ?? {}} getView={getView} viewMode={handleViewModeChange} />
82
82
  <div className='flex grow overflow-hidden' ref={parentRef} />
83
83
  </div>
84
84
  );
@@ -98,7 +98,7 @@ const meta: Meta<typeof EditorToolbar> = {
98
98
  title: 'plugins/plugin-markdown/Toolbar',
99
99
  component: EditorToolbar,
100
100
  render: DefaultStory as any,
101
- decorators: [withTheme, withLayout({ tooltips: true, fullscreen: true })],
101
+ decorators: [withTheme, withLayout({ fullscreen: true })],
102
102
  parameters: {
103
103
  translations,
104
104
  },
@@ -7,3 +7,4 @@ import { lazy } from 'react';
7
7
  export * from './MarkdownSettings';
8
8
 
9
9
  export const MarkdownContainer = lazy(() => import('./MarkdownContainer'));
10
+ export const MarkdownPreview = lazy(() => import('./MarkdownPreview'));
@@ -13,7 +13,7 @@ import {
13
13
  useIntentDispatcher,
14
14
  } from '@dxos/app-framework';
15
15
  import { invariant } from '@dxos/invariant';
16
- import { createDocAccessor, fullyQualifiedId, getSpace, type Query } from '@dxos/react-client/echo';
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
19
  import {
@@ -35,7 +35,7 @@ import {
35
35
  type RenderCallback,
36
36
  } from '@dxos/react-ui-editor';
37
37
  import { defaultTx } from '@dxos/react-ui-theme';
38
- import { type TextType } from '@dxos/schema';
38
+ import { type DataType } from '@dxos/schema';
39
39
  import { isNotFalsy } from '@dxos/util';
40
40
 
41
41
  import { MarkdownCapabilities } from './capabilities';
@@ -45,9 +45,9 @@ import { setFallbackName } from './util';
45
45
  type ExtensionsOptions = {
46
46
  document?: DocumentType;
47
47
  id?: string;
48
- text?: TextType;
48
+ text?: DataType.Text;
49
49
  dispatch?: PromiseIntentDispatcher;
50
- query?: Query<DocumentType>;
50
+ query?: QueryResult<DocumentType>;
51
51
  settings: MarkdownSettingsProps;
52
52
  viewMode?: EditorViewMode;
53
53
  editorStateStore?: EditorStateStore;
@@ -68,7 +68,7 @@ export const useExtensions = ({
68
68
 
69
69
  // TODO(wittjosiah): Autocomplete is not working and this query is causing performance issues.
70
70
  // TODO(burdon): Unsubscribe.
71
- // const query = space?.db.query(Filter.schema(DocumentType));
71
+ // const query = space?.db.query(Filter.type(DocumentType));
72
72
  // query?.subscribe();
73
73
  const baseExtensions = useMemo(
74
74
  () =>
@@ -3,10 +3,10 @@
3
3
  //
4
4
 
5
5
  import { EditorView } from '@codemirror/view';
6
+ import { Schema } from 'effect';
6
7
  import { useMemo } from 'react';
7
8
 
8
9
  import { createResolver, LayoutAction, useIntentResolver } from '@dxos/app-framework';
9
- import { S } from '@dxos/echo-schema';
10
10
  import { invariant } from '@dxos/invariant';
11
11
  import { Cursor, setSelection } from '@dxos/react-ui-editor';
12
12
 
@@ -22,7 +22,7 @@ export const useSelectCurrentThread = (editorView: EditorView | undefined, docum
22
22
  intent: LayoutAction.UpdateLayout,
23
23
  position: 'hoist',
24
24
  filter: (data): data is { part: 'current'; subject: string; options: { cursor: string } } => {
25
- if (!S.is(LayoutAction.ScrollIntoView.fields.input)(data)) {
25
+ if (!Schema.is(LayoutAction.ScrollIntoView.fields.input)(data)) {
26
26
  return false;
27
27
  }
28
28
 
@@ -2,15 +2,13 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { getSchemaTypename } from '@dxos/echo-schema';
6
-
7
5
  import { MARKDOWN_PLUGIN } from './meta';
8
6
  import { DocumentType } from './types';
9
7
 
10
8
  export default [
11
9
  {
12
10
  'en-US': {
13
- [getSchemaTypename(DocumentType)!]: {
11
+ [DocumentType.typename]: {
14
12
  'typename label': 'Document',
15
13
  'object name placeholder': 'New document',
16
14
  },
@@ -35,6 +33,8 @@ export default [
35
33
  'toggle view mode label': 'Toggle read-only',
36
34
  'default view mode label': 'Default view mode',
37
35
  'upload image label': 'Upload image',
36
+ 'fallback title': 'Untitled',
37
+ 'navigate to document label': 'Open document',
38
38
  },
39
39
  },
40
40
  },