@dxos/react-ui-editor 0.7.5-main.9d26e3a → 0.7.5-main.e9bb01b
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/index.mjs +1110 -1127
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +1133 -1164
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +1110 -1127
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/InputMode.stories.d.ts.map +1 -1
- package/dist/types/src/components/EditorToolbar/EditorToolbar.d.ts +4 -0
- package/dist/types/src/components/EditorToolbar/EditorToolbar.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/blocks.d.ts +18 -0
- package/dist/types/src/components/EditorToolbar/blocks.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/comment.d.ts +17 -0
- package/dist/types/src/components/EditorToolbar/comment.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/formatting.d.ts +18 -0
- package/dist/types/src/components/EditorToolbar/formatting.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/headings.d.ts +18 -0
- package/dist/types/src/components/EditorToolbar/headings.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/index.d.ts +3 -0
- package/dist/types/src/components/EditorToolbar/index.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/lists.d.ts +18 -0
- package/dist/types/src/components/EditorToolbar/lists.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/util.d.ts +58 -0
- package/dist/types/src/components/EditorToolbar/util.d.ts.map +1 -0
- package/dist/types/src/components/EditorToolbar/viewMode.d.ts +18 -0
- package/dist/types/src/components/EditorToolbar/viewMode.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +1 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts +3 -4
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/editorAction.d.ts +12 -0
- package/dist/types/src/extensions/markdown/editorAction.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/formatting.d.ts +14 -12
- package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/index.d.ts +1 -1
- package/dist/types/src/extensions/markdown/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/styles.d.ts.map +1 -1
- package/dist/types/src/hooks/useActionHandler.d.ts +2 -2
- package/dist/types/src/hooks/useActionHandler.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/styles/stack-item-content-class-names.d.ts +3 -0
- package/dist/types/src/styles/stack-item-content-class-names.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +30 -29
- package/src/InputMode.stories.tsx +7 -10
- package/src/components/EditorToolbar/EditorToolbar.tsx +106 -0
- package/src/components/EditorToolbar/blocks.ts +41 -0
- package/src/components/EditorToolbar/comment.ts +23 -0
- package/src/components/EditorToolbar/formatting.ts +41 -0
- package/src/components/EditorToolbar/headings.ts +59 -0
- package/src/components/EditorToolbar/index.ts +6 -0
- package/src/components/EditorToolbar/lists.ts +40 -0
- package/src/components/EditorToolbar/util.ts +65 -0
- package/src/components/EditorToolbar/viewMode.ts +48 -0
- package/src/components/index.ts +1 -1
- package/src/extensions/comments.ts +8 -15
- package/src/extensions/markdown/decorate.ts +1 -1
- package/src/extensions/markdown/{action.ts → editorAction.ts} +22 -20
- package/src/extensions/markdown/formatting.test.ts +7 -6
- package/src/extensions/markdown/formatting.ts +20 -24
- package/src/extensions/markdown/index.ts +1 -1
- package/src/extensions/markdown/styles.ts +21 -0
- package/src/hooks/useActionHandler.ts +4 -4
- package/src/index.ts +4 -0
- package/src/styles/markdown.ts +1 -1
- package/src/styles/stack-item-content-class-names.ts +17 -0
- package/src/styles/theme.ts +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.d.ts +0 -34
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +0 -1
- package/dist/types/src/components/Toolbar/index.d.ts +0 -2
- package/dist/types/src/components/Toolbar/index.d.ts.map +0 -1
- package/dist/types/src/extensions/markdown/action.d.ts +0 -9
- package/dist/types/src/extensions/markdown/action.d.ts.map +0 -1
- package/src/components/Toolbar/Toolbar.tsx +0 -522
- package/src/components/Toolbar/index.ts +0 -5
@@ -0,0 +1,65 @@
|
|
1
|
+
//
|
2
|
+
// Copyright 2025 DXOS.org
|
3
|
+
//
|
4
|
+
|
5
|
+
import { useMemo } from 'react';
|
6
|
+
|
7
|
+
import { create, type ReactiveObject } from '@dxos/live-object';
|
8
|
+
import { type Label, type ThemedClassName } from '@dxos/react-ui';
|
9
|
+
import {
|
10
|
+
type MenuSeparator,
|
11
|
+
type MenuItemGroup,
|
12
|
+
type ToolbarMenuActionGroupProperties,
|
13
|
+
type MenuActionProperties,
|
14
|
+
createMenuAction,
|
15
|
+
createMenuItemGroup,
|
16
|
+
type ActionGraphProps,
|
17
|
+
} from '@dxos/react-ui-menu';
|
18
|
+
|
19
|
+
import type { EditorAction, EditorActionPayload, EditorViewMode, Formatting } from '../../extensions';
|
20
|
+
import { translationKey } from '../../translations';
|
21
|
+
|
22
|
+
export type EditorToolbarState = Formatting &
|
23
|
+
Partial<{ comment: boolean; viewMode: EditorViewMode; selection: boolean }>;
|
24
|
+
|
25
|
+
export const useEditorToolbarState = (initialState: Partial<EditorToolbarState> = {}) => {
|
26
|
+
return useMemo(() => create<EditorToolbarState>(initialState), []);
|
27
|
+
};
|
28
|
+
|
29
|
+
export type EditorToolbarFeatureFlags = Partial<{
|
30
|
+
headings: boolean;
|
31
|
+
formatting: boolean;
|
32
|
+
lists: boolean;
|
33
|
+
blocks: boolean;
|
34
|
+
comment: boolean;
|
35
|
+
search: boolean;
|
36
|
+
viewMode: boolean;
|
37
|
+
}>;
|
38
|
+
|
39
|
+
export type EditorToolbarActionGraphProps = {
|
40
|
+
state: ReactiveObject<EditorToolbarState>;
|
41
|
+
// TODO(wittjosiah): Control positioning.
|
42
|
+
customActions?: () => ActionGraphProps;
|
43
|
+
onAction: (action: EditorAction) => void;
|
44
|
+
};
|
45
|
+
|
46
|
+
export type EditorToolbarProps = ThemedClassName<
|
47
|
+
EditorToolbarActionGraphProps & EditorToolbarFeatureFlags & { attendableId?: string; role?: string }
|
48
|
+
>;
|
49
|
+
|
50
|
+
export type EditorToolbarItem = EditorAction | MenuItemGroup | MenuSeparator;
|
51
|
+
|
52
|
+
export const createEditorAction = (
|
53
|
+
payload: EditorActionPayload & Partial<MenuActionProperties>,
|
54
|
+
icon: string,
|
55
|
+
label: Label = [`${payload.type} label`, { ns: translationKey }],
|
56
|
+
id: string = payload.type,
|
57
|
+
) => createMenuAction(id, { icon, label, ...payload }) as EditorAction;
|
58
|
+
|
59
|
+
export const createEditorActionGroup = (
|
60
|
+
id: string,
|
61
|
+
props: Omit<ToolbarMenuActionGroupProperties, 'icon'>,
|
62
|
+
icon?: string,
|
63
|
+
) => createMenuItemGroup(id, { icon, iconOnly: true, ...props });
|
64
|
+
|
65
|
+
export const editorToolbarSearch = createEditorAction({ type: 'search' }, 'ph--magnifying-glass--regular');
|
@@ -0,0 +1,48 @@
|
|
1
|
+
//
|
2
|
+
// Copyright 2025 DXOS.org
|
3
|
+
//
|
4
|
+
|
5
|
+
import { type NodeArg } from '@dxos/app-graph';
|
6
|
+
import { type ToolbarMenuActionGroupProperties } from '@dxos/react-ui-menu';
|
7
|
+
|
8
|
+
import { createEditorAction, createEditorActionGroup, type EditorToolbarState } from './util';
|
9
|
+
import { translationKey } from '../../translations';
|
10
|
+
|
11
|
+
const createViewModeGroupAction = (value: string) =>
|
12
|
+
createEditorActionGroup(
|
13
|
+
'viewMode',
|
14
|
+
{
|
15
|
+
variant: 'dropdownMenu',
|
16
|
+
applyActive: true,
|
17
|
+
selectCardinality: 'single',
|
18
|
+
value,
|
19
|
+
} as ToolbarMenuActionGroupProperties,
|
20
|
+
'ph--eye--regular',
|
21
|
+
);
|
22
|
+
|
23
|
+
const createViewModeActions = (value: string) =>
|
24
|
+
Object.entries({
|
25
|
+
preview: 'ph--eye--regular',
|
26
|
+
source: 'ph--pencil-simple--regular',
|
27
|
+
readonly: 'ph--pencil-slash--regular',
|
28
|
+
}).map(([viewMode, icon]) => {
|
29
|
+
return createEditorAction(
|
30
|
+
{ type: 'view-mode', data: viewMode, checked: viewMode === value },
|
31
|
+
icon,
|
32
|
+
[`${viewMode} mode label`, { ns: translationKey }],
|
33
|
+
`view-mode--${viewMode}`,
|
34
|
+
);
|
35
|
+
});
|
36
|
+
|
37
|
+
export const createViewMode = (state: EditorToolbarState) => {
|
38
|
+
const value = state.viewMode ?? 'source';
|
39
|
+
const viewModeGroupAction = createViewModeGroupAction(value);
|
40
|
+
const viewModeActions = createViewModeActions(value);
|
41
|
+
return {
|
42
|
+
nodes: [viewModeGroupAction as NodeArg<any>, ...viewModeActions],
|
43
|
+
edges: [
|
44
|
+
{ source: 'root', target: 'viewMode' },
|
45
|
+
...viewModeActions.map(({ id }) => ({ source: viewModeGroupAction.id, target: id })),
|
46
|
+
],
|
47
|
+
};
|
48
|
+
};
|
package/src/components/index.ts
CHANGED
@@ -22,13 +22,15 @@ import {
|
|
22
22
|
ViewPlugin,
|
23
23
|
} from '@codemirror/view';
|
24
24
|
import sortBy from 'lodash.sortby';
|
25
|
-
import { useEffect, useMemo
|
25
|
+
import { useEffect, useMemo } from 'react';
|
26
26
|
|
27
27
|
import { debounce, type UnsubscribeCallback } from '@dxos/async';
|
28
|
+
import { type ReactiveObject } from '@dxos/live-object';
|
28
29
|
import { log } from '@dxos/log';
|
29
30
|
import { nonNullable } from '@dxos/util';
|
30
31
|
|
31
32
|
import { documentId } from './selection';
|
33
|
+
import { type EditorToolbarState } from '../components';
|
32
34
|
import { type Comment, type Range } from '../types';
|
33
35
|
import { Cursor, overlap, singleValueFacet, callbackWrapper } from '../util';
|
34
36
|
|
@@ -608,26 +610,17 @@ export const createExternalCommentSync = (
|
|
608
610
|
},
|
609
611
|
);
|
610
612
|
|
611
|
-
export const useCommentState = (
|
612
|
-
|
613
|
-
comment: false,
|
614
|
-
selection: false,
|
615
|
-
});
|
616
|
-
|
617
|
-
const observer = useMemo(
|
613
|
+
export const useCommentState = (state: ReactiveObject<EditorToolbarState>): Extension => {
|
614
|
+
return useMemo(
|
618
615
|
() =>
|
619
616
|
EditorView.updateListener.of((update) => {
|
620
617
|
if (update.docChanged || update.selectionSet) {
|
621
|
-
|
622
|
-
|
623
|
-
selection: hasActiveSelection(update.state),
|
624
|
-
});
|
618
|
+
state.comment = selectionOverlapsComment(update.state);
|
619
|
+
state.selection = hasActiveSelection(update.state);
|
625
620
|
}
|
626
621
|
}),
|
627
|
-
[],
|
622
|
+
[state],
|
628
623
|
);
|
629
|
-
|
630
|
-
return [state, observer];
|
631
624
|
};
|
632
625
|
|
633
626
|
/**
|
@@ -73,7 +73,7 @@ class CheckboxWidget extends WidgetType {
|
|
73
73
|
|
74
74
|
override toDOM(view: EditorView) {
|
75
75
|
const input = document.createElement('input');
|
76
|
-
input.className = 'cm-task-checkbox
|
76
|
+
input.className = 'cm-task-checkbox dx-checkbox';
|
77
77
|
input.type = 'checkbox';
|
78
78
|
input.tabIndex = -1;
|
79
79
|
input.checked = this._checked;
|
@@ -4,6 +4,9 @@
|
|
4
4
|
|
5
5
|
import { type EditorView } from '@codemirror/view';
|
6
6
|
|
7
|
+
import { type Action } from '@dxos/app-graph';
|
8
|
+
import { type MenuActionProperties } from '@dxos/react-ui-menu';
|
9
|
+
|
7
10
|
import {
|
8
11
|
Inline,
|
9
12
|
List,
|
@@ -24,7 +27,7 @@ import {
|
|
24
27
|
} from './formatting';
|
25
28
|
import { createComment } from '../comments';
|
26
29
|
|
27
|
-
export type
|
30
|
+
export type PayloadType =
|
28
31
|
| 'view-mode'
|
29
32
|
| 'blockquote'
|
30
33
|
| 'strong'
|
@@ -44,18 +47,20 @@ export type ActionType =
|
|
44
47
|
| 'strikethrough'
|
45
48
|
| 'table';
|
46
49
|
|
47
|
-
export type
|
48
|
-
type:
|
50
|
+
export type EditorActionPayload = {
|
51
|
+
type: PayloadType;
|
49
52
|
data?: any;
|
50
53
|
};
|
51
54
|
|
52
|
-
export type
|
55
|
+
export type EditorAction = Action<MenuActionProperties & EditorActionPayload>;
|
56
|
+
|
57
|
+
export type EditorPayloadHandler = (view: EditorView, payload: EditorActionPayload) => void;
|
53
58
|
|
54
|
-
export const
|
59
|
+
export const processEditorPayload: EditorPayloadHandler = (view, { type, data }) => {
|
55
60
|
let inlineType, listType;
|
56
|
-
switch (
|
61
|
+
switch (type) {
|
57
62
|
case 'heading':
|
58
|
-
setHeading(parseInt(
|
63
|
+
setHeading(parseInt(data))(view);
|
59
64
|
break;
|
60
65
|
|
61
66
|
case 'strong':
|
@@ -63,42 +68,39 @@ export const processAction: ActionHandler = (view, action) => {
|
|
63
68
|
case 'strikethrough':
|
64
69
|
case 'code':
|
65
70
|
inlineType =
|
66
|
-
|
71
|
+
type === 'strong'
|
67
72
|
? Inline.Strong
|
68
|
-
:
|
73
|
+
: type === 'emphasis'
|
69
74
|
? Inline.Emphasis
|
70
|
-
:
|
75
|
+
: type === 'strikethrough'
|
71
76
|
? Inline.Strikethrough
|
72
77
|
: Inline.Code;
|
73
|
-
(typeof
|
78
|
+
(typeof data === 'boolean' ? setStyle(inlineType, data) : toggleStyle(inlineType))(view);
|
74
79
|
break;
|
75
80
|
|
76
81
|
case 'list-ordered':
|
77
82
|
case 'list-bullet':
|
78
83
|
case 'list-task':
|
79
|
-
listType =
|
80
|
-
|
81
|
-
(action.data === false ? removeList(listType) : action.data === true ? addList(listType) : toggleList(listType))(
|
82
|
-
view,
|
83
|
-
);
|
84
|
+
listType = type === 'list-ordered' ? List.Ordered : type === 'list-bullet' ? List.Bullet : List.Task;
|
85
|
+
(data === false ? removeList(listType) : data === true ? addList(listType) : toggleList(listType))(view);
|
84
86
|
break;
|
85
87
|
|
86
88
|
case 'blockquote':
|
87
|
-
(
|
89
|
+
(data === false ? removeBlockquote : data === true ? addBlockquote : toggleBlockquote)(view);
|
88
90
|
break;
|
89
91
|
case 'codeblock':
|
90
|
-
(
|
92
|
+
(data === false ? removeCodeblock : addCodeblock)(view);
|
91
93
|
break;
|
92
94
|
case 'table':
|
93
95
|
insertTable(view);
|
94
96
|
break;
|
95
97
|
|
96
98
|
case 'link':
|
97
|
-
(
|
99
|
+
(data === false ? removeLink : addLink())(view);
|
98
100
|
break;
|
99
101
|
|
100
102
|
case 'image':
|
101
|
-
addLink({ url:
|
103
|
+
addLink({ url: data, image: true })(view);
|
102
104
|
break;
|
103
105
|
|
104
106
|
case 'comment':
|
@@ -182,12 +182,13 @@ describe('removeStyle', () => {
|
|
182
182
|
|
183
183
|
testCommand('can remove code style', 'a `{variable}`', code, 'a {variable}');
|
184
184
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
185
|
+
// TODO(dmaretskyi): Flaky on CI: https://cloud.nx.app/runs/0byxg4Uq5G/task/react-ui-editor%3Atest
|
186
|
+
// testCommand(
|
187
|
+
// 'can remove emphasis across multiple blocks',
|
188
|
+
// '{*one*\n\n# *two*\n\n> 1. *three} four*\n',
|
189
|
+
// em,
|
190
|
+
// '{one\n\n# two\n\n> 1. three} *four*\n',
|
191
|
+
// );
|
191
192
|
|
192
193
|
testCommand('can shrink existing styles', '*one {two three} four*', em, '*one* {two three} *four*');
|
193
194
|
|
@@ -15,7 +15,11 @@ import {
|
|
15
15
|
} from '@codemirror/state';
|
16
16
|
import { EditorView, keymap } from '@codemirror/view';
|
17
17
|
import { type SyntaxNodeRef, type SyntaxNode } from '@lezer/common';
|
18
|
-
import { useMemo
|
18
|
+
import { useMemo } from 'react';
|
19
|
+
|
20
|
+
import { type ReactiveObject } from '@dxos/live-object';
|
21
|
+
|
22
|
+
import { type EditorToolbarState } from '../../components';
|
19
23
|
|
20
24
|
// Markdown refs:
|
21
25
|
// https://github.github.com/gfm
|
@@ -25,11 +29,11 @@ import { useMemo, useState } from 'react';
|
|
25
29
|
// For inline styles `strong`, `emphasis`, `strikethrough`, and `code`,
|
26
30
|
// the field only holds true when *all* selected text has the style,
|
27
31
|
// or when the selection is a cursor inside such a style.
|
28
|
-
export type Formatting = {
|
29
|
-
blankLine
|
32
|
+
export type Formatting = Partial<{
|
33
|
+
blankLine: boolean;
|
30
34
|
// The type of the block at the selection.
|
31
35
|
// If multiple different block types are selected, this will hold null.
|
32
|
-
blockType
|
36
|
+
blockType:
|
33
37
|
| 'codeblock'
|
34
38
|
| 'heading1'
|
35
39
|
| 'heading2'
|
@@ -41,20 +45,20 @@ export type Formatting = {
|
|
41
45
|
| 'tablecell'
|
42
46
|
| null;
|
43
47
|
// Whether all selected text is wrapped in a blockquote.
|
44
|
-
blockQuote
|
48
|
+
blockQuote: boolean;
|
45
49
|
// Whether the selected text is strong.
|
46
|
-
strong
|
50
|
+
strong: boolean;
|
47
51
|
// Whether the selected text is emphasized.
|
48
|
-
emphasis
|
52
|
+
emphasis: boolean;
|
49
53
|
// Whether the selected text is stricken through.
|
50
|
-
strikethrough
|
54
|
+
strikethrough: boolean;
|
51
55
|
// Whether the selected text is inline code.
|
52
|
-
code
|
56
|
+
code: boolean;
|
53
57
|
// Whether there are links in the selected text.
|
54
|
-
link
|
58
|
+
link: boolean;
|
55
59
|
// If all selected blocks have the same (innermost) list style, that is indicated here.
|
56
|
-
listStyle
|
57
|
-
}
|
60
|
+
listStyle: null | 'ordered' | 'bullet' | 'task';
|
61
|
+
}>;
|
58
62
|
|
59
63
|
export const formattingEquals = (a: Formatting, b: Formatting) =>
|
60
64
|
a.blockType === b.blockType &&
|
@@ -1246,24 +1250,16 @@ export const getFormatting = (state: EditorState): Formatting => {
|
|
1246
1250
|
/**
|
1247
1251
|
* Hook provides an extension to compute the current formatting state.
|
1248
1252
|
*/
|
1249
|
-
export const useFormattingState = ():
|
1250
|
-
|
1251
|
-
const observer = useMemo(
|
1253
|
+
export const useFormattingState = (state: ReactiveObject<EditorToolbarState>): Extension => {
|
1254
|
+
return useMemo(
|
1252
1255
|
() =>
|
1253
1256
|
EditorView.updateListener.of((update) => {
|
1254
1257
|
if (update.docChanged || update.selectionSet) {
|
1255
|
-
|
1256
|
-
|
1257
|
-
if (!prevState || !formattingEquals(prevState, newState)) {
|
1258
|
-
return newState;
|
1259
|
-
}
|
1260
|
-
|
1261
|
-
return prevState;
|
1258
|
+
Object.entries(getFormatting(update.state)).forEach(([key, active]) => {
|
1259
|
+
state[key as keyof Formatting] = active as any;
|
1262
1260
|
});
|
1263
1261
|
}
|
1264
1262
|
}),
|
1265
1263
|
[],
|
1266
1264
|
);
|
1267
|
-
|
1268
|
-
return [state, observer];
|
1269
1265
|
};
|
@@ -110,4 +110,25 @@ export const formattingStyles = EditorView.theme({
|
|
110
110
|
borderTop: '0.5rem solid transparent',
|
111
111
|
borderBottom: '0.5rem solid transparent',
|
112
112
|
},
|
113
|
+
'.cm-image-with-loader': {
|
114
|
+
display: 'block',
|
115
|
+
opacity: '0',
|
116
|
+
transitionDuration: '350ms',
|
117
|
+
transitionProperty: 'opacity',
|
118
|
+
},
|
119
|
+
'.cm-image-with-loader.cm-loaded-image': {
|
120
|
+
opacity: '1',
|
121
|
+
},
|
122
|
+
'.cm-image-wrapper': {
|
123
|
+
'grid-template-columns': '1fr',
|
124
|
+
display: 'grid',
|
125
|
+
margin: '0.5rem 0',
|
126
|
+
overflow: 'hidden',
|
127
|
+
transitionDuration: '350ms',
|
128
|
+
transitionProperty: 'height',
|
129
|
+
'& > *': {
|
130
|
+
'grid-row-start': 1,
|
131
|
+
'grid-column-start': 1,
|
132
|
+
},
|
133
|
+
},
|
113
134
|
});
|
@@ -3,10 +3,10 @@
|
|
3
3
|
//
|
4
4
|
|
5
5
|
import { type EditorView } from '@codemirror/view';
|
6
|
+
import { useCallback } from 'react';
|
6
7
|
|
7
|
-
import { type
|
8
|
-
import { processAction } from '../extensions';
|
8
|
+
import { type EditorAction, processEditorPayload } from '../extensions';
|
9
9
|
|
10
|
-
export const useActionHandler = (view?: EditorView | null)
|
11
|
-
return (action) => view &&
|
10
|
+
export const useActionHandler = (view?: EditorView | null) => {
|
11
|
+
return useCallback((action: EditorAction) => view && processEditorPayload(view, action.properties), [view]);
|
12
12
|
};
|
package/src/index.ts
CHANGED
@@ -14,6 +14,10 @@ export * from './components';
|
|
14
14
|
export * from './defaults';
|
15
15
|
export * from './extensions';
|
16
16
|
export * from './hooks';
|
17
|
+
export {
|
18
|
+
stackItemContentEditorClassNames,
|
19
|
+
stackItemContentToolbarClassNames,
|
20
|
+
} from './styles/stack-item-content-class-names';
|
17
21
|
export * from './types';
|
18
22
|
export * from './util';
|
19
23
|
|
package/src/styles/markdown.ts
CHANGED
@@ -0,0 +1,17 @@
|
|
1
|
+
//
|
2
|
+
// Copyright 2025 DXOS.org
|
3
|
+
//
|
4
|
+
|
5
|
+
import { mx } from '@dxos/react-ui-theme';
|
6
|
+
|
7
|
+
export const stackItemContentEditorClassNames = (role?: string) =>
|
8
|
+
mx(
|
9
|
+
'dx-focus-ring-inset data-[toolbar=disabled]:pbs-2 attention-surface',
|
10
|
+
role === 'article' ? 'min-bs-0' : '[&_.cm-scroller]:overflow-hidden [&_.cm-scroller]:min-bs-24',
|
11
|
+
);
|
12
|
+
|
13
|
+
export const stackItemContentToolbarClassNames = (role?: string) =>
|
14
|
+
mx(
|
15
|
+
'attention-surface is-full border-be !border-separator',
|
16
|
+
role === 'section' && 'sticky block-start-0 z-[1] -mbe-px min-is-0',
|
17
|
+
);
|
package/src/styles/theme.ts
CHANGED
@@ -1,34 +0,0 @@
|
|
1
|
-
import { type Icon } from '@phosphor-icons/react';
|
2
|
-
import React, { type PropsWithChildren } from 'react';
|
3
|
-
import { type ThemedClassName, type ToolbarToggleGroupItemProps as NaturalToolbarToggleGroupItemProps } from '@dxos/react-ui';
|
4
|
-
import { type EditorViewMode, type Action, type Formatting } from '../../extensions';
|
5
|
-
declare const useToolbarContext: (consumerName: string) => ToolbarProps;
|
6
|
-
export type ToolbarProps = ThemedClassName<PropsWithChildren<{
|
7
|
-
state: (Formatting & {
|
8
|
-
comment?: boolean;
|
9
|
-
mode?: EditorViewMode;
|
10
|
-
selection?: boolean;
|
11
|
-
}) | undefined;
|
12
|
-
onAction?: (action: Action) => void;
|
13
|
-
}>>;
|
14
|
-
type ToolbarToggleButtonProps = NaturalToolbarToggleGroupItemProps & {
|
15
|
-
Icon: Icon;
|
16
|
-
};
|
17
|
-
export type MarkdownCustomOptions = {
|
18
|
-
onUpload?: (file: File) => Promise<{
|
19
|
-
url?: string;
|
20
|
-
} | undefined>;
|
21
|
-
};
|
22
|
-
export declare const Toolbar: {
|
23
|
-
Root: ({ children, onAction, classNames, state }: ToolbarProps) => React.JSX.Element;
|
24
|
-
Button: ({ Icon, children, ...props }: ToolbarToggleButtonProps) => React.JSX.Element;
|
25
|
-
Separator: () => React.JSX.Element;
|
26
|
-
View: ({ mode }: {
|
27
|
-
mode: EditorViewMode;
|
28
|
-
}) => React.JSX.Element;
|
29
|
-
Markdown: () => React.JSX.Element;
|
30
|
-
Custom: ({ onUpload }?: MarkdownCustomOptions) => React.JSX.Element;
|
31
|
-
Actions: () => React.JSX.Element;
|
32
|
-
};
|
33
|
-
export { useToolbarContext };
|
34
|
-
//# sourceMappingURL=Toolbar.d.ts.map
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"Toolbar.d.ts","sourceRoot":"","sources":["../../../../../src/components/Toolbar/Toolbar.tsx"],"names":[],"mappings":"AAIA,OAAO,EACL,KAAK,IAAI,EA2BV,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,EAAE,KAAK,iBAAiB,EAA+B,MAAM,OAAO,CAAC;AAGnF,OAAO,EAML,KAAK,eAAe,EACpB,KAAK,2BAA2B,IAAI,kCAAkC,EAGvE,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,MAAM,EAAmB,KAAK,UAAU,EAAmB,MAAM,kBAAkB,CAAC;AAavH,QAAA,MAA+B,iBAAiB,wCAA0C,CAAC;AAE3F,MAAM,MAAM,YAAY,GAAG,eAAe,CACxC,iBAAiB,CAAC;IAChB,KAAK,EAAE,CAAC,UAAU,GAAG;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,cAAc,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,GAAG,SAAS,CAAC;IACpG,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC,CAAC,CACH,CAAC;AA4BF,KAAK,wBAAwB,GAAG,kCAAkC,GAAG;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,CAAC;AAyPpF,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC,CAAC;CAClE,CAAC;AAkKF,eAAO,MAAM,OAAO;sDAvb4C,YAAY;2CA4BjB,wBAAwB;;qBA6SnD;QAAE,IAAI,EAAE,cAAc,CAAA;KAAE;;4BAlDlB,qBAAqB;;CAwK1D,CAAC;AAEF,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/Toolbar/index.ts"],"names":[],"mappings":"AAIA,cAAc,WAAW,CAAC"}
|
@@ -1,9 +0,0 @@
|
|
1
|
-
import { type EditorView } from '@codemirror/view';
|
2
|
-
export type ActionType = 'view-mode' | 'blockquote' | 'strong' | 'codeblock' | 'comment' | 'heading' | 'image' | 'emphasis' | 'code' | 'link' | 'list-bullet' | 'list-ordered' | 'list-task' | 'mention' | 'prompt' | 'search' | 'strikethrough' | 'table';
|
3
|
-
export type Action = {
|
4
|
-
type: ActionType;
|
5
|
-
data?: any;
|
6
|
-
};
|
7
|
-
export type ActionHandler = (view: EditorView, action: Action) => void;
|
8
|
-
export declare const processAction: ActionHandler;
|
9
|
-
//# sourceMappingURL=action.d.ts.map
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"action.d.ts","sourceRoot":"","sources":["../../../../../src/extensions/markdown/action.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAsBnD,MAAM,MAAM,UAAU,GAClB,WAAW,GACX,YAAY,GACZ,QAAQ,GACR,WAAW,GACX,SAAS,GACT,SAAS,GACT,OAAO,GACP,UAAU,GACV,MAAM,GACN,MAAM,GACN,aAAa,GACb,cAAc,GACd,WAAW,GACX,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,eAAe,GACf,OAAO,CAAC;AAEZ,MAAM,MAAM,MAAM,GAAG;IACnB,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,CAAC,EAAE,GAAG,CAAC;CACZ,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;AAEvE,eAAO,MAAM,aAAa,EAAE,aA4D3B,CAAC"}
|