@uxf/wysiwyg 11.129.0 → 11.130.0
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/README.md +9 -7
- package/create-all-plugins-with-ui.d.ts +78 -14
- package/create-all-plugins-with-ui.js +3 -5
- package/create-plugins-with-ui.d.ts +2 -2
- package/create-plugins-with-ui.js +25 -30
- package/data-format.test.d.ts +1 -0
- package/data-format.test.js +132 -0
- package/editor-smoke.test.d.ts +1 -0
- package/editor-smoke.test.js +9 -0
- package/hooks.d.ts +1971 -8
- package/hooks.js +18 -11
- package/package.json +15 -47
- package/plugins/blockquote/create-blockquote-plugin.d.ts +9 -3
- package/plugins/blockquote/create-blockquote-plugin.js +31 -3
- package/plugins/blockquote/create-blockquote-plugin.test.d.ts +1 -0
- package/plugins/blockquote/create-blockquote-plugin.test.js +55 -0
- package/plugins/blockquote/types.d.ts +1 -1
- package/plugins/blockquote/types.js +2 -2
- package/plugins/button/create-button-plugin.d.ts +1 -2
- package/plugins/button/create-button-plugin.js +3 -5
- package/plugins/button/transforms/is-button-active.js +1 -2
- package/plugins/button/transforms/update-button.js +1 -2
- package/plugins/constants.test.d.ts +1 -0
- package/plugins/constants.test.js +52 -0
- package/plugins/embedded/types.d.ts +6 -0
- package/plugins/embedded/types.js +2 -0
- package/plugins/embedded/utils.d.ts +2 -1
- package/plugins/embedded/utils.js +4 -4
- package/plugins/embedded/video/create-video-plugin.d.ts +10 -3
- package/plugins/embedded/video/create-video-plugin.js +8 -9
- package/plugins/embedded/video/create-video-plugin.test.d.ts +1 -0
- package/plugins/embedded/video/create-video-plugin.test.js +30 -0
- package/plugins/embedded/video/update-video.js +1 -2
- package/plugins/exit-break/create-exit-break-plugin.d.ts +8 -3
- package/plugins/exit-break/create-exit-break-plugin.js +8 -25
- package/plugins/heading/create-headings-plugin.d.ts +13 -4
- package/plugins/heading/create-headings-plugin.js +22 -36
- package/plugins/heading/create-headings-plugin.test.d.ts +1 -0
- package/plugins/heading/create-headings-plugin.test.js +42 -0
- package/plugins/highlight/createHighlightPlugin.d.ts +4 -2
- package/plugins/highlight/createHighlightPlugin.js +8 -21
- package/plugins/highlight/types.d.ts +1 -2
- package/plugins/image/create-image-plugin.d.ts +3 -3
- package/plugins/image/create-image-plugin.js +58 -91
- package/plugins/image/create-image-plugin.test.d.ts +1 -0
- package/plugins/image/create-image-plugin.test.js +33 -0
- package/plugins/image/transforms/is-image-active.js +1 -2
- package/plugins/image/transforms/update-image.js +1 -2
- package/plugins/image/types.d.ts +6 -3
- package/plugins/image/types.js +2 -2
- package/plugins/image/utils/is-image-url.js +2 -2
- package/plugins/image/with-paste-image-url.d.ts +5 -5
- package/plugins/image/with-paste-image-url.js +29 -25
- package/plugins/image/with-paste-image.d.ts +4 -7
- package/plugins/image/with-paste-image.js +41 -39
- package/plugins/link/constants.d.ts +1 -1
- package/plugins/link/constants.js +2 -2
- package/plugins/link/create-link-plugin.d.ts +38 -3
- package/plugins/link/create-link-plugin.js +9 -7
- package/plugins/link/create-link-plugin.test.d.ts +1 -0
- package/plugins/link/create-link-plugin.test.js +24 -0
- package/plugins/link/floating-link-wrapper.d.ts +14 -7
- package/plugins/link/floating-link-wrapper.js +46 -17
- package/plugins/link/hooks/index.d.ts +1 -1
- package/plugins/link/hooks/index.js +2 -2
- package/plugins/link/hooks/use-floating-link-selectors.d.ts +8 -0
- package/plugins/link/hooks/use-floating-link-selectors.js +21 -0
- package/plugins/link/hooks/use-link-actions.d.ts +991 -8
- package/plugins/link/hooks/use-link-actions.js +22 -19
- package/plugins/link/hooks/use-link-cancel-on-escape.d.ts +1 -1
- package/plugins/link/hooks/use-link-cancel-on-escape.js +2 -2
- package/plugins/link/hooks/use-link-submit-on-enter.js +5 -5
- package/plugins/link/transforms/get-active-link.d.ts +1 -1
- package/plugins/link/transforms/get-active-link.js +3 -5
- package/plugins/link/transforms/insert-link.js +9 -9
- package/plugins/link/transforms/submit-link.d.ts +2 -3
- package/plugins/link/transforms/submit-link.js +13 -13
- package/plugins/link/transforms/trigger-link-insert-or-edit.js +2 -2
- package/plugins/link/transforms/unwrap-link.js +2 -2
- package/plugins/list/constants.d.ts +11 -3
- package/plugins/list/constants.js +14 -10
- package/plugins/list/create-list-plugin.d.ts +26 -4
- package/plugins/list/create-list-plugin.js +13 -12
- package/plugins/list/create-list-plugin.test.d.ts +1 -0
- package/plugins/list/create-list-plugin.test.js +20 -0
- package/plugins/mark-bold/create-bold-plugin.d.ts +3 -3
- package/plugins/mark-bold/create-bold-plugin.js +2 -2
- package/plugins/mark-bold/types.d.ts +2 -2
- package/plugins/mark-bold/types.js +3 -3
- package/plugins/mark-code/create-code-plugin.d.ts +7 -3
- package/plugins/mark-code/create-code-plugin.js +6 -2
- package/plugins/mark-code/types.d.ts +2 -2
- package/plugins/mark-code/types.js +3 -3
- package/plugins/mark-italic/create-italic-plugin.d.ts +3 -3
- package/plugins/mark-italic/create-italic-plugin.js +2 -2
- package/plugins/mark-italic/types.d.ts +2 -2
- package/plugins/mark-italic/types.js +3 -3
- package/plugins/mark-underline/create-underline-plugin.d.ts +3 -3
- package/plugins/mark-underline/create-underline-plugin.js +2 -2
- package/plugins/mark-underline/types.d.ts +2 -2
- package/plugins/mark-underline/types.js +3 -3
- package/plugins/marks.test.d.ts +1 -0
- package/plugins/marks.test.js +42 -0
- package/plugins/node-id/add-ids-to-nodes.d.ts +1 -1
- package/plugins/node-id/create-node-id-plugin.d.ts +22 -3
- package/plugins/node-id/create-node-id-plugin.js +3 -2
- package/plugins/paragraph/create-paragraph-plugin.d.ts +1 -3
- package/plugins/paragraph/create-paragraph-plugin.js +3 -4
- package/plugins/paragraph/types.d.ts +1 -1
- package/plugins/paragraph/types.js +2 -2
- package/plugins/structural.test.d.ts +1 -0
- package/plugins/structural.test.js +29 -0
- package/plugins/trailing-block/create-trailing-block-plugin.d.ts +13 -3
- package/plugins/trailing-block/create-trailing-block-plugin.js +8 -2
- package/serializers/serialize-to-plaintext.js +2 -2
- package/styles/styles.css +1 -0
- package/types.d.ts +23 -14
- package/ui/floating-link.js +28 -28
- package/ui/highlight-mark.d.ts +2 -3
- package/ui/highlight-mark.js +4 -1
- package/ui/link-element.js +6 -3
- package/ui/toolbar/buttons/button-toolbar-button.d.ts +1 -1
- package/ui/toolbar/buttons/element-toolbar-button.d.ts +1 -1
- package/ui/toolbar/buttons/image-toolbar-button.d.ts +1 -1
- package/ui/toolbar/buttons/link-toolbar-button.d.ts +1 -1
- package/ui/toolbar/buttons/link-toolbar-button.js +1 -1
- package/ui/toolbar/buttons/list-toolbar-button.d.ts +1 -1
- package/ui/toolbar/buttons/list-toolbar-button.js +3 -3
- package/ui/toolbar/buttons/mark-toolbar-button.d.ts +1 -1
- package/ui/toolbar/buttons/undo-redo-button-group.d.ts +1 -1
- package/ui/toolbar/buttons/video-toolbar-button.d.ts +1 -1
- package/ui/toolbar/types.d.ts +1 -1
- package/ui/utils.js +1 -1
- package/utils.d.ts +18 -19
- package/utils.js +31 -28
- package/utils.test.d.ts +1 -0
- package/utils.test.js +23 -0
- package/wysiwyg-editor.d.ts +2 -2
- package/wysiwyg-editor.js +29 -23
- package/wysiwyg-editor.test.js +111 -6
- package/plugins/image/with-image.d.ts +0 -7
- package/plugins/image/with-image.js +0 -19
- package/plugins/reset-node/create-reset-node.d.ts +0 -3
- package/plugins/reset-node/create-reset-node.js +0 -28
- package/plugins/select-on-backspace/create-select-on-backspace-plugin.d.ts +0 -3
- package/plugins/select-on-backspace/create-select-on-backspace-plugin.js +0 -14
- package/plugins/soft-break/create-soft-break-plugin.d.ts +0 -3
- package/plugins/soft-break/create-soft-break-plugin.js +0 -22
package/utils.js
CHANGED
|
@@ -1,36 +1,39 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.removeSelectedNode = exports.insertVoid = exports.removeElement = exports.getActiveElement = exports.getSelectedNode = exports.isSomeOfPluginsEnabled = exports.isPluginEnabled = exports.toggleMark = exports.isMarkActive = exports.isRangeInSingleText = exports.focusEditor = exports.toggleNodeType = exports.someNode = exports.getPluginType = exports.getPluginOptions = exports.getUxfEditor = void 0;
|
|
4
|
-
const plate_break_1 = require("@udecode/plate-break");
|
|
5
|
-
const plate_common_1 = require("@udecode/plate-common");
|
|
6
|
-
const plate_core_1 = require("@udecode/plate-core");
|
|
7
|
-
const slate_1 = require("@udecode/slate");
|
|
8
|
-
const slate_react_1 = require("@udecode/slate-react");
|
|
9
4
|
const is_not_nil_1 = require("@uxf/core/utils/is-not-nil");
|
|
10
5
|
const types_1 = require("./plugins/paragraph/types");
|
|
11
|
-
const getUxfEditor = (editor) =>
|
|
6
|
+
const getUxfEditor = (editor) => editor;
|
|
12
7
|
exports.getUxfEditor = getUxfEditor;
|
|
13
|
-
const getPluginOptions = (editor, pluginKey) => {
|
|
14
|
-
return (0, plate_core_1.getPluginOptions)(editor, pluginKey);
|
|
15
|
-
};
|
|
8
|
+
const getPluginOptions = (editor, pluginKey) => editor.getOptions({ key: pluginKey });
|
|
16
9
|
exports.getPluginOptions = getPluginOptions;
|
|
17
|
-
const getPluginType = (editor, key) =>
|
|
10
|
+
const getPluginType = (editor, key) => editor.getType(key);
|
|
18
11
|
exports.getPluginType = getPluginType;
|
|
19
|
-
const someNode = (editor, options) =>
|
|
12
|
+
const someNode = (editor, options) => editor.api.some(options);
|
|
20
13
|
exports.someNode = someNode;
|
|
21
|
-
const toggleNodeType = (editor, options, editorNodesOptions) =>
|
|
14
|
+
const toggleNodeType = (editor, options, editorNodesOptions) => {
|
|
15
|
+
var _a;
|
|
16
|
+
return editor.tf.toggleBlock((_a = options.activeType) !== null && _a !== void 0 ? _a : types_1.PARAGRAPH_PLUGIN_TYPE, {
|
|
17
|
+
defaultType: options.inactiveType,
|
|
18
|
+
someOptions: editorNodesOptions,
|
|
19
|
+
});
|
|
20
|
+
};
|
|
22
21
|
exports.toggleNodeType = toggleNodeType;
|
|
23
|
-
const focusEditor = (editor, target) =>
|
|
22
|
+
const focusEditor = (editor, target) => editor.tf.focus({ at: target });
|
|
24
23
|
exports.focusEditor = focusEditor;
|
|
25
|
-
const isRangeInSingleText = (editor) => editor.selection ? (
|
|
24
|
+
const isRangeInSingleText = (editor) => (editor.selection ? editor.api.isAt({ text: true }) : false);
|
|
26
25
|
exports.isRangeInSingleText = isRangeInSingleText;
|
|
27
|
-
const isMarkActive = (editor, type) => (
|
|
26
|
+
const isMarkActive = (editor, type) => Boolean(editor.api.mark(type)) && (0, exports.isRangeInSingleText)(editor);
|
|
28
27
|
exports.isMarkActive = isMarkActive;
|
|
29
|
-
const toggleMark = (editor, { key, clear }) =>
|
|
28
|
+
const toggleMark = (editor, { key, clear }) => editor.tf.toggleMark(key, { remove: clear });
|
|
30
29
|
exports.toggleMark = toggleMark;
|
|
31
|
-
|
|
30
|
+
/**
|
|
31
|
+
* `editor.plugins` is a keyed record in Plate 53, not the array it was in Plate 20. Both helpers gate
|
|
32
|
+
* every toolbar button, so indexing it as an array here would hide the whole toolbar.
|
|
33
|
+
*/
|
|
34
|
+
const isPluginEnabled = (editor, pluginKey) => Boolean(editor.plugins[pluginKey]);
|
|
32
35
|
exports.isPluginEnabled = isPluginEnabled;
|
|
33
|
-
const isSomeOfPluginsEnabled = (editor, pluginKeys) =>
|
|
36
|
+
const isSomeOfPluginsEnabled = (editor, pluginKeys) => pluginKeys.some((pluginKey) => (0, exports.isPluginEnabled)(editor, pluginKey));
|
|
34
37
|
exports.isSomeOfPluginsEnabled = isSomeOfPluginsEnabled;
|
|
35
38
|
const getSelectedNode = (editor) => {
|
|
36
39
|
var _a;
|
|
@@ -44,11 +47,11 @@ const getSelectedNode = (editor) => {
|
|
|
44
47
|
exports.getSelectedNode = getSelectedNode;
|
|
45
48
|
const getActiveElement = (editor, elementKey) => {
|
|
46
49
|
var _a;
|
|
47
|
-
const entry =
|
|
50
|
+
const entry = editor.api.node({
|
|
51
|
+
at: (_a = editor.selection) !== null && _a !== void 0 ? _a : undefined,
|
|
48
52
|
match: {
|
|
49
53
|
type: (0, exports.getPluginType)(editor, elementKey),
|
|
50
54
|
},
|
|
51
|
-
at: (_a = editor.selection) !== null && _a !== void 0 ? _a : undefined,
|
|
52
55
|
});
|
|
53
56
|
if (!entry) {
|
|
54
57
|
return;
|
|
@@ -59,8 +62,8 @@ const getActiveElement = (editor, elementKey) => {
|
|
|
59
62
|
exports.getActiveElement = getActiveElement;
|
|
60
63
|
const removeElement = (editor, node) => {
|
|
61
64
|
var _a;
|
|
62
|
-
const path =
|
|
63
|
-
|
|
65
|
+
const path = editor.api.findPath(node);
|
|
66
|
+
editor.tf.removeNodes({ at: path });
|
|
64
67
|
(0, exports.focusEditor)(editor, (_a = editor.selection) !== null && _a !== void 0 ? _a : undefined);
|
|
65
68
|
return true;
|
|
66
69
|
};
|
|
@@ -69,20 +72,20 @@ const insertVoid = (editor, node) => {
|
|
|
69
72
|
var _a;
|
|
70
73
|
const selectedNode = (0, exports.getSelectedNode)(editor);
|
|
71
74
|
if (!selectedNode) {
|
|
72
|
-
|
|
75
|
+
editor.tf.insertNodes(node);
|
|
73
76
|
}
|
|
74
77
|
else {
|
|
75
|
-
if (selectedNode.type !== types_1.PARAGRAPH_PLUGIN_TYPE || !
|
|
76
|
-
|
|
78
|
+
if (selectedNode.type !== types_1.PARAGRAPH_PLUGIN_TYPE || !editor.api.isEmpty(selectedNode)) {
|
|
79
|
+
editor.tf.insertExitBreak();
|
|
77
80
|
}
|
|
78
|
-
|
|
81
|
+
editor.tf.setNodes(node);
|
|
79
82
|
}
|
|
80
83
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
81
|
-
(0, exports.focusEditor)(editor, (_a = editor.selection) !== null && _a !== void 0 ? _a : editor.prevSelection);
|
|
84
|
+
(0, exports.focusEditor)(editor, (_a = editor.selection) !== null && _a !== void 0 ? _a : editor.dom.prevSelection);
|
|
82
85
|
};
|
|
83
86
|
exports.insertVoid = insertVoid;
|
|
84
87
|
const removeSelectedNode = (editor) => {
|
|
85
|
-
|
|
88
|
+
editor.tf.removeNodes();
|
|
86
89
|
(0, exports.focusEditor)(editor);
|
|
87
90
|
};
|
|
88
91
|
exports.removeSelectedNode = removeSelectedNode;
|
package/utils.test.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/utils.test.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const platejs_1 = require("platejs");
|
|
4
|
+
const create_paragraph_plugin_1 = require("./plugins/paragraph/create-paragraph-plugin");
|
|
5
|
+
const utils_1 = require("./utils");
|
|
6
|
+
function editor() {
|
|
7
|
+
return (0, platejs_1.createSlateEditor)({ plugins: [(0, create_paragraph_plugin_1.createParagraphPlugin)()] });
|
|
8
|
+
}
|
|
9
|
+
describe("plugin lookup helpers", () => {
|
|
10
|
+
it("resolves a plugin key to its stored node type", () => {
|
|
11
|
+
expect((0, utils_1.getPluginType)(editor(), "p")).toBe("paragraph");
|
|
12
|
+
});
|
|
13
|
+
it("reports a registered plugin as enabled", () => {
|
|
14
|
+
expect((0, utils_1.isPluginEnabled)(editor(), "p")).toBe(true);
|
|
15
|
+
});
|
|
16
|
+
it("reports an unregistered plugin as disabled", () => {
|
|
17
|
+
expect((0, utils_1.isPluginEnabled)(editor(), "image")).toBe(false);
|
|
18
|
+
});
|
|
19
|
+
it("matches when any one of several keys is registered", () => {
|
|
20
|
+
expect((0, utils_1.isSomeOfPluginsEnabled)(editor(), ["image", "p"])).toBe(true);
|
|
21
|
+
expect((0, utils_1.isSomeOfPluginsEnabled)(editor(), ["image", "video"])).toBe(false);
|
|
22
|
+
});
|
|
23
|
+
});
|
package/wysiwyg-editor.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { TEditableProps } from "@udecode/plate-core";
|
|
2
1
|
import { Noop } from "@uxf/core/types";
|
|
2
|
+
import { PlateContentProps } from "platejs/react";
|
|
3
3
|
import { FC, ForwardedRef, ReactNode } from "react";
|
|
4
4
|
import { UxfPlatePlugin, WysiwygContent } from "./types";
|
|
5
5
|
export interface WysiwygEditorHandle {
|
|
@@ -8,7 +8,7 @@ export interface WysiwygEditorHandle {
|
|
|
8
8
|
export interface WysiwygEditorProps {
|
|
9
9
|
className?: string;
|
|
10
10
|
customPluginsToolbarButtons?: ReactNode;
|
|
11
|
-
editableProps?:
|
|
11
|
+
editableProps?: PlateContentProps;
|
|
12
12
|
editorRef?: ForwardedRef<WysiwygEditorHandle>;
|
|
13
13
|
id: string;
|
|
14
14
|
initialValue: WysiwygContent | undefined;
|
package/wysiwyg-editor.js
CHANGED
|
@@ -35,13 +35,12 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
})();
|
|
36
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
37
|
exports.WysiwygEditor = void 0;
|
|
38
|
-
const plate_core_1 = require("@udecode/plate-core");
|
|
39
38
|
const classes_1 = require("@uxf/core/constants/classes");
|
|
40
39
|
const use_is_mounted_1 = require("@uxf/core-react/hooks/use-is-mounted");
|
|
41
40
|
const translations_1 = require("@uxf/core-react/translations");
|
|
42
41
|
const loader_1 = require("@uxf/ui/loader");
|
|
43
|
-
const react_1 =
|
|
44
|
-
const
|
|
42
|
+
const react_1 = require("platejs/react");
|
|
43
|
+
const react_2 = __importStar(require("react"));
|
|
45
44
|
const hooks_1 = require("./hooks");
|
|
46
45
|
const toolbar_1 = require("./ui/toolbar/toolbar");
|
|
47
46
|
const utils_1 = require("./utils");
|
|
@@ -50,13 +49,12 @@ const CLASS_NAME = "uxf-wysiwyg";
|
|
|
50
49
|
* Component that accesses the editor from Slate context and exposes focus method via ref
|
|
51
50
|
* Must be rendered inside Plate component
|
|
52
51
|
*/
|
|
53
|
-
const EditorRefHandler = (0,
|
|
52
|
+
const EditorRefHandler = (0, react_2.forwardRef)((props, ref) => {
|
|
54
53
|
const editor = (0, hooks_1.useUxfEditorRef)();
|
|
55
|
-
(0,
|
|
54
|
+
(0, react_2.useImperativeHandle)(ref, () => ({
|
|
56
55
|
focus: () => {
|
|
57
56
|
// Select the end of the document first
|
|
58
|
-
|
|
59
|
-
slate_1.Transforms.select(editor, end);
|
|
57
|
+
editor.tf.select(editor.api.end([]));
|
|
60
58
|
// Then focus the editor
|
|
61
59
|
(0, utils_1.focusEditor)(editor);
|
|
62
60
|
},
|
|
@@ -67,27 +65,35 @@ EditorRefHandler.displayName = "EditorRefHandler";
|
|
|
67
65
|
const Editor = (props) => {
|
|
68
66
|
var _a, _b;
|
|
69
67
|
const t = (0, translations_1.useUxfTranslation)();
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
68
|
+
/**
|
|
69
|
+
* `<Plate>` renders no DOM of its own, so the toolbar moving inside it leaves the markup identical
|
|
70
|
+
* while letting it take the editor from context instead of by id.
|
|
71
|
+
*/
|
|
72
|
+
const editor = (0, react_1.usePlateEditor)({
|
|
73
|
+
id: props.id,
|
|
74
|
+
plugins: props.plugins,
|
|
75
|
+
shouldNormalizeEditor: true,
|
|
76
|
+
value: props.initialValue,
|
|
77
|
+
}, [props.plugins]);
|
|
78
|
+
return (react_2.default.createElement(react_1.Plate, { editor: editor, onChange: ({ value }) => props.onChange(value) },
|
|
79
|
+
react_2.default.createElement(toolbar_1.Toolbar, { customPluginsButtons: props.customPluginsToolbarButtons, leftElement: props.toolbarLeftElement, plateId: props.id, rightElement: props.toolbarRightElement }),
|
|
80
|
+
react_2.default.createElement("div", { className: `${CLASS_NAME}__content` },
|
|
81
|
+
react_2.default.createElement(react_1.PlateContent, { autoFocus: false,
|
|
82
|
+
placeholder: t("uxf-wysiwyg:common.placeholder"),
|
|
83
|
+
readOnly: false,
|
|
84
|
+
spellCheck: false,
|
|
85
|
+
...props.editableProps,
|
|
86
|
+
className: `${CLASS_NAME}__editable ${(_b = (_a = props.editableProps) === null || _a === void 0 ? void 0 : _a.className) !== null && _b !== void 0 ? _b : ""}` }),
|
|
87
|
+
props.editorRef && react_2.default.createElement(EditorRefHandler, { ref: props.editorRef }))));
|
|
81
88
|
};
|
|
82
89
|
const WysiwygEditor = (props) => {
|
|
83
90
|
var _a, _b;
|
|
84
91
|
const isMounted = (0, use_is_mounted_1.useIsMounted)();
|
|
85
92
|
if (!isMounted) {
|
|
86
|
-
return (
|
|
87
|
-
|
|
93
|
+
return (react_2.default.createElement("div", { className: `${CLASS_NAME} ${CLASS_NAME}--${classes_1.CLASSES.IS_LOADING} ${(_a = props.className) !== null && _a !== void 0 ? _a : ""}` },
|
|
94
|
+
react_2.default.createElement(loader_1.Loader, { className: `${CLASS_NAME}__loader` })));
|
|
88
95
|
}
|
|
89
|
-
return (
|
|
90
|
-
|
|
91
|
-
react_1.default.createElement(Editor, { customPluginsToolbarButtons: props.customPluginsToolbarButtons, editableProps: props.editableProps, editorRef: props.editorRef, plateId: props.id, toolbarLeftElement: props.toolbarLeftElement, toolbarRightElement: props.toolbarRightElement }))));
|
|
96
|
+
return (react_2.default.createElement("div", { className: `${CLASS_NAME} ${(_b = props.className) !== null && _b !== void 0 ? _b : ""}` },
|
|
97
|
+
react_2.default.createElement(Editor, { customPluginsToolbarButtons: props.customPluginsToolbarButtons, editableProps: props.editableProps, editorRef: props.editorRef, id: props.id, initialValue: props.initialValue, onChange: props.onChange, plugins: props.plugins, toolbarLeftElement: props.toolbarLeftElement, toolbarRightElement: props.toolbarRightElement })));
|
|
92
98
|
};
|
|
93
99
|
exports.WysiwygEditor = WysiwygEditor;
|
package/wysiwyg-editor.test.js
CHANGED
|
@@ -58,19 +58,124 @@ const UI_CONTEXT = {
|
|
|
58
58
|
translationFn: (key) => key,
|
|
59
59
|
};
|
|
60
60
|
const INITIAL_VALUE = [{ type: "paragraph", children: [{ text: "hello" }] }];
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
// Plate's post-mount normalisation writes to its jotai store, which notifies subscribers a microtask
|
|
62
|
+
// later, outside render's act scope. Flushing it here settles the editor before the assertions.
|
|
63
|
+
async function settle() {
|
|
64
|
+
await (0, react_1.act)(async () => undefined);
|
|
65
|
+
}
|
|
66
|
+
async function renderEditor(editorRef) {
|
|
67
|
+
const result = (0, react_1.render)(react_2.default.createElement(context_1.UiContextProvider, { value: UI_CONTEXT },
|
|
63
68
|
react_2.default.createElement(wysiwyg_editor_1.WysiwygEditor, { editorRef: editorRef, id: "test-editor", initialValue: INITIAL_VALUE, onChange: () => undefined, plugins: (0, create_plugins_with_ui_1.createPluginsWithUi)([(0, create_all_plugins_with_ui_1.createBoldPluginWithUi)()]) })));
|
|
69
|
+
await settle();
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
const FILE = { extension: ".png", id: 1, name: "a.png", namespace: "wysiwyg", uuid: "u" };
|
|
73
|
+
/** One node of every element type, so each plugin's component has something to render. */
|
|
74
|
+
const EVERY_ELEMENT = [
|
|
75
|
+
{ children: [{ text: "Nadpis" }], type: "h1" },
|
|
76
|
+
{
|
|
77
|
+
children: [
|
|
78
|
+
{ bold: true, text: "tučně" },
|
|
79
|
+
{ italic: true, text: "kurzíva" },
|
|
80
|
+
{ text: "podtržené", underline: true },
|
|
81
|
+
{ code: true, text: "kód" },
|
|
82
|
+
{ highlight: true, text: "zvýrazněné" },
|
|
83
|
+
],
|
|
84
|
+
type: "paragraph",
|
|
85
|
+
},
|
|
86
|
+
{ children: [{ text: "citace" }], type: "blockquote" },
|
|
87
|
+
{ children: [{ children: [{ children: [{ text: "položka" }], type: "lic" }], type: "li" }], type: "ul" },
|
|
88
|
+
{ children: [{ children: [{ children: [{ text: "první" }], type: "lic" }], type: "li" }], type: "ol" },
|
|
89
|
+
{
|
|
90
|
+
children: [
|
|
91
|
+
{ text: "" },
|
|
92
|
+
{ children: [{ text: "odkaz" }], target: "_blank", type: "link", url: "https://uxf.cz" },
|
|
93
|
+
{ text: "" },
|
|
94
|
+
],
|
|
95
|
+
type: "paragraph",
|
|
96
|
+
},
|
|
97
|
+
{ alt: "alt", children: [{ text: "" }], file: FILE, type: "image", url: "https://example.test/a.png" },
|
|
98
|
+
{
|
|
99
|
+
children: [{ text: "" }],
|
|
100
|
+
embeddedUrl: "https://www.youtube.com/embed/x",
|
|
101
|
+
metaData: null,
|
|
102
|
+
provider: "youtube",
|
|
103
|
+
type: "video",
|
|
104
|
+
url: "https://youtu.be/x",
|
|
105
|
+
videoId: "x",
|
|
106
|
+
},
|
|
107
|
+
{ buttonText: "klik", buttonUrl: "https://uxf.cz", children: [{ text: "" }], type: "button" },
|
|
108
|
+
];
|
|
109
|
+
async function renderEditorWithAllPlugins() {
|
|
110
|
+
const result = (0, react_1.render)(react_2.default.createElement(context_1.UiContextProvider, { value: UI_CONTEXT },
|
|
111
|
+
react_2.default.createElement(wysiwyg_editor_1.WysiwygEditor, { id: "all-plugins-editor", initialValue: EVERY_ELEMENT, onChange: () => undefined, plugins: (0, create_all_plugins_with_ui_1.createAllPluginsWithUi)({
|
|
112
|
+
image: { getImageUrl: (file) => file.name, uploadImage: async () => FILE },
|
|
113
|
+
}) })));
|
|
114
|
+
await settle();
|
|
115
|
+
return result;
|
|
64
116
|
}
|
|
117
|
+
// Act warnings fail the test instead of scrolling past.
|
|
118
|
+
let actWarnings = [];
|
|
119
|
+
let consoleError;
|
|
120
|
+
beforeEach(() => {
|
|
121
|
+
actWarnings = [];
|
|
122
|
+
consoleError = jest.spyOn(console, "error").mockImplementation((...args) => {
|
|
123
|
+
if (String(args.at(0)).includes("not wrapped in act")) {
|
|
124
|
+
actWarnings.push(String(args.at(0)));
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
afterEach(() => {
|
|
129
|
+
consoleError.mockRestore();
|
|
130
|
+
expect(actWarnings).toEqual([]);
|
|
131
|
+
});
|
|
65
132
|
describe("WysiwygEditor", () => {
|
|
66
|
-
it("renders without an editorRef", () => {
|
|
67
|
-
const { container } = renderEditor();
|
|
133
|
+
it("renders without an editorRef", async () => {
|
|
134
|
+
const { container } = await renderEditor();
|
|
68
135
|
expect(container.querySelector(".uxf-wysiwyg__editable")).not.toBeNull();
|
|
69
136
|
});
|
|
70
|
-
it("exposes focus() through editorRef", () => {
|
|
137
|
+
it("exposes focus() through editorRef", async () => {
|
|
71
138
|
var _a;
|
|
72
139
|
const editorRef = (0, react_2.createRef)();
|
|
73
|
-
renderEditor(editorRef);
|
|
140
|
+
await renderEditor(editorRef);
|
|
74
141
|
expect(typeof ((_a = editorRef.current) === null || _a === void 0 ? void 0 : _a.focus)).toBe("function");
|
|
75
142
|
});
|
|
143
|
+
// Catches a plugin whose component never got attached: it typechecks, the editor renders, and the
|
|
144
|
+
// node silently comes out as a bare div.
|
|
145
|
+
it.each([
|
|
146
|
+
["uxf-wysiwyg__element-heading-h1"],
|
|
147
|
+
["uxf-wysiwyg__element-blockquote"],
|
|
148
|
+
["uxf-wysiwyg__element-list-unordered"],
|
|
149
|
+
["uxf-wysiwyg__element-list-ordered"],
|
|
150
|
+
["uxf-wysiwyg__element-list-item"],
|
|
151
|
+
["uxf-wysiwyg__element-link"],
|
|
152
|
+
["uxf-wysiwyg__element-image"],
|
|
153
|
+
["uxf-wysiwyg__element-video"],
|
|
154
|
+
["uxf-wysiwyg__element-button"],
|
|
155
|
+
])("renders %s through its own component", async (className) => {
|
|
156
|
+
const { container } = await renderEditorWithAllPlugins();
|
|
157
|
+
expect(container.querySelector(`.${className}`)).not.toBeNull();
|
|
158
|
+
});
|
|
159
|
+
// The element tests above pass even when a mark component is broken, which is how the highlight
|
|
160
|
+
// regression got through: the <mark> rendered, it just never received its colour.
|
|
161
|
+
it.each([
|
|
162
|
+
["uxf-wysiwyg__element-bold"],
|
|
163
|
+
["uxf-wysiwyg__element-italic"],
|
|
164
|
+
["uxf-wysiwyg__element-underline"],
|
|
165
|
+
["uxf-wysiwyg__element-code"],
|
|
166
|
+
["uxf-wysiwyg__element-highlight"],
|
|
167
|
+
])("renders %s through its own component", async (className) => {
|
|
168
|
+
const { container } = await renderEditorWithAllPlugins();
|
|
169
|
+
expect(container.querySelector(`.${className}`)).not.toBeNull();
|
|
170
|
+
});
|
|
171
|
+
it("gives highlight its configured colour, not a stray DOM attribute", async () => {
|
|
172
|
+
const { container } = await renderEditorWithAllPlugins();
|
|
173
|
+
const mark = container.querySelector(".uxf-wysiwyg__element-highlight");
|
|
174
|
+
expect(mark === null || mark === void 0 ? void 0 : mark.style.getPropertyValue("--highlight-color")).toBe("#fde047");
|
|
175
|
+
expect(mark === null || mark === void 0 ? void 0 : mark.hasAttribute("color")).toBe(false);
|
|
176
|
+
});
|
|
177
|
+
it("renders the paragraph component, which the facade attaches itself", async () => {
|
|
178
|
+
const { container } = await renderEditorWithAllPlugins();
|
|
179
|
+
expect(container.querySelector(".uxf-wysiwyg__element-paragraph")).not.toBeNull();
|
|
180
|
+
});
|
|
76
181
|
});
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { WithPlatePlugin } from "@udecode/plate-core";
|
|
2
|
-
import { UxfEditor, WysiwygContent } from "../../types";
|
|
3
|
-
import { UxfImagePluginOptions } from "./types";
|
|
4
|
-
/**
|
|
5
|
-
* @see withPasteImageUrl
|
|
6
|
-
*/
|
|
7
|
-
export declare const withImage: (editor: UxfEditor, plugin: WithPlatePlugin<UxfImagePluginOptions, WysiwygContent, UxfEditor>) => UxfEditor;
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.withImage = void 0;
|
|
4
|
-
const with_paste_image_1 = require("./with-paste-image");
|
|
5
|
-
const with_paste_image_url_1 = require("./with-paste-image-url");
|
|
6
|
-
/**
|
|
7
|
-
* @see withPasteImageUrl
|
|
8
|
-
*/
|
|
9
|
-
const withImage = (editor, plugin) => {
|
|
10
|
-
const { options: { disableUploadOnPasteImage, disableUploadOnPasteImageUrl }, } = plugin;
|
|
11
|
-
if (!disableUploadOnPasteImage) {
|
|
12
|
-
editor = (0, with_paste_image_1.withPasteImage)(editor, plugin);
|
|
13
|
-
}
|
|
14
|
-
if (!disableUploadOnPasteImageUrl) {
|
|
15
|
-
editor = (0, with_paste_image_url_1.withPasteImageUrl)(editor, plugin);
|
|
16
|
-
}
|
|
17
|
-
return editor;
|
|
18
|
-
};
|
|
19
|
-
exports.withImage = withImage;
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createResetNodePlugin = void 0;
|
|
4
|
-
const plate_common_1 = require("@udecode/plate-common");
|
|
5
|
-
const plate_reset_node_1 = require("@udecode/plate-reset-node");
|
|
6
|
-
const types_1 = require("../blockquote/types");
|
|
7
|
-
const types_2 = require("../paragraph/types");
|
|
8
|
-
const resetBlockTypesCommonRule = {
|
|
9
|
-
types: [types_1.BLOCKQUOTE_PLUGIN_KEY],
|
|
10
|
-
defaultType: types_2.PARAGRAPH_PLUGIN_KEY,
|
|
11
|
-
};
|
|
12
|
-
const createResetNodePlugin = () => (0, plate_reset_node_1.createResetNodePlugin)({
|
|
13
|
-
options: {
|
|
14
|
-
rules: [
|
|
15
|
-
{
|
|
16
|
-
...resetBlockTypesCommonRule,
|
|
17
|
-
hotkey: "Enter",
|
|
18
|
-
predicate: plate_common_1.isBlockAboveEmpty,
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
...resetBlockTypesCommonRule,
|
|
22
|
-
hotkey: "Backspace",
|
|
23
|
-
predicate: plate_common_1.isSelectionAtBlockStart,
|
|
24
|
-
},
|
|
25
|
-
],
|
|
26
|
-
},
|
|
27
|
-
});
|
|
28
|
-
exports.createResetNodePlugin = createResetNodePlugin;
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createSelectOnBackspacePlugin = void 0;
|
|
4
|
-
const plate_media_1 = require("@udecode/plate-media");
|
|
5
|
-
const plate_select_1 = require("@udecode/plate-select");
|
|
6
|
-
const types_1 = require("../image/types");
|
|
7
|
-
const createSelectOnBackspacePlugin = () => (0, plate_select_1.createSelectOnBackspacePlugin)({
|
|
8
|
-
options: {
|
|
9
|
-
query: {
|
|
10
|
-
allow: [types_1.IMAGE_PLUGIN_KEY, plate_media_1.ELEMENT_MEDIA_EMBED],
|
|
11
|
-
},
|
|
12
|
-
},
|
|
13
|
-
});
|
|
14
|
-
exports.createSelectOnBackspacePlugin = createSelectOnBackspacePlugin;
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createSoftBreakPlugin = void 0;
|
|
4
|
-
const plate_break_1 = require("@udecode/plate-break");
|
|
5
|
-
const types_1 = require("../blockquote/types");
|
|
6
|
-
const types_2 = require("../paragraph/types");
|
|
7
|
-
const createSoftBreakPlugin = () => (0, plate_break_1.createSoftBreakPlugin)({
|
|
8
|
-
options: {
|
|
9
|
-
rules: [
|
|
10
|
-
{
|
|
11
|
-
hotkey: "shift+enter",
|
|
12
|
-
},
|
|
13
|
-
{
|
|
14
|
-
hotkey: "enter",
|
|
15
|
-
query: {
|
|
16
|
-
allow: [types_2.PARAGRAPH_PLUGIN_KEY, types_1.BLOCKQUOTE_PLUGIN_KEY],
|
|
17
|
-
},
|
|
18
|
-
},
|
|
19
|
-
],
|
|
20
|
-
},
|
|
21
|
-
});
|
|
22
|
-
exports.createSoftBreakPlugin = createSoftBreakPlugin;
|