@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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # Change Log
2
2
 
3
+ ## 1.70.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 0513957: `enableTableTool` prop added to the Editor to control the display of the table insertion tool until we are ready to release it
8
+
3
9
  ## 1.69.0
4
10
 
5
11
  ### 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>&nbsp;
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>&nbsp;
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>&nbsp;
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>&nbsp;
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>
@@ -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;
@@ -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,3 @@
1
+ import React from 'react';
2
+ declare const TableButton: () => React.JSX.Element;
3
+ export default TableButton;
@@ -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.69.0",
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",
@@ -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>
@@ -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
  });