@squiz/formatted-text-editor 1.21.1-alpha.20 → 1.21.1-alpha.22
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/lib/Editor/Editor.js +15 -9
- package/lib/EditorToolbar/FloatingToolbar.js +1 -1
- package/lib/EditorToolbar/Tools/Image/ImageButton.js +4 -3
- package/lib/EditorToolbar/Tools/Link/LinkButton.js +9 -4
- package/lib/index.css +3 -0
- package/package.json +2 -2
- package/src/Editor/Editor.tsx +21 -15
- package/src/Editor/_editor.scss +6 -0
- package/src/EditorToolbar/FloatingToolbar.tsx +1 -4
- package/src/EditorToolbar/Tools/Image/ImageButton.tsx +4 -3
- package/src/EditorToolbar/Tools/Link/LinkButton.tsx +11 -8
package/lib/Editor/Editor.js
CHANGED
@@ -32,6 +32,19 @@ const EditorToolbar_1 = require("../EditorToolbar");
|
|
32
32
|
const EditorContext_1 = require("./EditorContext");
|
33
33
|
const Extensions_1 = require("../Extensions/Extensions");
|
34
34
|
const clsx_1 = __importDefault(require("clsx"));
|
35
|
+
const WrappedEditor = () => {
|
36
|
+
const preventImagePaste = (0, react_1.useCallback)((event) => {
|
37
|
+
const { clipboardData } = event;
|
38
|
+
const pastedData = clipboardData?.files[0];
|
39
|
+
if (pastedData?.type && pastedData?.type.startsWith('image/')) {
|
40
|
+
event.preventDefault();
|
41
|
+
}
|
42
|
+
// Allow other paste event handlers to be run.
|
43
|
+
return false;
|
44
|
+
}, []);
|
45
|
+
(0, react_2.useEditorEvent)('paste', preventImagePaste);
|
46
|
+
return react_1.default.createElement(react_2.EditorComponent, null);
|
47
|
+
};
|
35
48
|
const Editor = ({ content, editable = true, onChange }) => {
|
36
49
|
const { manager, state, setState } = (0, react_2.useRemirror)({
|
37
50
|
extensions: (0, Extensions_1.createExtensions)((0, react_1.useContext)(EditorContext_1.EditorContext)),
|
@@ -43,18 +56,11 @@ const Editor = ({ content, editable = true, onChange }) => {
|
|
43
56
|
setState(parameter.state);
|
44
57
|
onChange?.(parameter);
|
45
58
|
};
|
46
|
-
const preventImagePaste = (event) => {
|
47
|
-
const { clipboardData } = event;
|
48
|
-
const pastedData = clipboardData?.items[0];
|
49
|
-
if (pastedData?.type && pastedData?.type.startsWith('image/')) {
|
50
|
-
event.preventDefault();
|
51
|
-
}
|
52
|
-
};
|
53
59
|
return (react_1.default.createElement("div", { className: "squiz-fte-scope" },
|
54
|
-
react_1.default.createElement("div", { className: (0, clsx_1.default)('remirror-theme formatted-text-editor', !editable && 'formatted-text-editor--is-disabled')
|
60
|
+
react_1.default.createElement("div", { className: (0, clsx_1.default)('remirror-theme formatted-text-editor', !editable && 'formatted-text-editor--is-disabled') },
|
55
61
|
react_1.default.createElement(react_2.Remirror, { manager: manager, state: state, editable: editable, onChange: handleChange, placeholder: "Write something", label: "Text editor" },
|
56
62
|
editable && react_1.default.createElement(EditorToolbar_1.Toolbar, null),
|
57
|
-
react_1.default.createElement(
|
63
|
+
react_1.default.createElement(WrappedEditor, null),
|
58
64
|
editable && react_1.default.createElement(EditorToolbar_1.FloatingToolbar, null)))));
|
59
65
|
};
|
60
66
|
exports.default = Editor;
|
@@ -51,7 +51,7 @@ const FloatingToolbar = () => {
|
|
51
51
|
extensionNames.underline && react_1.default.createElement(UnderlineButton_1.default, { key: "underline" }),
|
52
52
|
];
|
53
53
|
if (active.image()) {
|
54
|
-
buttons
|
54
|
+
buttons = [react_1.default.createElement(ImageButton_1.default, { key: "add-image", inPopover: true })];
|
55
55
|
}
|
56
56
|
else if (marks?.[Extensions_1.MarkName.Link].isExclusivelyActive || marks?.[Extensions_1.MarkName.AssetLink].isExclusivelyActive) {
|
57
57
|
// if all of the selected text is a link show the options to update/remove the link instead of the regular
|
@@ -64,10 +64,11 @@ const ImageButton = ({ inPopover = false }) => {
|
|
64
64
|
// Prevent other key handlers being run
|
65
65
|
return true;
|
66
66
|
}, []);
|
67
|
+
// when Ctrl+l is pressed show the modal, only registered in the toolbar button instance to avoid the key press
|
68
|
+
// being double handled.
|
67
69
|
if (!inPopover) {
|
68
|
-
//
|
69
|
-
|
70
|
-
(0, react_2.useKeymap)('Mod-l', handleShortcut);
|
70
|
+
// disable the shortcut if the button is disabled
|
71
|
+
(0, react_2.useKeymap)('Mod-l', disabled ? () => false : handleShortcut);
|
71
72
|
}
|
72
73
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
73
74
|
react_1.default.createElement(Button_1.default, { handleOnClick: handleClick, isActive: active.image(), icon: react_1.default.createElement(ImageRounded_1.default, null), label: "Image (cmd+L)", isDisabled: disabled }),
|
@@ -31,7 +31,6 @@ const InsertLinkRounded_1 = __importDefault(require("@mui/icons-material/InsertL
|
|
31
31
|
const LinkModal_1 = __importDefault(require("./LinkModal"));
|
32
32
|
const Button_1 = __importDefault(require("../../../ui/Button/Button"));
|
33
33
|
const react_2 = require("@remirror/react");
|
34
|
-
const LinkExtension_1 = require("../../../Extensions/LinkExtension/LinkExtension");
|
35
34
|
const Extensions_1 = require("../../../Extensions/Extensions");
|
36
35
|
const LinkButton = ({ inPopover = false }) => {
|
37
36
|
const [showModal, setShowModal] = (0, react_1.useState)(false);
|
@@ -44,6 +43,11 @@ const LinkButton = ({ inPopover = false }) => {
|
|
44
43
|
setShowModal(true);
|
45
44
|
}
|
46
45
|
};
|
46
|
+
const handleShortcut = (0, react_1.useCallback)(() => {
|
47
|
+
handleClick();
|
48
|
+
// Prevent other key handlers being run
|
49
|
+
return true;
|
50
|
+
}, []);
|
47
51
|
const handleSubmit = (data) => {
|
48
52
|
if (data.linkType === Extensions_1.MarkName.AssetLink) {
|
49
53
|
updateAssetLink({ text: data.text, attrs: data.assetLink, range: data.range });
|
@@ -53,10 +57,11 @@ const LinkButton = ({ inPopover = false }) => {
|
|
53
57
|
}
|
54
58
|
setShowModal(false);
|
55
59
|
};
|
60
|
+
// when Ctrl+K is pressed show the modal, only registered in the toolbar button instance to avoid the key press
|
61
|
+
// being double handled.
|
56
62
|
if (!inPopover) {
|
57
|
-
//
|
58
|
-
|
59
|
-
(0, react_2.useExtensionEvent)(LinkExtension_1.LinkExtension, 'onShortcut', (0, react_1.useCallback)(() => handleClick(), []));
|
63
|
+
// disable the shortcut if the button is disabled
|
64
|
+
(0, react_2.useKeymap)('Mod-k', disabled ? () => true : handleShortcut);
|
60
65
|
}
|
61
66
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
62
67
|
react_1.default.createElement(Button_1.default, { handleOnClick: handleClick, isActive: active.link() || active.assetLink(), icon: react_1.default.createElement(InsertLinkRounded_1.default, null), label: "Link (cmd+K)", isDisabled: disabled }),
|
package/lib/index.css
CHANGED
@@ -737,6 +737,9 @@
|
|
737
737
|
--tw-border-opacity: 1;
|
738
738
|
border-color: rgb(7 116 210 / var(--tw-border-opacity));
|
739
739
|
}
|
740
|
+
.squiz-fte-scope .formatted-text-editor img {
|
741
|
+
display: inline;
|
742
|
+
}
|
740
743
|
.squiz-fte-scope .editor-toolbar,
|
741
744
|
.squiz-fte-scope__floating-popover {
|
742
745
|
border-bottom-width: 2px;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@squiz/formatted-text-editor",
|
3
|
-
"version": "1.21.1-alpha.
|
3
|
+
"version": "1.21.1-alpha.22",
|
4
4
|
"main": "lib/index.js",
|
5
5
|
"types": "lib/index.d.ts",
|
6
6
|
"scripts": {
|
@@ -72,5 +72,5 @@
|
|
72
72
|
"volta": {
|
73
73
|
"node": "18.15.0"
|
74
74
|
},
|
75
|
-
"gitHead": "
|
75
|
+
"gitHead": "82a7818468c6bcc2eee98748a0962d233c35f55e"
|
76
76
|
}
|
package/src/Editor/Editor.tsx
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
-
import React, {
|
2
|
-
import { EditorComponent, Remirror, useRemirror } from '@remirror/react';
|
1
|
+
import React, { useContext, useCallback } from 'react';
|
2
|
+
import { EditorComponent, Remirror, useRemirror, useEditorEvent } from '@remirror/react';
|
3
3
|
import { RemirrorContentType, RemirrorEventListener, Extension } from '@remirror/core';
|
4
4
|
import { Toolbar, FloatingToolbar } from '../EditorToolbar';
|
5
5
|
import { EditorContext } from './EditorContext';
|
6
6
|
import { createExtensions } from '../Extensions/Extensions';
|
7
7
|
import clsx from 'clsx';
|
8
|
+
import { ClipboardEventHandler } from '@remirror/extension-events/dist-types/events-extension';
|
8
9
|
|
9
10
|
type EditorProps = {
|
10
11
|
content?: RemirrorContentType;
|
@@ -12,6 +13,22 @@ type EditorProps = {
|
|
12
13
|
editable?: boolean;
|
13
14
|
};
|
14
15
|
|
16
|
+
const WrappedEditor = () => {
|
17
|
+
const preventImagePaste = useCallback((event) => {
|
18
|
+
const { clipboardData } = event;
|
19
|
+
const pastedData = clipboardData?.files[0];
|
20
|
+
if (pastedData?.type && pastedData?.type.startsWith('image/')) {
|
21
|
+
event.preventDefault();
|
22
|
+
}
|
23
|
+
|
24
|
+
// Allow other paste event handlers to be run.
|
25
|
+
return false;
|
26
|
+
}, []) as ClipboardEventHandler;
|
27
|
+
|
28
|
+
useEditorEvent('paste', preventImagePaste);
|
29
|
+
return <EditorComponent />;
|
30
|
+
};
|
31
|
+
|
15
32
|
const Editor = ({ content, editable = true, onChange }: EditorProps) => {
|
16
33
|
const { manager, state, setState } = useRemirror({
|
17
34
|
extensions: createExtensions(useContext(EditorContext)),
|
@@ -25,20 +42,9 @@ const Editor = ({ content, editable = true, onChange }: EditorProps) => {
|
|
25
42
|
onChange?.(parameter);
|
26
43
|
};
|
27
44
|
|
28
|
-
const preventImagePaste = (event: ClipboardEvent<HTMLDivElement>) => {
|
29
|
-
const { clipboardData } = event;
|
30
|
-
const pastedData = clipboardData?.items[0];
|
31
|
-
if (pastedData?.type && pastedData?.type.startsWith('image/')) {
|
32
|
-
event.preventDefault();
|
33
|
-
}
|
34
|
-
};
|
35
|
-
|
36
45
|
return (
|
37
46
|
<div className="squiz-fte-scope">
|
38
|
-
<div
|
39
|
-
className={clsx('remirror-theme formatted-text-editor', !editable && 'formatted-text-editor--is-disabled')}
|
40
|
-
onPaste={preventImagePaste}
|
41
|
-
>
|
47
|
+
<div className={clsx('remirror-theme formatted-text-editor', !editable && 'formatted-text-editor--is-disabled')}>
|
42
48
|
<Remirror
|
43
49
|
manager={manager}
|
44
50
|
state={state}
|
@@ -48,7 +54,7 @@ const Editor = ({ content, editable = true, onChange }: EditorProps) => {
|
|
48
54
|
label="Text editor"
|
49
55
|
>
|
50
56
|
{editable && <Toolbar />}
|
51
|
-
<
|
57
|
+
<WrappedEditor />
|
52
58
|
{editable && <FloatingToolbar />}
|
53
59
|
</Remirror>
|
54
60
|
</div>
|
package/src/Editor/_editor.scss
CHANGED
@@ -28,10 +28,7 @@ export const FloatingToolbar = () => {
|
|
28
28
|
];
|
29
29
|
|
30
30
|
if (active.image()) {
|
31
|
-
buttons
|
32
|
-
<VerticalDivider key="image-divider" className="editor-divider" />,
|
33
|
-
<ImageButton key="add-image" inPopover={true} />,
|
34
|
-
);
|
31
|
+
buttons = [<ImageButton key="add-image" inPopover={true} />];
|
35
32
|
} else if (marks?.[MarkName.Link].isExclusivelyActive || marks?.[MarkName.AssetLink].isExclusivelyActive) {
|
36
33
|
// if all of the selected text is a link show the options to update/remove the link instead of the regular
|
37
34
|
// formatting options.
|
@@ -48,10 +48,11 @@ const ImageButton = ({ inPopover = false }: ImageButtonProps) => {
|
|
48
48
|
return true;
|
49
49
|
}, []);
|
50
50
|
|
51
|
+
// when Ctrl+l is pressed show the modal, only registered in the toolbar button instance to avoid the key press
|
52
|
+
// being double handled.
|
51
53
|
if (!inPopover) {
|
52
|
-
//
|
53
|
-
|
54
|
-
useKeymap('Mod-l', handleShortcut);
|
54
|
+
// disable the shortcut if the button is disabled
|
55
|
+
useKeymap('Mod-l', disabled ? () => false : handleShortcut);
|
55
56
|
}
|
56
57
|
|
57
58
|
return (
|
@@ -3,7 +3,7 @@ import InsertLinkRoundedIcon from '@mui/icons-material/InsertLinkRounded';
|
|
3
3
|
import LinkModal from './LinkModal';
|
4
4
|
import { LinkFormData } from './Form/LinkForm';
|
5
5
|
import Button from '../../../ui/Button/Button';
|
6
|
-
import { useActive, useCommands,
|
6
|
+
import { useActive, useCommands, useKeymap } from '@remirror/react';
|
7
7
|
import { LinkExtension } from '../../../Extensions/LinkExtension/LinkExtension';
|
8
8
|
import { CommandsExtension } from '../../../Extensions/CommandsExtension/CommandsExtension';
|
9
9
|
import { AssetLinkExtension } from '../../../Extensions/LinkExtension/AssetLinkExtension';
|
@@ -25,6 +25,12 @@ const LinkButton = ({ inPopover = false }: LinkButtonProps) => {
|
|
25
25
|
setShowModal(true);
|
26
26
|
}
|
27
27
|
};
|
28
|
+
const handleShortcut = useCallback(() => {
|
29
|
+
handleClick();
|
30
|
+
// Prevent other key handlers being run
|
31
|
+
return true;
|
32
|
+
}, []);
|
33
|
+
|
28
34
|
const handleSubmit = (data: LinkFormData) => {
|
29
35
|
if (data.linkType === MarkName.AssetLink) {
|
30
36
|
updateAssetLink({ text: data.text, attrs: data.assetLink, range: data.range });
|
@@ -35,14 +41,11 @@ const LinkButton = ({ inPopover = false }: LinkButtonProps) => {
|
|
35
41
|
setShowModal(false);
|
36
42
|
};
|
37
43
|
|
44
|
+
// when Ctrl+K is pressed show the modal, only registered in the toolbar button instance to avoid the key press
|
45
|
+
// being double handled.
|
38
46
|
if (!inPopover) {
|
39
|
-
//
|
40
|
-
|
41
|
-
useExtensionEvent(
|
42
|
-
LinkExtension,
|
43
|
-
'onShortcut',
|
44
|
-
useCallback(() => handleClick(), []),
|
45
|
-
);
|
47
|
+
// disable the shortcut if the button is disabled
|
48
|
+
useKeymap('Mod-k', disabled ? () => true : handleShortcut);
|
46
49
|
}
|
47
50
|
|
48
51
|
return (
|