@squiz/formatted-text-editor 1.33.1-alpha.3 → 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.
- package/demo/App.tsx +4 -24
- package/demo/AppContext.tsx +28 -0
- package/demo/index.scss +0 -2
- package/demo/main.tsx +2 -0
- package/demo/resources.json +28 -0
- package/demo/sources.json +23 -0
- package/lib/Editor/EditorContext.d.ts +0 -7
- package/lib/Editor/EditorContext.js +0 -2
- package/lib/EditorToolbar/Tools/Image/Form/ImageForm.js +8 -19
- package/lib/EditorToolbar/Tools/Link/Form/LinkForm.js +6 -38
- package/lib/EditorToolbar/Tools/Link/RemoveLinkButton.js +1 -1
- package/lib/Extensions/Extensions.js +0 -2
- package/lib/Extensions/ImageExtension/AssetImageExtension.d.ts +0 -1
- package/lib/Extensions/ImageExtension/AssetImageExtension.js +1 -2
- package/lib/Extensions/LinkExtension/AssetLinkExtension.d.ts +0 -1
- package/lib/Extensions/LinkExtension/AssetLinkExtension.js +1 -2
- package/lib/index.css +7 -2
- package/lib/types.d.ts +3 -3
- package/lib/ui/Fields/Checkbox/Checkbox.js +1 -1
- package/lib/ui/Fields/Input/Input.d.ts +2 -4
- package/lib/ui/Fields/Input/Input.js +3 -9
- package/lib/ui/Fields/InputContainer/InputContainer.d.ts +9 -0
- package/lib/ui/Fields/InputContainer/InputContainer.js +16 -0
- package/lib/ui/Fields/MatrixAsset/MatrixAsset.d.ts +17 -0
- package/lib/ui/Fields/MatrixAsset/MatrixAsset.js +29 -0
- package/lib/utils/validation.d.ts +2 -1
- package/lib/utils/validation.js +8 -2
- package/package.json +4 -3
- package/src/Editor/Editor.spec.tsx +1 -1
- package/src/Editor/EditorContext.spec.tsx +11 -13
- package/src/Editor/EditorContext.ts +0 -11
- package/src/EditorToolbar/Tools/Image/Form/ImageForm.spec.tsx +27 -10
- package/src/EditorToolbar/Tools/Image/Form/ImageForm.tsx +25 -29
- package/src/EditorToolbar/Tools/Image/ImageButton.spec.tsx +69 -43
- package/src/EditorToolbar/Tools/Link/Form/LinkForm.spec.tsx +15 -5
- package/src/EditorToolbar/Tools/Link/Form/LinkForm.tsx +14 -20
- package/src/EditorToolbar/Tools/Link/LinkButton.spec.tsx +45 -29
- package/src/EditorToolbar/Tools/Link/RemoveLinkButton.spec.tsx +47 -4
- package/src/EditorToolbar/Tools/Link/RemoveLinkButton.tsx +3 -2
- package/src/Extensions/Extensions.ts +0 -2
- package/src/Extensions/ImageExtension/AssetImageExtension.ts +1 -3
- package/src/Extensions/LinkExtension/AssetLinkExtension.ts +1 -3
- package/src/types.ts +7 -5
- package/src/ui/Fields/Checkbox/Checkbox.tsx +1 -1
- package/src/ui/Fields/Input/Input.tsx +4 -18
- package/src/ui/Fields/InputContainer/InputContainer.spec.tsx +18 -0
- package/src/ui/Fields/InputContainer/InputContainer.tsx +29 -0
- package/src/ui/Fields/MatrixAsset/MatrixAsset.spec.tsx +103 -0
- package/src/ui/Fields/MatrixAsset/MatrixAsset.tsx +55 -0
- package/src/ui/_forms.scss +4 -2
- package/src/utils/validation.spec.ts +22 -0
- package/src/utils/validation.ts +9 -1
- package/tests/index.ts +2 -0
- package/tests/mockResourceBrowserContext.tsx +63 -0
- package/tests/renderWithContext.tsx +18 -0
- package/tests/renderWithEditor.tsx +18 -21
- package/vite.config.ts +8 -0
package/demo/App.tsx
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
import React, { useState } from 'react';
|
2
|
-
import { Editor,
|
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
|
-
<
|
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
|
-
</
|
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
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 EditorContext_1 = require("../../../../Editor/EditorContext");
|
39
38
|
const validation_1 = require("../../../../utils/validation");
|
40
39
|
const Tabs_1 = require("../../../../ui/Tabs/Tabs");
|
40
|
+
const MatrixAsset_1 = require("../../../../ui/Fields/MatrixAsset/MatrixAsset");
|
41
41
|
const imageTypeOptions = {
|
42
42
|
[Extensions_1.NodeName.AssetImage]: { label: 'From source' },
|
43
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
49
|
const imageType = watch('imageType') || Extensions_1.NodeName.AssetImage;
|
50
|
-
const context = (0, react_1.useContext)(EditorContext_1.EditorContext);
|
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);
|
@@ -136,19 +135,9 @@ const ImageForm = ({ data, onSubmit }) => {
|
|
136
135
|
}) }))),
|
137
136
|
react_1.default.createElement("div", { className: "squiz-fte-form-group mb-2" },
|
138
137
|
react_1.default.createElement(Input_1.Input, { label: "Alternative description", error: errors?.image?.alt?.message, ...register('image.alt') })))),
|
139
|
-
imageType === Extensions_1.NodeName.AssetImage && (react_1.default.createElement(
|
140
|
-
react_1.default.createElement(
|
141
|
-
|
142
|
-
|
143
|
-
validate: {
|
144
|
-
isImage: async (assetId) => {
|
145
|
-
const asset = await context.matrix.resolveMatrixAsset(assetId);
|
146
|
-
if (asset?.type !== 'image') {
|
147
|
-
return 'Asset ID is invalid or not an image';
|
148
|
-
}
|
149
|
-
},
|
150
|
-
noEmptySpaces: validation_1.noEmptySpacesValidation,
|
151
|
-
},
|
152
|
-
}) }))))));
|
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 })) })))));
|
153
142
|
};
|
154
143
|
exports.default = ImageForm;
|
@@ -1,49 +1,25 @@
|
|
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 =
|
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
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");
|
39
15
|
const Tabs_1 = require("../../../../ui/Tabs/Tabs");
|
16
|
+
const MatrixAsset_1 = require("../../../../ui/Fields/MatrixAsset/MatrixAsset");
|
40
17
|
const linkTypeOptions = {
|
41
18
|
[Extensions_1.MarkName.AssetLink]: { label: 'From source' },
|
42
19
|
[Extensions_1.MarkName.Link]: { label: 'From URL' },
|
43
20
|
};
|
44
21
|
const LinkForm = ({ data, onSubmit }) => {
|
45
|
-
const
|
46
|
-
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)({
|
47
23
|
defaultValues: data,
|
48
24
|
});
|
49
25
|
const linkType = watch('linkType') || Extensions_1.MarkName.AssetLink;
|
@@ -71,17 +47,9 @@ const LinkForm = ({ data, onSubmit }) => {
|
|
71
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 })))),
|
72
48
|
linkType === Extensions_1.MarkName.AssetLink && (react_1.default.createElement(react_1.default.Fragment, null,
|
73
49
|
react_1.default.createElement("div", { className: (0, clsx_1.default)('squiz-fte-form-group mb-2') },
|
74
|
-
react_1.default.createElement(
|
75
|
-
|
76
|
-
|
77
|
-
isValidAsset: async (assetId) => {
|
78
|
-
if (assetId && !(await context.matrix.resolveMatrixAsset(assetId))) {
|
79
|
-
return 'Invalid asset ID';
|
80
|
-
}
|
81
|
-
},
|
82
|
-
noEmptySpaces: validation_1.noEmptySpacesValidation,
|
83
|
-
},
|
84
|
-
}) })),
|
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 })) })),
|
85
53
|
react_1.default.createElement("div", { className: (0, clsx_1.default)('squiz-fte-form-group mb-2') },
|
86
54
|
react_1.default.createElement(Input_1.Input, { label: "Text", required: true, error: errors?.text?.message, ...register('text', {
|
87
55
|
required: 'Text is required',
|
@@ -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: {
|
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,
|
@@ -25,7 +25,7 @@ let AssetLinkExtension = class AssetLinkExtension extends core_1.MarkExtension {
|
|
25
25
|
attrs: {
|
26
26
|
...extra.defaults(),
|
27
27
|
matrixAssetId: {},
|
28
|
-
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],
|
package/lib/index.css
CHANGED
@@ -630,6 +630,9 @@
|
|
630
630
|
--tw-blur: blur(8px) !important;
|
631
631
|
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow) !important;
|
632
632
|
}
|
633
|
+
.squiz-fte-scope .filter {
|
634
|
+
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow) !important;
|
635
|
+
}
|
633
636
|
.squiz-fte-scope a {
|
634
637
|
--tw-text-opacity: 1;
|
635
638
|
color: rgb(7 116 210 / var(--tw-text-opacity));
|
@@ -683,6 +686,7 @@
|
|
683
686
|
color: rgb(112 112 112 / var(--tw-text-opacity));
|
684
687
|
}
|
685
688
|
.squiz-fte-scope .squiz-fte-form-control {
|
689
|
+
height: 36px;
|
686
690
|
padding: 6px 12px;
|
687
691
|
position: relative;
|
688
692
|
width: 100%;
|
@@ -716,13 +720,14 @@
|
|
716
720
|
.squiz-fte-scope .squiz-fte-form-control:active {
|
717
721
|
box-shadow: none;
|
718
722
|
}
|
719
|
-
.squiz-fte-scope .squiz-fte-invalid-form-field .squiz-fte-form-control
|
723
|
+
.squiz-fte-scope .squiz-fte-invalid-form-field .squiz-fte-form-control,
|
724
|
+
.squiz-fte-scope .squiz-fte-invalid-form-field .resource-picker {
|
720
725
|
--tw-border-opacity: 1;
|
721
726
|
border-color: rgb(215 35 33 / var(--tw-border-opacity));
|
722
727
|
background-repeat: no-repeat;
|
723
728
|
padding-right: 2rem;
|
724
729
|
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjQiIHdpZHRoPSIyNCI+PHJlY3Qgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0ibm9uZSIvPjxnIGNsYXNzPSJjdXJyZW50TGF5ZXIiPjxwYXRoIGQ9Ik00LjQ3IDIxaDE1LjA2YzEuNTQgMCAyLjUtMS42NyAxLjczLTNMMTMuNzMgNC45OWMtLjc3LTEuMzMtMi42OS0xLjMzLTMuNDYgMEwyLjc0IDE4Yy0uNzcgMS4zMy4xOSAzIDEuNzMgM3pNMTIgMTRjLS41NSAwLTEtLjQ1LTEtMXYtMmMwLS41NS40NS0xIDEtMXMxIC40NSAxIDF2MmMwIC41NS0uNDUgMS0xIDF6bTEgNGgtMnYtMmgydjJ6IiBjbGFzcz0ic2VsZWN0ZWQiIGZpbGw9IiNkNzIzMjEiLz48L2c+PC9zdmc+);
|
725
|
-
background-position:
|
730
|
+
background-position: center right 0.25rem;
|
726
731
|
background-size: 1.5rem;
|
727
732
|
}
|
728
733
|
.squiz-fte-scope .squiz-fte-form-error {
|
package/lib/types.d.ts
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
export type DeepPartial<T> =
|
2
|
-
[P in keyof T]?: DeepPartial<T[P]>;
|
3
|
-
}
|
1
|
+
export type DeepPartial<T> = {
|
2
|
+
[P in keyof T]?: T[P] extends Array<infer U> ? Array<DeepPartial<U>> : T[P] extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>> : DeepPartial<T[P]>;
|
3
|
+
};
|
@@ -42,6 +42,6 @@ const Checkbox = ({ label, onChange, defaultChecked = false, unchecked, checked,
|
|
42
42
|
const toggleCheckbox = () => setToggled(!toggled);
|
43
43
|
return (react_1.default.createElement("div", { className: "squiz-fte-checkbox" },
|
44
44
|
react_1.default.createElement("button", { type: "button", role: "checkbox", "aria-label": label, "aria-checked": toggled, className: "checkbox", onClick: toggleCheckbox }, toggled && react_1.default.createElement(CheckRounded_1.default, null)),
|
45
|
-
react_1.default.createElement("button", { type: "button", className: "label", onClick: toggleCheckbox }, label)));
|
45
|
+
react_1.default.createElement("button", { type: "button", className: "label", onClick: toggleCheckbox, tabIndex: -1 }, label)));
|
46
46
|
};
|
47
47
|
exports.Checkbox = Checkbox;
|
@@ -1,5 +1,3 @@
|
|
1
1
|
import React from 'react';
|
2
|
-
|
3
|
-
|
4
|
-
error?: string | undefined;
|
5
|
-
} & React.RefAttributes<HTMLInputElement>>;
|
2
|
+
import { InputContainerProps } from '../InputContainer/InputContainer';
|
3
|
+
export declare const Input: React.ForwardRefExoticComponent<React.InputHTMLAttributes<HTMLInputElement> & Omit<InputContainerProps, "children"> & React.RefAttributes<HTMLInputElement>>;
|
@@ -22,18 +22,12 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
22
22
|
__setModuleDefault(result, mod);
|
23
23
|
return result;
|
24
24
|
};
|
25
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
26
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
27
|
-
};
|
28
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
29
26
|
exports.Input = void 0;
|
30
27
|
const react_1 = __importStar(require("react"));
|
31
|
-
const
|
28
|
+
const InputContainer_1 = require("../InputContainer/InputContainer");
|
32
29
|
const InputInternal = ({ name, label, type = 'text', error, required, ...rest }, ref) => {
|
33
|
-
return (react_1.default.createElement(
|
34
|
-
|
35
|
-
required && (react_1.default.createElement("span", { className: "text-gray-600", "aria-label": "Required field" }, "*")),
|
36
|
-
react_1.default.createElement("input", { ref: ref, id: name, name: name, type: type, "aria-invalid": !!error, className: "squiz-fte-form-control", ...rest }),
|
37
|
-
error && react_1.default.createElement("div", { className: "squiz-fte-form-error" }, error)));
|
30
|
+
return (react_1.default.createElement(InputContainer_1.InputContainer, { name: name, label: label, error: error, required: required },
|
31
|
+
react_1.default.createElement("input", { ref: ref, id: name, name: name, type: type, "aria-invalid": !!error, className: "squiz-fte-form-control", ...rest })));
|
38
32
|
};
|
39
33
|
exports.Input = (0, react_1.forwardRef)(InputInternal);
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import { ReactNode } from 'react';
|
2
|
+
export type InputContainerProps = {
|
3
|
+
name?: string;
|
4
|
+
label?: string;
|
5
|
+
error?: string;
|
6
|
+
required?: boolean;
|
7
|
+
children: ReactNode;
|
8
|
+
};
|
9
|
+
export declare const InputContainer: ({ name, label, error, required, children }: InputContainerProps) => JSX.Element;
|
@@ -0,0 +1,16 @@
|
|
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
|
+
exports.InputContainer = void 0;
|
7
|
+
const react_1 = __importDefault(require("react"));
|
8
|
+
const clsx_1 = __importDefault(require("clsx"));
|
9
|
+
const InputContainer = ({ name, label, error, required, children }) => {
|
10
|
+
return (react_1.default.createElement("div", { className: (0, clsx_1.default)(error && 'squiz-fte-invalid-form-field') },
|
11
|
+
label && (react_1.default.createElement("label", { htmlFor: name, className: "squiz-fte-form-label" }, label)),
|
12
|
+
label && required && (react_1.default.createElement("span", { className: "text-gray-600", "aria-label": "Required field" }, "*")),
|
13
|
+
children,
|
14
|
+
error && react_1.default.createElement("div", { className: "squiz-fte-form-error" }, error)));
|
15
|
+
};
|
16
|
+
exports.InputContainer = InputContainer;
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import { InputContainerProps } from '../InputContainer/InputContainer';
|
2
|
+
type MatrixAssetValue = {
|
3
|
+
matrixIdentifier?: string;
|
4
|
+
matrixAssetId?: string;
|
5
|
+
};
|
6
|
+
export type MatrixAssetProps<T extends MatrixAssetValue> = Omit<InputContainerProps, 'children'> & {
|
7
|
+
modalTitle: string;
|
8
|
+
allowedTypes?: string[];
|
9
|
+
value?: T | null;
|
10
|
+
onChange: (value: {
|
11
|
+
target: {
|
12
|
+
value: T;
|
13
|
+
};
|
14
|
+
}) => void;
|
15
|
+
};
|
16
|
+
export declare const MatrixAsset: <T extends MatrixAssetValue>({ modalTitle, allowedTypes, value, onChange, ...props }: MatrixAssetProps<T>) => JSX.Element;
|
17
|
+
export {};
|
@@ -0,0 +1,29 @@
|
|
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
|
+
exports.MatrixAsset = void 0;
|
7
|
+
const react_1 = __importDefault(require("react"));
|
8
|
+
const resource_browser_1 = require("@squiz/resource-browser");
|
9
|
+
const InputContainer_1 = require("../InputContainer/InputContainer");
|
10
|
+
const MatrixAsset = ({ modalTitle, allowedTypes, value, onChange, ...props }) => {
|
11
|
+
return (react_1.default.createElement(InputContainer_1.InputContainer, { ...props },
|
12
|
+
react_1.default.createElement(resource_browser_1.ResourceBrowserInput, { modalTitle: modalTitle, allowedTypes: allowedTypes, value: value && value.matrixIdentifier && value.matrixAssetId
|
13
|
+
? {
|
14
|
+
source: value.matrixIdentifier,
|
15
|
+
resource: value.matrixAssetId,
|
16
|
+
}
|
17
|
+
: null, onChange: (reference) => {
|
18
|
+
onChange({
|
19
|
+
target: {
|
20
|
+
value: {
|
21
|
+
...value,
|
22
|
+
matrixIdentifier: reference?.source?.id,
|
23
|
+
matrixAssetId: reference?.resource?.id,
|
24
|
+
},
|
25
|
+
},
|
26
|
+
});
|
27
|
+
} })));
|
28
|
+
};
|
29
|
+
exports.MatrixAsset = MatrixAsset;
|
@@ -1,2 +1,3 @@
|
|
1
|
-
export declare const noEmptySpacesValidation: (value: string | undefined) =>
|
1
|
+
export declare const noEmptySpacesValidation: (value: string | undefined) => "Empty space is not allowed" | undefined;
|
2
|
+
export declare const hasProperties: <T>(message: string, properties: (keyof T)[]) => (value: T) => string | undefined;
|
2
3
|
export declare const regexDataURI: RegExp;
|
package/lib/utils/validation.js
CHANGED
@@ -1,10 +1,16 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.regexDataURI = exports.noEmptySpacesValidation = void 0;
|
4
|
-
const noEmptySpacesValidation =
|
3
|
+
exports.regexDataURI = exports.hasProperties = exports.noEmptySpacesValidation = void 0;
|
4
|
+
const noEmptySpacesValidation = (value) => {
|
5
5
|
if (value && !(value.trim().length > 0)) {
|
6
6
|
return 'Empty space is not allowed';
|
7
7
|
}
|
8
8
|
};
|
9
9
|
exports.noEmptySpacesValidation = noEmptySpacesValidation;
|
10
|
+
const hasProperties = (message, properties) => (value) => {
|
11
|
+
if (!value || properties.filter((property) => value[property]).length !== properties.length) {
|
12
|
+
return message;
|
13
|
+
}
|
14
|
+
};
|
15
|
+
exports.hasProperties = hasProperties;
|
10
16
|
exports.regexDataURI = /^data:([a-z]+\/[a-z0-9-+.]+(;[a-z-]+=[a-z0-9-]+)?)?(;base64)?,([a-z0-9!$&',()*+;=\-._~:@/?%\s]*)$/i;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@squiz/formatted-text-editor",
|
3
|
-
"version": "1.33.1-alpha.
|
3
|
+
"version": "1.33.1-alpha.4",
|
4
4
|
"main": "lib/index.js",
|
5
5
|
"types": "lib/index.d.ts",
|
6
6
|
"scripts": {
|
@@ -20,7 +20,8 @@
|
|
20
20
|
"@headlessui/react": "1.7.11",
|
21
21
|
"@mui/icons-material": "5.11.16",
|
22
22
|
"@remirror/react": "2.0.25",
|
23
|
-
"@squiz/dx-json-schema-lib": "1.
|
23
|
+
"@squiz/dx-json-schema-lib": "1.33.1-alpha.4",
|
24
|
+
"@squiz/resource-browser": "1.33.1-alpha.4",
|
24
25
|
"clsx": "1.2.1",
|
25
26
|
"react-hook-form": "7.43.2",
|
26
27
|
"react-image-size": "2.0.0",
|
@@ -74,5 +75,5 @@
|
|
74
75
|
"volta": {
|
75
76
|
"node": "18.15.0"
|
76
77
|
},
|
77
|
-
"gitHead": "
|
78
|
+
"gitHead": "00015ccc2b5c7761d3a62e8bbcdf88be15038877"
|
78
79
|
}
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
2
2
|
import { act, fireEvent, render, screen } from '@testing-library/react';
|
3
3
|
import Editor from './Editor';
|
4
4
|
import '@testing-library/jest-dom';
|
5
|
-
import { renderWithEditor } from '../../tests
|
5
|
+
import { renderWithEditor } from '../../tests';
|
6
6
|
import ImageButton from '../EditorToolbar/Tools/Image/ImageButton';
|
7
7
|
|
8
8
|
describe('Formatted text editor', () => {
|