@dxos/plugin-markdown 0.6.13 → 0.6.14-main.1366248
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-J5BZUIVL.mjs +472 -0
- package/dist/lib/browser/MarkdownContainer-J5BZUIVL.mjs.map +7 -0
- package/dist/lib/browser/chunk-4X6YX3KU.mjs +15 -0
- package/dist/lib/browser/chunk-4X6YX3KU.mjs.map +7 -0
- package/dist/lib/browser/chunk-PV4AWYWK.mjs +52 -0
- package/dist/lib/browser/chunk-PV4AWYWK.mjs.map +7 -0
- package/dist/lib/browser/{chunk-CQJL4G4X.mjs → chunk-VZAGHNHU.mjs} +4 -2
- package/dist/lib/browser/chunk-VZAGHNHU.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +84 -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-UYBYWCRU.cjs +487 -0
- package/dist/lib/node/MarkdownContainer-UYBYWCRU.cjs.map +7 -0
- package/dist/lib/node/chunk-2A5P424C.cjs +74 -0
- package/dist/lib/node/chunk-2A5P424C.cjs.map +7 -0
- package/dist/lib/node/{chunk-VWQH4WC2.cjs → chunk-BHPFK7YI.cjs} +11 -8
- package/dist/lib/node/chunk-BHPFK7YI.cjs.map +7 -0
- package/dist/lib/node/{DocumentCard-EHJDDSRY.cjs → chunk-PHHIPRJC.cjs} +16 -10
- package/dist/lib/node/chunk-PHHIPRJC.cjs.map +7 -0
- package/dist/lib/node/index.cjs +116 -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-P3EAZ3OR.mjs +473 -0
- package/dist/lib/node-esm/MarkdownContainer-P3EAZ3OR.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-BABK7FMW.mjs +17 -0
- package/dist/lib/node-esm/chunk-BABK7FMW.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-EREAR7QS.mjs +53 -0
- package/dist/lib/node-esm/chunk-EREAR7QS.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-OEMU3XY7.mjs +42 -0
- package/dist/lib/node-esm/chunk-OEMU3XY7.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +492 -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 +13 -8
- 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 +11 -14
- 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 +56 -114
- package/src/components/MarkdownContainer.tsx +109 -0
- package/src/components/MarkdownEditor.stories.tsx +34 -23
- package/src/components/MarkdownEditor.tsx +48 -80
- 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 +139 -66
- 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,21 +2,18 @@
|
|
|
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,
|
|
13
|
-
type LayoutCoordinate,
|
|
14
12
|
NavigationAction,
|
|
15
13
|
type PluginDefinition,
|
|
16
14
|
} from '@dxos/app-framework';
|
|
17
15
|
import { create } from '@dxos/echo-schema';
|
|
18
16
|
import { LocalStorageStore } from '@dxos/local-storage';
|
|
19
|
-
import { log } from '@dxos/log';
|
|
20
17
|
import { parseClientPlugin } from '@dxos/plugin-client';
|
|
21
18
|
import { type ActionGroup, createExtension, isActionGroup } from '@dxos/plugin-graph';
|
|
22
19
|
import { SpaceAction } from '@dxos/plugin-space';
|
|
@@ -33,13 +30,13 @@ import {
|
|
|
33
30
|
type EditorViewMode,
|
|
34
31
|
EditorViewModes,
|
|
35
32
|
translations as editorTranslations,
|
|
33
|
+
createEditorStateStore,
|
|
36
34
|
} from '@dxos/react-ui-editor';
|
|
37
|
-
import { isTileComponentProps } from '@dxos/react-ui-mosaic';
|
|
38
35
|
|
|
39
|
-
import {
|
|
36
|
+
import { MarkdownContainer, MarkdownSettings } from './components';
|
|
40
37
|
import meta, { MARKDOWN_PLUGIN } from './meta';
|
|
41
38
|
import translations from './translations';
|
|
42
|
-
import { DocumentType, TextType } from './types';
|
|
39
|
+
import { DocumentType, isEditorModel, TextType } from './types';
|
|
43
40
|
import {
|
|
44
41
|
type MarkdownPluginProvides,
|
|
45
42
|
type MarkdownSettingsProps,
|
|
@@ -48,52 +45,31 @@ import {
|
|
|
48
45
|
} from './types';
|
|
49
46
|
import { markdownExtensionPlugins, serializer } from './util';
|
|
50
47
|
|
|
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
|
-
};
|
|
48
|
+
// TODO(burdon): Normalize active/object.
|
|
49
|
+
const getDoc = (object: any) => (object instanceof DocumentType ? object : undefined);
|
|
64
50
|
|
|
65
51
|
export const MarkdownPlugin = (): PluginDefinition<MarkdownPluginProvides> => {
|
|
66
52
|
const settings = new LocalStorageStore<MarkdownSettingsProps>(MARKDOWN_PLUGIN, {
|
|
67
53
|
defaultViewMode: 'preview',
|
|
68
54
|
toolbar: true,
|
|
69
|
-
|
|
55
|
+
numberedHeadings: true,
|
|
56
|
+
folding: true,
|
|
70
57
|
experimental: false,
|
|
71
58
|
});
|
|
72
59
|
|
|
73
|
-
const
|
|
60
|
+
const editorStateStore = createEditorStateStore(`${MARKDOWN_PLUGIN}/editor`);
|
|
74
61
|
|
|
75
|
-
const
|
|
76
|
-
return (id && state.values.viewMode[id]) || settings.values.defaultViewMode;
|
|
77
|
-
};
|
|
62
|
+
const state = new LocalStorageStore<MarkdownPluginState>(MARKDOWN_PLUGIN, { extensionProviders: [], viewMode: {} });
|
|
78
63
|
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
};
|
|
64
|
+
const getViewMode = (id: string) => (id && state.values.viewMode[id]) || settings.values.defaultViewMode;
|
|
65
|
+
const setViewMode = (id: string, viewMode: EditorViewMode) => (state.values.viewMode[id] = viewMode);
|
|
82
66
|
|
|
83
67
|
return {
|
|
84
68
|
meta,
|
|
85
69
|
ready: async (plugins) => {
|
|
86
70
|
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
|
-
})
|
|
71
|
+
.prop({ key: 'defaultViewMode', type: LocalStorageStore.enum<EditorViewMode>() })
|
|
72
|
+
.prop({ key: 'editorInputMode', type: LocalStorageStore.enum<EditorInputMode>({ allowUndefined: true }) })
|
|
97
73
|
.prop({ key: 'toolbar', type: LocalStorageStore.bool({ allowUndefined: true }) })
|
|
98
74
|
.prop({ key: 'experimental', type: LocalStorageStore.bool({ allowUndefined: true }) })
|
|
99
75
|
.prop({ key: 'debug', type: LocalStorageStore.bool({ allowUndefined: true }) })
|
|
@@ -101,15 +77,11 @@ export const MarkdownPlugin = (): PluginDefinition<MarkdownPluginProvides> => {
|
|
|
101
77
|
.prop({ key: 'numberedHeadings', type: LocalStorageStore.bool({ allowUndefined: true }) })
|
|
102
78
|
.prop({ key: 'folding', type: LocalStorageStore.bool({ allowUndefined: true }) });
|
|
103
79
|
|
|
104
|
-
state.prop({
|
|
105
|
-
key: 'viewMode',
|
|
106
|
-
storageKey: 'view-mode',
|
|
107
|
-
type: LocalStorageStore.json<{ [key: string]: EditorViewMode }>(),
|
|
108
|
-
});
|
|
80
|
+
state.prop({ key: 'viewMode', type: LocalStorageStore.json<{ [key: string]: EditorViewMode }>() });
|
|
109
81
|
|
|
110
82
|
markdownExtensionPlugins(plugins).forEach((plugin) => {
|
|
111
83
|
const { extensions } = plugin.provides.markdown;
|
|
112
|
-
state.values.extensionProviders
|
|
84
|
+
state.values.extensionProviders?.push(extensions);
|
|
113
85
|
});
|
|
114
86
|
},
|
|
115
87
|
provides: {
|
|
@@ -117,10 +89,9 @@ export const MarkdownPlugin = (): PluginDefinition<MarkdownPluginProvides> => {
|
|
|
117
89
|
metadata: {
|
|
118
90
|
records: {
|
|
119
91
|
[DocumentType.typename]: {
|
|
120
|
-
label: (object: any) => (object instanceof DocumentType ? object.name
|
|
92
|
+
label: (object: any) => (object instanceof DocumentType ? object.name || object.fallbackName : undefined),
|
|
121
93
|
placeholder: ['document title placeholder', { ns: MARKDOWN_PLUGIN }],
|
|
122
|
-
icon:
|
|
123
|
-
iconSymbol: 'ph--text-aa--regular',
|
|
94
|
+
icon: 'ph--text-aa--regular',
|
|
124
95
|
graphProps: {
|
|
125
96
|
managesAutofocus: true,
|
|
126
97
|
},
|
|
@@ -134,6 +105,12 @@ export const MarkdownPlugin = (): PluginDefinition<MarkdownPluginProvides> => {
|
|
|
134
105
|
echo: {
|
|
135
106
|
schema: [DocumentType, TextType],
|
|
136
107
|
},
|
|
108
|
+
space: {
|
|
109
|
+
onSpaceCreate: {
|
|
110
|
+
label: ['create document label', { ns: MARKDOWN_PLUGIN }],
|
|
111
|
+
action: MarkdownAction.CREATE,
|
|
112
|
+
},
|
|
113
|
+
},
|
|
137
114
|
graph: {
|
|
138
115
|
builder: (plugins) => {
|
|
139
116
|
const client = resolvePlugin(plugins, parseClientPlugin)?.provides.client;
|
|
@@ -167,8 +144,7 @@ export const MarkdownPlugin = (): PluginDefinition<MarkdownPluginProvides> => {
|
|
|
167
144
|
},
|
|
168
145
|
properties: {
|
|
169
146
|
label: ['create document label', { ns: MARKDOWN_PLUGIN }],
|
|
170
|
-
icon:
|
|
171
|
-
iconSymbol: 'ph--text-aa--regular',
|
|
147
|
+
icon: 'ph--text-aa--regular',
|
|
172
148
|
testId: 'markdownPlugin.createObject',
|
|
173
149
|
},
|
|
174
150
|
},
|
|
@@ -241,13 +217,10 @@ export const MarkdownPlugin = (): PluginDefinition<MarkdownPluginProvides> => {
|
|
|
241
217
|
],
|
|
242
218
|
},
|
|
243
219
|
thread: {
|
|
244
|
-
// TODO(Zan): How to better handle the type predicate?
|
|
245
220
|
predicate: (obj) => obj instanceof DocumentType,
|
|
246
221
|
createSort: (doc: DocumentType) => {
|
|
247
222
|
const accessor = doc.content ? createDocAccessor(doc.content, ['content']) : undefined;
|
|
248
|
-
|
|
249
223
|
if (!accessor) {
|
|
250
|
-
log.warn('No accessor found for document content.');
|
|
251
224
|
return (_) => 0;
|
|
252
225
|
}
|
|
253
226
|
|
|
@@ -256,75 +229,44 @@ export const MarkdownPlugin = (): PluginDefinition<MarkdownPluginProvides> => {
|
|
|
256
229
|
return range?.start ?? Number.MAX_SAFE_INTEGER;
|
|
257
230
|
};
|
|
258
231
|
|
|
259
|
-
return (anchorA: string, anchorB: string
|
|
232
|
+
return (anchorA: string | undefined, anchorB: string | undefined): number => {
|
|
233
|
+
if (anchorA === undefined || anchorB === undefined) {
|
|
234
|
+
return 0;
|
|
235
|
+
}
|
|
236
|
+
const posA = getStartPosition(anchorA);
|
|
237
|
+
const posB = getStartPosition(anchorB);
|
|
238
|
+
return posA - posB;
|
|
239
|
+
};
|
|
260
240
|
},
|
|
261
241
|
},
|
|
262
242
|
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
|
-
|
|
243
|
+
component: ({ data, role }) => {
|
|
271
244
|
switch (role) {
|
|
272
245
|
case 'section':
|
|
273
246
|
case 'article': {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
extensionProviders={state.values.extensionProviders}
|
|
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
|
-
}
|
|
247
|
+
const doc = getDoc(data.object);
|
|
248
|
+
const { id, object } = isEditorModel(data.object)
|
|
249
|
+
? { id: data.object.id, object: data.object }
|
|
250
|
+
: doc
|
|
251
|
+
? { id: fullyQualifiedId(doc), object: doc }
|
|
252
|
+
: {};
|
|
305
253
|
|
|
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;
|
|
254
|
+
if (!id || !object) {
|
|
255
|
+
return null;
|
|
326
256
|
}
|
|
327
|
-
|
|
257
|
+
|
|
258
|
+
return (
|
|
259
|
+
<MarkdownContainer
|
|
260
|
+
id={id}
|
|
261
|
+
object={object}
|
|
262
|
+
role={role}
|
|
263
|
+
settings={settings.values}
|
|
264
|
+
extensionProviders={state.values.extensionProviders}
|
|
265
|
+
viewMode={getViewMode(id)}
|
|
266
|
+
editorStateStore={editorStateStore}
|
|
267
|
+
onViewModeChange={setViewMode}
|
|
268
|
+
/>
|
|
269
|
+
);
|
|
328
270
|
}
|
|
329
271
|
|
|
330
272
|
case 'settings': {
|
|
@@ -0,0 +1,109 @@
|
|
|
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' | '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 = ({
|
|
27
|
+
id,
|
|
28
|
+
role,
|
|
29
|
+
object,
|
|
30
|
+
extensionProviders,
|
|
31
|
+
settings,
|
|
32
|
+
viewMode,
|
|
33
|
+
editorStateStore,
|
|
34
|
+
onViewModeChange,
|
|
35
|
+
}: MarkdownContainerProps) => {
|
|
36
|
+
const scrollPastEnd = role === 'article';
|
|
37
|
+
const doc = object instanceof DocumentType ? object : undefined;
|
|
38
|
+
const extensions = useExtensions({ extensionProviders, document: doc, settings, viewMode, editorStateStore });
|
|
39
|
+
|
|
40
|
+
if (doc) {
|
|
41
|
+
return (
|
|
42
|
+
<DocumentEditor
|
|
43
|
+
id={fullyQualifiedId(object)}
|
|
44
|
+
role={role}
|
|
45
|
+
document={doc}
|
|
46
|
+
extensions={extensions}
|
|
47
|
+
settings={settings}
|
|
48
|
+
scrollPastEnd={scrollPastEnd}
|
|
49
|
+
onViewModeChange={onViewModeChange}
|
|
50
|
+
/>
|
|
51
|
+
);
|
|
52
|
+
} else {
|
|
53
|
+
return (
|
|
54
|
+
<MarkdownEditor
|
|
55
|
+
id={id}
|
|
56
|
+
role={role}
|
|
57
|
+
initialValue={object.text}
|
|
58
|
+
extensions={extensions}
|
|
59
|
+
viewMode={viewMode}
|
|
60
|
+
toolbar={settings.toolbar}
|
|
61
|
+
inputMode={settings.editorInputMode}
|
|
62
|
+
scrollPastEnd={scrollPastEnd}
|
|
63
|
+
onViewModeChange={onViewModeChange}
|
|
64
|
+
/>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
type DocumentEditorProps = Omit<MarkdownContainerProps, 'object' | 'extensionProviders' | 'editorStateStore'> &
|
|
70
|
+
Pick<MarkdownEditorProps, 'id' | 'scrollPastEnd' | 'extensions'> & {
|
|
71
|
+
document: DocumentType;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export const DocumentEditor = ({ id, document: doc, settings, viewMode, ...props }: DocumentEditorProps) => {
|
|
75
|
+
const space = getSpace(doc);
|
|
76
|
+
const initialValue = useMemo(() => doc.content?.content, [doc.content]);
|
|
77
|
+
|
|
78
|
+
// Migrate gradually to `fallbackName`.
|
|
79
|
+
useEffect(() => {
|
|
80
|
+
if (!doc.fallbackName && doc.content?.content) {
|
|
81
|
+
doc.fallbackName = getFallbackName(doc.content.content);
|
|
82
|
+
}
|
|
83
|
+
}, [doc, doc.content]);
|
|
84
|
+
|
|
85
|
+
// File dragging.
|
|
86
|
+
const fileManagerPlugin = useResolvePlugin(parseFileManagerPlugin);
|
|
87
|
+
const handleFileUpload = useMemo(() => {
|
|
88
|
+
if (space === undefined || fileManagerPlugin?.provides.file.upload === undefined) {
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// TODO(burdon): Re-order props: space, file.
|
|
93
|
+
return async (file: File) => fileManagerPlugin?.provides?.file?.upload?.(file, space);
|
|
94
|
+
}, [space, fileManagerPlugin]);
|
|
95
|
+
|
|
96
|
+
return (
|
|
97
|
+
<MarkdownEditor
|
|
98
|
+
id={id}
|
|
99
|
+
initialValue={initialValue}
|
|
100
|
+
viewMode={viewMode}
|
|
101
|
+
toolbar={settings.toolbar}
|
|
102
|
+
inputMode={settings.editorInputMode}
|
|
103
|
+
onFileUpload={handleFileUpload}
|
|
104
|
+
{...props}
|
|
105
|
+
/>
|
|
106
|
+
);
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
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;
|