@squiz/formatted-text-editor 1.56.1-alpha.3 → 1.56.1-alpha.30

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/demo/App.tsx CHANGED
@@ -8,7 +8,7 @@ import TextFieldsOutlinedIcon from '@mui/icons-material/TextFieldsOutlined';
8
8
  import DeleteOutlineOutlinedIcon from '@mui/icons-material/DeleteOutlineOutlined';
9
9
  import { VerticalDivider } from '@remirror/react-components';
10
10
  const ComponentHandlers = () => (
11
- <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '5px' }}>
11
+ <div style={{ display: 'flex', justifyContent: 'flex-end', maxHeight: '2rem' }}>
12
12
  <Button icon={<TextFieldsOutlinedIcon />} onClick={(x) => x} />
13
13
  <VerticalDivider />
14
14
  <Button icon={<DeleteOutlineOutlinedIcon />} onClick={(x) => x} />
@@ -16,12 +16,13 @@ const ComponentHandlers = () => (
16
16
  );
17
17
 
18
18
  function App() {
19
- const [showChildren] = useState(false);
19
+ const [showChildren, setShowChildren] = useState(false);
20
20
  const [doc, setDoc] = useState('');
21
21
  const [squizDoc, setSquizDoc] = useState('');
22
22
  const [reconvertedDoc, setReconvertedDoc] = useState('');
23
23
  const [error, setError] = useState<unknown>(null);
24
24
  const [editable, setEditable] = useState(true);
25
+ const [border, setBorder] = useState(true);
25
26
 
26
27
  const handleEditorChange: RemirrorEventListener<Extension> = (parameter) => {
27
28
  try {
@@ -44,6 +45,15 @@ function App() {
44
45
  <div className="form-group">
45
46
  <label htmlFor="editable">Editable</label>&nbsp;
46
47
  <input id="editable" type="checkbox" onChange={() => setEditable(!editable)} checked={editable} />
48
+ <label htmlFor="border">Border</label>&nbsp;
49
+ <input id="border" type="checkbox" onChange={() => setBorder(!border)} checked={border} />
50
+ <label htmlFor="showChildren">Show children</label>&nbsp;
51
+ <input
52
+ id="showChildren"
53
+ type="checkbox"
54
+ onChange={() => setShowChildren(!showChildren)}
55
+ checked={showChildren}
56
+ />
47
57
  </div>
48
58
  </div>
49
59
  <h1>Editor</h1>
@@ -51,6 +61,7 @@ function App() {
51
61
  <AppContext>
52
62
  <Editor
53
63
  editable={editable}
64
+ border={border}
54
65
  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>`}
55
66
  onChange={handleEditorChange}
56
67
  >
package/demo/index.scss CHANGED
@@ -28,12 +28,6 @@ h1 {
28
28
  overflow: scroll;
29
29
  }
30
30
 
31
- .remirror-editor {
32
- height: 35vh;
33
- max-height: 35vh;
34
- overflow: scroll;
35
- }
36
-
37
31
  .error {
38
32
  color: red;
39
33
  }
@@ -1,11 +1,13 @@
1
1
  import { ReactNode } from 'react';
2
2
  import { RemirrorContentType, RemirrorEventListener, Extension } from '@remirror/core';
3
3
  type EditorProps = {
4
+ className?: string;
4
5
  content?: RemirrorContentType;
5
6
  onChange?: RemirrorEventListener<Extension>;
6
7
  editable?: boolean;
8
+ border?: boolean;
7
9
  children?: ReactNode;
8
10
  isFocused?: boolean;
9
11
  };
10
- declare const Editor: ({ content, editable, onChange, children, isFocused }: EditorProps) => JSX.Element;
12
+ declare const Editor: ({ content, className, border, editable, onChange, children, isFocused }: EditorProps) => JSX.Element;
11
13
  export default Editor;
@@ -47,7 +47,7 @@ const WrappedEditor = () => {
47
47
  (0, react_2.useEditorEvent)('paste', preventImagePaste);
48
48
  return react_1.default.createElement(react_2.EditorComponent, null);
49
49
  };
50
- const Editor = ({ content, editable = true, onChange, children, isFocused }) => {
50
+ const Editor = ({ content, className, border = true, editable = true, onChange, children, isFocused }) => {
51
51
  const { manager, state, setState } = (0, react_2.useRemirror)({
52
52
  extensions: (0, Extensions_1.createExtensions)((0, react_1.useContext)(EditorContext_1.EditorContext), (0, react_1.useContext)(resource_browser_1.ResourceBrowserContext)),
53
53
  content,
@@ -65,12 +65,11 @@ const Editor = ({ content, editable = true, onChange, children, isFocused }) =>
65
65
  manager.view.dom.focus();
66
66
  }
67
67
  }, []);
68
- return (react_1.default.createElement("div", { className: "squiz-fte-scope" },
69
- react_1.default.createElement("div", { ref: wrapperRef, onBlur: handleBlur, onFocusCapture: handleFocus, className: (0, clsx_1.default)('formatted-text-editor', !editable && 'formatted-text-editor--is-disabled') },
70
- react_1.default.createElement(react_2.Remirror, { manager: manager, state: state, editable: editable, onChange: handleChange, placeholder: "Write something", label: "Text editor" },
71
- editable && react_1.default.createElement(EditorToolbar_1.Toolbar, { isVisible: isVisible }),
72
- children,
73
- react_1.default.createElement(WrappedEditor, null),
74
- editable && react_1.default.createElement(EditorToolbar_1.FloatingToolbar, null)))));
68
+ 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) },
69
+ react_1.default.createElement(react_2.Remirror, { manager: manager, state: state, editable: editable, onChange: handleChange, placeholder: "Write something", label: "Text editor" },
70
+ editable && react_1.default.createElement(EditorToolbar_1.Toolbar, { isVisible: isVisible }),
71
+ children && react_1.default.createElement("div", { className: "squiz-fte-scope__editor__children" }, children),
72
+ react_1.default.createElement(WrappedEditor, null),
73
+ editable && react_1.default.createElement(EditorToolbar_1.FloatingToolbar, null))));
75
74
  };
76
75
  exports.default = Editor;
@@ -23,22 +23,23 @@ const HorizontalLineButton_1 = __importDefault(require("./Tools/HorizontalLine/H
23
23
  const hooks_1 = require("../hooks");
24
24
  const Toolbar = ({ isVisible }) => {
25
25
  const extensionNames = (0, hooks_1.useExtensionNames)();
26
- return (react_1.default.createElement(react_components_1.Toolbar, { className: (0, clsx_1.default)('remirror-toolbar editor-toolbar header-toolbar', isVisible && 'show-toolbar'), role: "toolbar", tabIndex: 0 },
27
- extensionNames.history && (react_1.default.createElement(react_1.default.Fragment, null,
28
- react_1.default.createElement(UndoButton_1.default, null),
29
- react_1.default.createElement(RedoButton_1.default, null),
30
- react_1.default.createElement(react_components_1.VerticalDivider, null))),
31
- extensionNames.heading && extensionNames.paragraph && extensionNames.preformatted && react_1.default.createElement(TextTypeDropdown_1.default, null),
32
- extensionNames.bold && react_1.default.createElement(BoldButton_1.default, null),
33
- extensionNames.italic && react_1.default.createElement(ItalicButton_1.default, null),
34
- extensionNames.underline && react_1.default.createElement(UnderlineButton_1.default, null),
35
- extensionNames.nodeFormatting && react_1.default.createElement(TextAlignButtons_1.default, null),
36
- extensionNames.listItem && react_1.default.createElement(ListButtons_1.default, null),
37
- extensionNames.horizontalRule && react_1.default.createElement(HorizontalLineButton_1.default, null),
38
- extensionNames.link && (react_1.default.createElement(react_1.default.Fragment, null,
39
- react_1.default.createElement(LinkButton_1.default, null),
40
- react_1.default.createElement(RemoveLinkButton_1.default, null))),
41
- extensionNames.image && react_1.default.createElement(ImageButton_1.default, null),
42
- extensionNames.clearFormatting && react_1.default.createElement(ClearFormattingButton_1.default, null)));
26
+ 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
+ react_1.default.createElement("div", { className: "editor-toolbar__tools" },
28
+ extensionNames.history && (react_1.default.createElement(react_1.default.Fragment, null,
29
+ react_1.default.createElement(UndoButton_1.default, null),
30
+ react_1.default.createElement(RedoButton_1.default, null),
31
+ react_1.default.createElement(react_components_1.VerticalDivider, null))),
32
+ extensionNames.heading && extensionNames.paragraph && extensionNames.preformatted && react_1.default.createElement(TextTypeDropdown_1.default, null),
33
+ extensionNames.bold && react_1.default.createElement(BoldButton_1.default, null),
34
+ extensionNames.italic && react_1.default.createElement(ItalicButton_1.default, null),
35
+ extensionNames.underline && react_1.default.createElement(UnderlineButton_1.default, null),
36
+ extensionNames.nodeFormatting && react_1.default.createElement(TextAlignButtons_1.default, null),
37
+ extensionNames.listItem && react_1.default.createElement(ListButtons_1.default, null),
38
+ extensionNames.horizontalRule && react_1.default.createElement(HorizontalLineButton_1.default, null),
39
+ extensionNames.link && (react_1.default.createElement(react_1.default.Fragment, null,
40
+ react_1.default.createElement(LinkButton_1.default, null),
41
+ react_1.default.createElement(RemoveLinkButton_1.default, null))),
42
+ extensionNames.image && react_1.default.createElement(ImageButton_1.default, null),
43
+ extensionNames.clearFormatting && react_1.default.createElement(ClearFormattingButton_1.default, null))));
43
44
  };
44
45
  exports.Toolbar = Toolbar;
package/lib/index.css CHANGED
@@ -509,12 +509,15 @@
509
509
  white-space: nowrap !important;
510
510
  }
511
511
  .squiz-fte-scope .rounded {
512
- border-radius: 4px !important;
512
+ border-radius: 8px !important;
513
513
  }
514
514
  .squiz-fte-scope .rounded-t-sm {
515
515
  border-top-left-radius: 0.125rem !important;
516
516
  border-top-right-radius: 0.125rem !important;
517
517
  }
518
+ .squiz-fte-scope .border {
519
+ border-width: 1px !important;
520
+ }
518
521
  .squiz-fte-scope .border-0 {
519
522
  border-width: 0px !important;
520
523
  }
@@ -741,7 +744,7 @@
741
744
  padding: 6px 12px;
742
745
  position: relative;
743
746
  width: 100%;
744
- border-radius: 4px;
747
+ border-radius: 8px;
745
748
  border-width: 2px;
746
749
  --tw-border-opacity: 1;
747
750
  border-color: rgb(224 224 224 / var(--tw-border-opacity));
@@ -788,27 +791,23 @@
788
791
  line-height: 1.23;
789
792
  padding-top: 0.25rem;
790
793
  }
791
- .squiz-fte-scope .formatted-text-editor {
794
+ .squiz-fte-scope.squiz-fte-scope__editor {
792
795
  font-family: "Open Sans" !important;
793
- border-radius: 4px;
794
- border-width: 2px;
795
- border-style: solid;
796
+ border-radius: 8px;
796
797
  --tw-border-opacity: 1;
797
798
  border-color: rgb(224 224 224 / var(--tw-border-opacity));
798
799
  --tw-bg-opacity: 1;
799
800
  background-color: rgb(255 255 255 / var(--tw-bg-opacity));
800
801
  }
801
- .squiz-fte-scope .formatted-text-editor .remirror-editor-wrapper {
802
+ .squiz-fte-scope.squiz-fte-scope__editor:has(.squiz-fte-scope.squiz-fte-scope__editor__children) {
803
+ min-height: 2rem;
804
+ width: 100%;
805
+ }
806
+ .squiz-fte-scope.squiz-fte-scope__editor:has(.squiz-fte-scope.squiz-fte-scope__editor__children) .remirror-editor {
802
807
  padding-top: 0px;
803
- --tw-text-opacity: 1;
804
- color: rgb(61 61 61 / var(--tw-text-opacity));
805
808
  }
806
- .squiz-fte-scope .formatted-text-editor .remirror-editor {
807
- border-bottom-right-radius: 4px;
808
- border-bottom-left-radius: 4px;
809
- --tw-bg-opacity: 1;
810
- background-color: rgb(255 255 255 / var(--tw-bg-opacity));
811
- padding: 0.75rem;
809
+ .squiz-fte-scope.squiz-fte-scope__editor .remirror-editor {
810
+ padding: 2rem;
812
811
  --tw-shadow: 0 0 #0000;
813
812
  --tw-shadow-colored: 0 0 #0000;
814
813
  box-shadow:
@@ -818,22 +817,27 @@
818
817
  overflow: auto;
819
818
  min-height: 15vh;
820
819
  }
821
- .squiz-fte-scope .formatted-text-editor .remirror-editor:active,
822
- .squiz-fte-scope .formatted-text-editor .remirror-editor:focus {
820
+ .squiz-fte-scope.squiz-fte-scope__editor .remirror-editor:active,
821
+ .squiz-fte-scope.squiz-fte-scope__editor .remirror-editor:focus {
823
822
  outline-width: 0px;
824
823
  }
825
- .squiz-fte-scope .formatted-text-editor .remirror-editor p {
824
+ .squiz-fte-scope.squiz-fte-scope__editor .remirror-editor p {
826
825
  display: block;
827
826
  }
828
- .squiz-fte-scope .formatted-text-editor--is-disabled .remirror-editor {
827
+ .squiz-fte-scope.squiz-fte-scope__editor--bordered {
828
+ border-width: 2px;
829
+ border-style: solid;
830
+ }
831
+ .squiz-fte-scope.squiz-fte-scope__editor--is-disabled {
829
832
  cursor: not-allowed;
833
+ border-width: 0px;
830
834
  --tw-bg-opacity: 1;
831
- background-color: rgb(224 224 224 / var(--tw-bg-opacity));
835
+ background-color: rgb(247 247 247 / var(--tw-bg-opacity));
832
836
  }
833
- .squiz-fte-scope .formatted-text-editor--is-disabled .remirror-is-empty:first-of-type::before {
837
+ .squiz-fte-scope.squiz-fte-scope__editor--is-disabled .remirror-is-empty:first-of-type::before {
834
838
  display: none;
835
839
  }
836
- .squiz-fte-scope .formatted-text-editor .remirror-is-empty:first-of-type::before {
840
+ .squiz-fte-scope.squiz-fte-scope__editor .remirror-is-empty:first-of-type::before {
837
841
  position: absolute;
838
842
  pointer-events: none;
839
843
  height: 0;
@@ -842,16 +846,16 @@
842
846
  --tw-text-opacity: 1;
843
847
  color: rgb(148 148 148 / var(--tw-text-opacity));
844
848
  }
845
- .squiz-fte-scope .formatted-text-editor .ProseMirror-selectednode {
849
+ .squiz-fte-scope.squiz-fte-scope__editor .ProseMirror-selectednode {
846
850
  border-width: 2px;
847
851
  border-style: solid;
848
852
  --tw-border-opacity: 1;
849
853
  border-color: rgb(7 116 210 / var(--tw-border-opacity));
850
854
  }
851
- .squiz-fte-scope .formatted-text-editor img {
855
+ .squiz-fte-scope.squiz-fte-scope__editor img {
852
856
  display: inline;
853
857
  }
854
- .squiz-fte-scope .formatted-text-editor:has(.show-toolbar) {
858
+ .squiz-fte-scope.squiz-fte-scope__editor:has(.show-toolbar) {
855
859
  border-width: 0px;
856
860
  --tw-shadow: 0 0 0 1px rgba(0,0,0,0.04), 0 1px 12px 4px rgba(0,0,0,0.12);
857
861
  --tw-shadow-colored: 0 0 0 1px var(--tw-shadow-color), 0 1px 12px 4px var(--tw-shadow-color);
@@ -862,25 +866,25 @@
862
866
  }
863
867
  .squiz-fte-scope .editor-toolbar,
864
868
  .squiz-fte-scope__floating-popover {
865
- border-top-left-radius: 4px;
866
- border-top-right-radius: 4px;
869
+ border-top-left-radius: 8px;
870
+ border-top-right-radius: 8px;
871
+ background-color: transparent;
872
+ }
873
+ .squiz-fte-scope .editor-toolbar__tools {
874
+ display: flex;
875
+ width: 100%;
876
+ flex-wrap: wrap;
877
+ justify-items: center;
867
878
  border-bottom-width: 2px;
868
879
  border-style: solid;
869
880
  --tw-border-opacity: 1;
870
881
  border-color: rgb(237 237 237 / var(--tw-border-opacity));
871
- --tw-bg-opacity: 1;
872
- background-color: rgb(255 255 255 / var(--tw-bg-opacity));
873
882
  padding: 0.25rem;
874
- display: flex;
875
- justify-items: center;
876
- flex-wrap: wrap;
877
883
  }
878
- .squiz-fte-scope .editor-toolbar > *:not(:first-child, .MuiDivider-root),
879
- .squiz-fte-scope__floating-popover > *:not(:first-child, .MuiDivider-root) {
884
+ .squiz-fte-scope .editor-toolbar__tools > *:not(:first-child, .MuiDivider-root) {
880
885
  margin: 0 0 0 2px;
881
886
  }
882
- .squiz-fte-scope .editor-toolbar .MuiDivider-root,
883
- .squiz-fte-scope__floating-popover .MuiDivider-root {
887
+ .squiz-fte-scope .editor-toolbar__tools .MuiDivider-root {
884
888
  margin-top: 0px;
885
889
  margin-bottom: 0px;
886
890
  margin-left: 0.25rem;
@@ -889,17 +893,17 @@
889
893
  margin-right: 2px;
890
894
  height: auto;
891
895
  }
892
- .squiz-fte-scope .editor-toolbar .squiz-fte-btn,
893
- .squiz-fte-scope__floating-popover .squiz-fte-btn {
896
+ .squiz-fte-scope .editor-toolbar__tools .squiz-fte-btn {
894
897
  padding: 0.25rem;
895
898
  font-weight: 700;
896
899
  }
897
- .squiz-fte-scope .editor-toolbar .squiz-fte-btn ~ .squiz-fte-btn,
898
- .squiz-fte-scope__floating-popover .squiz-fte-btn ~ .squiz-fte-btn {
900
+ .squiz-fte-scope .editor-toolbar__tools .squiz-fte-btn ~ .squiz-fte-btn {
899
901
  margin-left: 2px;
900
902
  }
901
903
  .squiz-fte-scope .header-toolbar {
902
- transition: opacity 0.2s linear, max-height 0.2s linear;
904
+ transition-duration: 0.3s;
905
+ transition-property: max-height, opacity;
906
+ transition-timing-function: ease-out;
903
907
  opacity: 0;
904
908
  max-height: 0;
905
909
  }
@@ -928,7 +932,7 @@
928
932
  margin-bottom: 0px;
929
933
  }
930
934
  .squiz-fte-scope button.squiz-fte-btn {
931
- border-radius: 4px;
935
+ border-radius: 8px;
932
936
  --tw-bg-opacity: 1;
933
937
  background-color: rgb(255 255 255 / var(--tw-bg-opacity));
934
938
  font-weight: 700;
@@ -974,7 +978,7 @@
974
978
  .squiz-fte-scope .toolbar-dropdown__button {
975
979
  display: flex;
976
980
  align-items: center;
977
- border-radius: 4px;
981
+ border-radius: 8px;
978
982
  font-family:
979
983
  Open Sans,
980
984
  Arial,
@@ -1001,7 +1005,7 @@
1001
1005
  height: 1.5rem;
1002
1006
  }
1003
1007
  .squiz-fte-scope .toolbar-dropdown__menu {
1004
- border-radius: 4px;
1008
+ border-radius: 8px;
1005
1009
  border-width: 1px;
1006
1010
  --tw-border-opacity: 1;
1007
1011
  border-color: rgb(224 224 224 / var(--tw-border-opacity));
@@ -1148,24 +1152,22 @@
1148
1152
  display: flex;
1149
1153
  align-items: center;
1150
1154
  justify-content: flex-end;
1151
- border-bottom-right-radius: 4px;
1152
- border-bottom-left-radius: 4px;
1155
+ border-bottom-right-radius: 8px;
1156
+ border-bottom-left-radius: 8px;
1153
1157
  }
1154
1158
  .squiz-fte-scope .squiz-fte-modal-footer__button {
1155
1159
  font-size: 0.875rem;
1156
1160
  font-weight: 700;
1157
1161
  }
1158
- .squiz-fte-scope .editor-toolbar .squiz-fte-modal-footer__button,
1159
- .squiz-fte-scope__floating-popover .squiz-fte-modal-footer__button {
1162
+ .squiz-fte-scope .editor-toolbar__tools .squiz-fte-modal-footer__button {
1160
1163
  padding: 0.25rem;
1161
1164
  font-weight: 700;
1162
1165
  }
1163
- .squiz-fte-scope .editor-toolbar .squiz-fte-modal-footer__button ~ .squiz-fte-btn,
1164
- .squiz-fte-scope__floating-popover .squiz-fte-modal-footer__button ~ .squiz-fte-btn {
1166
+ .squiz-fte-scope .editor-toolbar__tools .squiz-fte-modal-footer__button ~ .squiz-fte-btn {
1165
1167
  margin-left: 2px;
1166
1168
  }
1167
1169
  .squiz-fte-scope button.squiz-fte-modal-footer__button {
1168
- border-radius: 4px;
1170
+ border-radius: 8px;
1169
1171
  --tw-bg-opacity: 1;
1170
1172
  background-color: rgb(255 255 255 / var(--tw-bg-opacity));
1171
1173
  font-weight: 700;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@squiz/formatted-text-editor",
3
- "version": "1.56.1-alpha.3",
3
+ "version": "1.56.1-alpha.30",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "scripts": {
@@ -10,7 +10,6 @@
10
10
  "compile:code": "tsc",
11
11
  "compile:styles": "node build.js",
12
12
  "dev": "vite",
13
- "preview": "vite preview",
14
13
  "test": "jest",
15
14
  "test:coverage": "jest --coverage",
16
15
  "test:e2e": "vite build && vite preview --port 8080 & cypress open",
@@ -20,8 +19,8 @@
20
19
  "@headlessui/react": "1.7.11",
21
20
  "@mui/icons-material": "5.11.16",
22
21
  "@remirror/react": "2.0.25",
23
- "@squiz/dx-json-schema-lib": "1.56.1-alpha.3",
24
- "@squiz/resource-browser": "1.56.1-alpha.3",
22
+ "@squiz/dx-json-schema-lib": "1.56.1-alpha.30",
23
+ "@squiz/resource-browser": "1.56.1-alpha.30",
25
24
  "clsx": "1.2.1",
26
25
  "react-hook-form": "7.43.2",
27
26
  "react-image-size": "2.0.0",
@@ -55,7 +54,7 @@
55
54
  "tailwindcss": "3.2.6",
56
55
  "ts-jest": "29.0.5",
57
56
  "typescript": "4.9.3",
58
- "vite": "4.0.0"
57
+ "vite": "^4.5.0"
59
58
  },
60
59
  "peerDependencies": {
61
60
  "@types/react": "^16.14.0 || ^17 || ^18",
@@ -75,5 +74,5 @@
75
74
  "volta": {
76
75
  "node": "18.15.0"
77
76
  },
78
- "gitHead": "612c5b93f4c427865ea0d2da8b46111da78bb90c"
77
+ "gitHead": "a7c213b73e9131ac1739a6212820ea54e7839042"
79
78
  }
package/postcss.config.js CHANGED
@@ -5,7 +5,7 @@ module.exports = {
5
5
  require('postcss-nested'),
6
6
  require('postcss-prefix-selector')({
7
7
  prefix: '.squiz-fte-scope',
8
- exclude: [/\.squiz-fte-scope__floating-popover/],
8
+ exclude: [/\.squiz-fte-scope__floating-popover/, /\.squiz-fte-scope__editor/],
9
9
  includeFiles: ['./src/index.scss'],
10
10
  }),
11
11
  ],
@@ -10,9 +10,11 @@ import useFocus from '../hooks/useFocus';
10
10
  import { ResourceBrowserContext } from '@squiz/resource-browser';
11
11
 
12
12
  type EditorProps = {
13
+ className?: string;
13
14
  content?: RemirrorContentType;
14
15
  onChange?: RemirrorEventListener<Extension>;
15
16
  editable?: boolean;
17
+ border?: boolean;
16
18
  children?: ReactNode;
17
19
  isFocused?: boolean;
18
20
  };
@@ -33,7 +35,7 @@ const WrappedEditor = () => {
33
35
  return <EditorComponent />;
34
36
  };
35
37
 
36
- const Editor = ({ content, editable = true, onChange, children, isFocused }: EditorProps) => {
38
+ const Editor = ({ content, className, border = true, editable = true, onChange, children, isFocused }: EditorProps) => {
37
39
  const { manager, state, setState } = useRemirror({
38
40
  extensions: createExtensions(useContext(EditorContext), useContext(ResourceBrowserContext)),
39
41
  content,
@@ -56,27 +58,31 @@ const Editor = ({ content, editable = true, onChange, children, isFocused }: Edi
56
58
  }, []);
57
59
 
58
60
  return (
59
- <div className="squiz-fte-scope">
60
- <div
61
- ref={wrapperRef}
62
- onBlur={handleBlur}
63
- onFocusCapture={handleFocus}
64
- className={clsx('formatted-text-editor', !editable && 'formatted-text-editor--is-disabled')}
61
+ <div
62
+ ref={wrapperRef}
63
+ onBlur={handleBlur}
64
+ onFocusCapture={handleFocus}
65
+ className={clsx(
66
+ 'squiz-fte-scope',
67
+ 'squiz-fte-scope__editor',
68
+ !editable && 'squiz-fte-scope__editor--is-disabled',
69
+ border && 'squiz-fte-scope__editor--bordered',
70
+ className,
71
+ )}
72
+ >
73
+ <Remirror
74
+ manager={manager}
75
+ state={state}
76
+ editable={editable}
77
+ onChange={handleChange}
78
+ placeholder="Write something"
79
+ label="Text editor"
65
80
  >
66
- <Remirror
67
- manager={manager}
68
- state={state}
69
- editable={editable}
70
- onChange={handleChange}
71
- placeholder="Write something"
72
- label="Text editor"
73
- >
74
- {editable && <Toolbar isVisible={isVisible} />}
75
- {children}
76
- <WrappedEditor />
77
- {editable && <FloatingToolbar />}
78
- </Remirror>
79
- </div>
81
+ {editable && <Toolbar isVisible={isVisible} />}
82
+ {children && <div className="squiz-fte-scope__editor__children">{children}</div>}
83
+ <WrappedEditor />
84
+ {editable && <FloatingToolbar />}
85
+ </Remirror>
80
86
  </div>
81
87
  );
82
88
  };
@@ -1,13 +1,19 @@
1
- .formatted-text-editor {
1
+ /* 2 class selectors so specificity is higher vs eg. ".squiz-ce-scope *" which would take priority over this. */
2
+ .squiz-fte-scope.squiz-fte-scope__editor {
2
3
  font-family: 'Open Sans' !important;
3
- @apply bg-white rounded border-gray-300 border-2 border-solid;
4
+ @apply bg-white rounded border-gray-300;
4
5
 
5
- .remirror-editor-wrapper {
6
- @apply text-gray-800 pt-0;
6
+ &:has(&__children) {
7
+ /* The children replace the space taken up by top padding of the editor when present. */
8
+ @apply w-full min-h-[2rem];
9
+
10
+ .remirror-editor {
11
+ @apply pt-0;
12
+ }
7
13
  }
8
14
 
9
15
  .remirror-editor {
10
- @apply bg-white shadow-none rounded-b p-3;
16
+ @apply shadow-none p-8;
11
17
  overflow: auto;
12
18
  min-height: 15vh;
13
19
 
@@ -22,10 +28,13 @@
22
28
  }
23
29
  }
24
30
 
31
+ &--bordered {
32
+ @apply border-2 border-solid;
33
+ }
34
+
25
35
  &--is-disabled {
26
- .remirror-editor {
27
- @apply bg-gray-300 cursor-not-allowed;
28
- }
36
+ @apply bg-gray-50 border-0 cursor-not-allowed;
37
+
29
38
  .remirror-is-empty:first-of-type::before {
30
39
  display: none;
31
40
  }
@@ -24,32 +24,34 @@ export const Toolbar = ({ isVisible }: ToolbarProps) => {
24
24
 
25
25
  return (
26
26
  <RemirrorToolbar
27
- className={clsx('remirror-toolbar editor-toolbar header-toolbar', isVisible && 'show-toolbar')}
27
+ className={clsx('editor-toolbar header-toolbar', isVisible && 'show-toolbar')}
28
28
  role="toolbar"
29
29
  tabIndex={0}
30
30
  >
31
- {extensionNames.history && (
32
- <>
33
- <UndoButton />
34
- <RedoButton />
35
- <VerticalDivider />
36
- </>
37
- )}
38
- {extensionNames.heading && extensionNames.paragraph && extensionNames.preformatted && <TextTypeDropdown />}
39
- {extensionNames.bold && <BoldButton />}
40
- {extensionNames.italic && <ItalicButton />}
41
- {extensionNames.underline && <UnderlineButton />}
42
- {extensionNames.nodeFormatting && <TextAlignButtons />}
43
- {extensionNames.listItem && <ListButtons />}
44
- {extensionNames.horizontalRule && <HorizontalLineButton />}
45
- {extensionNames.link && (
46
- <>
47
- <LinkButton />
48
- <RemoveLinkButton />
49
- </>
50
- )}
51
- {extensionNames.image && <ImageButton />}
52
- {extensionNames.clearFormatting && <ClearFormattingButton />}
31
+ <div className="editor-toolbar__tools">
32
+ {extensionNames.history && (
33
+ <>
34
+ <UndoButton />
35
+ <RedoButton />
36
+ <VerticalDivider />
37
+ </>
38
+ )}
39
+ {extensionNames.heading && extensionNames.paragraph && extensionNames.preformatted && <TextTypeDropdown />}
40
+ {extensionNames.bold && <BoldButton />}
41
+ {extensionNames.italic && <ItalicButton />}
42
+ {extensionNames.underline && <UnderlineButton />}
43
+ {extensionNames.nodeFormatting && <TextAlignButtons />}
44
+ {extensionNames.listItem && <ListButtons />}
45
+ {extensionNames.horizontalRule && <HorizontalLineButton />}
46
+ {extensionNames.link && (
47
+ <>
48
+ <LinkButton />
49
+ <RemoveLinkButton />
50
+ </>
51
+ )}
52
+ {extensionNames.image && <ImageButton />}
53
+ {extensionNames.clearFormatting && <ClearFormattingButton />}
54
+ </div>
53
55
  </RemirrorToolbar>
54
56
  );
55
57
  };
@@ -1,30 +1,32 @@
1
1
  .editor-toolbar {
2
- @apply bg-white border-gray-200 border-b-2 border-solid p-1 rounded-t;
2
+ @apply bg-transparent rounded-t;
3
3
 
4
- display: flex;
5
- justify-items: center;
6
- flex-wrap: wrap;
4
+ &__tools {
5
+ @apply border-gray-200 border-b-2 border-solid p-1 w-full flex flex-wrap justify-items-center;
7
6
 
8
- > *:not(:first-child, .MuiDivider-root) {
9
- margin: 0 0 0 2px;
10
- }
7
+ > *:not(:first-child, .MuiDivider-root) {
8
+ margin: 0 0 0 2px;
9
+ }
11
10
 
12
- .MuiDivider-root {
13
- @apply my-0 mx-1 border;
14
- margin-right: 2px;
15
- height: auto;
16
- }
11
+ .MuiDivider-root {
12
+ @apply my-0 mx-1 border;
13
+ margin-right: 2px;
14
+ height: auto;
15
+ }
17
16
 
18
- .squiz-fte-btn {
19
- @apply p-1 font-bold;
20
- ~ .squiz-fte-btn {
21
- margin-left: 2px;
17
+ .squiz-fte-btn {
18
+ @apply p-1 font-bold;
19
+ ~ .squiz-fte-btn {
20
+ margin-left: 2px;
21
+ }
22
22
  }
23
23
  }
24
24
  }
25
25
 
26
26
  .header-toolbar {
27
- transition: opacity 0.2s linear, max-height 0.2s linear;
27
+ transition-duration: 0.3s;
28
+ transition-property: max-height, opacity;
29
+ transition-timing-function: ease-out;
28
30
  opacity: 0;
29
31
  max-height: 0;
30
32
 
@@ -4,7 +4,7 @@ module.exports = {
4
4
  theme: {
5
5
  extend: {
6
6
  borderRadius: {
7
- DEFAULT: '4px',
7
+ DEFAULT: '8px',
8
8
  md: '6px',
9
9
  },
10
10
  fontFamily: {