@dxos/plugin-markdown 0.8.4-main.9be5663bfe → 0.8.4-main.abd8ff62ef

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 (208) hide show
  1. package/dist/lib/browser/blueprints/index.mjs +3 -4
  2. package/dist/lib/browser/blueprints/index.mjs.map +2 -2
  3. package/dist/lib/browser/{chunk-XKUKZNUS.mjs → chunk-DNSKDWUL.mjs} +4 -6
  4. package/dist/lib/browser/chunk-DNSKDWUL.mjs.map +7 -0
  5. package/dist/lib/browser/{chunk-46WIDM4R.mjs → chunk-SW6IK2GJ.mjs} +39 -13
  6. package/dist/lib/browser/chunk-SW6IK2GJ.mjs.map +7 -0
  7. package/dist/lib/browser/{create-HSXPXCC5.mjs → create-SRADQOTE.mjs} +4 -5
  8. package/dist/lib/browser/create-SRADQOTE.mjs.map +7 -0
  9. package/dist/lib/browser/{create-markdown-WB7DH3UF.mjs → create-markdown-A2ERCEOZ.mjs} +4 -5
  10. package/dist/lib/browser/create-markdown-A2ERCEOZ.mjs.map +7 -0
  11. package/dist/lib/browser/index.mjs +7 -545
  12. package/dist/lib/browser/index.mjs.map +4 -4
  13. package/dist/lib/browser/meta.json +1 -1
  14. package/dist/lib/browser/{open-N6PAX6DY.mjs → open-ANTKMST5.mjs} +4 -5
  15. package/dist/lib/browser/open-ANTKMST5.mjs.map +7 -0
  16. package/dist/lib/browser/operations/index.mjs +4 -5
  17. package/dist/lib/browser/operations/index.mjs.map +3 -3
  18. package/dist/lib/browser/{scroll-to-anchor-5M4F24AB.mjs → scroll-to-anchor-4RJ6MQ7I.mjs} +4 -5
  19. package/dist/lib/browser/scroll-to-anchor-4RJ6MQ7I.mjs.map +7 -0
  20. package/dist/lib/browser/{set-view-mode-NBNF2I5W.mjs → set-view-mode-2S7KKY7C.mjs} +4 -5
  21. package/dist/lib/browser/set-view-mode-2S7KKY7C.mjs.map +7 -0
  22. package/dist/lib/browser/types/index.mjs +1 -2
  23. package/dist/lib/browser/{update-5QIRVGTL.mjs → update-markdown-CPM5KOQW.mjs} +7 -8
  24. package/dist/lib/browser/update-markdown-CPM5KOQW.mjs.map +7 -0
  25. package/dist/lib/node-esm/blueprints/index.mjs +3 -4
  26. package/dist/lib/node-esm/blueprints/index.mjs.map +2 -2
  27. package/dist/lib/node-esm/{chunk-E4BQCEXF.mjs → chunk-MWYFGI2J.mjs} +4 -6
  28. package/dist/lib/node-esm/chunk-MWYFGI2J.mjs.map +7 -0
  29. package/dist/lib/node-esm/{chunk-4MSJO6IJ.mjs → chunk-ZE6QJ4S5.mjs} +39 -13
  30. package/dist/lib/node-esm/chunk-ZE6QJ4S5.mjs.map +7 -0
  31. package/dist/lib/node-esm/{create-6Z2KYISY.mjs → create-6JGQPPQ6.mjs} +4 -5
  32. package/dist/lib/node-esm/create-6JGQPPQ6.mjs.map +7 -0
  33. package/dist/lib/node-esm/{create-markdown-JWQZICKY.mjs → create-markdown-KXSM2I2M.mjs} +4 -5
  34. package/dist/lib/{browser/create-markdown-WB7DH3UF.mjs.map → node-esm/create-markdown-KXSM2I2M.mjs.map} +1 -1
  35. package/dist/lib/node-esm/index.mjs +7 -545
  36. package/dist/lib/node-esm/index.mjs.map +4 -4
  37. package/dist/lib/node-esm/meta.json +1 -1
  38. package/dist/lib/node-esm/{open-DSNFRSNZ.mjs → open-GB6HNBHS.mjs} +4 -5
  39. package/dist/lib/node-esm/open-GB6HNBHS.mjs.map +7 -0
  40. package/dist/lib/node-esm/operations/index.mjs +4 -5
  41. package/dist/lib/node-esm/operations/index.mjs.map +3 -3
  42. package/dist/lib/node-esm/{scroll-to-anchor-D6SHGU2R.mjs → scroll-to-anchor-UABP74RR.mjs} +4 -5
  43. package/dist/lib/{browser/scroll-to-anchor-5M4F24AB.mjs.map → node-esm/scroll-to-anchor-UABP74RR.mjs.map} +1 -1
  44. package/dist/lib/node-esm/{set-view-mode-REYB4L7J.mjs → set-view-mode-JEDC5ZL7.mjs} +4 -5
  45. package/dist/lib/{browser/set-view-mode-NBNF2I5W.mjs.map → node-esm/set-view-mode-JEDC5ZL7.mjs.map} +1 -1
  46. package/dist/lib/node-esm/types/index.mjs +1 -2
  47. package/dist/lib/node-esm/{update-YMQAIKOF.mjs → update-markdown-AXLYHK6S.mjs} +7 -8
  48. package/dist/lib/node-esm/update-markdown-AXLYHK6S.mjs.map +7 -0
  49. package/dist/types/src/MarkdownPlugin.d.ts +1 -0
  50. package/dist/types/src/MarkdownPlugin.d.ts.map +1 -1
  51. package/dist/types/src/{cli/plugin.d.ts → MarkdownPlugin.node.d.ts} +2 -1
  52. package/dist/types/src/MarkdownPlugin.node.d.ts.map +1 -0
  53. package/dist/types/src/MarkdownPlugin.test.d.ts +2 -0
  54. package/dist/types/src/MarkdownPlugin.test.d.ts.map +1 -0
  55. package/dist/types/src/blueprints/markdown-blueprint.d.ts +2 -2
  56. package/dist/types/src/blueprints/markdown-blueprint.d.ts.map +1 -1
  57. package/dist/types/src/capabilities/anchor-sort.d.ts.map +1 -1
  58. package/dist/types/src/capabilities/app-graph-serializer.d.ts.map +1 -1
  59. package/dist/types/src/capabilities/artifact-definition.d.ts.map +1 -1
  60. package/dist/types/src/capabilities/blueprint-definition.d.ts +2 -2
  61. package/dist/types/src/capabilities/blueprint-definition.d.ts.map +1 -1
  62. package/dist/types/src/capabilities/index.d.ts +3 -21
  63. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  64. package/dist/types/src/capabilities/node.d.ts +1 -1
  65. package/dist/types/src/capabilities/node.d.ts.map +1 -1
  66. package/dist/types/src/capabilities/operation-handler.d.ts +1 -1
  67. package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -1
  68. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  69. package/dist/types/src/capabilities/settings.d.ts +1 -19
  70. package/dist/types/src/capabilities/settings.d.ts.map +1 -1
  71. package/dist/types/src/capabilities/state.d.ts.map +1 -1
  72. package/dist/types/src/components/MarkdownEditor/MarkdownEditor.d.ts +14 -6
  73. package/dist/types/src/components/MarkdownEditor/MarkdownEditor.d.ts.map +1 -1
  74. package/dist/types/src/components/MarkdownEditor/MarkdownEditor.stories.d.ts.map +1 -1
  75. package/dist/types/src/components/MarkdownEditor/MarkdownEditorContent.d.ts +2 -1
  76. package/dist/types/src/components/MarkdownEditor/MarkdownEditorContent.d.ts.map +1 -1
  77. package/dist/types/src/components/MarkdownEditor/MarkdownEditorToolbar.d.ts +2 -2
  78. package/dist/types/src/components/MarkdownEditor/MarkdownEditorToolbar.d.ts.map +1 -1
  79. package/dist/types/src/components/MarkdownSettings/MarkdownSettings.d.ts +1 -1
  80. package/dist/types/src/components/MarkdownSettings/MarkdownSettings.d.ts.map +1 -1
  81. package/dist/types/src/components/MarkdownSettings/MarkdownSettings.stories.d.ts +46 -90
  82. package/dist/types/src/components/MarkdownSettings/MarkdownSettings.stories.d.ts.map +1 -1
  83. package/dist/types/src/containers/MarkdownCard/MarkdownCard.d.ts.map +1 -1
  84. package/dist/types/src/containers/MarkdownCard/MarkdownCard.stories.d.ts +1 -1
  85. package/dist/types/src/containers/MarkdownCard/MarkdownCard.stories.d.ts.map +1 -1
  86. package/dist/types/src/containers/MarkdownCard/MarkdownEditableCard.d.ts +15 -0
  87. package/dist/types/src/containers/MarkdownCard/MarkdownEditableCard.d.ts.map +1 -0
  88. package/dist/types/src/containers/MarkdownCard/index.d.ts +1 -0
  89. package/dist/types/src/containers/MarkdownCard/index.d.ts.map +1 -1
  90. package/dist/types/src/containers/MarkdownCard/snippet.d.ts +7 -5
  91. package/dist/types/src/containers/MarkdownCard/snippet.d.ts.map +1 -1
  92. package/dist/types/src/containers/MarkdownContainer/MarkdownContainer.d.ts +4 -4
  93. package/dist/types/src/containers/MarkdownContainer/MarkdownContainer.d.ts.map +1 -1
  94. package/dist/types/src/containers/MarkdownContainer/MarkdownContainer.stories.d.ts +70 -72
  95. package/dist/types/src/containers/MarkdownContainer/MarkdownContainer.stories.d.ts.map +1 -1
  96. package/dist/types/src/containers/index.d.ts +1 -0
  97. package/dist/types/src/containers/index.d.ts.map +1 -1
  98. package/dist/types/src/hooks/useEditorMenuOptions.d.ts.map +1 -1
  99. package/dist/types/src/hooks/useExtensions.d.ts +3 -1
  100. package/dist/types/src/hooks/useExtensions.d.ts.map +1 -1
  101. package/dist/types/src/hooks/useLinkQuery.d.ts.map +1 -1
  102. package/dist/types/src/index.d.ts +2 -3
  103. package/dist/types/src/index.d.ts.map +1 -1
  104. package/dist/types/src/operations/create-markdown.d.ts +1 -1
  105. package/dist/types/src/operations/create-markdown.d.ts.map +1 -1
  106. package/dist/types/src/operations/create.d.ts +1 -1
  107. package/dist/types/src/operations/create.d.ts.map +1 -1
  108. package/dist/types/src/operations/definitions.d.ts +2 -2
  109. package/dist/types/src/operations/definitions.d.ts.map +1 -1
  110. package/dist/types/src/operations/index.d.ts +1 -1
  111. package/dist/types/src/operations/index.d.ts.map +1 -1
  112. package/dist/types/src/operations/open.d.ts +1 -1
  113. package/dist/types/src/operations/open.d.ts.map +1 -1
  114. package/dist/types/src/operations/scroll-to-anchor.d.ts +1 -1
  115. package/dist/types/src/operations/scroll-to-anchor.d.ts.map +1 -1
  116. package/dist/types/src/operations/set-view-mode.d.ts +1 -1
  117. package/dist/types/src/operations/set-view-mode.d.ts.map +1 -1
  118. package/dist/types/src/operations/{update.d.ts → update-markdown.d.ts} +2 -2
  119. package/dist/types/src/operations/update-markdown.d.ts.map +1 -0
  120. package/dist/types/src/testing.d.ts.map +1 -1
  121. package/dist/types/src/translations.d.ts +70 -73
  122. package/dist/types/src/translations.d.ts.map +1 -1
  123. package/dist/types/src/types/Markdown.d.ts +8 -8
  124. package/dist/types/src/types/Markdown.d.ts.map +1 -1
  125. package/dist/types/src/types/Settings.d.ts +10 -9
  126. package/dist/types/src/types/Settings.d.ts.map +1 -1
  127. package/dist/types/src/types/capabilities.d.ts +3 -20
  128. package/dist/types/src/types/capabilities.d.ts.map +1 -1
  129. package/dist/types/src/types/events.d.ts.map +1 -1
  130. package/dist/types/src/types/types.d.ts +1 -0
  131. package/dist/types/src/types/types.d.ts.map +1 -1
  132. package/dist/types/src/util.d.ts.map +1 -1
  133. package/dist/types/tsconfig.tsbuildinfo +1 -1
  134. package/package.json +60 -73
  135. package/src/{cli/plugin.ts → MarkdownPlugin.node.ts} +4 -2
  136. package/src/MarkdownPlugin.test.ts +26 -0
  137. package/src/MarkdownPlugin.tsx +6 -4
  138. package/src/blueprints/markdown-blueprint.ts +2 -3
  139. package/src/capabilities/app-graph-serializer.ts +1 -2
  140. package/src/capabilities/artifact-definition.ts +1 -1
  141. package/src/capabilities/blueprint-definition.ts +2 -0
  142. package/src/capabilities/index.ts +2 -1
  143. package/src/capabilities/node.ts +1 -1
  144. package/src/capabilities/operation-handler.ts +1 -1
  145. package/src/capabilities/react-surface.tsx +15 -8
  146. package/src/components/MarkdownEditor/MarkdownEditor.stories.tsx +3 -2
  147. package/src/components/MarkdownEditor/MarkdownEditor.tsx +4 -4
  148. package/src/components/MarkdownEditor/MarkdownEditorContent.tsx +3 -3
  149. package/src/components/MarkdownEditor/MarkdownEditorToolbar.tsx +4 -15
  150. package/src/components/MarkdownSettings/MarkdownSettings.stories.tsx +2 -1
  151. package/src/components/MarkdownSettings/MarkdownSettings.tsx +16 -119
  152. package/src/containers/MarkdownCard/MarkdownCard.stories.tsx +3 -2
  153. package/src/containers/MarkdownCard/MarkdownCard.tsx +13 -7
  154. package/src/containers/MarkdownCard/MarkdownEditableCard.tsx +42 -0
  155. package/src/containers/MarkdownCard/index.ts +1 -0
  156. package/src/containers/MarkdownCard/snippet.ts +27 -51
  157. package/src/containers/MarkdownContainer/MarkdownContainer.stories.tsx +4 -3
  158. package/src/containers/MarkdownContainer/MarkdownContainer.tsx +5 -4
  159. package/src/containers/index.ts +3 -0
  160. package/src/hooks/useExtensions.tsx +7 -8
  161. package/src/index.ts +5 -4
  162. package/src/operations/create-markdown.ts +1 -1
  163. package/src/operations/create.conversations.json +1 -1
  164. package/src/operations/create.test.ts +4 -5
  165. package/src/operations/create.ts +1 -1
  166. package/src/operations/definitions.ts +1 -1
  167. package/src/operations/index.ts +2 -2
  168. package/src/operations/open.ts +1 -1
  169. package/src/operations/scroll-to-anchor.ts +1 -1
  170. package/src/operations/set-view-mode.ts +1 -1
  171. package/src/operations/{update.ts → update-markdown.ts} +1 -1
  172. package/src/operations/update.conversations.json +1 -1
  173. package/src/operations/update.test.ts +4 -5
  174. package/src/translations.ts +2 -26
  175. package/src/types/Settings.ts +47 -10
  176. package/src/types/capabilities.ts +2 -1
  177. package/src/types/types.ts +4 -1
  178. package/src/util.tsx +1 -1
  179. package/dist/lib/browser/MarkdownSettings-YZFNSJJY.mjs +0 -121
  180. package/dist/lib/browser/MarkdownSettings-YZFNSJJY.mjs.map +0 -7
  181. package/dist/lib/browser/chunk-46WIDM4R.mjs.map +0 -7
  182. package/dist/lib/browser/chunk-J5LGTIGS.mjs +0 -10
  183. package/dist/lib/browser/chunk-J5LGTIGS.mjs.map +0 -7
  184. package/dist/lib/browser/chunk-XKUKZNUS.mjs.map +0 -7
  185. package/dist/lib/browser/cli/index.mjs +0 -39
  186. package/dist/lib/browser/cli/index.mjs.map +0 -7
  187. package/dist/lib/browser/create-HSXPXCC5.mjs.map +0 -7
  188. package/dist/lib/browser/open-N6PAX6DY.mjs.map +0 -7
  189. package/dist/lib/browser/update-5QIRVGTL.mjs.map +0 -7
  190. package/dist/lib/node-esm/MarkdownSettings-X6SDS35F.mjs +0 -122
  191. package/dist/lib/node-esm/MarkdownSettings-X6SDS35F.mjs.map +0 -7
  192. package/dist/lib/node-esm/chunk-4MSJO6IJ.mjs.map +0 -7
  193. package/dist/lib/node-esm/chunk-E4BQCEXF.mjs.map +0 -7
  194. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +0 -11
  195. package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +0 -7
  196. package/dist/lib/node-esm/cli/index.mjs +0 -40
  197. package/dist/lib/node-esm/cli/index.mjs.map +0 -7
  198. package/dist/lib/node-esm/create-6Z2KYISY.mjs.map +0 -7
  199. package/dist/lib/node-esm/create-markdown-JWQZICKY.mjs.map +0 -7
  200. package/dist/lib/node-esm/open-DSNFRSNZ.mjs.map +0 -7
  201. package/dist/lib/node-esm/scroll-to-anchor-D6SHGU2R.mjs.map +0 -7
  202. package/dist/lib/node-esm/set-view-mode-REYB4L7J.mjs.map +0 -7
  203. package/dist/lib/node-esm/update-YMQAIKOF.mjs.map +0 -7
  204. package/dist/types/src/cli/index.d.ts +0 -2
  205. package/dist/types/src/cli/index.d.ts.map +0 -1
  206. package/dist/types/src/cli/plugin.d.ts.map +0 -1
  207. package/dist/types/src/operations/update.d.ts.map +0 -1
  208. package/src/cli/index.ts +0 -5
@@ -5,133 +5,30 @@
5
5
  import React from 'react';
6
6
 
7
7
  import { type AppSurface } from '@dxos/app-toolkit/ui';
8
- import { Input, Select, useTranslation } from '@dxos/react-ui';
9
- import { Settings as SettingsForm } from '@dxos/react-ui-form';
10
- import { type EditorInputMode, EditorInputModes, type EditorViewMode, EditorViewModes } from '@dxos/ui-editor';
8
+ import { Input } from '@dxos/react-ui';
9
+ import { Settings as SettingsForm, type SettingsFieldProps } from '@dxos/react-ui-form';
11
10
 
12
11
  import { meta } from '#meta';
13
- import { type Markdown } from '#types';
12
+ import { Markdown } from '#types';
14
13
 
15
14
  export type MarkdownSettingsProps = AppSurface.SettingsArticleProps<Markdown.Settings>;
16
15
 
17
- export const MarkdownSettings = ({ settings, onSettingsChange }: MarkdownSettingsProps) => {
18
- const { t } = useTranslation(meta.id);
16
+ const SnippetsField = ({ value, onChange, readonly }: SettingsFieldProps<string | undefined>) => (
17
+ <Input.TextArea disabled={readonly} rows={5} value={value ?? ''} onChange={(event) => onChange(event.target.value)} />
18
+ );
19
19
 
20
- // TODO(wittjosiah): Add skill test confirmation for entering vim mode.
20
+ export const MarkdownSettings = ({ settings, onSettingsChange }: MarkdownSettingsProps) => {
21
21
  return (
22
22
  <SettingsForm.Viewport>
23
- <SettingsForm.Section title={t('settings.title', { ns: meta.id })}>
24
- <SettingsForm.Item title={t('default-view-mode.label')} description={t('default-view-mode.description')}>
25
- <Select.Root
26
- disabled={!onSettingsChange}
27
- value={settings.defaultViewMode}
28
- onValueChange={(value) => {
29
- onSettingsChange?.((s) => ({ ...s, defaultViewMode: value as EditorViewMode }));
30
- }}
31
- >
32
- <Select.TriggerButton disabled={!onSettingsChange} />
33
- <Select.Portal>
34
- <Select.Content>
35
- <Select.Viewport>
36
- {EditorViewModes.map((mode) => (
37
- <Select.Option key={mode} value={mode}>
38
- {t(`view-mode.${mode}.label`, { ns: '@dxos/react-ui-editor' })}
39
- </Select.Option>
40
- ))}
41
- </Select.Viewport>
42
- <Select.Arrow />
43
- </Select.Content>
44
- </Select.Portal>
45
- </Select.Root>
46
- </SettingsForm.Item>
47
-
48
- <SettingsForm.Item title={t('editor-input-mode.label')} description={t('editor-input-mode.description')}>
49
- <Select.Root
50
- disabled={!onSettingsChange}
51
- value={settings.editorInputMode ?? 'default'}
52
- onValueChange={(value) => {
53
- onSettingsChange?.((s) => ({ ...s, editorInputMode: value as EditorInputMode }));
54
- }}
55
- >
56
- <Select.TriggerButton
57
- disabled={!onSettingsChange}
58
- placeholder={t('select-editor-input-mode.placeholder')}
59
- />
60
- <Select.Portal>
61
- <Select.Content>
62
- <Select.Viewport>
63
- {EditorInputModes.map((mode) => (
64
- <Select.Option key={mode} value={mode}>
65
- {t(`settings.editor-input-mode.${mode}.label`)}
66
- </Select.Option>
67
- ))}
68
- </Select.Viewport>
69
- <Select.Arrow />
70
- </Select.Content>
71
- </Select.Portal>
72
- </Select.Root>
73
- </SettingsForm.Item>
74
-
75
- <SettingsForm.Item title={t('settings.toolbar.label')} description={t('settings.toolbar.description')}>
76
- <Input.Switch
77
- disabled={!onSettingsChange}
78
- checked={settings.toolbar}
79
- onCheckedChange={(checked) => onSettingsChange?.((s) => ({ ...s, toolbar: !!checked }))}
80
- />
81
- </SettingsForm.Item>
82
-
83
- <SettingsForm.Item
84
- title={t('settings.numbered-headings.label')}
85
- description={t('settings.numbered-headings.description')}
86
- >
87
- <Input.Switch
88
- disabled={!onSettingsChange}
89
- checked={settings.numberedHeadings}
90
- onCheckedChange={(checked) => onSettingsChange?.((s) => ({ ...s, numberedHeadings: !!checked }))}
91
- />
92
- </SettingsForm.Item>
93
-
94
- <SettingsForm.Item title={t('settings.folding.label')} description={t('settings.folding.description')}>
95
- <Input.Switch
96
- disabled={!onSettingsChange}
97
- checked={settings.folding}
98
- onCheckedChange={(checked) => onSettingsChange?.((s) => ({ ...s, folding: !!checked }))}
99
- />
100
- </SettingsForm.Item>
101
-
102
- <SettingsForm.Item
103
- title={t('settings.experimental.label')}
104
- description={t('settings.experimental.description')}
105
- >
106
- <Input.Switch
107
- disabled={!onSettingsChange}
108
- checked={settings.experimental}
109
- onCheckedChange={(checked) => onSettingsChange?.((s) => ({ ...s, experimental: !!checked }))}
110
- />
111
- </SettingsForm.Item>
112
-
113
- <SettingsForm.Item title={t('settings.debug.label')} description={t('settings.debug.description')}>
114
- <Input.Switch
115
- disabled={!onSettingsChange}
116
- checked={settings.debug}
117
- onCheckedChange={(checked) => onSettingsChange?.((s) => ({ ...s, debug: !!checked }))}
118
- />
119
- </SettingsForm.Item>
120
-
121
- {settings.debug && (
122
- <SettingsForm.Item
123
- title={t('settings.debug-typewriter.label', { ns: meta.id })}
124
- description={t('settings.debug-typewriter.description')}
125
- >
126
- <Input.TextArea
127
- disabled={!onSettingsChange}
128
- rows={5}
129
- value={settings.typewriter}
130
- onChange={({ target: { value } }) => onSettingsChange?.((s) => ({ ...s, typewriter: value }))}
131
- placeholder={t('settings.debug-typewriter.placeholder')}
132
- />
133
- </SettingsForm.Item>
134
- )}
23
+ <SettingsForm.Section title={meta.name ?? 'Editor'}>
24
+ <SettingsForm.FieldSet
25
+ readonly={!onSettingsChange}
26
+ schema={Markdown.Settings}
27
+ visible={(path, values) => path !== 'snippets' || !!values.debug}
28
+ fieldMap={{ snippets: SnippetsField }}
29
+ values={settings}
30
+ onValuesChanged={(values) => onSettingsChange?.(() => values)}
31
+ />
135
32
  </SettingsForm.Section>
136
33
  </SettingsForm.Viewport>
137
34
  );
@@ -15,7 +15,8 @@ import { Card } from '@dxos/react-ui';
15
15
  import { CardContainer } from '@dxos/react-ui-mosaic/testing';
16
16
  import { withTheme } from '@dxos/react-ui/testing';
17
17
 
18
- import { translations } from '../../translations';
18
+ import { translations } from '#translations';
19
+
19
20
  import { MarkdownCard, type MarkdownCardProps } from './MarkdownCard';
20
21
 
21
22
  random.seed(1234);
@@ -25,7 +26,7 @@ const MarkdownCardStory = ({ ...args }: Omit<MarkdownCardProps, 'subject'>) => {
25
26
  () =>
26
27
  Markdown.make({
27
28
  name: random.lorem.words(3),
28
- content: random.lorem.paragraphs(5),
29
+ content: '# Title\n' + random.lorem.paragraphs(5),
29
30
  }),
30
31
  [],
31
32
  );
@@ -8,6 +8,7 @@ import { Obj } from '@dxos/echo';
8
8
  import { Card, useTranslation } from '@dxos/react-ui';
9
9
  import { Editor } from '@dxos/react-ui-editor';
10
10
  import { Text } from '@dxos/schema';
11
+ import { mx } from '@dxos/ui-theme';
11
12
 
12
13
  import { MarkdownEditor, MarkdownEditorProvider } from '#components';
13
14
  import { meta } from '#meta';
@@ -21,13 +22,13 @@ export type MarkdownCardProps = { subject: Markdown.Document | Text.Text };
21
22
  export const MarkdownCard = ({ subject }: MarkdownCardProps) => {
22
23
  const { t } = useTranslation(meta.id);
23
24
  const snippet = useMemo(() => getSnippet(subject), [subject]);
24
- const extensions = useMemo(() => [snippetExtension({ height: 240, scale: 0.8 })], []);
25
+ const extensions = useMemo(() => [snippetExtension({ height: 300, scale: 0.8 })], []);
25
26
  const info = getInfo(subject);
26
27
 
27
28
  return (
28
29
  <Card.Content>
29
30
  {snippet && (
30
- <Card.Section className='px-1'>
31
+ <Card.Section className='relative px-1'>
31
32
  <MarkdownEditorProvider id={subject.id} viewMode='readonly' extensions={extensions}>
32
33
  {(editorRootProps) => (
33
34
  <Editor.Root {...editorRootProps}>
@@ -35,6 +36,13 @@ export const MarkdownCard = ({ subject }: MarkdownCardProps) => {
35
36
  </Editor.Root>
36
37
  )}
37
38
  </MarkdownEditorProvider>
39
+ <div
40
+ role='none'
41
+ className={mx(
42
+ 'z-10 absolute bottom-0 inset-x-0 h-12 w-full',
43
+ 'bg-gradient-to-b from-transparent to-(--surface-bg) pointer-events-none',
44
+ )}
45
+ />
38
46
  </Card.Section>
39
47
  )}
40
48
  <Card.Section>
@@ -46,13 +54,11 @@ export const MarkdownCard = ({ subject }: MarkdownCardProps) => {
46
54
  );
47
55
  };
48
56
 
49
- const MAX_LINES = 5;
50
-
51
- const getSnippet = (subject: Markdown.Document | Text.Text, fallback?: string) => {
57
+ const getSnippet = (subject: Markdown.Document | Text.Text, fallback?: string, maxLines = 16) => {
52
58
  if (Obj.instanceOf(Markdown.Document, subject)) {
53
- return Obj.getDescription(subject) || getContentSnippet(subject.content?.target?.content ?? fallback, MAX_LINES);
59
+ return Obj.getDescription(subject) || getContentSnippet(subject.content?.target?.content ?? fallback, maxLines);
54
60
  } else if (Obj.instanceOf(Text.Text, subject)) {
55
- return getContentSnippet(subject.content ?? fallback, MAX_LINES);
61
+ return getContentSnippet(subject.content ?? fallback, maxLines);
56
62
  }
57
63
  };
58
64
 
@@ -0,0 +1,42 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import React from 'react';
6
+
7
+ import { Obj } from '@dxos/echo';
8
+ import { useObject } from '@dxos/react-client/echo';
9
+ import { Card } from '@dxos/react-ui';
10
+ import { Editor } from '@dxos/react-ui-editor';
11
+ import { Text } from '@dxos/schema';
12
+
13
+ import { MarkdownEditor, MarkdownEditorProvider } from '#components';
14
+ import { Markdown } from '#types';
15
+
16
+ export type MarkdownEditableCardProps = { subject: Markdown.Document | Text.Text };
17
+
18
+ /**
19
+ * Full-bleed editable variant of {@link MarkdownCard}. Activated by the host
20
+ * passing `editable: true` on the card surface data (e.g. plugin-board cells).
21
+ * Renders a plain editor (no app-graph toolbar / file upload / link queries)
22
+ * so it stays self-contained inside the card; the regular MarkdownContainer
23
+ * remains the canonical surface for full article views.
24
+ */
25
+ export const MarkdownEditableCard = ({ subject }: MarkdownEditableCardProps) => {
26
+ const id = Obj.getDXN(subject).toString();
27
+ const [docContent] = useObject(Obj.instanceOf(Markdown.Document, subject) ? subject.content : undefined, 'content');
28
+ const [textContent] = useObject(Obj.instanceOf(Text.Text, subject) ? subject : undefined, 'content');
29
+ const initialValue = docContent ?? textContent;
30
+
31
+ return (
32
+ <Card.Section classNames='col-span-3 min-h-0'>
33
+ <MarkdownEditorProvider id={id} object={subject} viewMode='source'>
34
+ {(editorRootProps) => (
35
+ <Editor.Root {...editorRootProps}>
36
+ <MarkdownEditor.Content initialValue={initialValue} />
37
+ </Editor.Root>
38
+ )}
39
+ </MarkdownEditorProvider>
40
+ </Card.Section>
41
+ );
42
+ };
@@ -3,3 +3,4 @@
3
3
  //
4
4
 
5
5
  export { MarkdownCard as default } from './MarkdownCard';
6
+ export { MarkdownEditableCard } from './MarkdownEditableCard';
@@ -2,10 +2,11 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { type PluginValue, EditorView, ViewPlugin, type ViewUpdate } from '@codemirror/view';
5
+ import { EditorState } from '@codemirror/state';
6
+ import { EditorView } from '@codemirror/view';
6
7
 
7
8
  export type SnippetOptions = {
8
- /** Maximum height of the editor in pixels. Content is clipped to whole lines within this height. */
9
+ /** Maximum height of the editor in pixels. Overflowing content is hidden. */
9
10
  height: number;
10
11
  /** Zoom factor applied to the editor (e.g. 0.5 renders at 50%). @default 1 */
11
12
  scale?: number;
@@ -13,66 +14,41 @@ export type SnippetOptions = {
13
14
 
14
15
  /**
15
16
  * CodeMirror extension for rendering a non-scrollable snippet of editor content.
16
- * Constrains the editor to the given height, clips to whole line boundaries,
17
- * and disables scrolling entirely.
18
- * Uses requestMeasure to read post-layout heights and lineBlockAtHeight to handle
19
- * varying line heights from headings and other decorated blocks.
17
+ * Constrains the editor to the given height via CSS `max-height`, wraps long
18
+ * lines (`pre-wrap`), and disables scrolling entirely.
19
+ *
20
+ * NOTE: Uses CSS `zoom` rather than `transform: scale` because `zoom` affects
21
+ * layout, so line wrapping fills the full visual width of the container.
22
+ * `transform: scale` only scales paint output, leaving empty space on the right.
20
23
  */
21
24
  export const snippet = ({ height, scale = 1 }: SnippetOptions) => {
22
- // Internal height is divided by scale so the visible area matches the requested height.
23
- const internalHeight = Math.round(height / scale);
24
-
25
- const clipPlugin = ViewPlugin.fromClass(
26
- class SnippetPlugin implements PluginValue {
27
- private clipHeight = 0;
28
-
29
- update(update: ViewUpdate) {
30
- update.view.requestMeasure({
31
- // key deduplicates concurrent requests within the same animation frame.
32
- key: this,
33
- read: (view) => {
34
- const containerHeight = view.dom.clientHeight;
35
- if (containerHeight === 0) {
36
- return 0;
37
- }
38
- // With CSS zoom, clientHeight can be in visual pixels while line positions use
39
- // layout pixels (same space as internalHeight / theme maxHeight).
40
- const clipLimit = scale === 1 ? containerHeight : Math.min(internalHeight, containerHeight / scale);
41
- // Find the block (line) at the very bottom of the visible area.
42
- const block = view.lineBlockAtHeight(clipLimit - 1);
43
- // If the block overflows the container, clip at the block's top edge.
44
- return block.top + block.height > clipLimit ? block.top : clipLimit;
45
- },
46
- write: (clipHeight, view) => {
47
- if (clipHeight > 0 && clipHeight !== this.clipHeight) {
48
- this.clipHeight = clipHeight;
49
- view.dom.style.maxHeight = `${clipHeight}px`;
50
- }
51
- },
52
- });
53
- }
54
- },
55
- );
56
-
57
25
  return [
58
- clipPlugin,
26
+ EditorState.readOnly.of(true),
27
+ EditorView.editable.of(false),
28
+ EditorState.transactionFilter.of((tr) => {
29
+ if (tr.selection) {
30
+ return [];
31
+ } // Drop any selection changes.
32
+ return tr;
33
+ }),
59
34
  EditorView.theme({
35
+ // Outer editor element: clip to the caller-specified height.
60
36
  '&': {
61
- maxHeight: `${internalHeight}px`,
37
+ maxHeight: `${height}px`,
62
38
  overflow: 'hidden',
63
- ...(scale !== 1 && { zoom: `${scale}` }),
64
39
  },
65
- '.cm-content': {
66
- whiteSpace: 'pre',
67
- margin: '0',
40
+ '.cm-scroller': {
41
+ // Prevent scroll; scale up the inner clip so the final pixel height matches `height`.
42
+ maxHeight: `${height / scale}px`,
43
+ overflow: 'hidden !important',
68
44
  padding: '0',
69
45
  },
70
- '.cm-line': {
46
+ '.cm-content': {
47
+ // zoom (unlike transform: scale) affects layout, so line-wrapping fills the full visual width of the container.
48
+ zoom: scale,
49
+ margin: '0',
71
50
  padding: '0',
72
51
  },
73
- '.cm-scroller': {
74
- overflow: 'hidden !important',
75
- },
76
52
  }),
77
53
  ];
78
54
  };
@@ -10,6 +10,7 @@ import { Capability, Plugin } from '@dxos/app-framework';
10
10
  import { withPluginManager } from '@dxos/app-framework/testing';
11
11
  import { Surface, useOperationInvoker } from '@dxos/app-framework/ui';
12
12
  import { AppActivationEvents, LayoutOperation } from '@dxos/app-toolkit';
13
+ import { AppSurface } from '@dxos/app-toolkit/ui';
13
14
  import { Obj, Query } from '@dxos/echo';
14
15
  import { ClientPlugin } from '@dxos/plugin-client';
15
16
  import { initializeIdentity } from '@dxos/plugin-client/testing';
@@ -24,10 +25,10 @@ import { Text } from '@dxos/schema';
24
25
  import { type ValueGenerator, createObjectFactory } from '@dxos/schema/testing';
25
26
  import { Organization, Person } from '@dxos/types';
26
27
 
28
+ import { translations } from '#translations';
27
29
  import { Markdown, MarkdownCapabilities, MarkdownEvents } from '#types';
28
30
 
29
31
  import { MarkdownPlugin } from '../../MarkdownPlugin';
30
- import { translations } from '../../translations';
31
32
 
32
33
  random.seed(1);
33
34
 
@@ -47,8 +48,8 @@ const DefaultStory = () => {
47
48
  const { invokePromise } = useOperationInvoker();
48
49
  const [space] = useSpaces();
49
50
  const [doc] = useQuery(space?.db, Query.type(Markdown.Document));
50
- const data = useMemo(() => ({ subject: doc }), [doc]);
51
51
  const id = doc && Obj.getDXN(doc).toString();
52
+ const data = useMemo(() => ({ subject: doc, attendableId: id ?? 'story' }), [doc, id]);
52
53
  const attentionAttrs = useAttentionAttributes(id);
53
54
 
54
55
  useAsyncEffect(async () => {
@@ -59,7 +60,7 @@ const DefaultStory = () => {
59
60
 
60
61
  return (
61
62
  <div className='contents' {...attentionAttrs}>
62
- <Surface.Surface role='article' data={data} limit={1} />
63
+ <Surface.Surface type={AppSurface.Article} data={data} limit={1} />
63
64
  </div>
64
65
  );
65
66
  };
@@ -39,7 +39,7 @@ export type MarkdownContainerProps = AppSurface.ObjectArticleProps<
39
39
 
40
40
  export const MarkdownContainer = forwardRef<HTMLDivElement, MarkdownContainerProps>(
41
41
  (
42
- { role, subject: object, id, attendableId, settings, extensionProviders, onSelectObject, ...props },
42
+ { role, subject: object, id, attendableId, settings, extensionProviders, onSelectObject, viewMode, ...props },
43
43
  forwardedRef,
44
44
  ) => {
45
45
  const db = Obj.isObject(object) ? Obj.getDatabase(object) : undefined;
@@ -54,18 +54,18 @@ export const MarkdownContainer = forwardRef<HTMLDivElement, MarkdownContainerPro
54
54
  return [];
55
55
  }
56
56
 
57
+ const document = Obj.instanceOf(Markdown.Document, object) ? object : undefined;
57
58
  return [...(otherExtensionProviders ?? []), ...(extensionProviders ?? [])]
58
59
  .flat()
59
60
  .reduce((acc: Extension[], provider) => {
60
- const extension =
61
- typeof provider === 'function' ? provider({ document: object as Markdown.Document }) : provider;
61
+ const extension = typeof provider === 'function' ? provider({ document, viewMode }) : provider;
62
62
  if (extension) {
63
63
  acc.push(extension);
64
64
  }
65
65
 
66
66
  return acc;
67
67
  }, []);
68
- }, [extensionProviders, otherExtensionProviders, object]);
68
+ }, [extensionProviders, otherExtensionProviders, object, viewMode]);
69
69
 
70
70
  // Toolbar actions from app graph.
71
71
  const { graph } = useAppGraph();
@@ -118,6 +118,7 @@ export const MarkdownContainer = forwardRef<HTMLDivElement, MarkdownContainerPro
118
118
  compact={role !== 'article'}
119
119
  extensions={extensions}
120
120
  settings={settings}
121
+ viewMode={viewMode}
121
122
  onAction={runAction}
122
123
  onFileUpload={handleFileUpload}
123
124
  onLinkQuery={handleLinkQuery}
@@ -7,4 +7,7 @@ import { type ComponentType, lazy } from 'react';
7
7
  export type { MarkdownContainerProps } from './MarkdownContainer';
8
8
 
9
9
  export const MarkdownCard: ComponentType<any> = lazy(() => import('./MarkdownCard'));
10
+ export const MarkdownEditableCard: ComponentType<any> = lazy(() =>
11
+ import('./MarkdownCard').then((m) => ({ default: m.MarkdownEditableCard })),
12
+ );
10
13
  export const MarkdownContainer: ComponentType<any> = lazy(() => import('./MarkdownContainer'));
@@ -20,11 +20,9 @@ import {
20
20
  Cursor,
21
21
  type EditorStateStore,
22
22
  EditorView,
23
- type EditorViewMode,
24
23
  type Extension,
25
24
  InputModeExtensions,
26
25
  type PreviewOptions,
27
- type RenderCallback,
28
26
  createDataExtensions,
29
27
  decorateMarkdown,
30
28
  documentId,
@@ -35,8 +33,9 @@ import {
35
33
  preview,
36
34
  replacer,
37
35
  selectionState,
38
- typewriter,
36
+ snippets,
39
37
  } from '@dxos/ui-editor';
38
+ import { type EditorViewMode, type RenderCallback } from '@dxos/ui-editor/types';
40
39
  import { isTruthy, safeUrl } from '@dxos/util';
41
40
 
42
41
  import { Markdown } from '#types';
@@ -51,6 +50,7 @@ export type ExtensionsOptions = {
51
50
  settings?: Markdown.Settings;
52
51
  compact?: boolean;
53
52
  viewMode?: EditorViewMode;
53
+ editable?: boolean;
54
54
  selectionManager?: SelectionManager;
55
55
  editorStateStore?: EditorStateStore;
56
56
  previewOptions?: PreviewOptions;
@@ -97,8 +97,8 @@ export const useExtensions = ({
97
97
  viewMode,
98
98
  selectionManager,
99
99
  previewOptions,
100
- onSelectObject,
101
100
  platform,
101
+ onSelectObject,
102
102
  }),
103
103
  [
104
104
  id,
@@ -107,14 +107,13 @@ export const useExtensions = ({
107
107
  viewMode,
108
108
  selectionManager,
109
109
  previewOptions,
110
- onSelectObject,
111
110
  settings,
112
111
  settings?.debug,
113
112
  settings?.editorInputMode,
114
113
  settings?.folding,
115
114
  settings?.numberedHeadings,
116
115
  platform,
117
- settings?.typewriter,
116
+ onSelectObject,
118
117
  ],
119
118
  );
120
119
 
@@ -187,9 +186,9 @@ const createBaseExtensions = ({
187
186
  }
188
187
 
189
188
  if (settings?.debug) {
190
- const items = settings.typewriter?.split(/[,\n]/) ?? '';
189
+ const items = settings.snippets?.split(/[,\n]/) ?? '';
191
190
  if (items) {
192
- extensions.push(typewriter({ items }));
191
+ extensions.push(snippets({ items }));
193
192
  }
194
193
  }
195
194
 
package/src/index.ts CHANGED
@@ -2,13 +2,14 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
+ import { Plugin } from '@dxos/app-framework';
6
+
7
+ import { meta } from './meta';
8
+
5
9
  export { MarkdownCapabilities, MarkdownEvents } from './types';
6
10
 
7
11
  export * from './meta';
8
12
  export * from './types';
9
13
  export * from './util';
10
14
 
11
- export * from './MarkdownPlugin';
12
-
13
- export { MarkdownEditor, MarkdownEditorProvider } from './components';
14
- export type { MarkdownEditorEditorRootProps } from './components';
15
+ export const MarkdownPlugin = Plugin.lazy(meta, () => import('#plugin'));
@@ -4,7 +4,7 @@
4
4
 
5
5
  import * as Effect from 'effect/Effect';
6
6
 
7
- import { Operation } from '@dxos/operation';
7
+ import { Operation } from '@dxos/compute';
8
8
 
9
9
  import { Markdown } from '../types';
10
10
  import { CreateMarkdown } from './definitions';