@eventuras/scribo 0.8.3 → 0.10.7
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/App.d.ts +11 -0
- package/dist/App.d.ts.map +1 -0
- package/dist/MarkdownEditor.d.ts +18 -0
- package/dist/MarkdownEditor.d.ts.map +1 -0
- package/dist/MarkdownEditor2.js +111 -0
- package/dist/MarkdownEditor2.js.map +1 -0
- package/dist/MarkdownInput.d.ts +27 -0
- package/dist/MarkdownInput.d.ts.map +1 -0
- package/dist/MarkdownInput.js +57 -0
- package/dist/MarkdownInput.js.map +1 -0
- package/dist/callout.js +5 -0
- package/dist/context/SharedHistoryContext.d.ts +11 -0
- package/dist/context/SharedHistoryContext.d.ts.map +1 -0
- package/dist/context/SharedHistoryContext.js +12 -0
- package/dist/context/SharedHistoryContext.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/main.d.ts +5 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +4 -0
- package/dist/nodes/EditorNodes.d.ts +4 -0
- package/dist/nodes/EditorNodes.d.ts.map +1 -0
- package/dist/nodes/EditorNodes.js +39 -0
- package/dist/nodes/EditorNodes.js.map +1 -0
- package/dist/nodes/callout/CalloutComponent.d.ts +6 -0
- package/dist/nodes/callout/CalloutComponent.d.ts.map +1 -0
- package/dist/nodes/callout/CalloutComponent.js +53 -0
- package/dist/nodes/callout/CalloutComponent.js.map +1 -0
- package/dist/nodes/callout/CalloutNode.d.ts +27 -0
- package/dist/nodes/callout/CalloutNode.d.ts.map +1 -0
- package/dist/nodes/callout/CalloutNode.js +153 -0
- package/dist/nodes/callout/CalloutNode.js.map +1 -0
- package/dist/nodes/callout/CalloutTransformer.d.ts +3 -0
- package/dist/nodes/callout/CalloutTransformer.d.ts.map +1 -0
- package/dist/nodes/callout/CalloutTransformer.js +48 -0
- package/dist/nodes/callout/CalloutTransformer.js.map +1 -0
- package/dist/nodes/callout/calloutPlugin.d.ts +3 -0
- package/dist/nodes/callout/calloutPlugin.d.ts.map +1 -0
- package/dist/nodes/callout/calloutPlugin.js +34 -0
- package/dist/nodes/callout/calloutPlugin.js.map +1 -0
- package/dist/nodes/callout/index.d.ts +6 -0
- package/dist/nodes/callout/index.d.ts.map +1 -0
- package/dist/nodes/schedule/ScheduleItemComponent.d.ts +9 -0
- package/dist/nodes/schedule/ScheduleItemComponent.d.ts.map +1 -0
- package/dist/nodes/schedule/ScheduleItemComponent.js +167 -0
- package/dist/nodes/schedule/ScheduleItemComponent.js.map +1 -0
- package/dist/nodes/schedule/ScheduleItemNode.d.ts +31 -0
- package/dist/nodes/schedule/ScheduleItemNode.d.ts.map +1 -0
- package/dist/nodes/schedule/ScheduleItemNode.js +94 -0
- package/dist/nodes/schedule/ScheduleItemNode.js.map +1 -0
- package/dist/nodes/schedule/ScheduleTransformer.d.ts +22 -0
- package/dist/nodes/schedule/ScheduleTransformer.d.ts.map +1 -0
- package/dist/nodes/schedule/ScheduleTransformer.js +60 -0
- package/dist/nodes/schedule/ScheduleTransformer.js.map +1 -0
- package/dist/nodes/schedule/index.d.ts +5 -0
- package/dist/nodes/schedule/index.d.ts.map +1 -0
- package/dist/nodes/schedule/schedulePlugin.d.ts +3 -0
- package/dist/nodes/schedule/schedulePlugin.d.ts.map +1 -0
- package/dist/nodes/schedule/schedulePlugin.js +33 -0
- package/dist/nodes/schedule/schedulePlugin.js.map +1 -0
- package/dist/plugins/AutoLinkPlugin.d.ts +3 -0
- package/dist/plugins/AutoLinkPlugin.d.ts.map +1 -0
- package/dist/plugins/AutoLinkPlugin.js +22 -0
- package/dist/plugins/AutoLinkPlugin.js.map +1 -0
- package/dist/plugins/FloatingLinkEditorPlugin.d.ts +7 -0
- package/dist/plugins/FloatingLinkEditorPlugin.d.ts.map +1 -0
- package/dist/plugins/FloatingLinkEditorPlugin2.js +302 -0
- package/dist/plugins/FloatingLinkEditorPlugin2.js.map +1 -0
- package/dist/plugins/HistoryPlugin.d.ts +26 -0
- package/dist/plugins/HistoryPlugin.d.ts.map +1 -0
- package/dist/plugins/LinkPlugin.d.ts +3 -0
- package/dist/plugins/LinkPlugin.d.ts.map +1 -0
- package/dist/plugins/LinkPlugin.js +18 -0
- package/dist/plugins/LinkPlugin.js.map +1 -0
- package/dist/plugins/ToolbarPlugin.d.ts +7 -0
- package/dist/plugins/ToolbarPlugin.d.ts.map +1 -0
- package/dist/plugins/ToolbarPlugin.js +372 -0
- package/dist/plugins/ToolbarPlugin.js.map +1 -0
- package/dist/schedule.js +4 -0
- package/dist/scribo.css +1977 -0
- package/dist/themes/EditorTheme.d.ts +4 -0
- package/dist/themes/EditorTheme.d.ts.map +1 -0
- package/dist/themes/EditorTheme2.js +107 -0
- package/dist/themes/EditorTheme2.js.map +1 -0
- package/dist/types.d.ts +26 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/ui/ContentEditable.d.ts +6 -0
- package/dist/ui/ContentEditable.d.ts.map +1 -0
- package/dist/ui/ContentEditable2.js +14 -0
- package/dist/ui/ContentEditable2.js.map +1 -0
- package/dist/ui/DropDown.d.ts +18 -0
- package/dist/ui/DropDown.d.ts.map +1 -0
- package/dist/ui/DropDown.js +162 -0
- package/dist/ui/DropDown.js.map +1 -0
- package/dist/ui/Placeholder.d.ts +6 -0
- package/dist/ui/Placeholder.d.ts.map +1 -0
- package/dist/ui/Placeholder2.js +13 -0
- package/dist/ui/Placeholder2.js.map +1 -0
- package/dist/utils/environment.d.ts +24 -0
- package/dist/utils/environment.d.ts.map +1 -0
- package/dist/utils/environment.js +20 -0
- package/dist/utils/environment.js.map +1 -0
- package/dist/utils/getSelectedNode.d.ts +3 -0
- package/dist/utils/getSelectedNode.d.ts.map +1 -0
- package/dist/utils/getSelectedNode.js +23 -0
- package/dist/utils/getSelectedNode.js.map +1 -0
- package/dist/utils/setFloatingElemPosition.d.ts +2 -0
- package/dist/utils/setFloatingElemPosition.d.ts.map +1 -0
- package/dist/utils/setFloatingElemPositionForLinkEditor.d.ts +2 -0
- package/dist/utils/setFloatingElemPositionForLinkEditor.d.ts.map +1 -0
- package/dist/utils/setFloatingElemPositionForLinkEditor.js +33 -0
- package/dist/utils/setFloatingElemPositionForLinkEditor.js.map +1 -0
- package/dist/utils/url.d.ts +11 -0
- package/dist/utils/url.d.ts.map +1 -0
- package/dist/utils/url.js +33 -0
- package/dist/utils/url.js.map +1 -0
- package/dist/vite.svg +1 -0
- package/package.json +55 -38
- package/src/MarkdownEditor.css +61 -47
- package/src/MarkdownEditor.tsx +76 -29
- package/src/MarkdownInput.tsx +9 -10
- package/src/context/SharedHistoryContext.tsx +8 -16
- package/src/main.tsx +3 -3
- package/src/nodes/EditorNodes.ts +10 -10
- package/src/nodes/callout/Callout.css +94 -0
- package/src/nodes/callout/CalloutComponent.tsx +61 -0
- package/src/nodes/callout/CalloutNode.ts +197 -0
- package/src/nodes/callout/CalloutTransformer.ts +87 -0
- package/src/nodes/callout/calloutPlugin.ts +37 -0
- package/src/nodes/callout/index.ts +5 -0
- package/src/nodes/schedule/ScheduleItem.css +140 -0
- package/src/nodes/schedule/ScheduleItemComponent.tsx +195 -0
- package/src/nodes/schedule/ScheduleItemNode.ts +135 -0
- package/src/nodes/schedule/ScheduleTransformer.ts +80 -0
- package/src/nodes/schedule/index.ts +4 -0
- package/src/nodes/schedule/schedulePlugin.ts +33 -0
- package/src/plugins/AutoLinkPlugin.tsx +5 -10
- package/src/plugins/FloatingLinkEditorPlugin.tsx +42 -66
- package/src/plugins/HistoryPlugin.tsx +20 -30
- package/src/plugins/LinkPlugin.tsx +2 -3
- package/src/plugins/ToolbarPlugin.tsx +129 -141
- package/src/themes/EditorTheme.css +9 -5
- package/src/themes/EditorTheme.ts +89 -90
- package/src/types.ts +27 -0
- package/src/ui/ContentEditable.tsx +5 -5
- package/src/ui/DropDown.tsx +23 -41
- package/src/ui/Placeholder.tsx +21 -21
- package/src/utils/environment.ts +6 -12
- package/src/utils/getSelectedNode.ts +3 -5
- package/src/utils/setFloatingElemPosition.ts +2 -5
- package/src/utils/setFloatingElemPositionForLinkEditor.ts +1 -1
- package/src/utils/url.ts +4 -10
- package/tsconfig.json +8 -0
- package/CHANGELOG.md +0 -65
- package/README.md +0 -126
- package/RELEASE.md +0 -102
- package/eslint.config.js +0 -4
- package/src/App.css +0 -35
- package/src/App.tsx +0 -42
- package/src/index.tsx +0 -13
- package/tsconfig.node.json +0 -11
- package/vite.config.site.ts +0 -19
- package/vite.config.ts +0 -33
- /package/{src → dist}/vite-env.d.ts +0 -0
|
@@ -16,27 +16,23 @@ import {
|
|
|
16
16
|
CODE_LANGUAGE_MAP,
|
|
17
17
|
getLanguageFriendlyName,
|
|
18
18
|
} from '@lexical/code';
|
|
19
|
-
import { $isLinkNode, TOGGLE_LINK_COMMAND } from
|
|
19
|
+
import { $isLinkNode, TOGGLE_LINK_COMMAND } from '@lexical/link';
|
|
20
20
|
import {
|
|
21
21
|
$isListNode,
|
|
22
22
|
INSERT_ORDERED_LIST_COMMAND,
|
|
23
23
|
INSERT_UNORDERED_LIST_COMMAND,
|
|
24
24
|
ListNode,
|
|
25
25
|
REMOVE_LIST_COMMAND,
|
|
26
|
-
} from
|
|
26
|
+
} from '@lexical/list';
|
|
27
27
|
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
|
|
28
28
|
import {
|
|
29
29
|
$createHeadingNode,
|
|
30
30
|
$createQuoteNode,
|
|
31
31
|
$isHeadingNode,
|
|
32
|
-
HeadingTagType,
|
|
33
|
-
} from
|
|
34
|
-
import { $setBlocksType } from
|
|
35
|
-
import {
|
|
36
|
-
$findMatchingParent,
|
|
37
|
-
$getNearestNodeOfType,
|
|
38
|
-
mergeRegister,
|
|
39
|
-
} from "@lexical/utils";
|
|
32
|
+
type HeadingTagType,
|
|
33
|
+
} from '@lexical/rich-text';
|
|
34
|
+
import { $setBlocksType } from '@lexical/selection';
|
|
35
|
+
import { $findMatchingParent, $getNearestNodeOfType, mergeRegister } from '@lexical/utils';
|
|
40
36
|
import {
|
|
41
37
|
$createParagraphNode,
|
|
42
38
|
$getNodeByKey,
|
|
@@ -49,39 +45,37 @@ import {
|
|
|
49
45
|
COMMAND_PRIORITY_NORMAL,
|
|
50
46
|
FORMAT_TEXT_COMMAND,
|
|
51
47
|
KEY_MODIFIER_COMMAND,
|
|
52
|
-
LexicalEditor,
|
|
53
|
-
NodeKey,
|
|
48
|
+
type LexicalEditor,
|
|
49
|
+
type NodeKey,
|
|
54
50
|
REDO_COMMAND,
|
|
55
51
|
SELECTION_CHANGE_COMMAND,
|
|
56
52
|
UNDO_COMMAND,
|
|
57
53
|
} from 'lexical';
|
|
58
|
-
import {
|
|
59
|
-
import type
|
|
60
|
-
|
|
61
|
-
import DropDown, { DropDownItem } from
|
|
62
|
-
import { IS_APPLE } from
|
|
63
|
-
import { getSelectedNode } from
|
|
64
|
-
import { sanitizeUrl } from
|
|
54
|
+
import type { JSX } from 'react';
|
|
55
|
+
import { type Dispatch, useCallback, useEffect, useState } from 'react';
|
|
56
|
+
import type { ScriboToolbarButton } from '../types';
|
|
57
|
+
import DropDown, { DropDownItem } from '../ui/DropDown';
|
|
58
|
+
import { IS_APPLE } from '../utils/environment';
|
|
59
|
+
import { getSelectedNode } from '../utils/getSelectedNode';
|
|
60
|
+
import { sanitizeUrl } from '../utils/url';
|
|
65
61
|
|
|
66
62
|
const blockTypeToBlockName = {
|
|
67
|
-
paragraph:
|
|
68
|
-
h1:
|
|
69
|
-
h2:
|
|
70
|
-
h3:
|
|
71
|
-
h4:
|
|
72
|
-
bullet:
|
|
73
|
-
check:
|
|
74
|
-
code:
|
|
75
|
-
number:
|
|
76
|
-
quote:
|
|
63
|
+
paragraph: 'Normal',
|
|
64
|
+
h1: 'Heading 1',
|
|
65
|
+
h2: 'Heading 2',
|
|
66
|
+
h3: 'Heading 3',
|
|
67
|
+
h4: 'Heading 4',
|
|
68
|
+
bullet: 'Bulleted List',
|
|
69
|
+
check: 'Check List',
|
|
70
|
+
code: 'Code Block',
|
|
71
|
+
number: 'Numbered List',
|
|
72
|
+
quote: 'Quote',
|
|
77
73
|
};
|
|
78
74
|
|
|
79
75
|
function getCodeLanguageOptions(): [string, string][] {
|
|
80
76
|
const options: [string, string][] = [];
|
|
81
77
|
|
|
82
|
-
for (const [lang, friendlyName] of Object.entries(
|
|
83
|
-
CODE_LANGUAGE_FRIENDLY_NAME_MAP,
|
|
84
|
-
)) {
|
|
78
|
+
for (const [lang, friendlyName] of Object.entries(CODE_LANGUAGE_FRIENDLY_NAME_MAP)) {
|
|
85
79
|
options.push([lang, friendlyName]);
|
|
86
80
|
}
|
|
87
81
|
|
|
@@ -91,41 +85,41 @@ function getCodeLanguageOptions(): [string, string][] {
|
|
|
91
85
|
const CODE_LANGUAGE_OPTIONS = getCodeLanguageOptions();
|
|
92
86
|
|
|
93
87
|
function dropDownActiveClass(active: boolean) {
|
|
94
|
-
if (active) return
|
|
95
|
-
else return
|
|
88
|
+
if (active) return 'active dropdown-item-active';
|
|
89
|
+
else return '';
|
|
96
90
|
}
|
|
97
91
|
|
|
98
92
|
function BlockFormatDropDown({
|
|
99
93
|
editor,
|
|
100
94
|
blockType,
|
|
101
95
|
disabled = false,
|
|
102
|
-
}: {
|
|
96
|
+
}: Readonly<{
|
|
103
97
|
blockType: keyof typeof blockTypeToBlockName;
|
|
104
98
|
editor: LexicalEditor;
|
|
105
99
|
disabled?: boolean;
|
|
106
|
-
}): JSX.Element {
|
|
107
|
-
|
|
108
|
-
editor.update(() => {
|
|
109
|
-
const selection = $getSelection();
|
|
110
|
-
if ($isRangeSelection(selection)) {
|
|
111
|
-
$setBlocksType(selection, () => $createParagraphNode());
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
const formatHeading = (headingSize: HeadingTagType) => {
|
|
117
|
-
if (blockType !== headingSize) {
|
|
100
|
+
}>): JSX.Element {
|
|
101
|
+
const formatParagraph = () => {
|
|
118
102
|
editor.update(() => {
|
|
119
103
|
const selection = $getSelection();
|
|
120
104
|
if ($isRangeSelection(selection)) {
|
|
121
|
-
$setBlocksType(selection, () => $
|
|
105
|
+
$setBlocksType(selection, () => $createParagraphNode());
|
|
122
106
|
}
|
|
123
107
|
});
|
|
124
|
-
}
|
|
125
|
-
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const formatHeading = (headingSize: HeadingTagType) => {
|
|
111
|
+
if (blockType !== headingSize) {
|
|
112
|
+
editor.update(() => {
|
|
113
|
+
const selection = $getSelection();
|
|
114
|
+
if ($isRangeSelection(selection)) {
|
|
115
|
+
$setBlocksType(selection, () => $createHeadingNode(headingSize));
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
};
|
|
126
120
|
|
|
127
121
|
const formatBulletList = () => {
|
|
128
|
-
if (blockType !==
|
|
122
|
+
if (blockType !== 'bullet') {
|
|
129
123
|
editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND, undefined);
|
|
130
124
|
} else {
|
|
131
125
|
editor.dispatchCommand(REMOVE_LIST_COMMAND, undefined);
|
|
@@ -133,25 +127,25 @@ const formatHeading = (headingSize: HeadingTagType) => {
|
|
|
133
127
|
};
|
|
134
128
|
|
|
135
129
|
const formatNumberedList = () => {
|
|
136
|
-
if (blockType !==
|
|
130
|
+
if (blockType !== 'number') {
|
|
137
131
|
editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, undefined);
|
|
138
132
|
} else {
|
|
139
133
|
editor.dispatchCommand(REMOVE_LIST_COMMAND, undefined);
|
|
140
134
|
}
|
|
141
135
|
};
|
|
142
136
|
|
|
143
|
-
const formatQuote = () => {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
};
|
|
137
|
+
const formatQuote = () => {
|
|
138
|
+
if (blockType !== 'quote') {
|
|
139
|
+
editor.update(() => {
|
|
140
|
+
const selection = $getSelection();
|
|
141
|
+
if ($isRangeSelection(selection)) {
|
|
142
|
+
$setBlocksType(selection, () => $createQuoteNode());
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
};
|
|
153
147
|
|
|
154
|
-
|
|
148
|
+
const formatCode = () => {
|
|
155
149
|
if (blockType !== 'code') {
|
|
156
150
|
editor.update(() => {
|
|
157
151
|
let selection = $getSelection();
|
|
@@ -177,61 +171,61 @@ const formatQuote = () => {
|
|
|
177
171
|
<DropDown
|
|
178
172
|
disabled={disabled}
|
|
179
173
|
buttonClassName="toolbar-item block-controls"
|
|
180
|
-
buttonIconClassName={
|
|
174
|
+
buttonIconClassName={'icon block-type ' + blockType}
|
|
181
175
|
buttonLabel={blockTypeToBlockName[blockType]}
|
|
182
176
|
buttonAriaLabel="Formatting options for text style"
|
|
183
177
|
>
|
|
184
178
|
<DropDownItem
|
|
185
|
-
className={
|
|
179
|
+
className={'item ' + dropDownActiveClass(blockType === 'paragraph')}
|
|
186
180
|
onClick={formatParagraph}
|
|
187
181
|
>
|
|
188
182
|
<i className="icon paragraph" />
|
|
189
183
|
<span className="text">Normal</span>
|
|
190
184
|
</DropDownItem>
|
|
191
185
|
<DropDownItem
|
|
192
|
-
className={
|
|
193
|
-
onClick={() => formatHeading(
|
|
186
|
+
className={'item ' + dropDownActiveClass(blockType === 'h1')}
|
|
187
|
+
onClick={() => formatHeading('h1')}
|
|
194
188
|
>
|
|
195
189
|
<i className="icon h1" />
|
|
196
190
|
<span className="text">Heading 1</span>
|
|
197
191
|
</DropDownItem>
|
|
198
192
|
<DropDownItem
|
|
199
|
-
className={
|
|
200
|
-
onClick={() => formatHeading(
|
|
193
|
+
className={'item ' + dropDownActiveClass(blockType === 'h2')}
|
|
194
|
+
onClick={() => formatHeading('h2')}
|
|
201
195
|
>
|
|
202
196
|
<i className="icon h2" />
|
|
203
197
|
<span className="text">Heading 2</span>
|
|
204
198
|
</DropDownItem>
|
|
205
199
|
<DropDownItem
|
|
206
|
-
className={
|
|
207
|
-
onClick={() => formatHeading(
|
|
200
|
+
className={'item ' + dropDownActiveClass(blockType === 'h3')}
|
|
201
|
+
onClick={() => formatHeading('h3')}
|
|
208
202
|
>
|
|
209
203
|
<i className="icon h3" />
|
|
210
204
|
<span className="text">Heading 3</span>
|
|
211
205
|
</DropDownItem>
|
|
212
206
|
<DropDownItem
|
|
213
|
-
className={
|
|
214
|
-
onClick={() => formatHeading(
|
|
207
|
+
className={'item ' + dropDownActiveClass(blockType === 'h4')}
|
|
208
|
+
onClick={() => formatHeading('h4')}
|
|
215
209
|
>
|
|
216
210
|
<i className="icon h4" />
|
|
217
211
|
<span className="text">Heading 4</span>
|
|
218
212
|
</DropDownItem>
|
|
219
213
|
<DropDownItem
|
|
220
|
-
className={
|
|
214
|
+
className={'item ' + dropDownActiveClass(blockType === 'bullet')}
|
|
221
215
|
onClick={formatBulletList}
|
|
222
216
|
>
|
|
223
217
|
<i className="icon bullet-list" />
|
|
224
218
|
<span className="text">Bullet List</span>
|
|
225
219
|
</DropDownItem>
|
|
226
220
|
<DropDownItem
|
|
227
|
-
className={
|
|
221
|
+
className={'item ' + dropDownActiveClass(blockType === 'number')}
|
|
228
222
|
onClick={formatNumberedList}
|
|
229
223
|
>
|
|
230
224
|
<i className="icon numbered-list" />
|
|
231
225
|
<span className="text">Numbered List</span>
|
|
232
226
|
</DropDownItem>
|
|
233
227
|
<DropDownItem
|
|
234
|
-
className={
|
|
228
|
+
className={'item ' + dropDownActiveClass(blockType === 'quote')}
|
|
235
229
|
onClick={formatQuote}
|
|
236
230
|
>
|
|
237
231
|
<i className="icon quote" />
|
|
@@ -239,7 +233,8 @@ const formatQuote = () => {
|
|
|
239
233
|
</DropDownItem>
|
|
240
234
|
<DropDownItem
|
|
241
235
|
className={'item ' + dropDownActiveClass(blockType === 'code')}
|
|
242
|
-
onClick={formatCode}
|
|
236
|
+
onClick={formatCode}
|
|
237
|
+
>
|
|
243
238
|
<i className="icon code" />
|
|
244
239
|
<span className="text">Code Block</span>
|
|
245
240
|
</DropDownItem>
|
|
@@ -253,23 +248,22 @@ function Divider(): JSX.Element {
|
|
|
253
248
|
|
|
254
249
|
export default function ToolbarPlugin({
|
|
255
250
|
setIsLinkEditMode,
|
|
256
|
-
|
|
251
|
+
toolbarButtons = [],
|
|
252
|
+
}: Readonly<{
|
|
257
253
|
setIsLinkEditMode: Dispatch<boolean>;
|
|
258
|
-
|
|
254
|
+
toolbarButtons?: ScriboToolbarButton[];
|
|
255
|
+
}>): JSX.Element {
|
|
259
256
|
const [editor] = useLexicalComposerContext();
|
|
260
257
|
const [activeEditor, setActiveEditor] = useState(editor);
|
|
261
|
-
const [blockType, setBlockType] =
|
|
262
|
-
|
|
263
|
-
const [
|
|
264
|
-
null,
|
|
265
|
-
);
|
|
266
|
-
const [isCode, setIsCode] = useState(false);
|
|
258
|
+
const [blockType, setBlockType] = useState<keyof typeof blockTypeToBlockName>('paragraph');
|
|
259
|
+
const [selectedElementKey, setSelectedElementKey] = useState<NodeKey | null>(null);
|
|
260
|
+
const [_isCode, setIsCode] = useState(false);
|
|
267
261
|
const [isLink, setIsLink] = useState(false);
|
|
268
262
|
const [isBold, setIsBold] = useState(false);
|
|
269
263
|
const [isItalic, setIsItalic] = useState(false);
|
|
270
264
|
const [canUndo, setCanUndo] = useState(false);
|
|
271
265
|
const [canRedo, setCanRedo] = useState(false);
|
|
272
|
-
const [codeLanguage, setCodeLanguage] = useState<string>(
|
|
266
|
+
const [codeLanguage, setCodeLanguage] = useState<string>('');
|
|
273
267
|
const [isEditable, setIsEditable] = useState(() => editor.isEditable());
|
|
274
268
|
|
|
275
269
|
const $updateToolbar = useCallback(() => {
|
|
@@ -277,7 +271,7 @@ export default function ToolbarPlugin({
|
|
|
277
271
|
if ($isRangeSelection(selection)) {
|
|
278
272
|
const anchorNode = selection.anchor.getNode();
|
|
279
273
|
let element =
|
|
280
|
-
anchorNode.getKey() ===
|
|
274
|
+
anchorNode.getKey() === 'root'
|
|
281
275
|
? anchorNode
|
|
282
276
|
: $findMatchingParent(anchorNode, (e) => {
|
|
283
277
|
const parent = e.getParent();
|
|
@@ -292,9 +286,9 @@ export default function ToolbarPlugin({
|
|
|
292
286
|
const elementDOM = activeEditor.getElementByKey(elementKey);
|
|
293
287
|
|
|
294
288
|
// Update text format
|
|
295
|
-
setIsCode(selection.hasFormat(
|
|
296
|
-
setIsBold(selection.hasFormat(
|
|
297
|
-
setIsItalic(selection.hasFormat(
|
|
289
|
+
setIsCode(selection.hasFormat('code'));
|
|
290
|
+
setIsBold(selection.hasFormat('bold'));
|
|
291
|
+
setIsItalic(selection.hasFormat('italic'));
|
|
298
292
|
|
|
299
293
|
// Update links
|
|
300
294
|
const node = getSelectedNode(selection);
|
|
@@ -308,27 +302,17 @@ export default function ToolbarPlugin({
|
|
|
308
302
|
if (elementDOM !== null) {
|
|
309
303
|
setSelectedElementKey(elementKey);
|
|
310
304
|
if ($isListNode(element)) {
|
|
311
|
-
const parentList = $getNearestNodeOfType<ListNode>(
|
|
312
|
-
|
|
313
|
-
ListNode,
|
|
314
|
-
);
|
|
315
|
-
const type = parentList
|
|
316
|
-
? parentList.getListType()
|
|
317
|
-
: element.getListType();
|
|
305
|
+
const parentList = $getNearestNodeOfType<ListNode>(anchorNode, ListNode);
|
|
306
|
+
const type = parentList ? parentList.getListType() : element.getListType();
|
|
318
307
|
setBlockType(type);
|
|
319
308
|
} else {
|
|
320
|
-
const type = $isHeadingNode(element)
|
|
321
|
-
? element.getTag()
|
|
322
|
-
: element.getType();
|
|
309
|
+
const type = $isHeadingNode(element) ? element.getTag() : element.getType();
|
|
323
310
|
if (type in blockTypeToBlockName) {
|
|
324
311
|
setBlockType(type as keyof typeof blockTypeToBlockName);
|
|
325
312
|
}
|
|
326
313
|
if ($isCodeNode(element)) {
|
|
327
|
-
const language =
|
|
328
|
-
|
|
329
|
-
setCodeLanguage(
|
|
330
|
-
language ? CODE_LANGUAGE_MAP[language] || language : '',
|
|
331
|
-
);
|
|
314
|
+
const language = element.getLanguage() as keyof typeof CODE_LANGUAGE_MAP;
|
|
315
|
+
setCodeLanguage(language ? CODE_LANGUAGE_MAP[language] || language : '');
|
|
332
316
|
return;
|
|
333
317
|
}
|
|
334
318
|
}
|
|
@@ -344,7 +328,7 @@ export default function ToolbarPlugin({
|
|
|
344
328
|
setActiveEditor(newEditor);
|
|
345
329
|
return false;
|
|
346
330
|
},
|
|
347
|
-
COMMAND_PRIORITY_CRITICAL
|
|
331
|
+
COMMAND_PRIORITY_CRITICAL
|
|
348
332
|
);
|
|
349
333
|
}, [editor, $updateToolbar]);
|
|
350
334
|
|
|
@@ -364,7 +348,7 @@ export default function ToolbarPlugin({
|
|
|
364
348
|
setCanUndo(payload);
|
|
365
349
|
return false;
|
|
366
350
|
},
|
|
367
|
-
COMMAND_PRIORITY_CRITICAL
|
|
351
|
+
COMMAND_PRIORITY_CRITICAL
|
|
368
352
|
),
|
|
369
353
|
activeEditor.registerCommand<boolean>(
|
|
370
354
|
CAN_REDO_COMMAND,
|
|
@@ -372,8 +356,8 @@ export default function ToolbarPlugin({
|
|
|
372
356
|
setCanRedo(payload);
|
|
373
357
|
return false;
|
|
374
358
|
},
|
|
375
|
-
COMMAND_PRIORITY_CRITICAL
|
|
376
|
-
)
|
|
359
|
+
COMMAND_PRIORITY_CRITICAL
|
|
360
|
+
)
|
|
377
361
|
);
|
|
378
362
|
}, [$updateToolbar, activeEditor, editor]);
|
|
379
363
|
|
|
@@ -384,27 +368,24 @@ export default function ToolbarPlugin({
|
|
|
384
368
|
const event: KeyboardEvent = payload;
|
|
385
369
|
const { code, ctrlKey, metaKey } = event;
|
|
386
370
|
|
|
387
|
-
if (code ===
|
|
371
|
+
if (code === 'KeyK' && (ctrlKey || metaKey)) {
|
|
388
372
|
event.preventDefault();
|
|
389
373
|
if (!isLink) {
|
|
390
374
|
setIsLinkEditMode(true);
|
|
391
375
|
} else {
|
|
392
376
|
setIsLinkEditMode(false);
|
|
393
377
|
}
|
|
394
|
-
return activeEditor.dispatchCommand(
|
|
395
|
-
TOGGLE_LINK_COMMAND,
|
|
396
|
-
sanitizeUrl("https://"),
|
|
397
|
-
);
|
|
378
|
+
return activeEditor.dispatchCommand(TOGGLE_LINK_COMMAND, sanitizeUrl('https://'));
|
|
398
379
|
}
|
|
399
380
|
return false;
|
|
400
381
|
},
|
|
401
|
-
COMMAND_PRIORITY_NORMAL
|
|
382
|
+
COMMAND_PRIORITY_NORMAL
|
|
402
383
|
);
|
|
403
384
|
}, [activeEditor, isLink, setIsLinkEditMode]);
|
|
404
385
|
|
|
405
386
|
const insertLink = useCallback(() => {
|
|
406
387
|
if (!isLink) {
|
|
407
|
-
editor.dispatchCommand(TOGGLE_LINK_COMMAND, sanitizeUrl(
|
|
388
|
+
editor.dispatchCommand(TOGGLE_LINK_COMMAND, sanitizeUrl('https://'));
|
|
408
389
|
} else {
|
|
409
390
|
editor.dispatchCommand(TOGGLE_LINK_COMMAND, null);
|
|
410
391
|
}
|
|
@@ -421,7 +402,7 @@ export default function ToolbarPlugin({
|
|
|
421
402
|
}
|
|
422
403
|
});
|
|
423
404
|
},
|
|
424
|
-
[activeEditor, selectedElementKey]
|
|
405
|
+
[activeEditor, selectedElementKey]
|
|
425
406
|
);
|
|
426
407
|
return (
|
|
427
408
|
<div className="toolbar">
|
|
@@ -430,7 +411,7 @@ export default function ToolbarPlugin({
|
|
|
430
411
|
onClick={() => {
|
|
431
412
|
activeEditor.dispatchCommand(UNDO_COMMAND, undefined);
|
|
432
413
|
}}
|
|
433
|
-
title={IS_APPLE ?
|
|
414
|
+
title={IS_APPLE ? 'Undo (⌘Z)' : 'Undo (Ctrl+Z)'}
|
|
434
415
|
type="button"
|
|
435
416
|
className="toolbar-item spaced"
|
|
436
417
|
aria-label="Undo"
|
|
@@ -442,7 +423,7 @@ export default function ToolbarPlugin({
|
|
|
442
423
|
onClick={() => {
|
|
443
424
|
activeEditor.dispatchCommand(REDO_COMMAND, undefined);
|
|
444
425
|
}}
|
|
445
|
-
title={IS_APPLE ?
|
|
426
|
+
title={IS_APPLE ? 'Redo (⌘Y)' : 'Redo (Ctrl+Y)'}
|
|
446
427
|
type="button"
|
|
447
428
|
className="toolbar-item"
|
|
448
429
|
aria-label="Redo"
|
|
@@ -452,15 +433,11 @@ export default function ToolbarPlugin({
|
|
|
452
433
|
<Divider />
|
|
453
434
|
{blockType in blockTypeToBlockName && activeEditor === editor && (
|
|
454
435
|
<>
|
|
455
|
-
<BlockFormatDropDown
|
|
456
|
-
disabled={!isEditable}
|
|
457
|
-
blockType={blockType}
|
|
458
|
-
editor={editor}
|
|
459
|
-
/>
|
|
436
|
+
<BlockFormatDropDown disabled={!isEditable} blockType={blockType} editor={editor} />
|
|
460
437
|
<Divider />
|
|
461
438
|
</>
|
|
462
439
|
)}
|
|
463
|
-
{blockType ===
|
|
440
|
+
{blockType === 'code' ? (
|
|
464
441
|
<DropDown
|
|
465
442
|
disabled={!isEditable}
|
|
466
443
|
buttonClassName="toolbar-item code-language"
|
|
@@ -470,9 +447,7 @@ export default function ToolbarPlugin({
|
|
|
470
447
|
{CODE_LANGUAGE_OPTIONS.map(([value, name]) => {
|
|
471
448
|
return (
|
|
472
449
|
<DropDownItem
|
|
473
|
-
className={`item ${dropDownActiveClass(
|
|
474
|
-
value === codeLanguage,
|
|
475
|
-
)}`}
|
|
450
|
+
className={`item ${dropDownActiveClass(value === codeLanguage)}`}
|
|
476
451
|
onClick={() => onCodeLanguageSelect(value)}
|
|
477
452
|
key={value}
|
|
478
453
|
>
|
|
@@ -486,35 +461,31 @@ export default function ToolbarPlugin({
|
|
|
486
461
|
<button
|
|
487
462
|
disabled={!isEditable}
|
|
488
463
|
onClick={() => {
|
|
489
|
-
activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND,
|
|
464
|
+
activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND, 'bold');
|
|
490
465
|
}}
|
|
491
|
-
className={
|
|
492
|
-
title={IS_APPLE ?
|
|
466
|
+
className={'toolbar-item spaced ' + (isBold ? 'active' : '')}
|
|
467
|
+
title={IS_APPLE ? 'Bold (⌘B)' : 'Bold (Ctrl+B)'}
|
|
493
468
|
type="button"
|
|
494
|
-
aria-label={`Format text as bold. Shortcut: ${
|
|
495
|
-
IS_APPLE ? "⌘B" : "Ctrl+B"
|
|
496
|
-
}`}
|
|
469
|
+
aria-label={`Format text as bold. Shortcut: ${IS_APPLE ? '⌘B' : 'Ctrl+B'}`}
|
|
497
470
|
>
|
|
498
471
|
<i className="format bold" />
|
|
499
472
|
</button>
|
|
500
473
|
<button
|
|
501
474
|
disabled={!isEditable}
|
|
502
475
|
onClick={() => {
|
|
503
|
-
activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND,
|
|
476
|
+
activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND, 'italic');
|
|
504
477
|
}}
|
|
505
|
-
className={
|
|
506
|
-
title={IS_APPLE ?
|
|
478
|
+
className={'toolbar-item spaced ' + (isItalic ? 'active' : '')}
|
|
479
|
+
title={IS_APPLE ? 'Italic (⌘I)' : 'Italic (Ctrl+I)'}
|
|
507
480
|
type="button"
|
|
508
|
-
aria-label={`Format text as italics. Shortcut: ${
|
|
509
|
-
IS_APPLE ? "⌘I" : "Ctrl+I"
|
|
510
|
-
}`}
|
|
481
|
+
aria-label={`Format text as italics. Shortcut: ${IS_APPLE ? '⌘I' : 'Ctrl+I'}`}
|
|
511
482
|
>
|
|
512
483
|
<i className="format italic" />
|
|
513
484
|
</button>
|
|
514
485
|
<button
|
|
515
486
|
disabled={!isEditable}
|
|
516
487
|
onClick={insertLink}
|
|
517
|
-
className={
|
|
488
|
+
className={'toolbar-item spaced ' + (isLink ? 'active' : '')}
|
|
518
489
|
aria-label="Insert link"
|
|
519
490
|
title="Insert link"
|
|
520
491
|
type="button"
|
|
@@ -523,6 +494,23 @@ export default function ToolbarPlugin({
|
|
|
523
494
|
</button>
|
|
524
495
|
</>
|
|
525
496
|
)}
|
|
497
|
+
{toolbarButtons.length > 0 && (
|
|
498
|
+
<>
|
|
499
|
+
<Divider />
|
|
500
|
+
{toolbarButtons.map((btn) => (
|
|
501
|
+
<button
|
|
502
|
+
type="button"
|
|
503
|
+
key={btn.key}
|
|
504
|
+
onClick={() => btn.onSelect(activeEditor)}
|
|
505
|
+
className="toolbar-item"
|
|
506
|
+
title={btn.label}
|
|
507
|
+
aria-label={btn.label}
|
|
508
|
+
>
|
|
509
|
+
<i className={`icon ${btn.iconClass ?? 'bullet-list'}`} />
|
|
510
|
+
</button>
|
|
511
|
+
))}
|
|
512
|
+
</>
|
|
513
|
+
)}
|
|
526
514
|
</div>
|
|
527
515
|
);
|
|
528
516
|
}
|
|
@@ -41,7 +41,8 @@
|
|
|
41
41
|
margin: 0;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
[data-theme="dark"] .EditorTheme__h1
|
|
44
|
+
[data-theme="dark"] .EditorTheme__h1,
|
|
45
|
+
[data-color-scheme="dark"] .EditorTheme__h1 {
|
|
45
46
|
color: #ffffff;
|
|
46
47
|
}
|
|
47
48
|
|
|
@@ -54,7 +55,8 @@
|
|
|
54
55
|
margin: 0;
|
|
55
56
|
}
|
|
56
57
|
|
|
57
|
-
[data-theme="dark"] .EditorTheme__h2
|
|
58
|
+
[data-theme="dark"] .EditorTheme__h2,
|
|
59
|
+
[data-color-scheme="dark"] .EditorTheme__h2 {
|
|
58
60
|
color: #ffffff;
|
|
59
61
|
}
|
|
60
62
|
|
|
@@ -67,7 +69,8 @@
|
|
|
67
69
|
margin: 0;
|
|
68
70
|
}
|
|
69
71
|
|
|
70
|
-
[data-theme="dark"] .EditorTheme__h3
|
|
72
|
+
[data-theme="dark"] .EditorTheme__h3,
|
|
73
|
+
[data-color-scheme="dark"] .EditorTheme__h3 {
|
|
71
74
|
color: #ffffff;
|
|
72
75
|
}
|
|
73
76
|
|
|
@@ -80,7 +83,8 @@
|
|
|
80
83
|
margin: 0;
|
|
81
84
|
}
|
|
82
85
|
|
|
83
|
-
[data-theme="dark"] .EditorTheme__h4
|
|
86
|
+
[data-theme="dark"] .EditorTheme__h4,
|
|
87
|
+
[data-color-scheme="dark"] .EditorTheme__h4 {
|
|
84
88
|
color: #ffffff;
|
|
85
89
|
}
|
|
86
90
|
|
|
@@ -163,7 +167,7 @@
|
|
|
163
167
|
top: 0;
|
|
164
168
|
border-right: 1px solid #ccc;
|
|
165
169
|
padding: 8px;
|
|
166
|
-
color: #
|
|
170
|
+
color: #696969;
|
|
167
171
|
white-space: pre-wrap;
|
|
168
172
|
text-align: right;
|
|
169
173
|
min-width: 25px;
|