@dxos/plugin-markdown 0.8.2-main.fbd8ed0 → 0.8.2-staging.7ac8446

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 (201) hide show
  1. package/dist/lib/browser/{MarkdownContainer-KKWICAKV.mjs → MarkdownContainer-T3HU27RE.mjs} +67 -55
  2. package/dist/lib/browser/MarkdownContainer-T3HU27RE.mjs.map +7 -0
  3. package/dist/lib/browser/{app-graph-serializer-MPJQUYTQ.mjs → app-graph-serializer-NOXI4IQ5.mjs} +6 -5
  4. package/dist/lib/browser/app-graph-serializer-NOXI4IQ5.mjs.map +7 -0
  5. package/dist/lib/browser/{artifact-definition-DAF3YCVL.mjs → artifact-definition-CE6J6NY4.mjs} +9 -10
  6. package/dist/lib/browser/artifact-definition-CE6J6NY4.mjs.map +7 -0
  7. package/dist/lib/browser/{chunk-S42YXFZ7.mjs → chunk-3ULJ4FIJ.mjs} +24 -11
  8. package/dist/lib/browser/chunk-3ULJ4FIJ.mjs.map +7 -0
  9. package/dist/lib/browser/{chunk-TUCSFCS5.mjs → chunk-QXDKFACU.mjs} +5 -6
  10. package/dist/lib/browser/chunk-QXDKFACU.mjs.map +7 -0
  11. package/dist/lib/browser/chunk-YCJNW2RU.mjs +75 -0
  12. package/dist/lib/browser/chunk-YCJNW2RU.mjs.map +7 -0
  13. package/dist/lib/browser/index.mjs +6 -10
  14. package/dist/lib/browser/index.mjs.map +3 -3
  15. package/dist/lib/browser/intent-resolver-42GQ6HNZ.mjs +50 -0
  16. package/dist/lib/browser/intent-resolver-42GQ6HNZ.mjs.map +7 -0
  17. package/dist/lib/browser/meta.json +1 -1
  18. package/dist/lib/browser/{react-surface-EMQV3GVI.mjs → react-surface-RQX3CPFV.mjs} +7 -18
  19. package/dist/lib/browser/react-surface-RQX3CPFV.mjs.map +7 -0
  20. package/dist/lib/browser/{settings-GPB6WOIU.mjs → settings-GCSS3Y4Z.mjs} +4 -4
  21. package/dist/lib/browser/settings-GCSS3Y4Z.mjs.map +7 -0
  22. package/dist/lib/browser/{state-XTP5IP3W.mjs → state-O7P5JDIH.mjs} +2 -2
  23. package/dist/lib/browser/state-O7P5JDIH.mjs.map +7 -0
  24. package/dist/lib/browser/{thread-KW43PJ53.mjs → thread-3QGCFNVZ.mjs} +2 -2
  25. package/dist/lib/browser/types/index.mjs +1 -3
  26. package/dist/lib/node/{MarkdownContainer-LBI6ZESS.cjs → MarkdownContainer-6ZJIFAP6.cjs} +70 -58
  27. package/dist/lib/node/MarkdownContainer-6ZJIFAP6.cjs.map +7 -0
  28. package/dist/lib/node/{app-graph-serializer-Z7UJYSSL.cjs → app-graph-serializer-HKK3SEDN.cjs} +11 -10
  29. package/dist/lib/node/app-graph-serializer-HKK3SEDN.cjs.map +7 -0
  30. package/dist/lib/node/{artifact-definition-UIZSL2AL.cjs → artifact-definition-XGADFWCQ.cjs} +14 -15
  31. package/dist/lib/node/artifact-definition-XGADFWCQ.cjs.map +7 -0
  32. package/dist/lib/node/{chunk-AJHB57YQ.cjs → chunk-7QVONRSI.cjs} +57 -13
  33. package/dist/lib/node/chunk-7QVONRSI.cjs.map +7 -0
  34. package/dist/lib/node/{chunk-4525YF72.cjs → chunk-H5MYVP6F.cjs} +8 -9
  35. package/dist/lib/node/chunk-H5MYVP6F.cjs.map +7 -0
  36. package/dist/lib/node/{chunk-EO5H4OZJ.cjs → chunk-UEXGNGSS.cjs} +31 -44
  37. package/dist/lib/node/chunk-UEXGNGSS.cjs.map +7 -0
  38. package/dist/lib/node/index.cjs +21 -24
  39. package/dist/lib/node/index.cjs.map +3 -3
  40. package/dist/lib/node/intent-resolver-NW27BF3W.cjs +63 -0
  41. package/dist/lib/node/intent-resolver-NW27BF3W.cjs.map +7 -0
  42. package/dist/lib/node/meta.json +1 -1
  43. package/dist/lib/node/{react-surface-REHX3ABQ.cjs → react-surface-5X3SMHGI.cjs} +10 -21
  44. package/dist/lib/node/react-surface-5X3SMHGI.cjs.map +7 -0
  45. package/dist/lib/node/{settings-SF6JDJG6.cjs → settings-S2ISUVIH.cjs} +7 -7
  46. package/dist/lib/node/settings-S2ISUVIH.cjs.map +7 -0
  47. package/dist/lib/node/{state-K4IPZTRO.cjs → state-L44SG3ZM.cjs} +5 -5
  48. package/dist/lib/node/state-L44SG3ZM.cjs.map +7 -0
  49. package/dist/lib/node/{thread-NWBGBGOR.cjs → thread-42R57L4K.cjs} +6 -6
  50. package/dist/lib/node/types/index.cjs +6 -8
  51. package/dist/lib/node/types/index.cjs.map +2 -2
  52. package/dist/lib/node-esm/{MarkdownContainer-62XZY5EP.mjs → MarkdownContainer-URAPTO37.mjs} +67 -55
  53. package/dist/lib/node-esm/MarkdownContainer-URAPTO37.mjs.map +7 -0
  54. package/dist/lib/node-esm/{app-graph-serializer-DDMFMNYI.mjs → app-graph-serializer-QQ2CTHOQ.mjs} +6 -5
  55. package/dist/lib/node-esm/app-graph-serializer-QQ2CTHOQ.mjs.map +7 -0
  56. package/dist/lib/node-esm/{artifact-definition-ER3446S7.mjs → artifact-definition-WRG5ZRN5.mjs} +9 -10
  57. package/dist/lib/node-esm/artifact-definition-WRG5ZRN5.mjs.map +7 -0
  58. package/dist/lib/node-esm/chunk-4AM4VU3Y.mjs +76 -0
  59. package/dist/lib/node-esm/chunk-4AM4VU3Y.mjs.map +7 -0
  60. package/dist/lib/node-esm/{chunk-PDD5B7EO.mjs → chunk-F6UHVLH7.mjs} +24 -11
  61. package/dist/lib/node-esm/chunk-F6UHVLH7.mjs.map +7 -0
  62. package/dist/lib/node-esm/{chunk-CXTVDT5U.mjs → chunk-JAVD67QP.mjs} +5 -6
  63. package/dist/lib/node-esm/chunk-JAVD67QP.mjs.map +7 -0
  64. package/dist/lib/node-esm/index.mjs +6 -10
  65. package/dist/lib/node-esm/index.mjs.map +3 -3
  66. package/dist/lib/node-esm/intent-resolver-7HOMUVHR.mjs +51 -0
  67. package/dist/lib/node-esm/intent-resolver-7HOMUVHR.mjs.map +7 -0
  68. package/dist/lib/node-esm/meta.json +1 -1
  69. package/dist/lib/node-esm/{react-surface-FA7JYF2A.mjs → react-surface-6IKC3G46.mjs} +7 -18
  70. package/dist/lib/node-esm/react-surface-6IKC3G46.mjs.map +7 -0
  71. package/dist/lib/node-esm/{settings-2DT2C4RA.mjs → settings-ZDIFTK4N.mjs} +4 -4
  72. package/dist/lib/node-esm/settings-ZDIFTK4N.mjs.map +7 -0
  73. package/dist/lib/node-esm/{state-7VFYPF6Z.mjs → state-DWPOKLEY.mjs} +2 -2
  74. package/dist/lib/node-esm/state-DWPOKLEY.mjs.map +7 -0
  75. package/dist/lib/node-esm/{thread-D2E6W44K.mjs → thread-R2KHZD6V.mjs} +2 -2
  76. package/dist/lib/node-esm/types/index.mjs +1 -3
  77. package/dist/types/src/capabilities/app-graph-serializer.d.ts +2 -2
  78. package/dist/types/src/capabilities/app-graph-serializer.d.ts.map +1 -1
  79. package/dist/types/src/capabilities/artifact-definition.d.ts.map +1 -1
  80. package/dist/types/src/capabilities/index.d.ts +3 -3
  81. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  82. package/dist/types/src/capabilities/intent-resolver.d.ts +2 -2
  83. package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
  84. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  85. package/dist/types/src/capabilities/state.d.ts +2 -2
  86. package/dist/types/src/capabilities/state.d.ts.map +1 -1
  87. package/dist/types/src/components/MarkdownContainer.d.ts +2 -2
  88. package/dist/types/src/components/MarkdownContainer.d.ts.map +1 -1
  89. package/dist/types/src/components/{MarkdownEditor/MarkdownEditor.d.ts → MarkdownEditor.d.ts} +16 -1
  90. package/dist/types/src/components/MarkdownEditor.d.ts.map +1 -0
  91. package/dist/types/src/components/{MarkdownEditor/MarkdownEditor.stories.d.ts → MarkdownEditor.stories.d.ts} +3 -3
  92. package/dist/types/src/components/MarkdownEditor.stories.d.ts.map +1 -0
  93. package/dist/types/src/components/{MarkdownSettings/MarkdownSettings.d.ts → MarkdownSettings.d.ts} +1 -1
  94. package/dist/types/src/components/MarkdownSettings.d.ts.map +1 -0
  95. package/dist/types/src/components/Toolbar.stories.d.ts +2 -2
  96. package/dist/types/src/components/Toolbar.stories.d.ts.map +1 -1
  97. package/dist/types/src/components/index.d.ts +0 -1
  98. package/dist/types/src/components/index.d.ts.map +1 -1
  99. package/dist/types/src/extensions.d.ts +4 -4
  100. package/dist/types/src/extensions.d.ts.map +1 -1
  101. package/dist/types/src/hooks/useSelectCurrentThread.d.ts.map +1 -1
  102. package/dist/types/src/translations.d.ts +42 -4
  103. package/dist/types/src/translations.d.ts.map +1 -1
  104. package/dist/types/src/types/schema.d.ts +123 -336
  105. package/dist/types/src/types/schema.d.ts.map +1 -1
  106. package/dist/types/src/types/types.d.ts +85 -139
  107. package/dist/types/src/types/types.d.ts.map +1 -1
  108. package/dist/types/src/util.d.ts +0 -1
  109. package/dist/types/src/util.d.ts.map +1 -1
  110. package/dist/types/tsconfig.tsbuildinfo +1 -1
  111. package/package.json +33 -40
  112. package/src/MarkdownPlugin.tsx +5 -5
  113. package/src/capabilities/app-graph-serializer.ts +5 -4
  114. package/src/capabilities/artifact-definition.ts +4 -6
  115. package/src/capabilities/intent-resolver.ts +10 -43
  116. package/src/capabilities/react-surface.tsx +5 -13
  117. package/src/capabilities/settings.ts +2 -2
  118. package/src/capabilities/state.ts +4 -4
  119. package/src/components/MarkdownContainer.tsx +4 -4
  120. package/src/components/{MarkdownEditor/MarkdownEditor.stories.tsx → MarkdownEditor.stories.tsx} +35 -22
  121. package/src/components/{MarkdownEditor/MarkdownEditor.tsx → MarkdownEditor.tsx} +44 -24
  122. package/src/components/{MarkdownSettings/MarkdownSettings.tsx → MarkdownSettings.tsx} +2 -2
  123. package/src/components/Toolbar.stories.tsx +27 -27
  124. package/src/components/index.ts +0 -1
  125. package/src/extensions.tsx +37 -42
  126. package/src/hooks/useSelectCurrentThread.tsx +2 -2
  127. package/src/translations.ts +3 -3
  128. package/src/types/schema.ts +11 -24
  129. package/src/types/types.ts +21 -23
  130. package/src/util.tsx +4 -8
  131. package/dist/lib/browser/MarkdownContainer-KKWICAKV.mjs.map +0 -7
  132. package/dist/lib/browser/MarkdownPreview-FVSYVJGN.mjs +0 -81
  133. package/dist/lib/browser/MarkdownPreview-FVSYVJGN.mjs.map +0 -7
  134. package/dist/lib/browser/app-graph-serializer-MPJQUYTQ.mjs.map +0 -7
  135. package/dist/lib/browser/artifact-definition-DAF3YCVL.mjs.map +0 -7
  136. package/dist/lib/browser/chunk-JJY5LKZS.mjs +0 -20
  137. package/dist/lib/browser/chunk-JJY5LKZS.mjs.map +0 -7
  138. package/dist/lib/browser/chunk-S42YXFZ7.mjs.map +0 -7
  139. package/dist/lib/browser/chunk-TUCSFCS5.mjs.map +0 -7
  140. package/dist/lib/browser/chunk-XP2ZPCLI.mjs +0 -87
  141. package/dist/lib/browser/chunk-XP2ZPCLI.mjs.map +0 -7
  142. package/dist/lib/browser/intent-resolver-PVKVTAFF.mjs +0 -81
  143. package/dist/lib/browser/intent-resolver-PVKVTAFF.mjs.map +0 -7
  144. package/dist/lib/browser/react-surface-EMQV3GVI.mjs.map +0 -7
  145. package/dist/lib/browser/settings-GPB6WOIU.mjs.map +0 -7
  146. package/dist/lib/browser/state-XTP5IP3W.mjs.map +0 -7
  147. package/dist/lib/node/MarkdownContainer-LBI6ZESS.cjs.map +0 -7
  148. package/dist/lib/node/MarkdownPreview-O3BR4PZW.cjs +0 -104
  149. package/dist/lib/node/MarkdownPreview-O3BR4PZW.cjs.map +0 -7
  150. package/dist/lib/node/app-graph-serializer-Z7UJYSSL.cjs.map +0 -7
  151. package/dist/lib/node/artifact-definition-UIZSL2AL.cjs.map +0 -7
  152. package/dist/lib/node/chunk-4525YF72.cjs.map +0 -7
  153. package/dist/lib/node/chunk-AJHB57YQ.cjs.map +0 -7
  154. package/dist/lib/node/chunk-BWRBWEKN.cjs +0 -75
  155. package/dist/lib/node/chunk-BWRBWEKN.cjs.map +0 -7
  156. package/dist/lib/node/chunk-EO5H4OZJ.cjs.map +0 -7
  157. package/dist/lib/node/intent-resolver-ND7PSRJX.cjs +0 -94
  158. package/dist/lib/node/intent-resolver-ND7PSRJX.cjs.map +0 -7
  159. package/dist/lib/node/react-surface-REHX3ABQ.cjs.map +0 -7
  160. package/dist/lib/node/settings-SF6JDJG6.cjs.map +0 -7
  161. package/dist/lib/node/state-K4IPZTRO.cjs.map +0 -7
  162. package/dist/lib/node-esm/MarkdownContainer-62XZY5EP.mjs.map +0 -7
  163. package/dist/lib/node-esm/MarkdownPreview-KYWRMBRM.mjs +0 -82
  164. package/dist/lib/node-esm/MarkdownPreview-KYWRMBRM.mjs.map +0 -7
  165. package/dist/lib/node-esm/app-graph-serializer-DDMFMNYI.mjs.map +0 -7
  166. package/dist/lib/node-esm/artifact-definition-ER3446S7.mjs.map +0 -7
  167. package/dist/lib/node-esm/chunk-66XM3JMR.mjs +0 -88
  168. package/dist/lib/node-esm/chunk-66XM3JMR.mjs.map +0 -7
  169. package/dist/lib/node-esm/chunk-CXTVDT5U.mjs.map +0 -7
  170. package/dist/lib/node-esm/chunk-PDD5B7EO.mjs.map +0 -7
  171. package/dist/lib/node-esm/chunk-T5Z5BIOF.mjs +0 -22
  172. package/dist/lib/node-esm/chunk-T5Z5BIOF.mjs.map +0 -7
  173. package/dist/lib/node-esm/intent-resolver-5BF5PLSN.mjs +0 -82
  174. package/dist/lib/node-esm/intent-resolver-5BF5PLSN.mjs.map +0 -7
  175. package/dist/lib/node-esm/react-surface-FA7JYF2A.mjs.map +0 -7
  176. package/dist/lib/node-esm/settings-2DT2C4RA.mjs.map +0 -7
  177. package/dist/lib/node-esm/state-7VFYPF6Z.mjs.map +0 -7
  178. package/dist/types/src/components/MarkdownEditor/MarkdownEditor.d.ts.map +0 -1
  179. package/dist/types/src/components/MarkdownEditor/MarkdownEditor.stories.d.ts.map +0 -1
  180. package/dist/types/src/components/MarkdownEditor/index.d.ts +0 -2
  181. package/dist/types/src/components/MarkdownEditor/index.d.ts.map +0 -1
  182. package/dist/types/src/components/MarkdownPreview/MarkdownPreview.d.ts +0 -6
  183. package/dist/types/src/components/MarkdownPreview/MarkdownPreview.d.ts.map +0 -1
  184. package/dist/types/src/components/MarkdownPreview/MarkdownPreview.stories.d.ts +0 -127
  185. package/dist/types/src/components/MarkdownPreview/MarkdownPreview.stories.d.ts.map +0 -1
  186. package/dist/types/src/components/MarkdownPreview/index.d.ts +0 -4
  187. package/dist/types/src/components/MarkdownPreview/index.d.ts.map +0 -1
  188. package/dist/types/src/components/MarkdownSettings/MarkdownSettings.d.ts.map +0 -1
  189. package/dist/types/src/components/MarkdownSettings/index.d.ts +0 -2
  190. package/dist/types/src/components/MarkdownSettings/index.d.ts.map +0 -1
  191. package/dist/types/src/components/Suggestions.stories.d.ts +0 -12
  192. package/dist/types/src/components/Suggestions.stories.d.ts.map +0 -1
  193. package/src/components/MarkdownEditor/index.ts +0 -5
  194. package/src/components/MarkdownPreview/MarkdownPreview.stories.tsx +0 -74
  195. package/src/components/MarkdownPreview/MarkdownPreview.tsx +0 -85
  196. package/src/components/MarkdownPreview/index.ts +0 -9
  197. package/src/components/MarkdownSettings/index.ts +0 -5
  198. package/src/components/Suggestions.stories.tsx +0 -191
  199. /package/dist/lib/browser/{thread-KW43PJ53.mjs.map → thread-3QGCFNVZ.mjs.map} +0 -0
  200. /package/dist/lib/node/{thread-NWBGBGOR.cjs.map → thread-42R57L4K.cjs.map} +0 -0
  201. /package/dist/lib/node-esm/{thread-D2E6W44K.mjs.map → thread-R2KHZD6V.mjs.map} +0 -0
@@ -3,13 +3,13 @@
3
3
  //
4
4
 
5
5
  import { Capabilities, contributes } from '@dxos/app-framework';
6
- import { live } from '@dxos/live-object';
6
+ import { create } from '@dxos/live-object';
7
7
 
8
8
  import { MARKDOWN_PLUGIN } from '../meta';
9
9
  import { type MarkdownSettingsProps, MarkdownSettingsSchema } from '../types';
10
10
 
11
11
  export default () => {
12
- const settings = live<MarkdownSettingsProps>({
12
+ const settings = create<MarkdownSettingsProps>({
13
13
  defaultViewMode: 'preview',
14
14
  toolbar: true,
15
15
  numberedHeadings: true,
@@ -2,7 +2,7 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { Capabilities, contributes, type PluginContext } from '@dxos/app-framework';
5
+ import { Capabilities, contributes, type PluginsContext } from '@dxos/app-framework';
6
6
  import { LocalStorageStore } from '@dxos/local-storage';
7
7
  import { type EditorViewMode, createEditorStateStore } from '@dxos/react-ui-editor';
8
8
 
@@ -10,8 +10,9 @@ import { MarkdownCapabilities } from './capabilities';
10
10
  import { MARKDOWN_PLUGIN } from '../meta';
11
11
  import { type MarkdownPluginState, type MarkdownSettingsProps } from '../types';
12
12
 
13
- export default (context: PluginContext) => {
13
+ export default (context: PluginsContext) => {
14
14
  const state = new LocalStorageStore<MarkdownPluginState>(MARKDOWN_PLUGIN, { extensionProviders: [], viewMode: {} });
15
+
15
16
  state.prop({ key: 'viewMode', type: LocalStorageStore.json<{ [key: string]: EditorViewMode }>() });
16
17
 
17
18
  // TODO(wittjosiah): Fold into state.
@@ -19,13 +20,12 @@ export default (context: PluginContext) => {
19
20
 
20
21
  const getViewMode = (id: string) => {
21
22
  const defaultViewMode = context
22
- .getCapability(Capabilities.SettingsStore)
23
+ .requestCapability(Capabilities.SettingsStore)
23
24
  .getStore<MarkdownSettingsProps>(MARKDOWN_PLUGIN)!.value.defaultViewMode;
24
25
  return (id && state.values.viewMode[id]) || defaultViewMode;
25
26
  };
26
27
 
27
28
  const setViewMode = (id: string, viewMode: EditorViewMode) => (state.values.viewMode[id] = viewMode);
28
29
 
29
- // Return object with methods.
30
30
  return contributes(MarkdownCapabilities.State, { state: state.values, editorState, getViewMode, setViewMode });
31
31
  };
@@ -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 { DataType } from '@dxos/schema';
10
+ import { TextType } from '@dxos/schema';
11
11
 
12
12
  import { MarkdownEditor, type MarkdownEditorProps } from './MarkdownEditor';
13
13
  import { useExtensions } from '../extensions';
@@ -19,10 +19,11 @@ export type MarkdownContainerProps = Pick<
19
19
  'role' | 'extensionProviders' | 'viewMode' | 'editorStateStore' | 'onViewModeChange'
20
20
  > & {
21
21
  id: string;
22
- object: DocumentType | DataType.Text | any;
22
+ object: DocumentType | TextType | any;
23
23
  settings: MarkdownSettingsProps;
24
24
  };
25
25
 
26
+ // TODO(burdon): Move toolbar here.
26
27
  // TODO(burdon): Factor out difference for ECHO and non-ECHO objects; i.e., single component.
27
28
  const MarkdownContainer = ({
28
29
  id,
@@ -35,7 +36,7 @@ const MarkdownContainer = ({
35
36
  }: MarkdownContainerProps) => {
36
37
  const scrollPastEnd = role === 'article';
37
38
  const doc = isInstanceOf(DocumentType, object) ? object : undefined;
38
- const text = isInstanceOf(DataType.Text, object) ? object : undefined;
39
+ const text = isInstanceOf(TextType, object) ? object : undefined;
39
40
  const extensions = useExtensions({ document: doc, text, id, settings, viewMode, editorStateStore });
40
41
 
41
42
  if (doc) {
@@ -67,7 +68,6 @@ const MarkdownContainer = ({
67
68
  />
68
69
  );
69
70
  } else {
70
- // TODO(burdon): Normalize with above.
71
71
  return (
72
72
  <MarkdownEditor
73
73
  id={id}
@@ -10,14 +10,19 @@ import React, { useMemo } from 'react';
10
10
  import { IntentPlugin } from '@dxos/app-framework';
11
11
  import { withPluginManager } from '@dxos/app-framework/testing';
12
12
  import { createDocAccessor, createObject } from '@dxos/react-client/echo';
13
+ import { Main } from '@dxos/react-ui';
14
+ import { AttendableContainer } from '@dxos/react-ui-attention';
13
15
  import { withAttention } from '@dxos/react-ui-attention/testing';
14
- import { automerge, translations as editorTranslations } from '@dxos/react-ui-editor';
16
+ import { editorWithToolbarLayout, automerge, translations as editorTranslations } from '@dxos/react-ui-editor';
17
+ import { topbarBlockPaddingStart } from '@dxos/react-ui-theme';
15
18
  import { withLayout, withTheme } from '@dxos/storybook-utils';
16
19
 
17
20
  import { MarkdownEditor, type MarkdownEditorProps } from './MarkdownEditor';
18
- import translations from '../../translations';
21
+ import translations from '../translations';
19
22
 
20
- const content = Array.from({ length: 100 }, (_, i) => `Line ${i + 1}`).join('\n');
23
+ const content = Array.from({ length: 100 })
24
+ .map((_, i) => `Line ${i + 1}`)
25
+ .join('\n');
21
26
 
22
27
  type StoryProps = MarkdownEditorProps & {
23
28
  content?: string;
@@ -27,26 +32,19 @@ type StoryProps = MarkdownEditorProps & {
27
32
  const DefaultStory = ({ content = '# Test', toolbar }: StoryProps) => {
28
33
  const doc = useMemo(() => createObject({ content }), [content]);
29
34
  const extensions = useMemo(() => [automerge(createDocAccessor(doc, ['content']))], [doc]);
30
- return <MarkdownEditor id='test' initialValue={doc.content} extensions={extensions} toolbar={toolbar} />;
35
+ return (
36
+ <Main.Content
37
+ bounce
38
+ data-toolbar={toolbar ? 'enabled' : 'disabled'}
39
+ classNames={[topbarBlockPaddingStart, editorWithToolbarLayout]}
40
+ >
41
+ <AttendableContainer id='test'>
42
+ <MarkdownEditor id='test' initialValue={doc.content} extensions={extensions} toolbar={toolbar} />
43
+ </AttendableContainer>
44
+ </Main.Content>
45
+ );
31
46
  };
32
47
 
33
- const meta: Meta<typeof MarkdownEditor> = {
34
- title: 'plugins/plugin-markdown/MarkdownEditor',
35
- component: MarkdownEditor,
36
- render: DefaultStory,
37
- decorators: [
38
- withTheme,
39
- withLayout({ fullscreen: true }),
40
- withAttention,
41
- withPluginManager({ plugins: [IntentPlugin()] }),
42
- ],
43
- parameters: {
44
- translations: [...translations, ...editorTranslations],
45
- },
46
- };
47
-
48
- export default meta;
49
-
50
48
  export const Default = {
51
49
  args: {
52
50
  content,
@@ -55,7 +53,22 @@ export const Default = {
55
53
 
56
54
  export const WithToolbar = {
57
55
  args: {
58
- toolbar: true,
59
56
  content,
57
+ toolbar: true,
60
58
  },
61
59
  };
60
+
61
+ const meta: Meta<typeof MarkdownEditor> = {
62
+ title: 'plugins/plugin-markdown/EditorMain',
63
+ component: MarkdownEditor,
64
+ render: DefaultStory,
65
+ decorators: [
66
+ withTheme,
67
+ withLayout({ tooltips: true }),
68
+ withAttention,
69
+ withPluginManager({ plugins: [IntentPlugin()] }),
70
+ ],
71
+ parameters: { layout: 'fullscreen', translations: [...translations, ...editorTranslations] },
72
+ };
73
+
74
+ export default meta;
@@ -2,16 +2,17 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
+ import { openSearchPanel } from '@codemirror/search';
5
6
  import { type EditorView } from '@codemirror/view';
6
7
  import React, { useMemo, useEffect, useCallback } from 'react';
7
8
  import { useDropzone } from 'react-dropzone';
8
9
 
9
10
  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,
15
16
  type EditorViewMode,
16
17
  type EditorInputMode,
17
18
  type EditorSelectionState,
@@ -19,6 +20,7 @@ import {
19
20
  EditorToolbar,
20
21
  type UseTextEditorProps,
21
22
  createBasicExtensions,
23
+ createEditorAction,
22
24
  createMarkdownExtensions,
23
25
  createThemeExtensions,
24
26
  dropFile,
@@ -26,19 +28,19 @@ import {
26
28
  editorGutter,
27
29
  processEditorPayload,
28
30
  stackItemContentEditorClassNames,
31
+ useActionHandler,
29
32
  useCommentState,
30
33
  useCommentClickListener,
31
34
  useFormattingState,
32
35
  useTextEditor,
33
36
  useEditorToolbarState,
34
- addLink,
35
37
  } from '@dxos/react-ui-editor';
36
38
  import { StackItem } from '@dxos/react-ui-stack';
37
39
  import { isNotFalsy, isNonNullable } from '@dxos/util';
38
40
 
39
- import { useSelectCurrentThread } from '../../hooks';
40
- import { MARKDOWN_PLUGIN } from '../../meta';
41
- import { type MarkdownPluginState } from '../../types';
41
+ import { useSelectCurrentThread } from '../hooks';
42
+ import { MARKDOWN_PLUGIN } from '../meta';
43
+ import { type MarkdownPluginState } from '../types';
42
44
 
43
45
  export type MarkdownEditorProps = {
44
46
  id: string;
@@ -176,28 +178,38 @@ export const MarkdownEditor = ({
176
178
 
177
179
  const info = await onFileUpload(file);
178
180
  if (info) {
179
- addLink({ url: info.url, image: true })(editorView);
181
+ processEditorPayload(editorView, { type: 'image', data: info.url });
180
182
  }
181
183
  });
182
184
  }
183
- }, [acceptedFiles, editorView, onFileUpload]);
185
+ }, [acceptedFiles, editorView]);
184
186
 
185
- const getView = useCallback(() => {
186
- invariant(editorView);
187
- return editorView;
188
- }, [editorView]);
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
+ }
189
207
 
190
- const handleViewModeChange = useCallback(
191
- (mode: EditorViewMode) => onViewModeChange?.(id, mode),
192
- [id, onViewModeChange],
208
+ handleToolbarAction?.(action);
209
+ },
210
+ [editorView, onViewModeChange, open],
193
211
  );
194
212
 
195
- const handleImageUpload = useCallback(() => {
196
- if (onFileUpload) {
197
- open();
198
- }
199
- }, [onFileUpload]);
200
-
201
213
  return (
202
214
  <StackItem.Content toolbar={!!toolbar}>
203
215
  {toolbar && (
@@ -206,10 +218,9 @@ export const MarkdownEditor = ({
206
218
  attendableId={id}
207
219
  role={role}
208
220
  state={toolbarState}
209
- getView={getView}
210
221
  comment={comment}
211
- image={handleImageUpload}
212
- viewMode={handleViewModeChange}
222
+ customActions={onFileUpload ? createUploadAction : undefined}
223
+ onAction={handleAction}
213
224
  />
214
225
  <input {...getInputProps()} />
215
226
  </>
@@ -220,7 +231,6 @@ export const MarkdownEditor = ({
220
231
  data-testid='composer.markdownRoot'
221
232
  data-toolbar={toolbar ? 'enabled' : 'disabled'}
222
233
  className={stackItemContentEditorClassNames(role)}
223
- data-popover-collision-boundary={true}
224
234
  {...focusAttributes}
225
235
  />
226
236
  </StackItem.Content>
@@ -237,3 +247,13 @@ const useTest = (view?: EditorView) => {
237
247
  }
238
248
  }, [view]);
239
249
  };
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
+ });
@@ -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);
@@ -5,16 +5,15 @@
5
5
  import '@dxos-theme';
6
6
 
7
7
  import { type Meta } from '@storybook/react';
8
- import React, { type FC, useCallback, useState } from 'react';
8
+ import React, { type FC, useState } from 'react';
9
9
 
10
- import { invariant } from '@dxos/invariant';
11
10
  import { PublicKey } from '@dxos/keys';
12
- import { live } from '@dxos/live-object';
11
+ import { create } from '@dxos/live-object';
13
12
  import { faker } from '@dxos/random';
14
13
  import { createDocAccessor, createObject } from '@dxos/react-client/echo';
15
14
  import { useThemeContext } from '@dxos/react-ui';
16
15
  import {
17
- EditorToolbar,
16
+ type EditorAction,
18
17
  type Comment,
19
18
  comments,
20
19
  createBasicExtensions,
@@ -24,21 +23,24 @@ import {
24
23
  decorateMarkdown,
25
24
  editorContent,
26
25
  formattingKeymap,
26
+ EditorToolbar,
27
27
  translations,
28
+ useActionHandler,
28
29
  useComments,
29
30
  useFormattingState,
30
31
  useTextEditor,
31
32
  useEditorToolbarState,
32
- type EditorViewMode,
33
33
  } from '@dxos/react-ui-editor';
34
- import { DataType } from '@dxos/schema';
34
+ import { TextType } from '@dxos/schema';
35
35
  import { withLayout, withTheme } from '@dxos/storybook-utils';
36
36
 
37
37
  faker.seed(101);
38
38
 
39
+ const _onUpload = async (file: File) => ({ url: file.name });
40
+
39
41
  const DefaultStory: FC<{ content?: string }> = ({ content = '' }) => {
40
42
  const { themeMode } = useThemeContext();
41
- const [text] = useState(createObject(live(DataType.Text, { content })));
43
+ const [text] = useState(createObject(create(TextType, { content })));
42
44
  const toolbarState = useEditorToolbarState({ viewMode: 'preview' });
43
45
  const formattingObserver = useFormattingState(toolbarState);
44
46
  const { parentRef, view } = useTextEditor(() => {
@@ -64,22 +66,22 @@ const DefaultStory: FC<{ content?: string }> = ({ content = '' }) => {
64
66
  };
65
67
  }, [text, formattingObserver, toolbarState.viewMode, themeMode]);
66
68
 
67
- const handleViewModeChange = (viewMode: EditorViewMode) => {
68
- toolbarState.viewMode = viewMode;
69
+ const handleToolbarAction = useActionHandler(view);
70
+ const handleAction = (action: EditorAction) => {
71
+ if (action.type === 'view-mode') {
72
+ toolbarState.viewMode = action.properties.data;
73
+ } else {
74
+ handleToolbarAction?.(action);
75
+ }
69
76
  };
70
77
 
71
- const getView = useCallback(() => {
72
- invariant(view);
73
- return view;
74
- }, [view]);
75
-
76
78
  const [_comments, setComments] = useState<Comment[]>([]);
77
79
  useComments(view, text.id, _comments);
78
80
 
79
81
  return (
80
- <div role='none' className='flex flex-col'>
81
- <EditorToolbar state={toolbarState ?? {}} getView={getView} viewMode={handleViewModeChange} />
82
- <div className='flex grow overflow-hidden' ref={parentRef} />
82
+ <div role='none' className='fixed inset-0 flex flex-col'>
83
+ <EditorToolbar onAction={handleAction} state={toolbarState ?? {}} />
84
+ <div ref={parentRef} />
83
85
  </div>
84
86
  );
85
87
  };
@@ -94,20 +96,18 @@ const content = [
94
96
  '',
95
97
  ].join('\n');
96
98
 
99
+ export const Default = {
100
+ args: {
101
+ content,
102
+ },
103
+ };
104
+
97
105
  const meta: Meta<typeof EditorToolbar> = {
98
106
  title: 'plugins/plugin-markdown/Toolbar',
99
107
  component: EditorToolbar,
100
108
  render: DefaultStory as any,
101
- decorators: [withTheme, withLayout({ fullscreen: true })],
102
- parameters: {
103
- translations,
104
- },
109
+ decorators: [withTheme, withLayout({ tooltips: true })],
110
+ parameters: { translations, layout: 'fullscreen' },
105
111
  };
106
112
 
107
113
  export default meta;
108
-
109
- export const Default = {
110
- args: {
111
- content,
112
- },
113
- };
@@ -7,4 +7,3 @@ 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 QueryResult } from '@dxos/react-client/echo';
16
+ import { createDocAccessor, fullyQualifiedId, getSpace, type Query } 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 {
@@ -29,13 +29,11 @@ import {
29
29
  formattingKeymap,
30
30
  linkTooltip,
31
31
  listener,
32
- preview,
33
32
  selectionState,
34
33
  typewriter,
35
- type RenderCallback,
36
34
  } from '@dxos/react-ui-editor';
37
35
  import { defaultTx } from '@dxos/react-ui-theme';
38
- import { type DataType } from '@dxos/schema';
36
+ import { type TextType } from '@dxos/schema';
39
37
  import { isNotFalsy } from '@dxos/util';
40
38
 
41
39
  import { MarkdownCapabilities } from './capabilities';
@@ -45,9 +43,9 @@ import { setFallbackName } from './util';
45
43
  type ExtensionsOptions = {
46
44
  document?: DocumentType;
47
45
  id?: string;
48
- text?: DataType.Text;
46
+ text?: TextType;
49
47
  dispatch?: PromiseIntentDispatcher;
50
- query?: QueryResult<DocumentType>;
48
+ query?: Query<DocumentType>;
51
49
  settings: MarkdownSettingsProps;
52
50
  viewMode?: EditorViewMode;
53
51
  editorStateStore?: EditorStateStore;
@@ -68,7 +66,7 @@ export const useExtensions = ({
68
66
 
69
67
  // TODO(wittjosiah): Autocomplete is not working and this query is causing performance issues.
70
68
  // TODO(burdon): Unsubscribe.
71
- // const query = space?.db.query(Filter.type(DocumentType));
69
+ // const query = space?.db.query(Filter.schema(DocumentType));
72
70
  // query?.subscribe();
73
71
  const baseExtensions = useMemo(
74
72
  () =>
@@ -177,7 +175,7 @@ const createBaseExtensions = ({
177
175
  // TODO(wittjosiah): For internal links, consider ignoring the link text and rendering the label of the object being linked to.
178
176
  renderLinkButton:
179
177
  dispatch && (document || id)
180
- ? createLinkRenderer((id: string) => {
178
+ ? onRenderLink((id: string) => {
181
179
  void dispatch(
182
180
  createIntent(LayoutAction.Open, {
183
181
  part: 'main',
@@ -191,7 +189,6 @@ const createBaseExtensions = ({
191
189
  : undefined,
192
190
  }),
193
191
  linkTooltip(renderLinkTooltip),
194
- preview(),
195
192
  ],
196
193
  );
197
194
  }
@@ -236,42 +233,40 @@ const style = {
236
233
  icon: 'inline-block leading-none mis-1 cursor-pointer',
237
234
  };
238
235
 
239
- const createLinkRenderer =
240
- (onSelectObject: (id: string) => void): RenderCallback<{ url: string }> =>
241
- (el, { url }) => {
242
- // TODO(burdon): Formalize/document internal link format.
243
- const isInternal =
244
- url.startsWith('/') ||
245
- // TODO(wittjosiah): This should probably be parsed out on paste?
246
- url.startsWith(window.location.origin);
236
+ const onRenderLink = (onSelectObject: (id: string) => void) => (el: Element, url: string) => {
237
+ // TODO(burdon): Formalize/document internal link format.
238
+ const isInternal =
239
+ url.startsWith('/') ||
240
+ // TODO(wittjosiah): This should probably be parsed out on paste?
241
+ url.startsWith(window.location.origin);
247
242
 
248
- const options: AnchorHTMLAttributes<any> = isInternal
249
- ? {
250
- onClick: () => {
251
- const qualifiedId = url.split('/').at(-1);
252
- invariant(qualifiedId, 'Invalid link format.');
253
- onSelectObject(qualifiedId);
254
- },
255
- }
256
- : {
257
- href: url,
258
- rel: 'noreferrer',
259
- target: '_blank',
260
- };
243
+ const options: AnchorHTMLAttributes<any> = isInternal
244
+ ? {
245
+ onClick: () => {
246
+ const qualifiedId = url.split('/').at(-1);
247
+ invariant(qualifiedId, 'Invalid link format.');
248
+ onSelectObject(qualifiedId);
249
+ },
250
+ }
251
+ : {
252
+ href: url,
253
+ rel: 'noreferrer',
254
+ target: '_blank',
255
+ };
261
256
 
262
- renderRoot(
263
- el,
264
- <a {...options} className={style.hover}>
265
- <Icon
266
- icon={isInternal ? 'ph--arrow-square-down--bold' : 'ph--arrow-square-out--bold'}
267
- size={4}
268
- classNames={style.icon}
269
- />
270
- </a>,
271
- );
272
- };
257
+ renderRoot(
258
+ el,
259
+ <a {...options} className={style.hover}>
260
+ <Icon
261
+ icon={isInternal ? 'ph--arrow-square-down--bold' : 'ph--arrow-square-out--bold'}
262
+ size={4}
263
+ classNames={style.icon}
264
+ />
265
+ </a>,
266
+ );
267
+ };
273
268
 
274
- const renderLinkTooltip: RenderCallback<{ url: string }> = (el, { url }) => {
269
+ const renderLinkTooltip = (el: Element, url: string) => {
275
270
  const web = new URL(url);
276
271
  renderRoot(
277
272
  el,
@@ -3,10 +3,10 @@
3
3
  //
4
4
 
5
5
  import { EditorView } from '@codemirror/view';
6
- import { Schema } from 'effect';
7
6
  import { useMemo } from 'react';
8
7
 
9
8
  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 (!Schema.is(LayoutAction.ScrollIntoView.fields.input)(data)) {
25
+ if (!S.is(LayoutAction.ScrollIntoView.fields.input)(data)) {
26
26
  return false;
27
27
  }
28
28
 
@@ -2,13 +2,15 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
+ import { getSchemaTypename } from '@dxos/echo-schema';
6
+
5
7
  import { MARKDOWN_PLUGIN } from './meta';
6
8
  import { DocumentType } from './types';
7
9
 
8
10
  export default [
9
11
  {
10
12
  'en-US': {
11
- [DocumentType.typename]: {
13
+ [getSchemaTypename(DocumentType)!]: {
12
14
  'typename label': 'Document',
13
15
  'object name placeholder': 'New document',
14
16
  },
@@ -33,8 +35,6 @@ export default [
33
35
  'toggle view mode label': 'Toggle read-only',
34
36
  'default view mode label': 'Default view mode',
35
37
  'upload image label': 'Upload image',
36
- 'fallback title': 'Untitled',
37
- 'navigate to document label': 'Open document',
38
38
  },
39
39
  },
40
40
  },
@@ -2,36 +2,23 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { Schema } from 'effect';
6
-
7
- import { Type } from '@dxos/echo';
8
- import { Expando, LabelAnnotationId, Ref } from '@dxos/echo-schema';
9
- import { makeRef, live } from '@dxos/live-object';
5
+ import { EchoObject, Expando, LabelAnnotationId, Ref, S } from '@dxos/echo-schema';
10
6
  import { ThreadType } from '@dxos/plugin-space/types';
11
- import { DataType } from '@dxos/schema';
7
+ import { TextType } from '@dxos/schema';
12
8
 
13
- export const DocumentSchema = Schema.Struct({
14
- name: Schema.optional(Schema.String),
15
- fallbackName: Schema.optional(Schema.String),
16
- content: Ref(DataType.Text),
17
- threads: Schema.mutable(Schema.Array(Ref(ThreadType))),
18
- assistantChatQueue: Schema.optional(Ref(Expando)),
9
+ export const DocumentSchema = S.Struct({
10
+ name: S.optional(S.String),
11
+ fallbackName: S.optional(S.String),
12
+ content: Ref(TextType),
13
+ threads: S.mutable(S.Array(Ref(ThreadType))),
14
+ assistantChatQueue: S.optional(Ref(Expando)),
19
15
  }).annotations({
20
- // TODO(dmaretskyi): `Schema.Struct(...).pipe(defaultLabel(['name', 'fallbackName']))` for type-safe annotations.
16
+ // TODO(dmaretskyi): `S.Struct(...).pipe(defaultLabel(['name', 'fallbackName']))` for type-safe annotations.
21
17
  [LabelAnnotationId]: ['name', 'fallbackName'],
22
18
  });
23
19
 
24
- export const DocumentType = DocumentSchema.pipe(
25
- Type.def({
26
- typename: 'dxos.org/type/Document',
27
- version: '0.1.0',
28
- }),
29
- );
30
- export type DocumentType = Schema.Schema.Type<typeof DocumentType>;
31
-
32
- // TODO(burdon): Replace when defaults are supported.
33
- export const createDocument = ({ name, content }: { name: string; content: string }) =>
34
- live(DocumentType, { name, content: makeRef(live(DataType.Text, { content })), threads: [] });
20
+ export const DocumentType = DocumentSchema.pipe(EchoObject({ typename: 'dxos.org/type/Document', version: '0.1.0' }));
21
+ export type DocumentType = S.Schema.Type<typeof DocumentType>;
35
22
 
36
23
  /**
37
24
  * Checks if an object conforms to the interface needed to render an editor.