@dxos/plugin-markdown 0.6.13 → 0.6.14-main.69511f5
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.
- package/dist/lib/browser/MarkdownContainer-HRGXWEA4.mjs +465 -0
- package/dist/lib/browser/MarkdownContainer-HRGXWEA4.mjs.map +7 -0
- package/dist/lib/browser/chunk-DRJ3FPYF.mjs +15 -0
- package/dist/lib/browser/chunk-DRJ3FPYF.mjs.map +7 -0
- package/dist/lib/browser/{chunk-CQJL4G4X.mjs → chunk-US5O2P3R.mjs} +4 -2
- package/dist/lib/browser/chunk-US5O2P3R.mjs.map +7 -0
- package/dist/lib/browser/chunk-VGIHBUXB.mjs +52 -0
- package/dist/lib/browser/chunk-VGIHBUXB.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +85 -125
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/meta.mjs +1 -1
- package/dist/lib/browser/types/index.mjs +6 -4
- package/dist/lib/node/MarkdownContainer-QZ4YLO7M.cjs +480 -0
- package/dist/lib/node/MarkdownContainer-QZ4YLO7M.cjs.map +7 -0
- package/dist/lib/node/chunk-6HPTH2F5.cjs +74 -0
- package/dist/lib/node/chunk-6HPTH2F5.cjs.map +7 -0
- package/dist/lib/node/{DocumentCard-EHJDDSRY.cjs → chunk-P7YU53RP.cjs} +16 -10
- package/dist/lib/node/chunk-P7YU53RP.cjs.map +7 -0
- package/dist/lib/node/{chunk-VWQH4WC2.cjs → chunk-UJMOZCIA.cjs} +11 -8
- package/dist/lib/node/chunk-UJMOZCIA.cjs.map +7 -0
- package/dist/lib/node/index.cjs +117 -153
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.cjs +3 -3
- package/dist/lib/node/meta.cjs.map +1 -1
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/types/index.cjs +8 -6
- package/dist/lib/node/types/index.cjs.map +2 -2
- package/dist/lib/node-esm/MarkdownContainer-FSWQL76V.mjs +466 -0
- package/dist/lib/node-esm/MarkdownContainer-FSWQL76V.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-HPOTHJC4.mjs +53 -0
- package/dist/lib/node-esm/chunk-HPOTHJC4.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-MIDCCMIX.mjs +42 -0
- package/dist/lib/node-esm/chunk-MIDCCMIX.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-NEVN5WR6.mjs +17 -0
- package/dist/lib/node-esm/chunk-NEVN5WR6.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +493 -0
- package/dist/lib/node-esm/index.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -0
- package/dist/lib/node-esm/meta.mjs +10 -0
- package/dist/lib/node-esm/types/index.mjs +15 -0
- package/dist/types/src/MarkdownPlugin.d.ts.map +1 -1
- package/dist/types/src/components/MarkdownContainer.d.ts +15 -0
- package/dist/types/src/components/MarkdownContainer.d.ts.map +1 -0
- package/dist/types/src/components/MarkdownEditor.d.ts +12 -6
- package/dist/types/src/components/MarkdownEditor.d.ts.map +1 -1
- package/dist/types/src/components/MarkdownEditor.stories.d.ts +4 -14
- package/dist/types/src/components/MarkdownEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar.stories.d.ts +4 -2
- package/dist/types/src/components/Toolbar.stories.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +1 -11
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/extensions.d.ts +12 -15
- package/dist/types/src/extensions.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +2 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -0
- package/dist/types/src/hooks/useSelectCurrentThread.d.ts +6 -0
- package/dist/types/src/hooks/useSelectCurrentThread.d.ts.map +1 -0
- package/dist/types/src/meta.d.ts +4 -9
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/types/document.d.ts +10 -1
- package/dist/types/src/types/document.d.ts.map +1 -1
- package/dist/types/src/types/types.d.ts +8 -9
- package/dist/types/src/types/types.d.ts.map +1 -1
- package/dist/types/src/util.d.ts.map +1 -1
- package/package.json +42 -45
- package/src/MarkdownPlugin.tsx +58 -113
- package/src/components/MarkdownContainer.tsx +103 -0
- package/src/components/MarkdownEditor.stories.tsx +34 -23
- package/src/components/MarkdownEditor.tsx +48 -79
- package/src/components/MarkdownSettings.tsx +15 -15
- package/src/components/Toolbar.stories.tsx +14 -11
- package/src/components/index.ts +2 -14
- package/src/extensions.tsx +128 -67
- package/src/hooks/index.ts +5 -0
- package/src/hooks/useSelectCurrentThread.tsx +46 -0
- package/src/meta.ts +15 -0
- package/src/translations.ts +1 -1
- package/src/types/document.ts +12 -0
- package/src/types/types.ts +10 -7
- package/src/util.tsx +6 -4
- package/dist/lib/browser/DocumentCard-2P4EICBA.mjs +0 -11
- package/dist/lib/browser/DocumentEditor-GPWV3VN3.mjs +0 -11
- package/dist/lib/browser/MarkdownEditor-EKJJQEFL.mjs +0 -10
- package/dist/lib/browser/MarkdownEditor-EKJJQEFL.mjs.map +0 -7
- package/dist/lib/browser/chunk-354DCID5.mjs +0 -117
- package/dist/lib/browser/chunk-354DCID5.mjs.map +0 -7
- package/dist/lib/browser/chunk-4GGD6YJO.mjs +0 -19
- package/dist/lib/browser/chunk-4GGD6YJO.mjs.map +0 -7
- package/dist/lib/browser/chunk-7AF2JLK4.mjs +0 -164
- package/dist/lib/browser/chunk-7AF2JLK4.mjs.map +0 -7
- package/dist/lib/browser/chunk-CQJL4G4X.mjs.map +0 -7
- package/dist/lib/browser/chunk-RL7QY322.mjs +0 -86
- package/dist/lib/browser/chunk-RL7QY322.mjs.map +0 -7
- package/dist/lib/browser/chunk-VUN4QKTT.mjs +0 -208
- package/dist/lib/browser/chunk-VUN4QKTT.mjs.map +0 -7
- package/dist/lib/node/DocumentCard-EHJDDSRY.cjs.map +0 -7
- package/dist/lib/node/DocumentEditor-I5GCRBKU.cjs +0 -29
- package/dist/lib/node/DocumentEditor-I5GCRBKU.cjs.map +0 -7
- package/dist/lib/node/MarkdownEditor-UE23H75V.cjs +0 -31
- package/dist/lib/node/MarkdownEditor-UE23H75V.cjs.map +0 -7
- package/dist/lib/node/chunk-7XIBNEI7.cjs +0 -238
- package/dist/lib/node/chunk-7XIBNEI7.cjs.map +0 -7
- package/dist/lib/node/chunk-KTYIOXL5.cjs +0 -149
- package/dist/lib/node/chunk-KTYIOXL5.cjs.map +0 -7
- package/dist/lib/node/chunk-Q4ZSCBQE.cjs +0 -114
- package/dist/lib/node/chunk-Q4ZSCBQE.cjs.map +0 -7
- package/dist/lib/node/chunk-RVGN72IX.cjs +0 -189
- package/dist/lib/node/chunk-RVGN72IX.cjs.map +0 -7
- package/dist/lib/node/chunk-TGMR2CKU.cjs +0 -52
- package/dist/lib/node/chunk-TGMR2CKU.cjs.map +0 -7
- package/dist/lib/node/chunk-VWQH4WC2.cjs.map +0 -7
- package/dist/types/src/components/DocumentCard.d.ts +0 -16
- package/dist/types/src/components/DocumentCard.d.ts.map +0 -1
- package/dist/types/src/components/DocumentEditor.d.ts +0 -14
- package/dist/types/src/components/DocumentEditor.d.ts.map +0 -1
- package/dist/types/src/components/HeadingMenu.d.ts +0 -13
- package/dist/types/src/components/HeadingMenu.d.ts.map +0 -1
- package/dist/types/src/components/Layout.d.ts +0 -6
- package/dist/types/src/components/Layout.d.ts.map +0 -1
- package/src/components/DocumentCard.tsx +0 -107
- package/src/components/DocumentEditor.tsx +0 -137
- package/src/components/HeadingMenu.tsx +0 -46
- package/src/components/Layout.tsx +0 -27
- package/src/meta.tsx +0 -19
- /package/dist/lib/{browser/DocumentCard-2P4EICBA.mjs.map → node-esm/meta.mjs.map} +0 -0
- /package/dist/lib/{browser/DocumentEditor-GPWV3VN3.mjs.map → node-esm/types/index.mjs.map} +0 -0
package/src/MarkdownPlugin.tsx
CHANGED
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import React
|
|
5
|
+
import { TextAa } from '@phosphor-icons/react';
|
|
6
|
+
import React from 'react';
|
|
7
7
|
|
|
8
8
|
import {
|
|
9
|
-
isObject,
|
|
10
9
|
parseIntentPlugin,
|
|
11
10
|
resolvePlugin,
|
|
12
11
|
LayoutAction,
|
|
@@ -16,7 +15,6 @@ import {
|
|
|
16
15
|
} from '@dxos/app-framework';
|
|
17
16
|
import { create } from '@dxos/echo-schema';
|
|
18
17
|
import { LocalStorageStore } from '@dxos/local-storage';
|
|
19
|
-
import { log } from '@dxos/log';
|
|
20
18
|
import { parseClientPlugin } from '@dxos/plugin-client';
|
|
21
19
|
import { type ActionGroup, createExtension, isActionGroup } from '@dxos/plugin-graph';
|
|
22
20
|
import { SpaceAction } from '@dxos/plugin-space';
|
|
@@ -33,13 +31,13 @@ import {
|
|
|
33
31
|
type EditorViewMode,
|
|
34
32
|
EditorViewModes,
|
|
35
33
|
translations as editorTranslations,
|
|
34
|
+
createEditorStateStore,
|
|
36
35
|
} from '@dxos/react-ui-editor';
|
|
37
|
-
import { isTileComponentProps } from '@dxos/react-ui-mosaic';
|
|
38
36
|
|
|
39
|
-
import {
|
|
37
|
+
import { MarkdownContainer, MarkdownSettings } from './components';
|
|
40
38
|
import meta, { MARKDOWN_PLUGIN } from './meta';
|
|
41
39
|
import translations from './translations';
|
|
42
|
-
import { DocumentType, TextType } from './types';
|
|
40
|
+
import { DocumentType, isEditorModel, TextType } from './types';
|
|
43
41
|
import {
|
|
44
42
|
type MarkdownPluginProvides,
|
|
45
43
|
type MarkdownSettingsProps,
|
|
@@ -48,52 +46,31 @@ import {
|
|
|
48
46
|
} from './types';
|
|
49
47
|
import { markdownExtensionPlugins, serializer } from './util';
|
|
50
48
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
*/
|
|
54
|
-
const isEditorModel = (data: any): data is { id: string; text: string } => {
|
|
55
|
-
return (
|
|
56
|
-
data &&
|
|
57
|
-
typeof data === 'object' &&
|
|
58
|
-
'id' in data &&
|
|
59
|
-
typeof data.id === 'string' &&
|
|
60
|
-
'text' in data &&
|
|
61
|
-
typeof data.text === 'string'
|
|
62
|
-
);
|
|
63
|
-
};
|
|
49
|
+
// TODO(burdon): Normalize active/object.
|
|
50
|
+
const getDoc = (object: any) => (object instanceof DocumentType ? object : undefined);
|
|
64
51
|
|
|
65
52
|
export const MarkdownPlugin = (): PluginDefinition<MarkdownPluginProvides> => {
|
|
66
53
|
const settings = new LocalStorageStore<MarkdownSettingsProps>(MARKDOWN_PLUGIN, {
|
|
67
54
|
defaultViewMode: 'preview',
|
|
68
55
|
toolbar: true,
|
|
69
|
-
|
|
56
|
+
numberedHeadings: true,
|
|
57
|
+
folding: true,
|
|
70
58
|
experimental: false,
|
|
71
59
|
});
|
|
72
60
|
|
|
73
|
-
const
|
|
61
|
+
const editorStateStore = createEditorStateStore(`${MARKDOWN_PLUGIN}/editor`);
|
|
74
62
|
|
|
75
|
-
const
|
|
76
|
-
return (id && state.values.viewMode[id]) || settings.values.defaultViewMode;
|
|
77
|
-
};
|
|
63
|
+
const state = new LocalStorageStore<MarkdownPluginState>(MARKDOWN_PLUGIN, { extensionProviders: [], viewMode: {} });
|
|
78
64
|
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
};
|
|
65
|
+
const getViewMode = (id: string) => (id && state.values.viewMode[id]) || settings.values.defaultViewMode;
|
|
66
|
+
const setViewMode = (id: string, viewMode: EditorViewMode) => (state.values.viewMode[id] = viewMode);
|
|
82
67
|
|
|
83
68
|
return {
|
|
84
69
|
meta,
|
|
85
70
|
ready: async (plugins) => {
|
|
86
71
|
settings
|
|
87
|
-
.prop({
|
|
88
|
-
|
|
89
|
-
storageKey: 'default-view-mode',
|
|
90
|
-
type: LocalStorageStore.enum<EditorViewMode>(),
|
|
91
|
-
})
|
|
92
|
-
.prop({
|
|
93
|
-
key: 'editorInputMode',
|
|
94
|
-
storageKey: 'editor-mode',
|
|
95
|
-
type: LocalStorageStore.enum<EditorInputMode>({ allowUndefined: true }),
|
|
96
|
-
})
|
|
72
|
+
.prop({ key: 'defaultViewMode', type: LocalStorageStore.enum<EditorViewMode>() })
|
|
73
|
+
.prop({ key: 'editorInputMode', type: LocalStorageStore.enum<EditorInputMode>({ allowUndefined: true }) })
|
|
97
74
|
.prop({ key: 'toolbar', type: LocalStorageStore.bool({ allowUndefined: true }) })
|
|
98
75
|
.prop({ key: 'experimental', type: LocalStorageStore.bool({ allowUndefined: true }) })
|
|
99
76
|
.prop({ key: 'debug', type: LocalStorageStore.bool({ allowUndefined: true }) })
|
|
@@ -101,15 +78,11 @@ export const MarkdownPlugin = (): PluginDefinition<MarkdownPluginProvides> => {
|
|
|
101
78
|
.prop({ key: 'numberedHeadings', type: LocalStorageStore.bool({ allowUndefined: true }) })
|
|
102
79
|
.prop({ key: 'folding', type: LocalStorageStore.bool({ allowUndefined: true }) });
|
|
103
80
|
|
|
104
|
-
state.prop({
|
|
105
|
-
key: 'viewMode',
|
|
106
|
-
storageKey: 'view-mode',
|
|
107
|
-
type: LocalStorageStore.json<{ [key: string]: EditorViewMode }>(),
|
|
108
|
-
});
|
|
81
|
+
state.prop({ key: 'viewMode', type: LocalStorageStore.json<{ [key: string]: EditorViewMode }>() });
|
|
109
82
|
|
|
110
83
|
markdownExtensionPlugins(plugins).forEach((plugin) => {
|
|
111
84
|
const { extensions } = plugin.provides.markdown;
|
|
112
|
-
state.values.extensionProviders
|
|
85
|
+
state.values.extensionProviders?.push(extensions);
|
|
113
86
|
});
|
|
114
87
|
},
|
|
115
88
|
provides: {
|
|
@@ -117,10 +90,9 @@ export const MarkdownPlugin = (): PluginDefinition<MarkdownPluginProvides> => {
|
|
|
117
90
|
metadata: {
|
|
118
91
|
records: {
|
|
119
92
|
[DocumentType.typename]: {
|
|
120
|
-
label: (object: any) => (object instanceof DocumentType ? object.name
|
|
93
|
+
label: (object: any) => (object instanceof DocumentType ? object.name || object.fallbackName : undefined),
|
|
121
94
|
placeholder: ['document title placeholder', { ns: MARKDOWN_PLUGIN }],
|
|
122
|
-
icon:
|
|
123
|
-
iconSymbol: 'ph--text-aa--regular',
|
|
95
|
+
icon: 'ph--text-aa--regular',
|
|
124
96
|
graphProps: {
|
|
125
97
|
managesAutofocus: true,
|
|
126
98
|
},
|
|
@@ -134,6 +106,12 @@ export const MarkdownPlugin = (): PluginDefinition<MarkdownPluginProvides> => {
|
|
|
134
106
|
echo: {
|
|
135
107
|
schema: [DocumentType, TextType],
|
|
136
108
|
},
|
|
109
|
+
space: {
|
|
110
|
+
onSpaceCreate: {
|
|
111
|
+
label: ['create document label', { ns: MARKDOWN_PLUGIN }],
|
|
112
|
+
action: MarkdownAction.CREATE,
|
|
113
|
+
},
|
|
114
|
+
},
|
|
137
115
|
graph: {
|
|
138
116
|
builder: (plugins) => {
|
|
139
117
|
const client = resolvePlugin(plugins, parseClientPlugin)?.provides.client;
|
|
@@ -167,8 +145,7 @@ export const MarkdownPlugin = (): PluginDefinition<MarkdownPluginProvides> => {
|
|
|
167
145
|
},
|
|
168
146
|
properties: {
|
|
169
147
|
label: ['create document label', { ns: MARKDOWN_PLUGIN }],
|
|
170
|
-
icon:
|
|
171
|
-
iconSymbol: 'ph--text-aa--regular',
|
|
148
|
+
icon: 'ph--text-aa--regular',
|
|
172
149
|
testId: 'markdownPlugin.createObject',
|
|
173
150
|
},
|
|
174
151
|
},
|
|
@@ -241,13 +218,10 @@ export const MarkdownPlugin = (): PluginDefinition<MarkdownPluginProvides> => {
|
|
|
241
218
|
],
|
|
242
219
|
},
|
|
243
220
|
thread: {
|
|
244
|
-
// TODO(Zan): How to better handle the type predicate?
|
|
245
221
|
predicate: (obj) => obj instanceof DocumentType,
|
|
246
222
|
createSort: (doc: DocumentType) => {
|
|
247
223
|
const accessor = doc.content ? createDocAccessor(doc.content, ['content']) : undefined;
|
|
248
|
-
|
|
249
224
|
if (!accessor) {
|
|
250
|
-
log.warn('No accessor found for document content.');
|
|
251
225
|
return (_) => 0;
|
|
252
226
|
}
|
|
253
227
|
|
|
@@ -256,75 +230,46 @@ export const MarkdownPlugin = (): PluginDefinition<MarkdownPluginProvides> => {
|
|
|
256
230
|
return range?.start ?? Number.MAX_SAFE_INTEGER;
|
|
257
231
|
};
|
|
258
232
|
|
|
259
|
-
return (anchorA: string, anchorB: string
|
|
233
|
+
return (anchorA: string | undefined, anchorB: string | undefined): number => {
|
|
234
|
+
if (anchorA === undefined || anchorB === undefined) {
|
|
235
|
+
return 0;
|
|
236
|
+
}
|
|
237
|
+
const posA = getStartPosition(anchorA);
|
|
238
|
+
const posB = getStartPosition(anchorB);
|
|
239
|
+
return posA - posB;
|
|
240
|
+
};
|
|
260
241
|
},
|
|
261
242
|
},
|
|
262
243
|
surface: {
|
|
263
|
-
component: ({ data, role
|
|
264
|
-
const doc =
|
|
265
|
-
data.active instanceof DocumentType
|
|
266
|
-
? data.active
|
|
267
|
-
: data.object instanceof DocumentType
|
|
268
|
-
? data.object
|
|
269
|
-
: undefined;
|
|
270
|
-
|
|
244
|
+
component: ({ data, role }) => {
|
|
271
245
|
switch (role) {
|
|
272
246
|
case 'section':
|
|
273
247
|
case 'article': {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
settings={settings.values}
|
|
282
|
-
scrollPastEnd
|
|
283
|
-
viewMode={getViewMode(fullyQualifiedId(doc))}
|
|
284
|
-
onViewModeChange={setViewMode}
|
|
285
|
-
/>
|
|
286
|
-
);
|
|
287
|
-
} else if (isEditorModel(data.object)) {
|
|
288
|
-
return (
|
|
289
|
-
<MarkdownEditor
|
|
290
|
-
id={data.object.id}
|
|
291
|
-
role={role}
|
|
292
|
-
coordinate={data.coordinate as LayoutCoordinate}
|
|
293
|
-
initialValue={data.object.text}
|
|
294
|
-
extensionProviders={state.values.extensionProviders}
|
|
295
|
-
inputMode={settings.values.editorInputMode}
|
|
296
|
-
toolbar={settings.values.toolbar}
|
|
297
|
-
scrollPastEnd
|
|
298
|
-
viewMode={getViewMode(data.object.id)}
|
|
299
|
-
onViewModeChange={setViewMode}
|
|
300
|
-
/>
|
|
301
|
-
);
|
|
302
|
-
}
|
|
303
|
-
break;
|
|
304
|
-
}
|
|
248
|
+
// TODO(burdon): Normalize types (from FilesPlugin).
|
|
249
|
+
const doc = getDoc(data.active) ?? getDoc(data.object);
|
|
250
|
+
const { id, object } = isEditorModel(data.object)
|
|
251
|
+
? { id: data.object.id, object: data.object }
|
|
252
|
+
: doc
|
|
253
|
+
? { id: fullyQualifiedId(doc), object: doc }
|
|
254
|
+
: {};
|
|
305
255
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
isObject(data.content) &&
|
|
309
|
-
typeof data.content.id === 'string' &&
|
|
310
|
-
data.content.object instanceof DocumentType
|
|
311
|
-
) {
|
|
312
|
-
// isTileComponentProps is a type guard for these props.
|
|
313
|
-
// `props` will not pass this guard without transforming `data` into `item`.
|
|
314
|
-
const cardProps = {
|
|
315
|
-
...props,
|
|
316
|
-
item: {
|
|
317
|
-
id: data.content.id,
|
|
318
|
-
object: data.content.object,
|
|
319
|
-
color: typeof data.content.color === 'string' ? data.content.color : undefined,
|
|
320
|
-
} as DocumentItemProps,
|
|
321
|
-
};
|
|
322
|
-
|
|
323
|
-
return isTileComponentProps(cardProps) ? (
|
|
324
|
-
<DocumentCard {...cardProps} settings={settings.values} ref={forwardedRef as Ref<HTMLDivElement>} />
|
|
325
|
-
) : null;
|
|
256
|
+
if (!id || !object) {
|
|
257
|
+
return null;
|
|
326
258
|
}
|
|
327
|
-
|
|
259
|
+
|
|
260
|
+
return (
|
|
261
|
+
<MarkdownContainer
|
|
262
|
+
id={id}
|
|
263
|
+
object={object}
|
|
264
|
+
role={role}
|
|
265
|
+
coordinate={data.coordinate as LayoutCoordinate}
|
|
266
|
+
settings={settings.values}
|
|
267
|
+
extensionProviders={state.values.extensionProviders}
|
|
268
|
+
viewMode={getViewMode(id)}
|
|
269
|
+
editorStateStore={editorStateStore}
|
|
270
|
+
onViewModeChange={setViewMode}
|
|
271
|
+
/>
|
|
272
|
+
);
|
|
328
273
|
}
|
|
329
274
|
|
|
330
275
|
case 'settings': {
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { useEffect, useMemo } from 'react';
|
|
6
|
+
|
|
7
|
+
import { useResolvePlugin, parseFileManagerPlugin } from '@dxos/app-framework';
|
|
8
|
+
import { fullyQualifiedId, getSpace } from '@dxos/react-client/echo';
|
|
9
|
+
|
|
10
|
+
import { MarkdownEditor, type MarkdownEditorProps } from './MarkdownEditor';
|
|
11
|
+
import { useExtensions } from '../extensions';
|
|
12
|
+
import { DocumentType, type MarkdownSettingsProps } from '../types';
|
|
13
|
+
import { getFallbackName } from '../util';
|
|
14
|
+
|
|
15
|
+
export type MarkdownContainerProps = Pick<
|
|
16
|
+
MarkdownEditorProps,
|
|
17
|
+
'role' | 'coordinate' | 'extensionProviders' | 'viewMode' | 'editorStateStore' | 'onViewModeChange'
|
|
18
|
+
> & {
|
|
19
|
+
id: string;
|
|
20
|
+
object: DocumentType | any;
|
|
21
|
+
settings: MarkdownSettingsProps;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// TODO(burdon): Move toolbar here.
|
|
25
|
+
// TODO(burdon): Factor out difference for ECHO and non-ECHO objects; i.e., single component.
|
|
26
|
+
const MarkdownContainer = ({ id, role, object, settings, ...props }: MarkdownContainerProps) => {
|
|
27
|
+
const scrollPastEnd = role === 'article';
|
|
28
|
+
if (object instanceof DocumentType) {
|
|
29
|
+
return (
|
|
30
|
+
<DocumentEditor
|
|
31
|
+
id={fullyQualifiedId(object)}
|
|
32
|
+
role={role}
|
|
33
|
+
document={object}
|
|
34
|
+
settings={settings}
|
|
35
|
+
scrollPastEnd={scrollPastEnd}
|
|
36
|
+
{...props}
|
|
37
|
+
/>
|
|
38
|
+
);
|
|
39
|
+
} else {
|
|
40
|
+
return (
|
|
41
|
+
<MarkdownEditor
|
|
42
|
+
id={id}
|
|
43
|
+
role={role}
|
|
44
|
+
initialValue={object.text}
|
|
45
|
+
toolbar={settings.toolbar}
|
|
46
|
+
scrollPastEnd={scrollPastEnd}
|
|
47
|
+
{...props}
|
|
48
|
+
/>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
type DocumentEditorProps = Omit<MarkdownContainerProps, 'object'> & { document: DocumentType } & Pick<
|
|
54
|
+
MarkdownEditorProps,
|
|
55
|
+
'id' | 'scrollPastEnd'
|
|
56
|
+
>;
|
|
57
|
+
|
|
58
|
+
export const DocumentEditor = ({
|
|
59
|
+
id,
|
|
60
|
+
document: doc,
|
|
61
|
+
extensionProviders,
|
|
62
|
+
settings,
|
|
63
|
+
viewMode,
|
|
64
|
+
editorStateStore,
|
|
65
|
+
...props
|
|
66
|
+
}: DocumentEditorProps) => {
|
|
67
|
+
const space = getSpace(doc);
|
|
68
|
+
const initialValue = useMemo(() => doc.content?.content, [doc.content]);
|
|
69
|
+
const extensions = useExtensions({ extensionProviders, document: doc, settings, viewMode, editorStateStore });
|
|
70
|
+
|
|
71
|
+
// Migrate gradually to `fallbackName`.
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
if (!doc.fallbackName && doc.content?.content) {
|
|
74
|
+
doc.fallbackName = getFallbackName(doc.content.content);
|
|
75
|
+
}
|
|
76
|
+
}, [doc, doc.content]);
|
|
77
|
+
|
|
78
|
+
// File dragging.
|
|
79
|
+
const fileManagerPlugin = useResolvePlugin(parseFileManagerPlugin);
|
|
80
|
+
const handleFileUpload = useMemo(() => {
|
|
81
|
+
if (space === undefined || fileManagerPlugin?.provides.file.upload === undefined) {
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// TODO(burdon): Re-order props: space, file.
|
|
86
|
+
return async (file: File) => fileManagerPlugin?.provides?.file?.upload?.(file, space);
|
|
87
|
+
}, [space, fileManagerPlugin]);
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<MarkdownEditor
|
|
91
|
+
id={id}
|
|
92
|
+
initialValue={initialValue}
|
|
93
|
+
extensions={extensions}
|
|
94
|
+
toolbar={settings.toolbar}
|
|
95
|
+
inputMode={settings.editorInputMode}
|
|
96
|
+
viewMode={viewMode}
|
|
97
|
+
onFileUpload={handleFileUpload}
|
|
98
|
+
{...props}
|
|
99
|
+
/>
|
|
100
|
+
);
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export default MarkdownContainer;
|
|
@@ -3,41 +3,42 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import '@dxos-theme';
|
|
6
|
-
import React, { useMemo, type FC } from 'react';
|
|
7
6
|
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
7
|
+
import { type Meta } from '@storybook/react';
|
|
8
|
+
import React, { useMemo } from 'react';
|
|
9
|
+
|
|
10
|
+
import { createDocAccessor, createObject } from '@dxos/react-client/echo';
|
|
11
|
+
import { Main } from '@dxos/react-ui';
|
|
12
|
+
import { editorWithToolbarLayout, automerge } from '@dxos/react-ui-editor';
|
|
13
|
+
import { topbarBlockPaddingStart } from '@dxos/react-ui-theme';
|
|
10
14
|
import { withLayout, withTheme } from '@dxos/storybook-utils';
|
|
11
15
|
|
|
12
|
-
import {
|
|
13
|
-
|
|
16
|
+
import { MarkdownEditor, type MarkdownEditorProps } from './MarkdownEditor';
|
|
17
|
+
|
|
18
|
+
const content = Array.from({ length: 100 })
|
|
19
|
+
.map((_, i) => `Line ${i + 1}`)
|
|
20
|
+
.join('\n');
|
|
14
21
|
|
|
15
|
-
|
|
16
|
-
content
|
|
22
|
+
type StoryProps = MarkdownEditorProps & {
|
|
23
|
+
content?: string;
|
|
17
24
|
toolbar?: boolean;
|
|
18
|
-
}
|
|
19
|
-
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const DefaultStory = ({ content = '# Test', toolbar }: StoryProps) => {
|
|
28
|
+
const doc = useMemo(() => createObject({ content }), [content]);
|
|
20
29
|
const extensions = useMemo(() => [automerge(createDocAccessor(doc, ['content']))], [doc]);
|
|
21
30
|
|
|
22
31
|
return (
|
|
23
|
-
<
|
|
32
|
+
<Main.Content
|
|
33
|
+
bounce
|
|
34
|
+
data-toolbar={toolbar ? 'enabled' : 'disabled'}
|
|
35
|
+
classNames={[topbarBlockPaddingStart, editorWithToolbarLayout]}
|
|
36
|
+
>
|
|
24
37
|
<MarkdownEditor id='test' initialValue={doc.content} extensions={extensions} toolbar={toolbar} />
|
|
25
|
-
</
|
|
38
|
+
</Main.Content>
|
|
26
39
|
);
|
|
27
40
|
};
|
|
28
41
|
|
|
29
|
-
export default {
|
|
30
|
-
title: 'plugin-markdown/EditorMain',
|
|
31
|
-
component: MarkdownEditor,
|
|
32
|
-
decorators: [withTheme, withLayout({ tooltips: true })],
|
|
33
|
-
render: Story,
|
|
34
|
-
parameters: { layout: 'fullscreen' },
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
const content = Array.from({ length: 100 })
|
|
38
|
-
.map((_, i) => `Line ${i + 1}`)
|
|
39
|
-
.join('\n');
|
|
40
|
-
|
|
41
42
|
export const Default = {
|
|
42
43
|
args: {
|
|
43
44
|
content,
|
|
@@ -50,3 +51,13 @@ export const WithToolbar = {
|
|
|
50
51
|
toolbar: true,
|
|
51
52
|
},
|
|
52
53
|
};
|
|
54
|
+
|
|
55
|
+
const meta: Meta<typeof MarkdownEditor> = {
|
|
56
|
+
title: 'plugins/plugin-markdown/EditorMain',
|
|
57
|
+
component: MarkdownEditor,
|
|
58
|
+
render: DefaultStory,
|
|
59
|
+
decorators: [withTheme, withLayout({ tooltips: true })],
|
|
60
|
+
parameters: { layout: 'fullscreen' },
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export default meta;
|