@squiz/formatted-text-editor 1.33.1-alpha.2 → 1.33.1-alpha.4

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.
Files changed (79) hide show
  1. package/demo/App.tsx +4 -24
  2. package/demo/AppContext.tsx +28 -0
  3. package/demo/index.scss +0 -2
  4. package/demo/main.tsx +2 -0
  5. package/demo/resources.json +28 -0
  6. package/demo/sources.json +23 -0
  7. package/lib/Editor/EditorContext.d.ts +0 -7
  8. package/lib/Editor/EditorContext.js +0 -2
  9. package/lib/EditorToolbar/Tools/Image/Form/ImageForm.js +16 -32
  10. package/lib/EditorToolbar/Tools/Image/ImageModal.js +3 -2
  11. package/lib/EditorToolbar/Tools/Link/Form/LinkForm.js +18 -58
  12. package/lib/EditorToolbar/Tools/Link/LinkModal.js +3 -2
  13. package/lib/EditorToolbar/Tools/Link/RemoveLinkButton.js +1 -1
  14. package/lib/Extensions/Extensions.js +0 -2
  15. package/lib/Extensions/ImageExtension/AssetImageExtension.d.ts +0 -1
  16. package/lib/Extensions/ImageExtension/AssetImageExtension.js +1 -2
  17. package/lib/Extensions/LinkExtension/AssetLinkExtension.d.ts +0 -1
  18. package/lib/Extensions/LinkExtension/AssetLinkExtension.js +2 -3
  19. package/lib/Extensions/LinkExtension/LinkExtension.js +1 -1
  20. package/lib/index.css +84 -4
  21. package/lib/types.d.ts +3 -3
  22. package/lib/ui/Fields/Checkbox/Checkbox.d.ts +8 -0
  23. package/lib/ui/Fields/Checkbox/Checkbox.js +47 -0
  24. package/lib/ui/Fields/Input/Input.d.ts +2 -4
  25. package/lib/ui/Fields/Input/Input.js +3 -9
  26. package/lib/ui/Fields/InputContainer/InputContainer.d.ts +9 -0
  27. package/lib/ui/Fields/InputContainer/InputContainer.js +16 -0
  28. package/lib/ui/Fields/MatrixAsset/MatrixAsset.d.ts +17 -0
  29. package/lib/ui/Fields/MatrixAsset/MatrixAsset.js +29 -0
  30. package/lib/ui/Modal/Modal.d.ts +1 -0
  31. package/lib/ui/Modal/Modal.js +3 -2
  32. package/lib/ui/Tabs/Tabs.d.ts +10 -0
  33. package/lib/ui/Tabs/Tabs.js +46 -0
  34. package/lib/utils/validation.d.ts +2 -1
  35. package/lib/utils/validation.js +8 -2
  36. package/package.json +4 -3
  37. package/src/Editor/Editor.spec.tsx +1 -1
  38. package/src/Editor/EditorContext.spec.tsx +11 -13
  39. package/src/Editor/EditorContext.ts +0 -11
  40. package/src/EditorToolbar/Tools/Image/Form/ImageForm.spec.tsx +29 -12
  41. package/src/EditorToolbar/Tools/Image/Form/ImageForm.tsx +37 -53
  42. package/src/EditorToolbar/Tools/Image/ImageButton.spec.tsx +76 -49
  43. package/src/EditorToolbar/Tools/Image/ImageModal.spec.tsx +1 -0
  44. package/src/EditorToolbar/Tools/Image/ImageModal.tsx +3 -2
  45. package/src/EditorToolbar/Tools/Link/Form/LinkForm.spec.tsx +22 -13
  46. package/src/EditorToolbar/Tools/Link/Form/LinkForm.tsx +35 -57
  47. package/src/EditorToolbar/Tools/Link/LinkButton.spec.tsx +52 -36
  48. package/src/EditorToolbar/Tools/Link/LinkModal.tsx +3 -2
  49. package/src/EditorToolbar/Tools/Link/RemoveLinkButton.spec.tsx +47 -4
  50. package/src/EditorToolbar/Tools/Link/RemoveLinkButton.tsx +3 -2
  51. package/src/Extensions/Extensions.ts +0 -2
  52. package/src/Extensions/ImageExtension/AssetImageExtension.ts +1 -3
  53. package/src/Extensions/LinkExtension/AssetLinkExtension.ts +2 -4
  54. package/src/Extensions/LinkExtension/LinkExtension.ts +1 -1
  55. package/src/index.scss +1 -0
  56. package/src/types.ts +7 -5
  57. package/src/ui/Fields/Checkbox/Checkbox.spec.tsx +50 -0
  58. package/src/ui/Fields/Checkbox/Checkbox.tsx +49 -0
  59. package/src/ui/Fields/Checkbox/_checkbox.scss +26 -0
  60. package/src/ui/Fields/Input/Input.tsx +4 -18
  61. package/src/ui/Fields/InputContainer/InputContainer.spec.tsx +18 -0
  62. package/src/ui/Fields/InputContainer/InputContainer.tsx +29 -0
  63. package/src/ui/Fields/MatrixAsset/MatrixAsset.spec.tsx +103 -0
  64. package/src/ui/Fields/MatrixAsset/MatrixAsset.tsx +55 -0
  65. package/src/ui/Modal/FormModal.spec.tsx +2 -1
  66. package/src/ui/Modal/Modal.spec.tsx +15 -7
  67. package/src/ui/Modal/Modal.tsx +4 -2
  68. package/src/ui/Tabs/Tabs.spec.tsx +44 -0
  69. package/src/ui/Tabs/Tabs.tsx +41 -0
  70. package/src/ui/_forms.scss +4 -2
  71. package/src/utils/validation.spec.ts +22 -0
  72. package/src/utils/validation.ts +9 -1
  73. package/tests/index.ts +2 -0
  74. package/tests/mockResourceBrowserContext.tsx +63 -0
  75. package/tests/renderWithContext.tsx +18 -0
  76. package/tests/renderWithEditor.tsx +18 -21
  77. package/vite.config.ts +8 -0
  78. package/lib/ui/Fields/Select/Select.d.ts +0 -12
  79. package/lib/ui/Fields/Select/Select.js +0 -53
package/demo/App.tsx CHANGED
@@ -1,7 +1,8 @@
1
1
  import React, { useState } from 'react';
2
- import { Editor, EditorContext, remirrorNodeToSquizNode, squizNodeToRemirrorNode } from '../src';
2
+ import { Editor, remirrorNodeToSquizNode, squizNodeToRemirrorNode } from '../src';
3
3
  import { RemirrorEventListener, Extension } from '@remirror/core';
4
4
  import ReactDiffViewer from 'react-diff-viewer-continued';
5
+ import { AppContext } from './AppContext';
5
6
 
6
7
  function App() {
7
8
  const [doc, setDoc] = useState('');
@@ -35,34 +36,13 @@ function App() {
35
36
  </div>
36
37
  <h1>Editor</h1>
37
38
  <div className="page-section">
38
- <EditorContext.Provider
39
- value={{
40
- matrix: {
41
- matrixDomain: 'https://matrix-domain.squiz.net',
42
- matrixIdentifier: 'matrix-api-identifier',
43
- resolveMatrixAsset: (assetId: string) => {
44
- return new Promise((resolve) => {
45
- setTimeout(() => {
46
- if (assetId.match(/invalid/i)) {
47
- resolve(null);
48
- } else {
49
- resolve({
50
- id: assetId,
51
- type: assetId.match(/(image)/i)?.[0] || 'unknown',
52
- });
53
- }
54
- }, 200);
55
- });
56
- },
57
- },
58
- }}
59
- >
39
+ <AppContext>
60
40
  <Editor
61
41
  editable={editable}
62
42
  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>`}
63
43
  onChange={handleEditorChange}
64
44
  />
65
- </EditorContext.Provider>
45
+ </AppContext>
66
46
  </div>
67
47
  <h1>Document</h1>
68
48
  <div className="page-section">
@@ -0,0 +1,28 @@
1
+ import React, { PropsWithChildren } from 'react';
2
+ import { ResourceBrowserContext, Source, Resource, ResourceReference } from '@squiz/resource-browser';
3
+ import { EditorContext } from '../src';
4
+ import resources from './resources.json';
5
+ import sources from './sources.json';
6
+
7
+ export type AppContextProps = PropsWithChildren;
8
+
9
+ export const AppContext = ({ children }: AppContextProps) => (
10
+ <ResourceBrowserContext.Provider
11
+ value={{
12
+ onRequestSources: (): Promise<Source> => Promise.resolve(sources),
13
+ onRequestChildren: (): Promise<Resource[]> => Promise.resolve(resources),
14
+ onRequestResource: (reference: ResourceReference): Promise<Resource | null> =>
15
+ Promise.resolve(resources.find((resource) => resource.id === reference.resource) || null),
16
+ }}
17
+ >
18
+ <EditorContext.Provider
19
+ value={{
20
+ matrix: {
21
+ matrixDomain: 'https://matrix-domain.squiz.net',
22
+ },
23
+ }}
24
+ >
25
+ {children}
26
+ </EditorContext.Provider>
27
+ </ResourceBrowserContext.Provider>
28
+ );
package/demo/index.scss CHANGED
@@ -1,5 +1,3 @@
1
- @import '../src/index.scss';
2
-
3
1
  body {
4
2
  font-family: 'Open Sans';
5
3
  }
package/demo/main.tsx CHANGED
@@ -1,6 +1,8 @@
1
1
  import React from 'react';
2
2
  import ReactDOM from 'react-dom/client';
3
3
  import App from './App';
4
+ import '@squiz/resource-browser/lib/index.css';
5
+ import '../src/index.scss';
4
6
  import './index.scss';
5
7
 
6
8
  ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
@@ -0,0 +1,28 @@
1
+ [
2
+ {
3
+ "id": "1",
4
+ "type": {
5
+ "code": "image",
6
+ "name": "Image"
7
+ },
8
+ "status": {
9
+ "code": "live",
10
+ "name": "Live"
11
+ },
12
+ "name": "Example image",
13
+ "childCount": 0
14
+ },
15
+ {
16
+ "id": "2",
17
+ "type": {
18
+ "code": "page_standard",
19
+ "name": "Standard Page"
20
+ },
21
+ "status": {
22
+ "code": "live",
23
+ "name": "Live"
24
+ },
25
+ "name": "Example page",
26
+ "childCount": 0
27
+ }
28
+ ]
@@ -0,0 +1,23 @@
1
+ [
2
+ {
3
+ "id": "my-matrix-instance",
4
+ "name": "My Matrix instance",
5
+ "nodes": [
6
+ {
7
+ "id": "1",
8
+ "name": "My site",
9
+ "childCount": 100,
10
+ "url": "https://my-matrix.squiz.net/site",
11
+ "urls": [],
12
+ "type": {
13
+ "code": "site",
14
+ "name": "Site"
15
+ },
16
+ "status": {
17
+ "code": "live",
18
+ "name": "Live"
19
+ }
20
+ }
21
+ ]
22
+ }
23
+ ]
@@ -1,14 +1,7 @@
1
1
  import React from 'react';
2
- export type MatrixAsset = {
3
- id: string;
4
- type: string | 'image';
5
- };
6
- export type MatrixAssetResolver = (assetId: string) => Promise<MatrixAsset | null>;
7
2
  export type EditorContextOptions = {
8
3
  matrix: {
9
- matrixIdentifier: string;
10
4
  matrixDomain: string;
11
- resolveMatrixAsset: MatrixAssetResolver;
12
5
  };
13
6
  };
14
7
  export declare const defaultEditorContext: EditorContextOptions;
@@ -7,9 +7,7 @@ exports.EditorContext = exports.defaultEditorContext = void 0;
7
7
  const react_1 = __importDefault(require("react"));
8
8
  exports.defaultEditorContext = {
9
9
  matrix: {
10
- matrixIdentifier: '',
11
10
  matrixDomain: '',
12
- resolveMatrixAsset: () => Promise.resolve(null),
13
11
  },
14
12
  };
15
13
  exports.EditorContext = react_1.default.createContext(exports.defaultEditorContext);
@@ -27,27 +27,26 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
29
  const react_1 = __importStar(require("react"));
30
- const Input_1 = require("../../../../ui/Fields/Input/Input");
31
30
  const react_hook_form_1 = require("react-hook-form");
32
31
  const react_image_size_1 = require("react-image-size");
32
+ const clsx_1 = __importDefault(require("clsx"));
33
+ const Input_1 = require("../../../../ui/Fields/Input/Input");
33
34
  const Button_1 = __importDefault(require("../../../../ui/Button/Button"));
34
35
  const LinkOff_1 = __importDefault(require("@mui/icons-material/LinkOff"));
35
36
  const InsertLinkRounded_1 = __importDefault(require("@mui/icons-material/InsertLinkRounded"));
36
- const clsx_1 = __importDefault(require("clsx"));
37
37
  const Extensions_1 = require("../../../../Extensions/Extensions");
38
- const Select_1 = require("../../../../ui/Fields/Select/Select");
39
- const EditorContext_1 = require("../../../../Editor/EditorContext");
40
38
  const validation_1 = require("../../../../utils/validation");
39
+ const Tabs_1 = require("../../../../ui/Tabs/Tabs");
40
+ const MatrixAsset_1 = require("../../../../ui/Fields/MatrixAsset/MatrixAsset");
41
41
  const imageTypeOptions = {
42
- [Extensions_1.NodeName.Image]: { label: 'External image' },
43
- [Extensions_1.NodeName.AssetImage]: { label: 'Asset image' },
42
+ [Extensions_1.NodeName.AssetImage]: { label: 'From source' },
43
+ [Extensions_1.NodeName.Image]: { label: 'From URL' },
44
44
  };
45
45
  const ImageForm = ({ data, onSubmit }) => {
46
- const { register, handleSubmit, setValue, watch, formState: { errors }, } = (0, react_hook_form_1.useForm)({
46
+ const { control, register, handleSubmit, setValue, watch, formState: { errors }, } = (0, react_hook_form_1.useForm)({
47
47
  defaultValues: data,
48
48
  });
49
- const imageType = watch('imageType') || Extensions_1.NodeName.Image;
50
- const context = (0, react_1.useContext)(EditorContext_1.EditorContext);
49
+ const imageType = watch('imageType') || Extensions_1.NodeName.AssetImage;
51
50
  const [aspectRatioFromWidth, setAspectRatioFromWidth] = (0, react_1.useState)(9 / 16);
52
51
  const [aspectRatioFromHeight, setAspectRatioFromHeight] = (0, react_1.useState)(16 / 9);
53
52
  const [aspectRatioLocked, setAspectRatioLocked] = (0, react_1.useState)(true);
@@ -88,8 +87,8 @@ const ImageForm = ({ data, onSubmit }) => {
88
87
  setAspectRatioLocked(!aspectRatioLocked);
89
88
  };
90
89
  return (react_1.default.createElement("form", { className: "squiz-fte-form", onSubmit: handleSubmit(onSubmit) },
91
- react_1.default.createElement("div", { className: "squiz-fte-form-group mb-2" },
92
- react_1.default.createElement(Select_1.Select, { name: "imageType", label: "Type", value: imageType, options: imageTypeOptions, onChange: (value) => setValue('imageType', value) })),
90
+ react_1.default.createElement("div", { className: "squiz-fte-form-group mb-4" },
91
+ react_1.default.createElement(Tabs_1.Tabs, { value: imageType, options: imageTypeOptions, onChange: (value) => setValue('imageType', value) })),
93
92
  imageType === Extensions_1.NodeName.Image && (react_1.default.createElement(react_1.default.Fragment, null,
94
93
  react_1.default.createElement("div", { className: "squiz-fte-form-group mb-2" },
95
94
  react_1.default.createElement(Input_1.Input, { label: "Source", required: true, error: errors?.image?.src?.message, ...register('image.src', {
@@ -107,13 +106,6 @@ const ImageForm = ({ data, onSubmit }) => {
107
106
  noEmptySpaces: validation_1.noEmptySpacesValidation,
108
107
  },
109
108
  }) })),
110
- react_1.default.createElement("div", { className: "squiz-fte-form-group mb-2" },
111
- react_1.default.createElement(Input_1.Input, { label: "Alternative description", required: true, error: errors?.image?.alt?.message, ...register('image.alt', {
112
- required: 'Alternative description is required',
113
- validate: {
114
- noEmptySpaces: validation_1.noEmptySpacesValidation,
115
- },
116
- }) })),
117
109
  react_1.default.createElement("div", { className: "flex flex-row" },
118
110
  react_1.default.createElement("div", { className: "squiz-fte-form-group mb-2" },
119
111
  react_1.default.createElement(Input_1.Input, { label: "Width", type: "number", required: true, error: errors?.image?.width?.message, ...register('image.width', {
@@ -140,20 +132,12 @@ const ImageForm = ({ data, onSubmit }) => {
140
132
  }
141
133
  },
142
134
  },
143
- }) }))))),
144
- imageType === Extensions_1.NodeName.AssetImage && (react_1.default.createElement(react_1.default.Fragment, null,
135
+ }) }))),
145
136
  react_1.default.createElement("div", { className: "squiz-fte-form-group mb-2" },
146
- react_1.default.createElement(Input_1.Input, { label: "Asset ID", required: true, error: errors?.assetImage?.matrixAssetId?.message, ...register('assetImage.matrixAssetId', {
147
- required: 'Asset ID is required',
148
- validate: {
149
- isImage: async (assetId) => {
150
- const asset = await context.matrix.resolveMatrixAsset(assetId);
151
- if (asset?.type !== 'image') {
152
- return 'Asset ID is invalid or not an image';
153
- }
154
- },
155
- noEmptySpaces: validation_1.noEmptySpacesValidation,
156
- },
157
- }) }))))));
137
+ react_1.default.createElement(Input_1.Input, { label: "Alternative description", error: errors?.image?.alt?.message, ...register('image.alt') })))),
138
+ imageType === Extensions_1.NodeName.AssetImage && (react_1.default.createElement("div", { className: "squiz-fte-form-group mb-2" },
139
+ react_1.default.createElement(react_hook_form_1.Controller, { control: control, name: "assetImage", rules: {
140
+ validate: (0, validation_1.hasProperties)('An image must be selected', ['matrixIdentifier', 'matrixAssetId']),
141
+ }, render: ({ field: { onChange, value }, fieldState: { error } }) => (react_1.default.createElement(MatrixAsset_1.MatrixAsset, { modalTitle: "Insert image", allowedTypes: ['image'], value: value, onChange: onChange, error: error?.message })) })))));
158
142
  };
159
143
  exports.default = ImageForm;
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const ImageForm_1 = __importDefault(require("./Form/ImageForm"));
7
7
  const react_1 = __importDefault(require("react"));
8
8
  const react_2 = require("@remirror/react");
9
+ const ImageRounded_1 = __importDefault(require("@mui/icons-material/ImageRounded"));
9
10
  const FormModal_1 = __importDefault(require("../../../ui/Modal/FormModal"));
10
11
  const Extensions_1 = require("../../../Extensions/Extensions");
11
12
  const ImageModal = ({ onCancel, onSubmit }) => {
@@ -13,11 +14,11 @@ const ImageModal = ({ onCancel, onSubmit }) => {
13
14
  const currentImage = selection?.node;
14
15
  const currentImageAttrs = { ...currentImage?.attrs };
15
16
  const formData = {
16
- imageType: currentImage?.type.name === Extensions_1.NodeName.AssetImage ? Extensions_1.NodeName.AssetImage : Extensions_1.NodeName.Image,
17
+ imageType: currentImage?.type.name === Extensions_1.NodeName.Image ? Extensions_1.NodeName.Image : Extensions_1.NodeName.AssetImage,
17
18
  image: currentImage?.type?.name === Extensions_1.NodeName.Image ? currentImageAttrs : {},
18
19
  assetImage: currentImage?.type?.name === Extensions_1.NodeName.AssetImage ? currentImageAttrs : {},
19
20
  };
20
- return (react_1.default.createElement(FormModal_1.default, { title: "Image", onCancel: onCancel },
21
+ return (react_1.default.createElement(FormModal_1.default, { title: "Image", icon: react_1.default.createElement(ImageRounded_1.default, null), onCancel: onCancel },
21
22
  react_1.default.createElement(ImageForm_1.default, { data: formData, onSubmit: onSubmit })));
22
23
  };
23
24
  exports.default = ImageModal;
@@ -1,58 +1,31 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
4
  };
28
5
  Object.defineProperty(exports, "__esModule", { value: true });
29
6
  exports.LinkForm = void 0;
30
- const react_1 = __importStar(require("react"));
7
+ const react_1 = __importDefault(require("react"));
31
8
  const clsx_1 = __importDefault(require("clsx"));
32
9
  const react_hook_form_1 = require("react-hook-form");
33
10
  const Input_1 = require("../../../../ui/Fields/Input/Input");
34
- const Select_1 = require("../../../../ui/Fields/Select/Select");
11
+ const Checkbox_1 = require("../../../../ui/Fields/Checkbox/Checkbox");
35
12
  const common_1 = require("../../../../Extensions/LinkExtension/common");
36
- const EditorContext_1 = require("../../../../Editor/EditorContext");
37
13
  const Extensions_1 = require("../../../../Extensions/Extensions");
38
14
  const validation_1 = require("../../../../utils/validation");
15
+ const Tabs_1 = require("../../../../ui/Tabs/Tabs");
16
+ const MatrixAsset_1 = require("../../../../ui/Fields/MatrixAsset/MatrixAsset");
39
17
  const linkTypeOptions = {
40
- [Extensions_1.MarkName.Link]: { label: 'Link to URL' },
41
- [Extensions_1.MarkName.AssetLink]: { label: 'Link to asset' },
42
- };
43
- const targetOptions = {
44
- [common_1.LinkTarget.Self]: { label: 'Current window' },
45
- [common_1.LinkTarget.Blank]: { label: 'New window' },
18
+ [Extensions_1.MarkName.AssetLink]: { label: 'From source' },
19
+ [Extensions_1.MarkName.Link]: { label: 'From URL' },
46
20
  };
47
21
  const LinkForm = ({ data, onSubmit }) => {
48
- const context = (0, react_1.useContext)(EditorContext_1.EditorContext);
49
- const { register, handleSubmit, setValue, watch, formState: { errors }, } = (0, react_hook_form_1.useForm)({
22
+ const { control, register, handleSubmit, setValue, watch, formState: { errors }, } = (0, react_hook_form_1.useForm)({
50
23
  defaultValues: data,
51
24
  });
52
- const linkType = watch('linkType') || Extensions_1.MarkName.Link;
25
+ const linkType = watch('linkType') || Extensions_1.MarkName.AssetLink;
53
26
  return (react_1.default.createElement("form", { className: "squiz-fte-form", onSubmit: handleSubmit(onSubmit) },
54
- react_1.default.createElement("div", { className: "squiz-fte-form-group mb-2" },
55
- react_1.default.createElement(Select_1.Select, { name: "linkType", label: "Type", value: linkType, options: linkTypeOptions, onChange: (value) => setValue('linkType', value) })),
27
+ react_1.default.createElement("div", { className: "squiz-fte-form-group mb-4" },
28
+ react_1.default.createElement(Tabs_1.Tabs, { value: linkType, options: linkTypeOptions, onChange: (value) => setValue('linkType', value) })),
56
29
  linkType === Extensions_1.MarkName.Link && (react_1.default.createElement(react_1.default.Fragment, null,
57
30
  react_1.default.createElement("div", { className: (0, clsx_1.default)('squiz-fte-form-group mb-2') },
58
31
  react_1.default.createElement(Input_1.Input, { label: "URL", required: true, error: errors?.link?.href?.message, ...register('link.href', {
@@ -69,27 +42,14 @@ const LinkForm = ({ data, onSubmit }) => {
69
42
  },
70
43
  }) })),
71
44
  react_1.default.createElement("div", { className: (0, clsx_1.default)('squiz-fte-form-group mb-2') },
72
- react_1.default.createElement(Input_1.Input, { label: "Title", required: true, error: errors?.link?.title?.message, ...register('link.title', {
73
- required: 'Title is required',
74
- validate: {
75
- noEmptySpaces: validation_1.noEmptySpacesValidation,
76
- },
77
- }) })),
78
- react_1.default.createElement("div", { className: (0, clsx_1.default)('squiz-fte-form-group mb-0') },
79
- react_1.default.createElement(Select_1.Select, { name: "link.target", label: "Target", value: data?.link?.target || '_self', options: targetOptions, onChange: (value) => setValue('link.target', value) })))),
45
+ react_1.default.createElement(Input_1.Input, { label: "Title", error: errors?.link?.title?.message, ...register('link.title') })),
46
+ react_1.default.createElement("div", { className: (0, clsx_1.default)('squiz-fte-form-group mb-2') },
47
+ react_1.default.createElement(Checkbox_1.Checkbox, { label: "Open link in new window", onChange: (value) => setValue('link.target', value), defaultChecked: data?.link?.target === common_1.LinkTarget.Blank, unchecked: common_1.LinkTarget.Self, checked: common_1.LinkTarget.Blank })))),
80
48
  linkType === Extensions_1.MarkName.AssetLink && (react_1.default.createElement(react_1.default.Fragment, null,
81
49
  react_1.default.createElement("div", { className: (0, clsx_1.default)('squiz-fte-form-group mb-2') },
82
- react_1.default.createElement(Input_1.Input, { label: "Asset ID", required: true, error: errors?.assetLink?.matrixAssetId?.message, ...register('assetLink.matrixAssetId', {
83
- required: 'Asset ID is required',
84
- validate: {
85
- isValidAsset: async (assetId) => {
86
- if (assetId && !(await context.matrix.resolveMatrixAsset(assetId))) {
87
- return 'Invalid asset ID';
88
- }
89
- },
90
- noEmptySpaces: validation_1.noEmptySpacesValidation,
91
- },
92
- }) })),
50
+ react_1.default.createElement(react_hook_form_1.Controller, { control: control, name: "assetLink", rules: {
51
+ validate: (0, validation_1.hasProperties)('An asset must be selected', ['matrixIdentifier', 'matrixAssetId']),
52
+ }, render: ({ field: { onChange, value }, fieldState: { error } }) => (react_1.default.createElement(MatrixAsset_1.MatrixAsset, { modalTitle: "Insert link", value: value, onChange: onChange, error: error?.message })) })),
93
53
  react_1.default.createElement("div", { className: (0, clsx_1.default)('squiz-fte-form-group mb-2') },
94
54
  react_1.default.createElement(Input_1.Input, { label: "Text", required: true, error: errors?.text?.message, ...register('text', {
95
55
  required: 'Text is required',
@@ -97,7 +57,7 @@ const LinkForm = ({ data, onSubmit }) => {
97
57
  noEmptySpaces: validation_1.noEmptySpacesValidation,
98
58
  },
99
59
  }) })),
100
- react_1.default.createElement("div", { className: (0, clsx_1.default)('squiz-fte-form-group mb-0') },
101
- react_1.default.createElement(Select_1.Select, { name: "assetLink.target", label: "Target", value: data?.assetLink?.target || '_self', options: targetOptions, onChange: (value) => setValue('assetLink.target', value) }))))));
60
+ react_1.default.createElement("div", { className: (0, clsx_1.default)('squiz-fte-form-group mb-2') },
61
+ react_1.default.createElement(Checkbox_1.Checkbox, { label: "Open link in new window", onChange: (value) => setValue('assetLink.target', value), defaultChecked: data?.assetLink?.target === '_blank', unchecked: '_self', checked: '_blank' }))))));
102
62
  };
103
63
  exports.LinkForm = LinkForm;
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const LinkForm_1 = require("./Form/LinkForm");
7
7
  const react_1 = __importDefault(require("react"));
8
8
  const react_2 = require("@remirror/react");
9
+ const InsertLinkRounded_1 = __importDefault(require("@mui/icons-material/InsertLinkRounded"));
9
10
  const FormModal_1 = __importDefault(require("../../../ui/Modal/FormModal"));
10
11
  const hooks_1 = require("../../../hooks");
11
12
  const Extensions_1 = require("../../../Extensions/Extensions");
@@ -14,13 +15,13 @@ const LinkModal = ({ onCancel, onSubmit }) => {
14
15
  const { selection, marks } = (0, hooks_1.useExpandedSelection)([Extensions_1.MarkName.Link, Extensions_1.MarkName.AssetLink]);
15
16
  const selectedText = helpers.getTextBetween(selection.from, selection.to, state.doc);
16
17
  const data = {
17
- linkType: marks[0]?.type?.name === Extensions_1.MarkName.AssetLink ? Extensions_1.MarkName.AssetLink : Extensions_1.MarkName.Link,
18
+ linkType: marks[0]?.type?.name === Extensions_1.MarkName.Link ? Extensions_1.MarkName.Link : Extensions_1.MarkName.AssetLink,
18
19
  text: selectedText,
19
20
  link: { ...marks.find((mark) => mark.type.name === 'link')?.attrs },
20
21
  assetLink: { ...marks.find((mark) => mark.type.name === Extensions_1.MarkName.AssetLink)?.attrs },
21
22
  range: { from: selection.from, to: selection.to },
22
23
  };
23
- return (react_1.default.createElement(FormModal_1.default, { title: "Link", onCancel: onCancel },
24
+ return (react_1.default.createElement(FormModal_1.default, { title: "Link", icon: react_1.default.createElement(InsertLinkRounded_1.default, null), onCancel: onCancel },
24
25
  react_1.default.createElement(LinkForm_1.LinkForm, { data: data, onSubmit: onSubmit })));
25
26
  };
26
27
  exports.default = LinkModal;
@@ -33,7 +33,7 @@ const LinkOff_1 = __importDefault(require("@mui/icons-material/LinkOff"));
33
33
  const RemoveLinkButton = ({ inPopover = false }) => {
34
34
  const chain = (0, react_2.useChainedCommands)();
35
35
  const active = (0, react_2.useActive)();
36
- const disabled = !active.link();
36
+ const disabled = !active.link() && !active.assetLink();
37
37
  const handleClick = () => {
38
38
  chain.removeLink().removeAssetLink().focus().run();
39
39
  };
@@ -34,12 +34,10 @@ const createExtensions = (context) => {
34
34
  new ImageExtension_1.ImageExtension(),
35
35
  new ImageExtension_1.ImageExtension({ preferPastedTextContent: false }),
36
36
  new AssetImageExtension_1.AssetImageExtension({
37
- matrixIdentifier: context.matrix.matrixIdentifier,
38
37
  matrixDomain: context.matrix.matrixDomain,
39
38
  }),
40
39
  new LinkExtension_1.LinkExtension(),
41
40
  new AssetLinkExtension_1.AssetLinkExtension({
42
- matrixIdentifier: context.matrix.matrixIdentifier,
43
41
  matrixDomain: context.matrix.matrixDomain,
44
42
  }),
45
43
  ];
@@ -1,7 +1,6 @@
1
1
  import { ApplySchemaAttributes, NodeExtension, NodeExtensionSpec, NodeSpecOverride, CommandFunction } from '@remirror/core';
2
2
  import { NodeName } from '../Extensions';
3
3
  export type AssetImageOptions = {
4
- matrixIdentifier?: string;
5
4
  matrixDomain?: string;
6
5
  };
7
6
  export type AssetImageAttributes = {
@@ -27,7 +27,7 @@ let AssetImageExtension = class AssetImageExtension extends core_1.NodeExtension
27
27
  attrs: {
28
28
  ...extra.defaults(),
29
29
  matrixAssetId: {},
30
- matrixIdentifier: { default: this.options.matrixIdentifier },
30
+ matrixIdentifier: {},
31
31
  matrixDomain: { default: this.options.matrixDomain },
32
32
  },
33
33
  parseDOM: [
@@ -83,7 +83,6 @@ __decorate([
83
83
  AssetImageExtension = __decorate([
84
84
  (0, core_1.extension)({
85
85
  defaultOptions: {
86
- matrixIdentifier: '',
87
86
  matrixDomain: '',
88
87
  },
89
88
  defaultPriority: core_1.ExtensionPriority.High,
@@ -8,7 +8,6 @@ export type AssetLinkAttributes = {
8
8
  target: LinkTarget;
9
9
  };
10
10
  export type AssetLinkOptions = {
11
- matrixIdentifier?: string;
12
11
  matrixDomain?: string;
13
12
  defaultTarget?: LinkTarget;
14
13
  supportedTargets?: LinkTarget[];
@@ -20,12 +20,12 @@ let AssetLinkExtension = class AssetLinkExtension extends core_1.MarkExtension {
20
20
  createMarkSpec(extra, override) {
21
21
  return {
22
22
  inclusive: false,
23
- excludes: Extensions_1.MarkName.Link,
23
+ excludes: [this.name, Extensions_1.MarkName.Link].join(' '),
24
24
  ...override,
25
25
  attrs: {
26
26
  ...extra.defaults(),
27
27
  matrixAssetId: {},
28
- matrixIdentifier: { default: this.options.matrixIdentifier },
28
+ matrixIdentifier: {},
29
29
  matrixDomain: { default: this.options.matrixDomain },
30
30
  target: { default: this.options.defaultTarget },
31
31
  },
@@ -91,7 +91,6 @@ __decorate([
91
91
  AssetLinkExtension = __decorate([
92
92
  (0, core_1.extension)({
93
93
  defaultOptions: {
94
- matrixIdentifier: '',
95
94
  matrixDomain: '',
96
95
  defaultTarget: common_1.LinkTarget.Self,
97
96
  supportedTargets: [common_1.LinkTarget.Self, common_1.LinkTarget.Blank],
@@ -19,7 +19,7 @@ let LinkExtension = class LinkExtension extends core_1.MarkExtension {
19
19
  createMarkSpec(extra, override) {
20
20
  return {
21
21
  inclusive: false,
22
- excludes: Extensions_1.MarkName.AssetLink,
22
+ excludes: [this.name, Extensions_1.MarkName.AssetLink].join(' '),
23
23
  ...override,
24
24
  attrs: {
25
25
  ...extra.defaults(),