@squiz/formatted-text-editor 1.69.0 → 1.71.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 +12 -0
- package/demo/App.tsx +15 -0
- package/lib/Editor/Editor.d.ts +2 -1
- package/lib/Editor/Editor.js +11 -3
- 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.d.ts +2 -0
- package/lib/Extensions/Extensions.js +6 -0
- package/lib/index.css +296 -0
- package/lib/utils/converters/remirrorNodeToSquizNode/remirrorNodeToSquizNode.js +19 -4
- package/lib/utils/converters/squizNodeToRemirrorNode/squizNodeToRemirrorNode.js +23 -0
- package/package.json +2 -1
- package/src/Editor/Editor.tsx +13 -2
- 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 +7 -0
- package/src/utils/converters/remirrorNodeToSquizNode/remirrorNodeToSquizNode.spec.ts +457 -0
- package/src/utils/converters/remirrorNodeToSquizNode/remirrorNodeToSquizNode.ts +24 -5
- package/src/utils/converters/squizNodeToRemirrorNode/squizNodeToRemirrorNode.spec.ts +210 -0
- package/src/utils/converters/squizNodeToRemirrorNode/squizNodeToRemirrorNode.ts +23 -0
- package/src/utils/getNodeNamesByGroup.spec.ts +5 -0
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## 1.71.0
|
4
|
+
|
5
|
+
### Minor Changes
|
6
|
+
|
7
|
+
- 882fb82: Added table transormation support between Squiz & Remirror models (allowing saving of tables)
|
8
|
+
|
9
|
+
## 1.70.0
|
10
|
+
|
11
|
+
### Minor Changes
|
12
|
+
|
13
|
+
- 0513957: `enableTableTool` prop added to the Editor to control the display of the table insertion tool until we are ready to release it
|
14
|
+
|
3
15
|
## 1.69.0
|
4
16
|
|
5
17
|
### Minor Changes
|
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,
|
@@ -67,12 +68,19 @@ const Editor = ({ content, className, border = true, editable = true, onChange,
|
|
67
68
|
if (isFocused) {
|
68
69
|
manager.view.dom.focus();
|
69
70
|
}
|
71
|
+
// TODO: May want to come back to this and see if there's a better solution
|
72
|
+
// We have to add a type button attribute to the delete buttons so they don't cause a submit by accident.
|
73
|
+
const tableDeleteButtons = document.querySelectorAll('.remirror-table-delete-inner-button');
|
74
|
+
tableDeleteButtons.forEach((button) => {
|
75
|
+
button.setAttribute('type', 'button');
|
76
|
+
});
|
70
77
|
}, []);
|
71
78
|
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
|
-
react_1.default.createElement(react_2.Remirror, { manager: manager,
|
73
|
-
editable && react_1.default.createElement(EditorToolbar_1.Toolbar, { isVisible: isVisible }),
|
79
|
+
react_1.default.createElement(react_2.Remirror, { manager: manager, initialContent: state, editable: editable, onChange: handleChange, placeholder: "Write something", label: "Text editor", attributes: attributes },
|
80
|
+
editable && react_1.default.createElement(EditorToolbar_1.Toolbar, { isVisible: isVisible, enableTableTool: enableTableTool }),
|
74
81
|
children && react_1.default.createElement("div", { className: "squiz-fte-scope__editor__children" }, children),
|
75
82
|
react_1.default.createElement(WrappedEditor, null),
|
83
|
+
enableTableTool && react_1.default.createElement(extension_react_tables_1.TableComponents, { enableTableCellMenu: false }),
|
76
84
|
editable && isVisible && react_1.default.createElement(EditorToolbar_1.FloatingToolbar, null))));
|
77
85
|
};
|
78
86
|
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,12 +12,16 @@ 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";
|
18
20
|
NodeName["CodeBlock"] = "codeBlock";
|
19
21
|
NodeName["AssetImage"] = "assetImage";
|
20
22
|
NodeName["Text"] = "text";
|
23
|
+
NodeName["TableControllerCell"] = "tableControllerCell";
|
24
|
+
NodeName["tableCell"] = "tableCell";
|
21
25
|
NodeName["hardBreak"] = "hardBreak";
|
22
26
|
NodeName["Unsupported"] = "unsupportedNode";
|
23
27
|
})(NodeName = exports.NodeName || (exports.NodeName = {}));
|
@@ -61,6 +65,8 @@ const createExtensions = (context, browserContext) => {
|
|
61
65
|
fetchUrl: browserContext.onRequestResource,
|
62
66
|
}),
|
63
67
|
new extensions_1.TextExtension(),
|
68
|
+
new extension_react_tables_1.TableExtension(),
|
69
|
+
new extension_react_component_1.ReactComponentExtension(),
|
64
70
|
];
|
65
71
|
};
|
66
72
|
};
|
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;
|
@@ -55,7 +55,7 @@ const resolveFontOptions = (node) => {
|
|
55
55
|
});
|
56
56
|
return fontOptions;
|
57
57
|
};
|
58
|
-
const transformAttributes = (attributes) => {
|
58
|
+
const transformAttributes = (attributes, nodeType) => {
|
59
59
|
const transformed = {};
|
60
60
|
Object.keys(attributes).forEach((key) => {
|
61
61
|
// Component service requires attributes to be a string, cast as needed.
|
@@ -63,6 +63,17 @@ const transformAttributes = (attributes) => {
|
|
63
63
|
transformed[key] = String(attributes[key]);
|
64
64
|
}
|
65
65
|
});
|
66
|
+
// We assign an attribute here for table controller cells as we need to differentiate
|
67
|
+
// between them and regular table headers (th)
|
68
|
+
if (nodeType === Extensions_1.NodeName.TableControllerCell) {
|
69
|
+
transformed[nodeType] = 'true';
|
70
|
+
}
|
71
|
+
// Another check here for more specific attributes for tables (column widths)
|
72
|
+
if (nodeType === Extensions_1.NodeName.TableControllerCell || nodeType === Extensions_1.NodeName.tableCell) {
|
73
|
+
if (Array.isArray(attributes.colwidth) && attributes.colwidth[0]) {
|
74
|
+
transformed.colwidth = String(attributes.colwidth[0]);
|
75
|
+
}
|
76
|
+
}
|
66
77
|
return transformed;
|
67
78
|
};
|
68
79
|
const transformFragment = (fragment) => {
|
@@ -75,9 +86,13 @@ const transformFragment = (fragment) => {
|
|
75
86
|
const transformNode = (node) => {
|
76
87
|
const formattingOptions = (0, undefinedIfEmpty_1.undefinedIfEmpty)(resolveFormattingOptions(node));
|
77
88
|
const font = (0, undefinedIfEmpty_1.undefinedIfEmpty)(resolveFontOptions(node));
|
78
|
-
|
79
|
-
|
80
|
-
|
89
|
+
let attributes;
|
90
|
+
if (node.type.name === Extensions_1.NodeName.Image ||
|
91
|
+
node.type.name === Extensions_1.NodeName.CodeBlock ||
|
92
|
+
node.type.name === Extensions_1.NodeName.TableControllerCell ||
|
93
|
+
node.type.name === Extensions_1.NodeName.tableCell) {
|
94
|
+
attributes = transformAttributes(node.attrs, node.type.name);
|
95
|
+
}
|
81
96
|
let transformedNode = { type: 'text', value: node.text || '' };
|
82
97
|
// Squiz "text" nodes can't have formatting/font options but Remirror "text" nodes can.
|
83
98
|
// If the node has formatting options wrap in a tag.
|
@@ -23,6 +23,10 @@ const getNodeType = (node) => {
|
|
23
23
|
li: 'listItem',
|
24
24
|
ul: 'bulletList',
|
25
25
|
hr: 'horizontalRule',
|
26
|
+
table: 'table',
|
27
|
+
tr: 'tableRow',
|
28
|
+
th: 'tableHeaderCell',
|
29
|
+
td: 'tableCell',
|
26
30
|
a: Extensions_1.NodeName.Text,
|
27
31
|
em: Extensions_1.NodeName.Text,
|
28
32
|
span: Extensions_1.NodeName.Text,
|
@@ -34,6 +38,12 @@ const getNodeType = (node) => {
|
|
34
38
|
return typeMap[node.type];
|
35
39
|
}
|
36
40
|
if (node.type === 'tag' && tagMap[node.tag]) {
|
41
|
+
// This is a specific check case for tables as there are some <th> tags which need to be returned
|
42
|
+
// as table controller cells.
|
43
|
+
if (node.attributes?.tableControllerCell) {
|
44
|
+
return 'tableControllerCell';
|
45
|
+
}
|
46
|
+
// Return regular tag for everything else
|
37
47
|
return tagMap[node.tag];
|
38
48
|
}
|
39
49
|
// Unsupported node type
|
@@ -42,6 +52,19 @@ const getNodeType = (node) => {
|
|
42
52
|
: `Unsupported node type provided: ${node.type}`);
|
43
53
|
};
|
44
54
|
const getNodeAttributes = (node) => {
|
55
|
+
if (node.type === 'tag' && node.tag === 'table') {
|
56
|
+
return {
|
57
|
+
isControllersInjected: true,
|
58
|
+
};
|
59
|
+
}
|
60
|
+
if (node.type === 'tag' && (node.tag === 'th' || node.tag === 'td')) {
|
61
|
+
return {
|
62
|
+
colspan: parseInt(node.attributes?.colspan ?? '1'),
|
63
|
+
rowspan: parseInt(node.attributes?.rowspan ?? '1'),
|
64
|
+
colwidth: node.attributes?.colwidth ? [parseInt(node.attributes.colwidth)] : null,
|
65
|
+
background: null,
|
66
|
+
};
|
67
|
+
}
|
45
68
|
if (node.type === 'tag' && node.tag === 'img') {
|
46
69
|
return {
|
47
70
|
alt: node.attributes?.alt,
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@squiz/formatted-text-editor",
|
3
|
-
"version": "1.
|
3
|
+
"version": "1.71.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",
|