@squiz/formatted-text-editor 1.69.0 → 1.70.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/CHANGELOG.md +6 -0
- package/demo/App.tsx +15 -0
- package/lib/Editor/Editor.d.ts +2 -1
- package/lib/Editor/Editor.js +4 -2
- package/lib/EditorToolbar/Toolbar.d.ts +2 -1
- package/lib/EditorToolbar/Toolbar.js +4 -2
- package/lib/EditorToolbar/Tools/Table/TableButton.d.ts +3 -0
- package/lib/EditorToolbar/Tools/Table/TableButton.js +22 -0
- package/lib/Extensions/Extensions.js +4 -0
- package/lib/index.css +296 -0
- package/package.json +2 -1
- package/src/Editor/Editor.tsx +5 -1
- package/src/Editor/_editor.scss +365 -0
- package/src/EditorToolbar/Toolbar.tsx +4 -1
- package/src/EditorToolbar/Tools/Table/TableButton.spec.tsx +25 -0
- package/src/EditorToolbar/Tools/Table/TableButton.tsx +32 -0
- package/src/Extensions/Extensions.ts +5 -0
- package/src/utils/getNodeNamesByGroup.spec.ts +5 -0
package/CHANGELOG.md
CHANGED
package/demo/App.tsx
CHANGED
@@ -22,6 +22,7 @@ function App() {
|
|
22
22
|
const [reconvertedDoc, setReconvertedDoc] = useState('');
|
23
23
|
const [error, setError] = useState<unknown>(null);
|
24
24
|
const [editable, setEditable] = useState(true);
|
25
|
+
const [enableTableTool, setEnableTableTool] = useState(true);
|
25
26
|
const [border, setBorder] = useState(true);
|
26
27
|
|
27
28
|
const handleEditorChange: RemirrorEventListener<Extension> = (parameter) => {
|
@@ -45,8 +46,12 @@ function App() {
|
|
45
46
|
<div className="form-group">
|
46
47
|
<label htmlFor="editable">Editable</label>
|
47
48
|
<input id="editable" type="checkbox" onChange={() => setEditable(!editable)} checked={editable} />
|
49
|
+
</div>
|
50
|
+
<div className="form-group">
|
48
51
|
<label htmlFor="border">Border</label>
|
49
52
|
<input id="border" type="checkbox" onChange={() => setBorder(!border)} checked={border} />
|
53
|
+
</div>
|
54
|
+
<div className="form-group">
|
50
55
|
<label htmlFor="showChildren">Show children</label>
|
51
56
|
<input
|
52
57
|
id="showChildren"
|
@@ -55,6 +60,15 @@ function App() {
|
|
55
60
|
checked={showChildren}
|
56
61
|
/>
|
57
62
|
</div>
|
63
|
+
<div className="form-group">
|
64
|
+
<label htmlFor="tableTool">Enable table tool</label>
|
65
|
+
<input
|
66
|
+
id="tableTool"
|
67
|
+
type="checkbox"
|
68
|
+
onChange={() => setEnableTableTool(!enableTableTool)}
|
69
|
+
checked={enableTableTool}
|
70
|
+
/>
|
71
|
+
</div>
|
58
72
|
</div>
|
59
73
|
<h1>Editor</h1>
|
60
74
|
<div className="page-section">
|
@@ -64,6 +78,7 @@ function App() {
|
|
64
78
|
border={border}
|
65
79
|
content={`<p>Hello <a href="https://www.google.com"><strong>Mr Bean</strong></a>, nice to <a href="https://www.google.com">meet you</a>.<img src="https://media2.giphy.com/media/3o6ozsIxg5legYvggo/giphy.gif" height="150" width="200"/></p>`}
|
66
80
|
onChange={handleEditorChange}
|
81
|
+
enableTableTool={enableTableTool}
|
67
82
|
>
|
68
83
|
{showChildren && <ComponentHandlers />}
|
69
84
|
</Editor>
|
package/lib/Editor/Editor.d.ts
CHANGED
@@ -10,6 +10,7 @@ type EditorProps = {
|
|
10
10
|
isFocused?: boolean;
|
11
11
|
label?: string;
|
12
12
|
attributes?: Record<string, string>;
|
13
|
+
enableTableTool?: boolean;
|
13
14
|
};
|
14
|
-
declare const Editor: ({ content, className, border, editable, onChange, children, isFocused, attributes, }: EditorProps) => React.JSX.Element;
|
15
|
+
declare const Editor: ({ content, className, border, editable, onChange, children, isFocused, attributes, enableTableTool, }: EditorProps) => React.JSX.Element;
|
15
16
|
export default Editor;
|
package/lib/Editor/Editor.js
CHANGED
@@ -34,6 +34,7 @@ const EditorContext_1 = require("./EditorContext");
|
|
34
34
|
const Extensions_1 = require("../Extensions/Extensions");
|
35
35
|
const useFocus_1 = __importDefault(require("../hooks/useFocus"));
|
36
36
|
const resource_browser_1 = require("@squiz/resource-browser");
|
37
|
+
const extension_react_tables_1 = require("@remirror/extension-react-tables");
|
37
38
|
const WrappedEditor = () => {
|
38
39
|
const preventImagePaste = (0, react_1.useCallback)((event) => {
|
39
40
|
const { clipboardData } = event;
|
@@ -50,7 +51,7 @@ const WrappedEditor = () => {
|
|
50
51
|
(0, react_2.useEditorEvent)('paste', preventImagePaste);
|
51
52
|
return react_1.default.createElement(react_2.EditorComponent, null);
|
52
53
|
};
|
53
|
-
const Editor = ({ content, className, border = true, editable = true, onChange, children, isFocused, attributes, }) => {
|
54
|
+
const Editor = ({ content, className, border = true, editable = true, onChange, children, isFocused, attributes, enableTableTool = false, }) => {
|
54
55
|
const { manager, state, setState } = (0, react_2.useRemirror)({
|
55
56
|
extensions: (0, Extensions_1.createExtensions)((0, react_1.useContext)(EditorContext_1.EditorContext), (0, react_1.useContext)(resource_browser_1.ResourceBrowserContext)),
|
56
57
|
content,
|
@@ -70,9 +71,10 @@ const Editor = ({ content, className, border = true, editable = true, onChange,
|
|
70
71
|
}, []);
|
71
72
|
return (react_1.default.createElement("div", { ref: wrapperRef, onBlur: handleBlur, onFocusCapture: handleFocus, className: (0, clsx_1.default)('squiz-fte-scope', 'squiz-fte-scope__editor', !editable && 'squiz-fte-scope__editor--is-disabled', border && 'squiz-fte-scope__editor--bordered', className) },
|
72
73
|
react_1.default.createElement(react_2.Remirror, { manager: manager, state: state, editable: editable, onChange: handleChange, placeholder: "Write something", label: "Text editor", attributes: attributes },
|
73
|
-
editable && react_1.default.createElement(EditorToolbar_1.Toolbar, { isVisible: isVisible }),
|
74
|
+
editable && react_1.default.createElement(EditorToolbar_1.Toolbar, { isVisible: isVisible, enableTableTool: enableTableTool }),
|
74
75
|
children && react_1.default.createElement("div", { className: "squiz-fte-scope__editor__children" }, children),
|
75
76
|
react_1.default.createElement(WrappedEditor, null),
|
77
|
+
enableTableTool && react_1.default.createElement(extension_react_tables_1.TableComponents, { enableTableCellMenu: false }),
|
76
78
|
editable && isVisible && react_1.default.createElement(EditorToolbar_1.FloatingToolbar, null))));
|
77
79
|
};
|
78
80
|
exports.default = Editor;
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
type ToolbarProps = {
|
3
3
|
isVisible: boolean;
|
4
|
+
enableTableTool: boolean;
|
4
5
|
};
|
5
|
-
export declare const Toolbar: ({ isVisible }: ToolbarProps) => React.JSX.Element;
|
6
|
+
export declare const Toolbar: ({ isVisible, enableTableTool }: ToolbarProps) => React.JSX.Element;
|
6
7
|
export {};
|
@@ -20,8 +20,9 @@ const RemoveLinkButton_1 = __importDefault(require("./Tools/Link/RemoveLinkButto
|
|
20
20
|
const ClearFormattingButton_1 = __importDefault(require("./Tools/ClearFormatting/ClearFormattingButton"));
|
21
21
|
const ListButtons_1 = __importDefault(require("./Tools/Lists/ListButtons"));
|
22
22
|
const HorizontalLineButton_1 = __importDefault(require("./Tools/HorizontalLine/HorizontalLineButton"));
|
23
|
+
const TableButton_1 = __importDefault(require("./Tools/Table/TableButton"));
|
23
24
|
const hooks_1 = require("../hooks");
|
24
|
-
const Toolbar = ({ isVisible }) => {
|
25
|
+
const Toolbar = ({ isVisible, enableTableTool }) => {
|
25
26
|
const extensionNames = (0, hooks_1.useExtensionNames)();
|
26
27
|
return (react_1.default.createElement(react_components_1.Toolbar, { className: (0, clsx_1.default)('editor-toolbar header-toolbar', isVisible && 'show-toolbar'), role: "toolbar", tabIndex: 0 },
|
27
28
|
react_1.default.createElement("div", { className: "editor-toolbar__tools" },
|
@@ -40,6 +41,7 @@ const Toolbar = ({ isVisible }) => {
|
|
40
41
|
react_1.default.createElement(LinkButton_1.default, null),
|
41
42
|
react_1.default.createElement(RemoveLinkButton_1.default, null))),
|
42
43
|
extensionNames.image && react_1.default.createElement(ImageButton_1.default, null),
|
43
|
-
extensionNames.clearFormatting && react_1.default.createElement(ClearFormattingButton_1.default, null)
|
44
|
+
extensionNames.clearFormatting && react_1.default.createElement(ClearFormattingButton_1.default, null),
|
45
|
+
enableTableTool && extensionNames.table && react_1.default.createElement(TableButton_1.default, null))));
|
44
46
|
};
|
45
47
|
exports.Toolbar = Toolbar;
|
@@ -0,0 +1,22 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
+
};
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
+
const react_1 = __importDefault(require("react"));
|
7
|
+
const react_2 = require("@remirror/react");
|
8
|
+
const react_components_1 = require("@remirror/react-components");
|
9
|
+
const Button_1 = __importDefault(require("../../../ui/Button/Button"));
|
10
|
+
const TableViewRounded_1 = __importDefault(require("@mui/icons-material/TableViewRounded"));
|
11
|
+
const TableButton = () => {
|
12
|
+
const { createTable } = (0, react_2.useCommands)();
|
13
|
+
const active = (0, react_2.useActive)();
|
14
|
+
const enabled = createTable.enabled();
|
15
|
+
const handleSelect = () => {
|
16
|
+
createTable({ rowsCount: 4, columnsCount: 3, withHeaderRow: false });
|
17
|
+
};
|
18
|
+
return (react_1.default.createElement(react_1.default.Fragment, null,
|
19
|
+
react_1.default.createElement(Button_1.default, { handleOnClick: handleSelect, isDisabled: !enabled, isActive: active.table(), icon: react_1.default.createElement(TableViewRounded_1.default, null), label: "Insert table" }),
|
20
|
+
react_1.default.createElement(react_components_1.VerticalDivider, null)));
|
21
|
+
};
|
22
|
+
exports.default = TableButton;
|
@@ -12,6 +12,8 @@ const CodeBlockExtension_1 = require("./CodeBlockExtension/CodeBlockExtension");
|
|
12
12
|
const ClearFormattingExtension_1 = require("./ClearFormattingExtension/ClearFormattingExtension");
|
13
13
|
const UnsupportedNodeExtension_1 = require("./UnsuportedExtension/UnsupportedNodeExtension");
|
14
14
|
const FetchUrlExtension_1 = require("./FetchUrlExtension/FetchUrlExtension");
|
15
|
+
const extension_react_tables_1 = require("@remirror/extension-react-tables");
|
16
|
+
const extension_react_component_1 = require("@remirror/extension-react-component");
|
15
17
|
var NodeName;
|
16
18
|
(function (NodeName) {
|
17
19
|
NodeName["Image"] = "image";
|
@@ -61,6 +63,8 @@ const createExtensions = (context, browserContext) => {
|
|
61
63
|
fetchUrl: browserContext.onRequestResource,
|
62
64
|
}),
|
63
65
|
new extensions_1.TextExtension(),
|
66
|
+
new extension_react_tables_1.TableExtension(),
|
67
|
+
new extension_react_component_1.ReactComponentExtension(),
|
64
68
|
];
|
65
69
|
};
|
66
70
|
};
|
package/lib/index.css
CHANGED
@@ -445,6 +445,9 @@
|
|
445
445
|
.squiz-fte-scope .flex {
|
446
446
|
display: flex !important;
|
447
447
|
}
|
448
|
+
.squiz-fte-scope .table {
|
449
|
+
display: table !important;
|
450
|
+
}
|
448
451
|
.squiz-fte-scope .grid {
|
449
452
|
display: grid !important;
|
450
453
|
}
|
@@ -799,6 +802,9 @@
|
|
799
802
|
--tw-bg-opacity: 1;
|
800
803
|
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
801
804
|
}
|
805
|
+
.squiz-fte-scope.squiz-fte-scope__editor .squiz-fte-scope__floating-popover {
|
806
|
+
z-index: 999;
|
807
|
+
}
|
802
808
|
.squiz-fte-scope.squiz-fte-scope__editor:has(.squiz-fte-scope.squiz-fte-scope__editor__children) {
|
803
809
|
min-height: 2rem;
|
804
810
|
width: 100%;
|
@@ -825,6 +831,9 @@
|
|
825
831
|
position: relative;
|
826
832
|
display: block;
|
827
833
|
}
|
834
|
+
.squiz-fte-scope.squiz-fte-scope__editor .remirror-editor-wrapper {
|
835
|
+
position: relative;
|
836
|
+
}
|
828
837
|
.squiz-fte-scope.squiz-fte-scope__editor--bordered {
|
829
838
|
border-width: 2px;
|
830
839
|
border-style: solid;
|
@@ -865,6 +874,293 @@
|
|
865
874
|
var(--tw-ring-shadow, 0 0 #0000),
|
866
875
|
var(--tw-shadow);
|
867
876
|
}
|
877
|
+
.squiz-fte-scope.squiz-fte-scope__editor .remirror-table {
|
878
|
+
width: 100%;
|
879
|
+
}
|
880
|
+
.squiz-fte-scope.squiz-fte-scope__editor .remirror-table-container {
|
881
|
+
margin: 2rem;
|
882
|
+
}
|
883
|
+
.squiz-fte-scope.squiz-fte-scope__editor .remirror-table tbody th,
|
884
|
+
.squiz-fte-scope.squiz-fte-scope__editor .remirror-table tbody td {
|
885
|
+
padding: 0.5rem;
|
886
|
+
}
|
887
|
+
.squiz-fte-scope.squiz-fte-scope__editor .remirror-table tbody p {
|
888
|
+
margin: 0;
|
889
|
+
}
|
890
|
+
.squiz-fte-scope :root {
|
891
|
+
--rmr-color-table-default-border: #e0e0e0;
|
892
|
+
--rmr-color-table-selected-cell: transparent;
|
893
|
+
--rmr-color-table-selected-border: #0774d2;
|
894
|
+
--rmr-color-table-selected-controller: #0774d2;
|
895
|
+
--rmr-hue-blue-7: #0774d2;
|
896
|
+
--rmr-color-table-mark: #f5f5f5;
|
897
|
+
--rmr-color-table-default-controller: #f7f7f7;
|
898
|
+
--rmr-color-table-predelete-cell: transparent;
|
899
|
+
--rmr-color-table-predelete-border: #d72321;
|
900
|
+
--rmr-color-table-predelete-controller: #d72321;
|
901
|
+
}
|
902
|
+
.squiz-fte-scope .remirror-positioner {
|
903
|
+
cursor: none;
|
904
|
+
min-height: 1px;
|
905
|
+
min-width: 1px;
|
906
|
+
pointer-events: none;
|
907
|
+
position: absolute;
|
908
|
+
-webkit-user-select: none;
|
909
|
+
-moz-user-select: none;
|
910
|
+
user-select: none;
|
911
|
+
z-index: -1;
|
912
|
+
}
|
913
|
+
.squiz-fte-scope .remirror-positioner-widget {
|
914
|
+
height: 0;
|
915
|
+
position: absolute;
|
916
|
+
width: 0;
|
917
|
+
}
|
918
|
+
.squiz-fte-scope .remirror-editor.ProseMirror .tableWrapper {
|
919
|
+
overflow-x: auto;
|
920
|
+
}
|
921
|
+
.squiz-fte-scope .remirror-editor.ProseMirror table {
|
922
|
+
border-collapse: collapse;
|
923
|
+
overflow: hidden;
|
924
|
+
table-layout: fixed;
|
925
|
+
width: 100%;
|
926
|
+
}
|
927
|
+
.squiz-fte-scope .remirror-editor.ProseMirror td,
|
928
|
+
.squiz-fte-scope .remirror-editor.ProseMirror th {
|
929
|
+
border-color: var(--rmr-color-table-default-border);
|
930
|
+
border-style: solid;
|
931
|
+
border-width: 1px;
|
932
|
+
box-sizing: border-box;
|
933
|
+
position: relative;
|
934
|
+
vertical-align: top;
|
935
|
+
}
|
936
|
+
.squiz-fte-scope .remirror-editor.ProseMirror .column-resize-handle {
|
937
|
+
background-color: var(--rmr-hue-blue-7);
|
938
|
+
bottom: 0;
|
939
|
+
pointer-events: none;
|
940
|
+
position: absolute;
|
941
|
+
right: -2px;
|
942
|
+
top: 0;
|
943
|
+
width: 4px;
|
944
|
+
z-index: 40;
|
945
|
+
}
|
946
|
+
.squiz-fte-scope .remirror-editor.ProseMirror.resize-cursor {
|
947
|
+
cursor: ew-resize;
|
948
|
+
cursor: col-resize;
|
949
|
+
}
|
950
|
+
.squiz-fte-scope .remirror-editor.ProseMirror td.selectedCell,
|
951
|
+
.squiz-fte-scope .remirror-editor.ProseMirror th.selectedCell {
|
952
|
+
background-color: var(--rmr-color-table-selected-cell);
|
953
|
+
border-color: var(--rmr-color-table-selected-border);
|
954
|
+
border-style: double;
|
955
|
+
}
|
956
|
+
.squiz-fte-scope .remirror-table-colgroup > col:first-of-type {
|
957
|
+
overflow: visible;
|
958
|
+
width: 13px;
|
959
|
+
}
|
960
|
+
.squiz-fte-scope .remirror-controllers-toggle {
|
961
|
+
visibility: hidden;
|
962
|
+
}
|
963
|
+
.squiz-fte-scope .remirror-table-show-controllers .remirror-controllers-toggle {
|
964
|
+
visibility: visible;
|
965
|
+
}
|
966
|
+
.squiz-fte-scope .remirror-table-insert-button {
|
967
|
+
background-color: #dcdcdc;
|
968
|
+
border-radius: 4px;
|
969
|
+
cursor: pointer;
|
970
|
+
height: 18px;
|
971
|
+
position: absolute;
|
972
|
+
transition: background-color 0.15s ease;
|
973
|
+
width: 18px;
|
974
|
+
z-index: 25;
|
975
|
+
}
|
976
|
+
.squiz-fte-scope .remirror-table-insert-button svg {
|
977
|
+
fill: #fff;
|
978
|
+
}
|
979
|
+
.squiz-fte-scope .remirror-table-insert-button:hover {
|
980
|
+
background-color: #136bda;
|
981
|
+
}
|
982
|
+
.squiz-fte-scope .remirror-table-insert-button:hover svg {
|
983
|
+
fill: #fff;
|
984
|
+
}
|
985
|
+
.squiz-fte-scope .remirror-table-delete-inner-button {
|
986
|
+
background-color: #cecece;
|
987
|
+
border: none;
|
988
|
+
border-radius: 4px;
|
989
|
+
cursor: pointer;
|
990
|
+
height: 18px;
|
991
|
+
padding: 0;
|
992
|
+
position: absolute;
|
993
|
+
transition: background-color 0.15s ease;
|
994
|
+
width: 18px;
|
995
|
+
z-index: 30;
|
996
|
+
}
|
997
|
+
.squiz-fte-scope .remirror-table-delete-inner-button:hover {
|
998
|
+
background-color: #ff7884;
|
999
|
+
}
|
1000
|
+
.squiz-fte-scope .remirror-table-delete-table-inner-button {
|
1001
|
+
left: calc(var(--remirror-table-delete-button-x) - 9px);
|
1002
|
+
top: calc(var(--remirror-table-delete-button-y) - 9px);
|
1003
|
+
}
|
1004
|
+
.squiz-fte-scope .remirror-table-delete-row-column-inner-button {
|
1005
|
+
left: calc(var(--remirror-table-delete-row-column-button-x) - 9px);
|
1006
|
+
top: calc(var(--remirror-table-delete-row-column-button-y) - 9px);
|
1007
|
+
}
|
1008
|
+
.squiz-fte-scope .remirror-table-with-controllers {
|
1009
|
+
height: 1px;
|
1010
|
+
margin-bottom: 40px;
|
1011
|
+
margin-top: 40px;
|
1012
|
+
}
|
1013
|
+
.squiz-fte-scope .ProseMirror table.remirror-table-with-controllers {
|
1014
|
+
overflow: visible;
|
1015
|
+
}
|
1016
|
+
.squiz-fte-scope .remirror-table-waitting-controllers {
|
1017
|
+
display: none;
|
1018
|
+
}
|
1019
|
+
.squiz-fte-scope .remirror-table-tbody-with-controllers > tr:first-of-type {
|
1020
|
+
height: 12px;
|
1021
|
+
overflow: visible;
|
1022
|
+
}
|
1023
|
+
.squiz-fte-scope .remirror-table-tbody-with-controllers > tr:first-of-type th:first-of-type {
|
1024
|
+
cursor: pointer;
|
1025
|
+
height: 12px;
|
1026
|
+
overflow: visible;
|
1027
|
+
padding: 0;
|
1028
|
+
position: relative;
|
1029
|
+
width: 12px;
|
1030
|
+
z-index: 15;
|
1031
|
+
}
|
1032
|
+
.squiz-fte-scope .remirror-table-tbody-with-controllers > tr:first-of-type th:first-of-type div.remirror-table-controller-wrapper {
|
1033
|
+
align-items: flex-end;
|
1034
|
+
display: flex;
|
1035
|
+
height: 12px;
|
1036
|
+
justify-content: flex-end;
|
1037
|
+
overflow: visible;
|
1038
|
+
width: 12px;
|
1039
|
+
}
|
1040
|
+
.squiz-fte-scope .remirror-table-tbody-with-controllers > tr:first-of-type th:first-of-type div.remirror-table-controller-trigger-area {
|
1041
|
+
display: none;
|
1042
|
+
flex: 1;
|
1043
|
+
position: relative;
|
1044
|
+
z-index: 10;
|
1045
|
+
}
|
1046
|
+
.squiz-fte-scope .remirror-table-tbody-with-controllers > tr:first-of-type th:first-of-type div.remirror-table-controller-mark-row-corner {
|
1047
|
+
border-color: var(--rmr-color-table-mark);
|
1048
|
+
border-radius: 50%;
|
1049
|
+
border-style: solid;
|
1050
|
+
border-width: 2px;
|
1051
|
+
bottom: -2px;
|
1052
|
+
height: 0;
|
1053
|
+
left: -12px;
|
1054
|
+
position: absolute;
|
1055
|
+
width: 0;
|
1056
|
+
}
|
1057
|
+
.squiz-fte-scope .remirror-table-tbody-with-controllers > tr:first-of-type th:first-of-type div.remirror-table-controller-mark-column-corner {
|
1058
|
+
border-color: var(--rmr-color-table-mark);
|
1059
|
+
border-radius: 50%;
|
1060
|
+
border-style: solid;
|
1061
|
+
border-width: 2px;
|
1062
|
+
height: 0;
|
1063
|
+
position: absolute;
|
1064
|
+
right: -2px;
|
1065
|
+
top: -12px;
|
1066
|
+
width: 0;
|
1067
|
+
}
|
1068
|
+
.squiz-fte-scope .remirror-table-tbody-with-controllers > tr:first-of-type th:nth-of-type(n + 2) {
|
1069
|
+
cursor: pointer;
|
1070
|
+
height: 12px;
|
1071
|
+
overflow: visible;
|
1072
|
+
padding: 0;
|
1073
|
+
position: relative;
|
1074
|
+
z-index: 15;
|
1075
|
+
}
|
1076
|
+
.squiz-fte-scope .remirror-table-tbody-with-controllers > tr:first-of-type th:nth-of-type(n + 2) div.remirror-table-controller-wrapper {
|
1077
|
+
align-items: flex-end;
|
1078
|
+
display: flex;
|
1079
|
+
flex-direction: row;
|
1080
|
+
height: 12px;
|
1081
|
+
justify-content: flex-end;
|
1082
|
+
overflow: visible;
|
1083
|
+
width: 100%;
|
1084
|
+
}
|
1085
|
+
.squiz-fte-scope .remirror-table-tbody-with-controllers > tr:first-of-type th:nth-of-type(n + 2) div.remirror-table-controller-trigger-area {
|
1086
|
+
flex: 1;
|
1087
|
+
height: 36px;
|
1088
|
+
position: relative;
|
1089
|
+
z-index: 10;
|
1090
|
+
}
|
1091
|
+
.squiz-fte-scope .remirror-table-tbody-with-controllers > tr:first-of-type th:nth-of-type(n + 2) div.remirror-table-controller-mark-row-corner {
|
1092
|
+
display: none;
|
1093
|
+
}
|
1094
|
+
.squiz-fte-scope .remirror-table-tbody-with-controllers > tr:first-of-type th:nth-of-type(n + 2) div.remirror-table-controller-mark-column-corner {
|
1095
|
+
border-color: var(--rmr-color-table-mark);
|
1096
|
+
border-radius: 50%;
|
1097
|
+
border-style: solid;
|
1098
|
+
border-width: 2px;
|
1099
|
+
height: 0;
|
1100
|
+
position: absolute;
|
1101
|
+
right: -2px;
|
1102
|
+
top: -12px;
|
1103
|
+
width: 0;
|
1104
|
+
}
|
1105
|
+
.squiz-fte-scope .remirror-table-tbody-with-controllers > tr:nth-of-type(n + 2) th {
|
1106
|
+
cursor: pointer;
|
1107
|
+
overflow: visible;
|
1108
|
+
padding: 0;
|
1109
|
+
position: relative;
|
1110
|
+
width: 12px;
|
1111
|
+
z-index: 15;
|
1112
|
+
}
|
1113
|
+
.squiz-fte-scope .remirror-table-tbody-with-controllers > tr:nth-of-type(n + 2) th div.remirror-table-controller-wrapper {
|
1114
|
+
align-items: flex-end;
|
1115
|
+
display: flex;
|
1116
|
+
flex-direction: column;
|
1117
|
+
height: 100%;
|
1118
|
+
justify-content: flex-end;
|
1119
|
+
overflow: visible;
|
1120
|
+
width: 12px;
|
1121
|
+
}
|
1122
|
+
.squiz-fte-scope .remirror-table-tbody-with-controllers > tr:nth-of-type(n + 2) th div.remirror-table-controller-trigger-area {
|
1123
|
+
flex: 1;
|
1124
|
+
position: relative;
|
1125
|
+
width: 36px;
|
1126
|
+
z-index: 10;
|
1127
|
+
}
|
1128
|
+
.squiz-fte-scope .remirror-table-tbody-with-controllers > tr:nth-of-type(n + 2) th div.remirror-table-controller-mark-row-corner {
|
1129
|
+
border-color: var(--rmr-color-table-mark);
|
1130
|
+
border-radius: 50%;
|
1131
|
+
border-style: solid;
|
1132
|
+
border-width: 2px;
|
1133
|
+
bottom: -2px;
|
1134
|
+
height: 0;
|
1135
|
+
left: -12px;
|
1136
|
+
position: absolute;
|
1137
|
+
width: 0;
|
1138
|
+
}
|
1139
|
+
.squiz-fte-scope .remirror-table-tbody-with-controllers > tr:nth-of-type(n + 2) th div.remirror-table-controller-mark-column-corner {
|
1140
|
+
display: none;
|
1141
|
+
}
|
1142
|
+
.squiz-fte-scope .remirror-table-tbody-with-controllers th.remirror-table-controller {
|
1143
|
+
background-color: var(--rmr-color-table-default-controller);
|
1144
|
+
}
|
1145
|
+
.squiz-fte-scope .remirror-table-tbody-with-controllers th.selectedCell.remirror-table-controller {
|
1146
|
+
background-color: var(--rmr-color-table-selected-controller);
|
1147
|
+
}
|
1148
|
+
.squiz-fte-scope .remirror-table-show-predelete td.selectedCell,
|
1149
|
+
.squiz-fte-scope .remirror-table-show-predelete th.selectedCell.remirror-table-controller {
|
1150
|
+
background-color: var(--rmr-color-table-predelete-cell) !important;
|
1151
|
+
border-color: var(--rmr-color-table-predelete-border) !important;
|
1152
|
+
}
|
1153
|
+
.squiz-fte-scope .remirror-table-show-predelete th.selectedCell.remirror-table-controller {
|
1154
|
+
background-color: var(--rmr-color-table-predelete-controller) !important;
|
1155
|
+
}
|
1156
|
+
.squiz-fte-scope .remirror-table-show-predelete.remirror-table-preselect-all td,
|
1157
|
+
.squiz-fte-scope .remirror-table-show-predelete.remirror-table-preselect-all th.remirror-table-controller {
|
1158
|
+
background-color: var(--rmr-color-table-predelete-cell) !important;
|
1159
|
+
border-color: var(--rmr-color-table-predelete-border) !important;
|
1160
|
+
}
|
1161
|
+
.squiz-fte-scope .remirror-table-show-predelete.remirror-table-preselect-all th.remirror-table-controller {
|
1162
|
+
background-color: var(--rmr-color-table-predelete-controller) !important;
|
1163
|
+
}
|
868
1164
|
.squiz-fte-scope .editor-toolbar,
|
869
1165
|
.squiz-fte-scope__floating-popover {
|
870
1166
|
border-top-left-radius: 8px;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@squiz/formatted-text-editor",
|
3
|
-
"version": "1.
|
3
|
+
"version": "1.70.0",
|
4
4
|
"main": "lib/index.js",
|
5
5
|
"types": "lib/index.d.ts",
|
6
6
|
"private": false,
|
@@ -22,6 +22,7 @@
|
|
22
22
|
"dependencies": {
|
23
23
|
"@headlessui/react": "1.7.11",
|
24
24
|
"@mui/icons-material": "5.11.16",
|
25
|
+
"@remirror/extension-react-tables": "^2.2.19",
|
25
26
|
"@remirror/react": "2.0.25",
|
26
27
|
"@squiz/dx-json-schema-lib": "^1.65.1",
|
27
28
|
"@squiz/resource-browser": "^1.66.3",
|
package/src/Editor/Editor.tsx
CHANGED
@@ -8,6 +8,7 @@ import { EditorContext } from './EditorContext';
|
|
8
8
|
import { createExtensions } from '../Extensions/Extensions';
|
9
9
|
import useFocus from '../hooks/useFocus';
|
10
10
|
import { ResourceBrowserContext } from '@squiz/resource-browser';
|
11
|
+
import { TableComponents } from '@remirror/extension-react-tables';
|
11
12
|
|
12
13
|
type EditorProps = {
|
13
14
|
className?: string;
|
@@ -19,6 +20,7 @@ type EditorProps = {
|
|
19
20
|
isFocused?: boolean;
|
20
21
|
label?: string;
|
21
22
|
attributes?: Record<string, string>;
|
23
|
+
enableTableTool?: boolean;
|
22
24
|
};
|
23
25
|
|
24
26
|
const WrappedEditor = () => {
|
@@ -51,6 +53,7 @@ const Editor = ({
|
|
51
53
|
children,
|
52
54
|
isFocused,
|
53
55
|
attributes,
|
56
|
+
enableTableTool = false,
|
54
57
|
}: EditorProps) => {
|
55
58
|
const { manager, state, setState } = useRemirror({
|
56
59
|
extensions: createExtensions(useContext(EditorContext), useContext(ResourceBrowserContext)),
|
@@ -95,9 +98,10 @@ const Editor = ({
|
|
95
98
|
label="Text editor"
|
96
99
|
attributes={attributes}
|
97
100
|
>
|
98
|
-
{editable && <Toolbar isVisible={isVisible} />}
|
101
|
+
{editable && <Toolbar isVisible={isVisible} enableTableTool={enableTableTool} />}
|
99
102
|
{children && <div className="squiz-fte-scope__editor__children">{children}</div>}
|
100
103
|
<WrappedEditor />
|
104
|
+
{enableTableTool && <TableComponents enableTableCellMenu={false} />}
|
101
105
|
{editable && isVisible && <FloatingToolbar />}
|
102
106
|
</Remirror>
|
103
107
|
</div>
|
package/src/Editor/_editor.scss
CHANGED
@@ -3,6 +3,10 @@
|
|
3
3
|
font-family: 'Open Sans' !important;
|
4
4
|
@apply bg-white rounded border-gray-300;
|
5
5
|
|
6
|
+
.squiz-fte-scope__floating-popover {
|
7
|
+
z-index: 999; // ensure table styles don't hide this menu
|
8
|
+
}
|
9
|
+
|
6
10
|
&:has(&__children) {
|
7
11
|
/* The children replace the space taken up by top padding of the editor when present. */
|
8
12
|
@apply w-full min-h-[2rem];
|
@@ -27,6 +31,10 @@
|
|
27
31
|
/* Make sure content aligned with "text-align: justify" is justified */
|
28
32
|
@apply block;
|
29
33
|
}
|
34
|
+
|
35
|
+
&-wrapper {
|
36
|
+
position: relative;
|
37
|
+
}
|
30
38
|
}
|
31
39
|
|
32
40
|
&--bordered {
|
@@ -62,4 +70,361 @@
|
|
62
70
|
&:has(.show-toolbar) {
|
63
71
|
@apply shadow-md border-0;
|
64
72
|
}
|
73
|
+
|
74
|
+
// Tables
|
75
|
+
.remirror-table {
|
76
|
+
&-container {
|
77
|
+
@apply m-8;
|
78
|
+
}
|
79
|
+
|
80
|
+
width: 100%;
|
81
|
+
|
82
|
+
tbody {
|
83
|
+
th,
|
84
|
+
td {
|
85
|
+
@apply p-2;
|
86
|
+
}
|
87
|
+
|
88
|
+
p {
|
89
|
+
margin: 0; // everything is by default a paragraph, inside the table that does not make sense so remove the margin
|
90
|
+
}
|
91
|
+
}
|
92
|
+
}
|
93
|
+
}
|
94
|
+
|
95
|
+
// TODO: work through this nonsense and see which bits are necessary for functionality
|
96
|
+
:root {
|
97
|
+
--rmr-color-table-default-border: #e0e0e0;
|
98
|
+
--rmr-color-table-selected-cell: transparent;
|
99
|
+
--rmr-color-table-selected-border: #0774d2;
|
100
|
+
--rmr-color-table-selected-controller: #0774d2;
|
101
|
+
--rmr-hue-blue-7: #0774d2;
|
102
|
+
--rmr-color-table-mark: #f5f5f5;
|
103
|
+
--rmr-color-table-default-controller: #f7f7f7;
|
104
|
+
--rmr-color-table-predelete-cell: transparent;
|
105
|
+
--rmr-color-table-predelete-border: #d72321;
|
106
|
+
--rmr-color-table-predelete-controller: #d72321;
|
107
|
+
}
|
108
|
+
|
109
|
+
//remirror styles
|
110
|
+
.remirror-positioner {
|
111
|
+
cursor: none;
|
112
|
+
min-height: 1px;
|
113
|
+
min-width: 1px;
|
114
|
+
pointer-events: none;
|
115
|
+
position: absolute;
|
116
|
+
-webkit-user-select: none;
|
117
|
+
-moz-user-select: none;
|
118
|
+
-ms-user-select: none;
|
119
|
+
user-select: none;
|
120
|
+
z-index: -1;
|
121
|
+
}
|
122
|
+
|
123
|
+
.remirror-positioner-widget {
|
124
|
+
height: 0;
|
125
|
+
position: absolute;
|
126
|
+
width: 0;
|
127
|
+
}
|
128
|
+
|
129
|
+
.remirror-editor.ProseMirror .tableWrapper {
|
130
|
+
overflow-x: auto;
|
131
|
+
}
|
132
|
+
|
133
|
+
.remirror-editor.ProseMirror table {
|
134
|
+
border-collapse: collapse;
|
135
|
+
overflow: hidden;
|
136
|
+
table-layout: fixed;
|
137
|
+
width: 100%;
|
138
|
+
}
|
139
|
+
|
140
|
+
.remirror-editor.ProseMirror td,
|
141
|
+
.remirror-editor.ProseMirror th {
|
142
|
+
border-color: var(--rmr-color-table-default-border);
|
143
|
+
border-style: solid;
|
144
|
+
border-width: 1px;
|
145
|
+
box-sizing: border-box;
|
146
|
+
position: relative;
|
147
|
+
vertical-align: top;
|
148
|
+
}
|
149
|
+
|
150
|
+
.remirror-editor.ProseMirror .column-resize-handle {
|
151
|
+
background-color: var(--rmr-hue-blue-7);
|
152
|
+
bottom: 0;
|
153
|
+
pointer-events: none;
|
154
|
+
position: absolute;
|
155
|
+
right: -2px;
|
156
|
+
top: 0;
|
157
|
+
width: 4px;
|
158
|
+
z-index: 40;
|
159
|
+
}
|
160
|
+
|
161
|
+
.remirror-editor.ProseMirror.resize-cursor {
|
162
|
+
cursor: ew-resize;
|
163
|
+
cursor: col-resize;
|
164
|
+
}
|
165
|
+
|
166
|
+
.remirror-editor.ProseMirror td.selectedCell,
|
167
|
+
.remirror-editor.ProseMirror th.selectedCell {
|
168
|
+
background-color: var(--rmr-color-table-selected-cell);
|
169
|
+
border-color: var(--rmr-color-table-selected-border);
|
170
|
+
border-style: double;
|
171
|
+
}
|
172
|
+
|
173
|
+
.remirror-table-colgroup > col:first-of-type {
|
174
|
+
overflow: visible;
|
175
|
+
width: 13px;
|
176
|
+
}
|
177
|
+
|
178
|
+
.remirror-controllers-toggle {
|
179
|
+
visibility: hidden;
|
180
|
+
}
|
181
|
+
|
182
|
+
.remirror-table-show-controllers .remirror-controllers-toggle {
|
183
|
+
visibility: visible;
|
184
|
+
}
|
185
|
+
|
186
|
+
.remirror-table-insert-button {
|
187
|
+
background-color: #dcdcdc;
|
188
|
+
border-radius: 4px;
|
189
|
+
cursor: pointer;
|
190
|
+
height: 18px;
|
191
|
+
position: absolute;
|
192
|
+
transition: background-color 0.15s ease;
|
193
|
+
width: 18px;
|
194
|
+
z-index: 25;
|
195
|
+
}
|
196
|
+
|
197
|
+
.remirror-table-insert-button svg {
|
198
|
+
fill: #fff;
|
199
|
+
}
|
200
|
+
|
201
|
+
.remirror-table-insert-button:hover {
|
202
|
+
background-color: #136bda;
|
203
|
+
}
|
204
|
+
|
205
|
+
.remirror-table-insert-button:hover svg {
|
206
|
+
fill: #fff;
|
207
|
+
}
|
208
|
+
|
209
|
+
.remirror-table-delete-inner-button {
|
210
|
+
background-color: #cecece;
|
211
|
+
border: none;
|
212
|
+
border-radius: 4px;
|
213
|
+
cursor: pointer;
|
214
|
+
height: 18px;
|
215
|
+
padding: 0;
|
216
|
+
position: absolute;
|
217
|
+
transition: background-color 0.15s ease;
|
218
|
+
width: 18px;
|
219
|
+
z-index: 30;
|
220
|
+
}
|
221
|
+
|
222
|
+
.remirror-table-delete-inner-button:hover {
|
223
|
+
background-color: #ff7884;
|
224
|
+
}
|
225
|
+
|
226
|
+
.remirror-table-delete-table-inner-button {
|
227
|
+
left: calc(var(--remirror-table-delete-button-x) - 9px);
|
228
|
+
top: calc(var(--remirror-table-delete-button-y) - 9px);
|
229
|
+
}
|
230
|
+
|
231
|
+
.remirror-table-delete-row-column-inner-button {
|
232
|
+
left: calc(var(--remirror-table-delete-row-column-button-x) - 9px);
|
233
|
+
top: calc(var(--remirror-table-delete-row-column-button-y) - 9px);
|
234
|
+
}
|
235
|
+
|
236
|
+
.remirror-table-with-controllers {
|
237
|
+
height: 1px;
|
238
|
+
margin-bottom: 40px;
|
239
|
+
margin-top: 40px;
|
240
|
+
}
|
241
|
+
|
242
|
+
.ProseMirror table.remirror-table-with-controllers {
|
243
|
+
overflow: visible;
|
244
|
+
}
|
245
|
+
|
246
|
+
.remirror-table-waitting-controllers {
|
247
|
+
display: none;
|
248
|
+
}
|
249
|
+
|
250
|
+
.remirror-table-tbody-with-controllers > tr:first-of-type {
|
251
|
+
height: 12px;
|
252
|
+
overflow: visible;
|
253
|
+
}
|
254
|
+
|
255
|
+
.remirror-table-tbody-with-controllers > tr:first-of-type th:first-of-type {
|
256
|
+
cursor: pointer;
|
257
|
+
height: 12px;
|
258
|
+
overflow: visible;
|
259
|
+
padding: 0;
|
260
|
+
position: relative;
|
261
|
+
width: 12px;
|
262
|
+
z-index: 15;
|
263
|
+
}
|
264
|
+
|
265
|
+
.remirror-table-tbody-with-controllers > tr:first-of-type th:first-of-type div.remirror-table-controller-wrapper {
|
266
|
+
align-items: flex-end;
|
267
|
+
display: flex;
|
268
|
+
height: 12px;
|
269
|
+
justify-content: flex-end;
|
270
|
+
overflow: visible;
|
271
|
+
width: 12px;
|
272
|
+
}
|
273
|
+
|
274
|
+
.remirror-table-tbody-with-controllers > tr:first-of-type th:first-of-type div.remirror-table-controller-trigger-area {
|
275
|
+
display: none;
|
276
|
+
flex: 1;
|
277
|
+
position: relative;
|
278
|
+
z-index: 10;
|
279
|
+
}
|
280
|
+
|
281
|
+
.remirror-table-tbody-with-controllers
|
282
|
+
> tr:first-of-type
|
283
|
+
th:first-of-type
|
284
|
+
div.remirror-table-controller-mark-row-corner {
|
285
|
+
border-color: var(--rmr-color-table-mark);
|
286
|
+
border-radius: 50%;
|
287
|
+
border-style: solid;
|
288
|
+
border-width: 2px;
|
289
|
+
bottom: -2px;
|
290
|
+
height: 0;
|
291
|
+
left: -12px;
|
292
|
+
position: absolute;
|
293
|
+
width: 0;
|
294
|
+
}
|
295
|
+
|
296
|
+
.remirror-table-tbody-with-controllers
|
297
|
+
> tr:first-of-type
|
298
|
+
th:first-of-type
|
299
|
+
div.remirror-table-controller-mark-column-corner {
|
300
|
+
border-color: var(--rmr-color-table-mark);
|
301
|
+
border-radius: 50%;
|
302
|
+
border-style: solid;
|
303
|
+
border-width: 2px;
|
304
|
+
height: 0;
|
305
|
+
position: absolute;
|
306
|
+
right: -2px;
|
307
|
+
top: -12px;
|
308
|
+
width: 0;
|
309
|
+
}
|
310
|
+
|
311
|
+
.remirror-table-tbody-with-controllers > tr:first-of-type th:nth-of-type(n + 2) {
|
312
|
+
cursor: pointer;
|
313
|
+
height: 12px;
|
314
|
+
overflow: visible;
|
315
|
+
padding: 0;
|
316
|
+
position: relative;
|
317
|
+
z-index: 15;
|
318
|
+
}
|
319
|
+
|
320
|
+
.remirror-table-tbody-with-controllers > tr:first-of-type th:nth-of-type(n + 2) div.remirror-table-controller-wrapper {
|
321
|
+
align-items: flex-end;
|
322
|
+
display: flex;
|
323
|
+
flex-direction: row;
|
324
|
+
height: 12px;
|
325
|
+
justify-content: flex-end;
|
326
|
+
overflow: visible;
|
327
|
+
width: 100%;
|
328
|
+
}
|
329
|
+
|
330
|
+
.remirror-table-tbody-with-controllers
|
331
|
+
> tr:first-of-type
|
332
|
+
th:nth-of-type(n + 2)
|
333
|
+
div.remirror-table-controller-trigger-area {
|
334
|
+
flex: 1;
|
335
|
+
height: 36px;
|
336
|
+
position: relative;
|
337
|
+
z-index: 10;
|
338
|
+
}
|
339
|
+
|
340
|
+
.remirror-table-tbody-with-controllers
|
341
|
+
> tr:first-of-type
|
342
|
+
th:nth-of-type(n + 2)
|
343
|
+
div.remirror-table-controller-mark-row-corner {
|
344
|
+
display: none;
|
345
|
+
}
|
346
|
+
|
347
|
+
.remirror-table-tbody-with-controllers
|
348
|
+
> tr:first-of-type
|
349
|
+
th:nth-of-type(n + 2)
|
350
|
+
div.remirror-table-controller-mark-column-corner {
|
351
|
+
border-color: var(--rmr-color-table-mark);
|
352
|
+
border-radius: 50%;
|
353
|
+
border-style: solid;
|
354
|
+
border-width: 2px;
|
355
|
+
height: 0;
|
356
|
+
position: absolute;
|
357
|
+
right: -2px;
|
358
|
+
top: -12px;
|
359
|
+
width: 0;
|
360
|
+
}
|
361
|
+
|
362
|
+
.remirror-table-tbody-with-controllers > tr:nth-of-type(n + 2) th {
|
363
|
+
cursor: pointer;
|
364
|
+
overflow: visible;
|
365
|
+
padding: 0;
|
366
|
+
position: relative;
|
367
|
+
width: 12px;
|
368
|
+
z-index: 15;
|
369
|
+
}
|
370
|
+
|
371
|
+
.remirror-table-tbody-with-controllers > tr:nth-of-type(n + 2) th div.remirror-table-controller-wrapper {
|
372
|
+
align-items: flex-end;
|
373
|
+
display: flex;
|
374
|
+
flex-direction: column;
|
375
|
+
height: 100%;
|
376
|
+
justify-content: flex-end;
|
377
|
+
overflow: visible;
|
378
|
+
width: 12px;
|
379
|
+
}
|
380
|
+
|
381
|
+
.remirror-table-tbody-with-controllers > tr:nth-of-type(n + 2) th div.remirror-table-controller-trigger-area {
|
382
|
+
flex: 1;
|
383
|
+
position: relative;
|
384
|
+
width: 36px;
|
385
|
+
z-index: 10;
|
386
|
+
}
|
387
|
+
|
388
|
+
.remirror-table-tbody-with-controllers > tr:nth-of-type(n + 2) th div.remirror-table-controller-mark-row-corner {
|
389
|
+
border-color: var(--rmr-color-table-mark);
|
390
|
+
border-radius: 50%;
|
391
|
+
border-style: solid;
|
392
|
+
border-width: 2px;
|
393
|
+
bottom: -2px;
|
394
|
+
height: 0;
|
395
|
+
left: -12px;
|
396
|
+
position: absolute;
|
397
|
+
width: 0;
|
398
|
+
}
|
399
|
+
|
400
|
+
.remirror-table-tbody-with-controllers > tr:nth-of-type(n + 2) th div.remirror-table-controller-mark-column-corner {
|
401
|
+
display: none;
|
402
|
+
}
|
403
|
+
|
404
|
+
.remirror-table-tbody-with-controllers th.remirror-table-controller {
|
405
|
+
background-color: var(--rmr-color-table-default-controller);
|
406
|
+
}
|
407
|
+
|
408
|
+
.remirror-table-tbody-with-controllers th.selectedCell.remirror-table-controller {
|
409
|
+
background-color: var(--rmr-color-table-selected-controller);
|
410
|
+
}
|
411
|
+
|
412
|
+
.remirror-table-show-predelete td.selectedCell,
|
413
|
+
.remirror-table-show-predelete th.selectedCell.remirror-table-controller {
|
414
|
+
background-color: var(--rmr-color-table-predelete-cell) !important;
|
415
|
+
border-color: var(--rmr-color-table-predelete-border) !important;
|
416
|
+
}
|
417
|
+
|
418
|
+
.remirror-table-show-predelete th.selectedCell.remirror-table-controller {
|
419
|
+
background-color: var(--rmr-color-table-predelete-controller) !important;
|
420
|
+
}
|
421
|
+
|
422
|
+
.remirror-table-show-predelete.remirror-table-preselect-all td,
|
423
|
+
.remirror-table-show-predelete.remirror-table-preselect-all th.remirror-table-controller {
|
424
|
+
background-color: var(--rmr-color-table-predelete-cell) !important;
|
425
|
+
border-color: var(--rmr-color-table-predelete-border) !important;
|
426
|
+
}
|
427
|
+
|
428
|
+
.remirror-table-show-predelete.remirror-table-preselect-all th.remirror-table-controller {
|
429
|
+
background-color: var(--rmr-color-table-predelete-controller) !important;
|
65
430
|
}
|
@@ -14,12 +14,14 @@ import RemoveLinkButton from './Tools/Link/RemoveLinkButton';
|
|
14
14
|
import ClearFormattingButton from './Tools/ClearFormatting/ClearFormattingButton';
|
15
15
|
import ListButtons from './Tools/Lists/ListButtons';
|
16
16
|
import HorizontalLineButton from './Tools/HorizontalLine/HorizontalLineButton';
|
17
|
+
import TableButton from './Tools/Table/TableButton';
|
17
18
|
import { useExtensionNames } from '../hooks';
|
18
19
|
|
19
20
|
type ToolbarProps = {
|
20
21
|
isVisible: boolean;
|
22
|
+
enableTableTool: boolean;
|
21
23
|
};
|
22
|
-
export const Toolbar = ({ isVisible }: ToolbarProps) => {
|
24
|
+
export const Toolbar = ({ isVisible, enableTableTool }: ToolbarProps) => {
|
23
25
|
const extensionNames = useExtensionNames();
|
24
26
|
|
25
27
|
return (
|
@@ -51,6 +53,7 @@ export const Toolbar = ({ isVisible }: ToolbarProps) => {
|
|
51
53
|
)}
|
52
54
|
{extensionNames.image && <ImageButton />}
|
53
55
|
{extensionNames.clearFormatting && <ClearFormattingButton />}
|
56
|
+
{enableTableTool && extensionNames.table && <TableButton />}
|
54
57
|
</div>
|
55
58
|
</RemirrorToolbar>
|
56
59
|
);
|
@@ -0,0 +1,25 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import '@testing-library/jest-dom';
|
3
|
+
import { screen, fireEvent } from '@testing-library/react';
|
4
|
+
import { renderWithEditor } from '../../../../tests';
|
5
|
+
import TableButton from './TableButton';
|
6
|
+
|
7
|
+
const defaultTableMarkup = `<div class="remirror-table-show-controllers"><table class="remirror-table remirror-table-with-controllers" data-controllers-injected="" style="min-width: 40px;"><colgroup class="remirror-table-colgroup"><col><col><col><col></colgroup><tbody class="remirror-table-tbody-with-controllers"><tr><th contenteditable="false" class="remirror-table-controller remirror-controllers-toggle selectedCell" data-controller-cell=""><div contenteditable="false" class="remirror-table-controller-wrapper"><div contenteditable="false"></div><div class="remirror-table-controller-trigger-area"></div><div class="remirror-table-controller-trigger-area"></div><div class="remirror-table-controller-mark-row-corner"></div><div class="remirror-table-controller-mark-column-corner"></div></div></th><th contenteditable="false" class="remirror-table-controller remirror-controllers-toggle" data-controller-cell=""><div contenteditable="false" class="remirror-table-controller-wrapper"><div contenteditable="false"></div><div class="remirror-table-controller-trigger-area"></div><div class="remirror-table-controller-trigger-area"></div><div class="remirror-table-controller-mark-row-corner"></div><div class="remirror-table-controller-mark-column-corner"></div></div></th><th contenteditable="false" class="remirror-table-controller remirror-controllers-toggle" data-controller-cell=""><div contenteditable="false" class="remirror-table-controller-wrapper"><div contenteditable="false"></div><div class="remirror-table-controller-trigger-area"></div><div class="remirror-table-controller-trigger-area"></div><div class="remirror-table-controller-mark-row-corner"></div><div class="remirror-table-controller-mark-column-corner"></div></div></th><th contenteditable="false" class="remirror-table-controller remirror-controllers-toggle" data-controller-cell=""><div contenteditable="false" class="remirror-table-controller-wrapper"><div contenteditable="false"></div><div class="remirror-table-controller-trigger-area"></div><div class="remirror-table-controller-trigger-area"></div><div class="remirror-table-controller-mark-row-corner"></div><div class="remirror-table-controller-mark-column-corner"></div></div></th></tr><tr><th contenteditable="false" class="remirror-table-controller remirror-controllers-toggle" data-controller-cell=""><div contenteditable="false" class="remirror-table-controller-wrapper"><div contenteditable="false"></div><div class="remirror-table-controller-trigger-area"></div><div class="remirror-table-controller-trigger-area"></div><div class="remirror-table-controller-mark-row-corner"></div><div class="remirror-table-controller-mark-column-corner"></div></div></th><td><p style=""><br class="ProseMirror-trailingBreak"></p></td><td><p style=""><br class="ProseMirror-trailingBreak"></p></td><td><p style=""><br class="ProseMirror-trailingBreak"></p></td></tr><tr><th contenteditable="false" class="remirror-table-controller remirror-controllers-toggle" data-controller-cell=""><div contenteditable="false" class="remirror-table-controller-wrapper"><div contenteditable="false"></div><div class="remirror-table-controller-trigger-area"></div><div class="remirror-table-controller-trigger-area"></div><div class="remirror-table-controller-mark-row-corner"></div><div class="remirror-table-controller-mark-column-corner"></div></div></th><td><p style=""><br class="ProseMirror-trailingBreak"></p></td><td><p style=""><br class="ProseMirror-trailingBreak"></p></td><td><p style=""><br class="ProseMirror-trailingBreak"></p></td></tr><tr><th contenteditable="false" class="remirror-table-controller remirror-controllers-toggle" data-controller-cell=""><div contenteditable="false" class="remirror-table-controller-wrapper"><div contenteditable="false"></div><div class="remirror-table-controller-trigger-area"></div><div class="remirror-table-controller-trigger-area"></div><div class="remirror-table-controller-mark-row-corner"></div><div class="remirror-table-controller-mark-column-corner"></div></div></th><td><p style=""><br class="ProseMirror-trailingBreak"></p></td><td><p style=""><br class="ProseMirror-trailingBreak"></p></td><td><p style=""><br class="ProseMirror-trailingBreak"></p></td></tr><tr><th contenteditable="false" class="remirror-table-controller remirror-controllers-toggle" data-controller-cell=""><div contenteditable="false" class="remirror-table-controller-wrapper"><div contenteditable="false"></div><div class="remirror-table-controller-trigger-area"></div><div class="remirror-table-controller-trigger-area"></div><div class="remirror-table-controller-mark-row-corner"></div><div class="remirror-table-controller-mark-column-corner"></div></div></th><td><p style=""><br class="ProseMirror-trailingBreak"></p></td><td><p style=""><br class="ProseMirror-trailingBreak"></p></td><td><p style=""><br class="ProseMirror-trailingBreak"></p></td></tr></tbody></table><div></div></div>`;
|
8
|
+
|
9
|
+
describe('Table button', () => {
|
10
|
+
it('Renders the table button', async () => {
|
11
|
+
await renderWithEditor(<TableButton />, { content: 'Some nonsense content here' });
|
12
|
+
expect(screen.getByRole('button', { name: 'Insert table' })).toBeInTheDocument();
|
13
|
+
});
|
14
|
+
|
15
|
+
it('Inserts a table into the editor content after clicking button', async () => {
|
16
|
+
const { getHtmlContent } = await renderWithEditor(<TableButton />, {
|
17
|
+
content: '<p>Hello Mr Goat</p>',
|
18
|
+
});
|
19
|
+
|
20
|
+
const horizontalLine = screen.getByRole('button', { name: 'Insert table' });
|
21
|
+
fireEvent.click(horizontalLine);
|
22
|
+
|
23
|
+
expect(getHtmlContent()).toBe(defaultTableMarkup + '<p style="">Hello Mr Goat</p>');
|
24
|
+
});
|
25
|
+
});
|
@@ -0,0 +1,32 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { useCommands, useActive } from '@remirror/react';
|
3
|
+
import { VerticalDivider } from '@remirror/react-components';
|
4
|
+
import { TableExtension } from '@remirror/extension-react-tables';
|
5
|
+
import Button from '../../../ui/Button/Button';
|
6
|
+
import TableViewRoundedIcon from '@mui/icons-material/TableViewRounded';
|
7
|
+
|
8
|
+
const TableButton = () => {
|
9
|
+
const { createTable } = useCommands();
|
10
|
+
|
11
|
+
const active = useActive<TableExtension>();
|
12
|
+
const enabled = createTable.enabled();
|
13
|
+
|
14
|
+
const handleSelect = () => {
|
15
|
+
createTable({ rowsCount: 4, columnsCount: 3, withHeaderRow: false });
|
16
|
+
};
|
17
|
+
|
18
|
+
return (
|
19
|
+
<>
|
20
|
+
<Button
|
21
|
+
handleOnClick={handleSelect}
|
22
|
+
isDisabled={!enabled}
|
23
|
+
isActive={active.table()}
|
24
|
+
icon={<TableViewRoundedIcon />}
|
25
|
+
label="Insert table"
|
26
|
+
/>
|
27
|
+
<VerticalDivider />
|
28
|
+
</>
|
29
|
+
);
|
30
|
+
};
|
31
|
+
|
32
|
+
export default TableButton;
|
@@ -28,6 +28,9 @@ import { ClearFormattingExtension } from './ClearFormattingExtension/ClearFormat
|
|
28
28
|
import { UnsupportedNodeExtension } from './UnsuportedExtension/UnsupportedNodeExtension';
|
29
29
|
import { ResourceBrowserContextProps } from '@squiz/resource-browser';
|
30
30
|
import { FetchUrlExtension } from './FetchUrlExtension/FetchUrlExtension';
|
31
|
+
import { TableExtension } from '@remirror/extension-react-tables';
|
32
|
+
import { ReactComponentExtension } from '@remirror/extension-react-component';
|
33
|
+
|
31
34
|
export enum NodeName {
|
32
35
|
Image = 'image',
|
33
36
|
CodeBlock = 'codeBlock',
|
@@ -77,6 +80,8 @@ export const createExtensions = (context: EditorContextOptions, browserContext:
|
|
77
80
|
fetchUrl: browserContext.onRequestResource,
|
78
81
|
}),
|
79
82
|
new TextExtension(),
|
83
|
+
new TableExtension(),
|
84
|
+
new ReactComponentExtension(),
|
80
85
|
];
|
81
86
|
};
|
82
87
|
};
|
@@ -19,6 +19,7 @@ describe('getNodeNamesByGroup', () => {
|
|
19
19
|
'assetImage',
|
20
20
|
'doc',
|
21
21
|
'text',
|
22
|
+
'tableControllerCell',
|
22
23
|
'codeBlock',
|
23
24
|
'image',
|
24
25
|
'unsupportedNode',
|
@@ -26,7 +27,11 @@ describe('getNodeNamesByGroup', () => {
|
|
26
27
|
'listItem',
|
27
28
|
'orderedList',
|
28
29
|
'horizontalRule',
|
30
|
+
'table',
|
29
31
|
'hardBreak',
|
32
|
+
'tableRow',
|
33
|
+
'tableCell',
|
34
|
+
'tableHeaderCell',
|
30
35
|
]);
|
31
36
|
});
|
32
37
|
});
|