@dxos/react-ui-editor 0.3.11-main.69484a6 → 0.3.11-main.69d4f1c
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 +1183 -168
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/hooks.stories.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.d.ts +8 -4
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +5 -3
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts +5 -1
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/formatting.d.ts +54 -10
- package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/formatting.test.d.ts +3 -0
- package/dist/types/src/extensions/markdown/formatting.test.d.ts.map +1 -0
- package/dist/types/src/hooks/useActionHandler.d.ts.map +1 -1
- package/dist/types/src/hooks/useTextModel.d.ts +12 -0
- package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/themes/default.d.ts.map +1 -1
- package/package.json +24 -24
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +2 -2
- package/src/components/TextEditor/TextEditor.tsx +3 -4
- package/src/components/TextEditor/hooks.stories.tsx +6 -1
- package/src/components/Toolbar/Toolbar.stories.tsx +15 -3
- package/src/components/Toolbar/Toolbar.tsx +108 -29
- package/src/extensions/awareness.ts +4 -1
- package/src/extensions/blast.ts +4 -1
- package/src/extensions/comments.ts +14 -4
- package/src/extensions/markdown/formatting.test.ts +481 -0
- package/src/extensions/markdown/formatting.ts +1080 -70
- package/src/extensions/markdown/link.ts +8 -2
- package/src/hooks/useActionHandler.ts +47 -16
- package/src/hooks/useTextModel.ts +17 -1
- package/src/index.ts +1 -1
- package/src/themes/default.ts +7 -4
- package/dist/types/src/components/TextEditor/comments.stories.d.ts +0 -26
- package/dist/types/src/components/TextEditor/comments.stories.d.ts.map +0 -1
- package/src/components/TextEditor/comments.stories.tsx +0 -357
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/react-ui-editor",
|
|
3
|
-
"version": "0.3.11-main.
|
|
3
|
+
"version": "0.3.11-main.69d4f1c",
|
|
4
4
|
"description": "Document editing experience within a DXOS shell.",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"@codemirror/state": "^6.4.0",
|
|
24
24
|
"@codemirror/theme-one-dark": "^6.1.2",
|
|
25
25
|
"@codemirror/view": "^6.23.0",
|
|
26
|
-
"@fluentui/react-tabster": "^9.
|
|
26
|
+
"@fluentui/react-tabster": "^9.18.0",
|
|
27
27
|
"@lezer/common": "^1.2.1",
|
|
28
28
|
"@lezer/highlight": "^1.2.0",
|
|
29
29
|
"@lezer/markdown": "^1.2.0",
|
|
@@ -36,20 +36,20 @@
|
|
|
36
36
|
"lodash.pick": "^4.4.0",
|
|
37
37
|
"lodash.sortby": "^4.7.0",
|
|
38
38
|
"style-mod": "^4.1.0",
|
|
39
|
-
"@dxos/async": "0.3.11-main.
|
|
40
|
-
"@dxos/
|
|
41
|
-
"@dxos/
|
|
42
|
-
"@dxos/debug": "0.3.11-main.
|
|
43
|
-
"@dxos/
|
|
44
|
-
"@dxos/
|
|
45
|
-
"@dxos/invariant": "0.3.11-main.
|
|
46
|
-
"@dxos/log": "0.3.11-main.
|
|
47
|
-
"@dxos/
|
|
48
|
-
"@dxos/react-
|
|
49
|
-
"@dxos/
|
|
50
|
-
"@dxos/
|
|
51
|
-
"@dxos/
|
|
52
|
-
"@dxos/util": "0.3.11-main.
|
|
39
|
+
"@dxos/async": "0.3.11-main.69d4f1c",
|
|
40
|
+
"@dxos/automerge": "0.3.11-main.69d4f1c",
|
|
41
|
+
"@dxos/context": "0.3.11-main.69d4f1c",
|
|
42
|
+
"@dxos/debug": "0.3.11-main.69d4f1c",
|
|
43
|
+
"@dxos/display-name": "0.3.11-main.69d4f1c",
|
|
44
|
+
"@dxos/echo-schema": "0.3.11-main.69d4f1c",
|
|
45
|
+
"@dxos/invariant": "0.3.11-main.69d4f1c",
|
|
46
|
+
"@dxos/log": "0.3.11-main.69d4f1c",
|
|
47
|
+
"@dxos/react-async": "0.3.11-main.69d4f1c",
|
|
48
|
+
"@dxos/react-ui": "0.3.11-main.69d4f1c",
|
|
49
|
+
"@dxos/protocols": "0.3.11-main.69d4f1c",
|
|
50
|
+
"@dxos/text-model": "0.3.11-main.69d4f1c",
|
|
51
|
+
"@dxos/react-ui-theme": "0.3.11-main.69d4f1c",
|
|
52
|
+
"@dxos/util": "0.3.11-main.69d4f1c"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
55
|
"@automerge/automerge-repo-network-broadcastchannel": "^1.1.0",
|
|
@@ -77,19 +77,19 @@
|
|
|
77
77
|
"vite-plugin-top-level-await": "^1.4.1",
|
|
78
78
|
"vite-plugin-wasm": "^3.3.0",
|
|
79
79
|
"vitest": "^1.2.1",
|
|
80
|
-
"@dxos/config": "0.3.11-main.
|
|
81
|
-
"@dxos/echo-
|
|
82
|
-
"@dxos/
|
|
83
|
-
"@dxos/
|
|
84
|
-
"@dxos/react-client": "0.3.11-main.
|
|
85
|
-
"@dxos/
|
|
86
|
-
"@dxos/
|
|
80
|
+
"@dxos/config": "0.3.11-main.69d4f1c",
|
|
81
|
+
"@dxos/echo-signals": "0.3.11-main.69d4f1c",
|
|
82
|
+
"@dxos/echo-typegen": "0.3.11-main.69d4f1c",
|
|
83
|
+
"@dxos/keyboard": "0.3.11-main.69d4f1c",
|
|
84
|
+
"@dxos/react-client": "0.3.11-main.69d4f1c",
|
|
85
|
+
"@dxos/storybook-utils": "0.3.11-main.69d4f1c",
|
|
86
|
+
"@dxos/react-ui": "0.3.11-main.69d4f1c"
|
|
87
87
|
},
|
|
88
88
|
"peerDependencies": {
|
|
89
89
|
"@phosphor-icons/react": "^2.0.5",
|
|
90
90
|
"react": "^18.2.0",
|
|
91
91
|
"react-dom": "^18.2.0",
|
|
92
|
-
"@dxos/react-client": "0.3.11-main.
|
|
92
|
+
"@dxos/react-client": "0.3.11-main.69d4f1c"
|
|
93
93
|
},
|
|
94
94
|
"publishConfig": {
|
|
95
95
|
"access": "public"
|
|
@@ -350,9 +350,9 @@ export const Comments = {
|
|
|
350
350
|
extensions={[
|
|
351
351
|
comments({
|
|
352
352
|
onHover: onCommentsHover,
|
|
353
|
-
onCreate: (
|
|
353
|
+
onCreate: ({ cursor }) => {
|
|
354
354
|
const id = PublicKey.random().toHex();
|
|
355
|
-
setComments((commentRanges) => [...commentRanges, { id, cursor
|
|
355
|
+
setComments((commentRanges) => [...commentRanges, { id, cursor }]);
|
|
356
356
|
return id;
|
|
357
357
|
},
|
|
358
358
|
onSelect: (state) => {
|
|
@@ -20,7 +20,7 @@ import React, {
|
|
|
20
20
|
|
|
21
21
|
import { log } from '@dxos/log';
|
|
22
22
|
import { useThemeContext } from '@dxos/react-ui';
|
|
23
|
-
import {
|
|
23
|
+
import { focusRing, mx } from '@dxos/react-ui-theme';
|
|
24
24
|
import { isNotFalsy } from '@dxos/util';
|
|
25
25
|
|
|
26
26
|
import { createBasicBundle, createMarkdownExtensions } from '../../extensions';
|
|
@@ -258,11 +258,10 @@ export const MarkdownEditor = forwardRef<EditorView, TextEditorProps>(
|
|
|
258
258
|
|
|
259
259
|
export const defaultSlots: TextEditorSlots = {
|
|
260
260
|
root: {
|
|
261
|
-
|
|
262
|
-
className: mx('flex flex-col grow overflow-y-auto', attentionSurface),
|
|
261
|
+
className: mx('grow', focusRing),
|
|
263
262
|
},
|
|
264
263
|
editor: {
|
|
265
|
-
className: '
|
|
264
|
+
className: 'bs-full',
|
|
266
265
|
},
|
|
267
266
|
};
|
|
268
267
|
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
link,
|
|
22
22
|
table,
|
|
23
23
|
tasklist,
|
|
24
|
+
useFormattingState,
|
|
24
25
|
} from '../../extensions';
|
|
25
26
|
import { createDataExtensions, createThemeExtensions, useActionHandler, useTextEditor } from '../../hooks';
|
|
26
27
|
import { markdownTheme } from '../../themes';
|
|
@@ -41,6 +42,7 @@ type StoryProps = {
|
|
|
41
42
|
|
|
42
43
|
const Story = ({ autoFocus, placeholder, doc, readonly }: StoryProps) => {
|
|
43
44
|
const { themeMode } = useThemeContext();
|
|
45
|
+
const [formattingState, trackFormatting] = useFormattingState();
|
|
44
46
|
const { parentRef, view } = useTextEditor({
|
|
45
47
|
autoFocus,
|
|
46
48
|
doc,
|
|
@@ -69,16 +71,19 @@ const Story = ({ autoFocus, placeholder, doc, readonly }: StoryProps) => {
|
|
|
69
71
|
link(),
|
|
70
72
|
table(),
|
|
71
73
|
tasklist(),
|
|
74
|
+
trackFormatting,
|
|
72
75
|
],
|
|
73
76
|
});
|
|
74
77
|
|
|
75
78
|
const handleAction = useActionHandler(view);
|
|
76
79
|
|
|
80
|
+
// FIXME This doesn't update the state on view changes. Also not
|
|
81
|
+
// sure if view is even guaranteed to exist at this point.
|
|
77
82
|
return (
|
|
78
83
|
<div className={mx(fixedInsetFlexLayout, groupSurface)}>
|
|
79
84
|
<div className='flex h-full justify-center'>
|
|
80
85
|
<div className='flex flex-col h-full w-[800px]'>
|
|
81
|
-
<Toolbar.Root onAction={handleAction}>
|
|
86
|
+
<Toolbar.Root onAction={handleAction} state={formattingState}>
|
|
82
87
|
<Toolbar.Markdown />
|
|
83
88
|
</Toolbar.Root>
|
|
84
89
|
|
|
@@ -13,7 +13,17 @@ import { fixedInsetFlexLayout, groupSurface, mx } from '@dxos/react-ui-theme';
|
|
|
13
13
|
import { withTheme } from '@dxos/storybook-utils';
|
|
14
14
|
|
|
15
15
|
import { Toolbar } from './Toolbar';
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
code,
|
|
18
|
+
comments,
|
|
19
|
+
formatting,
|
|
20
|
+
heading,
|
|
21
|
+
image,
|
|
22
|
+
table,
|
|
23
|
+
tasklist,
|
|
24
|
+
useComments,
|
|
25
|
+
useFormattingState,
|
|
26
|
+
} from '../../extensions';
|
|
17
27
|
import { type Comment, useActionHandler, useEditorView, useTextModel } from '../../hooks';
|
|
18
28
|
import { MarkdownEditor } from '../TextEditor';
|
|
19
29
|
|
|
@@ -24,11 +34,12 @@ const Story: FC<{ content: string }> = ({ content }) => {
|
|
|
24
34
|
const [_comments, setComments] = useState<Comment[]>([]);
|
|
25
35
|
const [editorRef, editorView] = useEditorView();
|
|
26
36
|
const model = useTextModel({ text: item.text });
|
|
37
|
+
const [formattingState, formattingObserver] = useFormattingState();
|
|
27
38
|
const extensions = useMemo(
|
|
28
39
|
() => [
|
|
29
40
|
code(),
|
|
30
41
|
comments({
|
|
31
|
-
onCreate: (cursor) => {
|
|
42
|
+
onCreate: ({ cursor }) => {
|
|
32
43
|
const id = PublicKey.random().toHex();
|
|
33
44
|
setComments((comments) => [...comments, { id, cursor }]);
|
|
34
45
|
return id;
|
|
@@ -39,6 +50,7 @@ const Story: FC<{ content: string }> = ({ content }) => {
|
|
|
39
50
|
image(),
|
|
40
51
|
table(),
|
|
41
52
|
tasklist(),
|
|
53
|
+
formattingObserver,
|
|
42
54
|
],
|
|
43
55
|
[],
|
|
44
56
|
);
|
|
@@ -54,7 +66,7 @@ const Story: FC<{ content: string }> = ({ content }) => {
|
|
|
54
66
|
<div className={mx(fixedInsetFlexLayout, groupSurface)}>
|
|
55
67
|
<div className='flex h-full justify-center'>
|
|
56
68
|
<div className='flex flex-col h-full w-[800px]'>
|
|
57
|
-
<Toolbar.Root onAction={handleAction}>
|
|
69
|
+
<Toolbar.Root onAction={handleAction} state={formattingState}>
|
|
58
70
|
<Toolbar.Markdown />
|
|
59
71
|
<Toolbar.Separator />
|
|
60
72
|
<Toolbar.Extended />
|
|
@@ -4,15 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
import {
|
|
6
6
|
type Icon,
|
|
7
|
-
At,
|
|
8
7
|
CaretRight,
|
|
9
8
|
ChatText,
|
|
10
9
|
Code,
|
|
11
|
-
Image,
|
|
12
10
|
Link,
|
|
13
11
|
ListBullets,
|
|
14
12
|
ListChecks,
|
|
15
13
|
ListNumbers,
|
|
14
|
+
Paragraph,
|
|
16
15
|
TextStrikethrough,
|
|
17
16
|
Table,
|
|
18
17
|
TextB,
|
|
@@ -22,19 +21,22 @@ import { createContext } from '@radix-ui/react-context';
|
|
|
22
21
|
import React, { type PropsWithChildren } from 'react';
|
|
23
22
|
|
|
24
23
|
import { Button, type ButtonProps, DensityProvider, Select } from '@dxos/react-ui';
|
|
25
|
-
import { getSize } from '@dxos/react-ui-theme';
|
|
24
|
+
import { getSize, mx } from '@dxos/react-ui-theme';
|
|
25
|
+
|
|
26
|
+
import { type Formatting } from '../../extensions';
|
|
26
27
|
|
|
27
28
|
// TODO(burdon): Revert to string to make extensible?
|
|
28
29
|
export type ActionType =
|
|
29
30
|
| 'blockquote'
|
|
30
|
-
| '
|
|
31
|
+
| 'strong'
|
|
31
32
|
| 'codeblock'
|
|
32
33
|
| 'comment'
|
|
33
34
|
| 'heading'
|
|
34
35
|
| 'image'
|
|
35
|
-
| '
|
|
36
|
+
| 'emphasis'
|
|
37
|
+
| 'code'
|
|
36
38
|
| 'link'
|
|
37
|
-
| 'list'
|
|
39
|
+
| 'list-bullet'
|
|
38
40
|
| 'list-ordered'
|
|
39
41
|
| 'list-tasks'
|
|
40
42
|
| 'mention'
|
|
@@ -48,16 +50,17 @@ export type Action = {
|
|
|
48
50
|
};
|
|
49
51
|
|
|
50
52
|
export type ToolbarProps = PropsWithChildren<{
|
|
53
|
+
state: Formatting | null;
|
|
51
54
|
onAction?: (action: Action) => void;
|
|
52
55
|
}>;
|
|
53
56
|
|
|
54
57
|
const [ToolbarContextProvider, useToolbarContext] = createContext<ToolbarProps>('Toolbar');
|
|
55
58
|
|
|
56
|
-
const ToolbarRoot = ({ children, onAction }: ToolbarProps) => {
|
|
59
|
+
const ToolbarRoot = ({ children, onAction, state }: ToolbarProps) => {
|
|
57
60
|
return (
|
|
58
|
-
<ToolbarContextProvider onAction={onAction}>
|
|
61
|
+
<ToolbarContextProvider onAction={onAction} state={state}>
|
|
59
62
|
<DensityProvider density='fine'>
|
|
60
|
-
<div role='toolbar' className='flex w-full shrink-0 p-
|
|
63
|
+
<div role='toolbar' className='flex w-full shrink-0 p-1 gap-2 items-center whitespace-nowrap overflow-hidden'>
|
|
61
64
|
{children}
|
|
62
65
|
</div>
|
|
63
66
|
</DensityProvider>
|
|
@@ -67,20 +70,32 @@ const ToolbarRoot = ({ children, onAction }: ToolbarProps) => {
|
|
|
67
70
|
|
|
68
71
|
type ToolbarButtonProps = {
|
|
69
72
|
Icon: Icon;
|
|
70
|
-
|
|
73
|
+
disable?: (state: Formatting) => boolean;
|
|
74
|
+
getState?: (state: Formatting) => boolean;
|
|
75
|
+
onClick: (state: Formatting | null) => Action | undefined;
|
|
71
76
|
} & NonNullable<Pick<ButtonProps, 'title'>>;
|
|
72
77
|
|
|
73
|
-
const ToolbarButton = ({ Icon, onClick, title }: ToolbarButtonProps) => {
|
|
74
|
-
const { onAction } = useToolbarContext('ToolbarButton');
|
|
75
|
-
const
|
|
76
|
-
|
|
78
|
+
const ToolbarButton = ({ Icon, onClick, title, getState, disable }: ToolbarButtonProps) => {
|
|
79
|
+
const { onAction, state } = useToolbarContext('ToolbarButton');
|
|
80
|
+
const active = getState && state ? getState(state) : false;
|
|
81
|
+
const disabled = disable && state ? disable(state) : false;
|
|
82
|
+
|
|
83
|
+
const handleClick = (event: React.MouseEvent) => {
|
|
84
|
+
const action = onClick(state);
|
|
77
85
|
if (action) {
|
|
78
86
|
onAction?.(action);
|
|
87
|
+
event.preventDefault();
|
|
79
88
|
}
|
|
80
89
|
};
|
|
81
90
|
|
|
82
91
|
return (
|
|
83
|
-
<Button
|
|
92
|
+
<Button
|
|
93
|
+
variant='ghost'
|
|
94
|
+
classNames={mx('p-2', active && 'ring-[1px]')}
|
|
95
|
+
onMouseDown={handleClick}
|
|
96
|
+
title={title}
|
|
97
|
+
disabled={disabled}
|
|
98
|
+
>
|
|
84
99
|
<Icon className={getSize(5)} />
|
|
85
100
|
</Button>
|
|
86
101
|
);
|
|
@@ -89,10 +104,19 @@ const ToolbarButton = ({ Icon, onClick, title }: ToolbarButtonProps) => {
|
|
|
89
104
|
const ToolbarSeparator = () => <div className='grow' />;
|
|
90
105
|
|
|
91
106
|
const MarkdownHeading = () => {
|
|
92
|
-
const { onAction } = useToolbarContext('MarkdownFormatting');
|
|
107
|
+
const { onAction, state } = useToolbarContext('MarkdownFormatting');
|
|
108
|
+
const blockType = state ? state.blockType : 'paragraph';
|
|
109
|
+
const header = blockType && /heading(\d)/.exec(blockType);
|
|
110
|
+
const value = header ? header[1] : blockType === 'paragraph' || !blockType ? '0' : null;
|
|
93
111
|
return (
|
|
94
|
-
<Select.Root
|
|
95
|
-
|
|
112
|
+
<Select.Root
|
|
113
|
+
disabled={value === null}
|
|
114
|
+
value={value ?? '0'}
|
|
115
|
+
onValueChange={(value) => onAction?.({ type: 'heading', data: parseInt(value) })}
|
|
116
|
+
>
|
|
117
|
+
<Select.TriggerButton>
|
|
118
|
+
<Paragraph className={getSize(5)} />
|
|
119
|
+
</Select.TriggerButton>
|
|
96
120
|
<Select.Portal>
|
|
97
121
|
<Select.Content>
|
|
98
122
|
<Select.Viewport>
|
|
@@ -111,33 +135,88 @@ const MarkdownHeading = () => {
|
|
|
111
135
|
|
|
112
136
|
const MarkdownStyles = () => (
|
|
113
137
|
<div role='none'>
|
|
114
|
-
<ToolbarButton
|
|
115
|
-
|
|
116
|
-
|
|
138
|
+
<ToolbarButton
|
|
139
|
+
Icon={TextB}
|
|
140
|
+
title='String'
|
|
141
|
+
disable={(s) => s.blockType === 'codeblock'}
|
|
142
|
+
getState={(s) => s.strong}
|
|
143
|
+
onClick={(s) => ({ type: 'strong', data: s ? !s.strong : null })}
|
|
144
|
+
/>
|
|
145
|
+
<ToolbarButton
|
|
146
|
+
Icon={TextItalic}
|
|
147
|
+
title='Emphasis'
|
|
148
|
+
disable={(s) => s.blockType === 'codeblock'}
|
|
149
|
+
getState={(s) => s.emphasis}
|
|
150
|
+
onClick={(s) => ({ type: 'emphasis', data: s ? !s.emphasis : null })}
|
|
151
|
+
/>
|
|
152
|
+
<ToolbarButton
|
|
153
|
+
Icon={TextStrikethrough}
|
|
154
|
+
title='Strike-through'
|
|
155
|
+
disable={(s) => s.blockType === 'codeblock'}
|
|
156
|
+
getState={(s) => s.strikethrough}
|
|
157
|
+
onClick={(s) => ({ type: 'strikethrough', data: s ? !s.strikethrough : null })}
|
|
158
|
+
/>
|
|
159
|
+
<ToolbarButton
|
|
160
|
+
Icon={Code}
|
|
161
|
+
title='Inline code'
|
|
162
|
+
disable={(s) => s.blockType === 'codeblock'}
|
|
163
|
+
getState={(s) => s.code}
|
|
164
|
+
onClick={(s) => ({ type: 'code', data: s ? !s.code : null })}
|
|
165
|
+
/>
|
|
117
166
|
</div>
|
|
118
167
|
);
|
|
119
168
|
|
|
120
169
|
const MarkdownLists = () => (
|
|
121
170
|
<div role='none'>
|
|
122
|
-
<ToolbarButton
|
|
123
|
-
|
|
124
|
-
|
|
171
|
+
<ToolbarButton
|
|
172
|
+
Icon={ListBullets}
|
|
173
|
+
title='Bullet list'
|
|
174
|
+
getState={(s) => s.listStyle === 'bullet'}
|
|
175
|
+
onClick={(s) => ({ type: 'list-bullet', data: s ? s.listStyle !== 'bullet' : null })}
|
|
176
|
+
/>
|
|
177
|
+
<ToolbarButton
|
|
178
|
+
Icon={ListNumbers}
|
|
179
|
+
title='Numbered list'
|
|
180
|
+
getState={(s) => s.listStyle === 'ordered'}
|
|
181
|
+
onClick={(s) => ({ type: 'list-ordered', data: s ? s.listStyle !== 'ordered' : null })}
|
|
182
|
+
/>
|
|
183
|
+
<ToolbarButton
|
|
184
|
+
Icon={ListChecks}
|
|
185
|
+
title='Task list'
|
|
186
|
+
getState={(s) => s.listStyle === 'task'}
|
|
187
|
+
onClick={(s) => ({ type: 'list-tasks', data: s ? s.listStyle !== 'task' : null })}
|
|
188
|
+
/>
|
|
125
189
|
</div>
|
|
126
190
|
);
|
|
127
191
|
|
|
128
192
|
const MarkdownBlocks = () => (
|
|
129
193
|
<div role='none'>
|
|
130
|
-
<ToolbarButton
|
|
131
|
-
|
|
194
|
+
<ToolbarButton
|
|
195
|
+
Icon={CaretRight}
|
|
196
|
+
title='Block quote'
|
|
197
|
+
getState={(s) => s.blockquote}
|
|
198
|
+
onClick={(s) => ({ type: 'blockquote', data: s ? !s.blockquote : null })}
|
|
199
|
+
/>
|
|
200
|
+
<ToolbarButton
|
|
201
|
+
Icon={Code}
|
|
202
|
+
title='Code block'
|
|
203
|
+
getState={(s) => s.blockType === 'codeblock'}
|
|
204
|
+
onClick={(s) => ({ type: 'codeblock', data: s ? s.blockType !== 'codeblock' : null })}
|
|
205
|
+
/>
|
|
132
206
|
<ToolbarButton Icon={Table} title='Table' onClick={() => ({ type: 'table' })} />
|
|
133
207
|
</div>
|
|
134
208
|
);
|
|
135
209
|
|
|
136
210
|
const MarkdownLinks = () => (
|
|
137
211
|
<div role='none'>
|
|
138
|
-
<ToolbarButton
|
|
139
|
-
|
|
140
|
-
|
|
212
|
+
<ToolbarButton
|
|
213
|
+
Icon={Link}
|
|
214
|
+
title='Link'
|
|
215
|
+
getState={(s) => s.link}
|
|
216
|
+
onClick={(s) => ({ type: 'link', data: s ? !s.link : null })}
|
|
217
|
+
/>
|
|
218
|
+
{/* <ToolbarButton Icon={At} title='Mention' onClick={() => ({ type: 'mention' })} /> */}
|
|
219
|
+
{/* <ToolbarButton Icon={Image} title='Image' onClick={() => ({ type: 'image' })} /> */}
|
|
141
220
|
</div>
|
|
142
221
|
);
|
|
143
222
|
|
|
@@ -207,7 +207,10 @@ export class RemoteSelectionsDecorator implements PluginValue {
|
|
|
207
207
|
}
|
|
208
208
|
|
|
209
209
|
class RemoteCaretWidget extends WidgetType {
|
|
210
|
-
constructor(
|
|
210
|
+
constructor(
|
|
211
|
+
private readonly _name: string,
|
|
212
|
+
private readonly _color: string,
|
|
213
|
+
) {
|
|
211
214
|
super();
|
|
212
215
|
}
|
|
213
216
|
|
package/src/extensions/blast.ts
CHANGED
|
@@ -125,7 +125,10 @@ class Blaster {
|
|
|
125
125
|
|
|
126
126
|
_lastPoint = { x: 0, y: 0 };
|
|
127
127
|
|
|
128
|
-
constructor(
|
|
128
|
+
constructor(
|
|
129
|
+
private readonly _node: HTMLElement,
|
|
130
|
+
private readonly _options: BlastOptions,
|
|
131
|
+
) {
|
|
129
132
|
this._effect = this._options.effect === 1 ? new Effect1(_options) : new Effect2(_options);
|
|
130
133
|
}
|
|
131
134
|
|
|
@@ -18,12 +18,22 @@ import { callbackWrapper } from '../util';
|
|
|
18
18
|
|
|
19
19
|
// TODO(burdon): Reconcile with theme.
|
|
20
20
|
const styles = EditorView.baseTheme({
|
|
21
|
-
'& .cm-comment': {
|
|
21
|
+
'&light .cm-comment, &light .cm-comment-current': { mixBlendMode: 'darken' },
|
|
22
|
+
'&dark .cm-comment, &dark .cm-comment-current': { mixBlendMode: 'plus-lighter' },
|
|
23
|
+
'&light .cm-comment': {
|
|
22
24
|
backgroundColor: getToken('extend.colors.yellow.50'),
|
|
23
25
|
},
|
|
24
|
-
'& .cm-comment-current': {
|
|
26
|
+
'&light .cm-comment-current': {
|
|
25
27
|
backgroundColor: getToken('extend.colors.yellow.100'),
|
|
26
28
|
},
|
|
29
|
+
'&dark .cm-comment': {
|
|
30
|
+
color: getToken('extend.colors.yellow.50'),
|
|
31
|
+
backgroundColor: getToken('extend.colors.yellow.900'),
|
|
32
|
+
},
|
|
33
|
+
'&dark .cm-comment-current': {
|
|
34
|
+
color: getToken('extend.colors.yellow.100'),
|
|
35
|
+
backgroundColor: getToken('extend.colors.yellow.950'),
|
|
36
|
+
},
|
|
27
37
|
});
|
|
28
38
|
|
|
29
39
|
const commentMark = Decoration.mark({ class: 'cm-comment' });
|
|
@@ -146,7 +156,7 @@ export type CommentsOptions = {
|
|
|
146
156
|
/**
|
|
147
157
|
* Called to create a new thread and return the thread id.
|
|
148
158
|
*/
|
|
149
|
-
onCreate?: (cursor: string
|
|
159
|
+
onCreate?: (params: { cursor: string; from: number; location?: Rect | null }) => string | undefined;
|
|
150
160
|
/**
|
|
151
161
|
* Selection cut/deleted.
|
|
152
162
|
*/
|
|
@@ -306,7 +316,7 @@ export const createComment: Command = (view) => {
|
|
|
306
316
|
const cursor = Cursor.getCursorFromRange(view.state, { from, to });
|
|
307
317
|
if (cursor) {
|
|
308
318
|
// Create thread via callback.
|
|
309
|
-
const id = options.onCreate?.(cursor, view.coordsAtPos(from));
|
|
319
|
+
const id = options.onCreate?.({ cursor, from, location: view.coordsAtPos(from) });
|
|
310
320
|
if (id) {
|
|
311
321
|
// Update range.
|
|
312
322
|
view.dispatch({
|