@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.
- 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 +16 -32
- package/lib/EditorToolbar/Tools/Image/ImageModal.js +3 -2
- package/lib/EditorToolbar/Tools/Link/Form/LinkForm.js +18 -58
- package/lib/EditorToolbar/Tools/Link/LinkModal.js +3 -2
- 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 +2 -3
- package/lib/Extensions/LinkExtension/LinkExtension.js +1 -1
- package/lib/index.css +84 -4
- package/lib/types.d.ts +3 -3
- package/lib/ui/Fields/Checkbox/Checkbox.d.ts +8 -0
- package/lib/ui/Fields/Checkbox/Checkbox.js +47 -0
- 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/ui/Modal/Modal.d.ts +1 -0
- package/lib/ui/Modal/Modal.js +3 -2
- package/lib/ui/Tabs/Tabs.d.ts +10 -0
- package/lib/ui/Tabs/Tabs.js +46 -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 +29 -12
- package/src/EditorToolbar/Tools/Image/Form/ImageForm.tsx +37 -53
- package/src/EditorToolbar/Tools/Image/ImageButton.spec.tsx +76 -49
- package/src/EditorToolbar/Tools/Image/ImageModal.spec.tsx +1 -0
- package/src/EditorToolbar/Tools/Image/ImageModal.tsx +3 -2
- package/src/EditorToolbar/Tools/Link/Form/LinkForm.spec.tsx +22 -13
- package/src/EditorToolbar/Tools/Link/Form/LinkForm.tsx +35 -57
- package/src/EditorToolbar/Tools/Link/LinkButton.spec.tsx +52 -36
- package/src/EditorToolbar/Tools/Link/LinkModal.tsx +3 -2
- 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 +2 -4
- package/src/Extensions/LinkExtension/LinkExtension.ts +1 -1
- package/src/index.scss +1 -0
- package/src/types.ts +7 -5
- package/src/ui/Fields/Checkbox/Checkbox.spec.tsx +50 -0
- package/src/ui/Fields/Checkbox/Checkbox.tsx +49 -0
- package/src/ui/Fields/Checkbox/_checkbox.scss +26 -0
- 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/Modal/FormModal.spec.tsx +2 -1
- package/src/ui/Modal/Modal.spec.tsx +15 -7
- package/src/ui/Modal/Modal.tsx +4 -2
- package/src/ui/Tabs/Tabs.spec.tsx +44 -0
- package/src/ui/Tabs/Tabs.tsx +41 -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/lib/ui/Fields/Select/Select.d.ts +0 -12
- package/lib/ui/Fields/Select/Select.js +0 -53
package/lib/index.css
CHANGED
@@ -404,18 +404,33 @@
|
|
404
404
|
.squiz-fte-scope .mb-2 {
|
405
405
|
margin-bottom: 0.5rem !important;
|
406
406
|
}
|
407
|
+
.squiz-fte-scope .mb-4 {
|
408
|
+
margin-bottom: 1rem !important;
|
409
|
+
}
|
407
410
|
.squiz-fte-scope .ml-3 {
|
408
411
|
margin-left: 0.75rem !important;
|
409
412
|
}
|
410
413
|
.squiz-fte-scope .ml-auto {
|
411
414
|
margin-left: auto !important;
|
412
415
|
}
|
416
|
+
.squiz-fte-scope .mr-1 {
|
417
|
+
margin-right: 0.25rem !important;
|
418
|
+
}
|
419
|
+
.squiz-fte-scope .mr-1\.5 {
|
420
|
+
margin-right: 0.375rem !important;
|
421
|
+
}
|
413
422
|
.squiz-fte-scope .mr-2 {
|
414
423
|
margin-right: 0.5rem !important;
|
415
424
|
}
|
416
425
|
.squiz-fte-scope .mt-1 {
|
417
426
|
margin-top: 0.25rem !important;
|
418
427
|
}
|
428
|
+
.squiz-fte-scope .mt-\[-1px\] {
|
429
|
+
margin-top: -1px !important;
|
430
|
+
}
|
431
|
+
.squiz-fte-scope .mt-\[7px\] {
|
432
|
+
margin-top: 7px !important;
|
433
|
+
}
|
419
434
|
.squiz-fte-scope .block {
|
420
435
|
display: block !important;
|
421
436
|
}
|
@@ -425,9 +440,21 @@
|
|
425
440
|
.squiz-fte-scope .flex {
|
426
441
|
display: flex !important;
|
427
442
|
}
|
443
|
+
.squiz-fte-scope .grid {
|
444
|
+
display: grid !important;
|
445
|
+
}
|
428
446
|
.squiz-fte-scope .hidden {
|
429
447
|
display: none !important;
|
430
448
|
}
|
449
|
+
.squiz-fte-scope .h-10 {
|
450
|
+
height: 2.5rem !important;
|
451
|
+
}
|
452
|
+
.squiz-fte-scope .h-\[3px\] {
|
453
|
+
height: 3px !important;
|
454
|
+
}
|
455
|
+
.squiz-fte-scope .w-11\/12 {
|
456
|
+
width: 91.666667% !important;
|
457
|
+
}
|
431
458
|
.squiz-fte-scope .w-169 {
|
432
459
|
width: 169px !important;
|
433
460
|
}
|
@@ -445,17 +472,29 @@
|
|
445
472
|
-moz-user-select: none !important;
|
446
473
|
user-select: none !important;
|
447
474
|
}
|
475
|
+
.squiz-fte-scope .grid-flow-col {
|
476
|
+
grid-auto-flow: column !important;
|
477
|
+
}
|
448
478
|
.squiz-fte-scope .flex-row {
|
449
479
|
flex-direction: row !important;
|
450
480
|
}
|
481
|
+
.squiz-fte-scope .flex-col {
|
482
|
+
flex-direction: column !important;
|
483
|
+
}
|
451
484
|
.squiz-fte-scope .items-center {
|
452
485
|
align-items: center !important;
|
453
486
|
}
|
487
|
+
.squiz-fte-scope .justify-between {
|
488
|
+
justify-content: space-between !important;
|
489
|
+
}
|
454
490
|
.squiz-fte-scope .divide-y > :not([hidden]) ~ :not([hidden]) {
|
455
491
|
--tw-divide-y-reverse: 0 !important;
|
456
492
|
border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse))) !important;
|
457
493
|
border-bottom-width: calc(1px * var(--tw-divide-y-reverse)) !important;
|
458
494
|
}
|
495
|
+
.squiz-fte-scope .self-center {
|
496
|
+
align-self: center !important;
|
497
|
+
}
|
459
498
|
.squiz-fte-scope .overflow-auto {
|
460
499
|
overflow: auto !important;
|
461
500
|
}
|
@@ -467,12 +506,19 @@
|
|
467
506
|
.squiz-fte-scope .rounded {
|
468
507
|
border-radius: 4px !important;
|
469
508
|
}
|
509
|
+
.squiz-fte-scope .rounded-t-sm {
|
510
|
+
border-top-left-radius: 0.125rem !important;
|
511
|
+
border-top-right-radius: 0.125rem !important;
|
512
|
+
}
|
470
513
|
.squiz-fte-scope .border-0 {
|
471
514
|
border-width: 0px !important;
|
472
515
|
}
|
473
516
|
.squiz-fte-scope .border-2 {
|
474
517
|
border-width: 2px !important;
|
475
518
|
}
|
519
|
+
.squiz-fte-scope .border-b {
|
520
|
+
border-bottom-width: 1px !important;
|
521
|
+
}
|
476
522
|
.squiz-fte-scope .border-gray-300 {
|
477
523
|
--tw-border-opacity: 1 !important;
|
478
524
|
border-color: rgb(224 224 224 / var(--tw-border-opacity)) !important;
|
@@ -493,6 +539,10 @@
|
|
493
539
|
--tw-bg-opacity: 1 !important;
|
494
540
|
background-color: rgb(237 237 237 / var(--tw-bg-opacity)) !important;
|
495
541
|
}
|
542
|
+
.squiz-fte-scope .bg-gray-800 {
|
543
|
+
--tw-bg-opacity: 1 !important;
|
544
|
+
background-color: rgb(61 61 61 / var(--tw-bg-opacity)) !important;
|
545
|
+
}
|
496
546
|
.squiz-fte-scope .bg-transparent {
|
497
547
|
background-color: transparent !important;
|
498
548
|
}
|
@@ -511,8 +561,8 @@
|
|
511
561
|
padding-top: 0.5rem !important;
|
512
562
|
padding-bottom: 0.5rem !important;
|
513
563
|
}
|
514
|
-
.squiz-fte-scope .pb-
|
515
|
-
padding-bottom:
|
564
|
+
.squiz-fte-scope .pb-4 {
|
565
|
+
padding-bottom: 1rem !important;
|
516
566
|
}
|
517
567
|
.squiz-fte-scope .pl-3 {
|
518
568
|
padding-left: 0.75rem !important;
|
@@ -533,6 +583,9 @@
|
|
533
583
|
.squiz-fte-scope .text-md {
|
534
584
|
font-size: 0.875rem !important;
|
535
585
|
}
|
586
|
+
.squiz-fte-scope .font-bold {
|
587
|
+
font-weight: 700 !important;
|
588
|
+
}
|
536
589
|
.squiz-fte-scope .font-semibold {
|
537
590
|
font-weight: 600 !important;
|
538
591
|
}
|
@@ -577,6 +630,9 @@
|
|
577
630
|
--tw-blur: blur(8px) !important;
|
578
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;
|
579
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
|
+
}
|
580
636
|
.squiz-fte-scope a {
|
581
637
|
--tw-text-opacity: 1;
|
582
638
|
color: rgb(7 116 210 / var(--tw-text-opacity));
|
@@ -630,6 +686,7 @@
|
|
630
686
|
color: rgb(112 112 112 / var(--tw-text-opacity));
|
631
687
|
}
|
632
688
|
.squiz-fte-scope .squiz-fte-form-control {
|
689
|
+
height: 36px;
|
633
690
|
padding: 6px 12px;
|
634
691
|
position: relative;
|
635
692
|
width: 100%;
|
@@ -663,13 +720,14 @@
|
|
663
720
|
.squiz-fte-scope .squiz-fte-form-control:active {
|
664
721
|
box-shadow: none;
|
665
722
|
}
|
666
|
-
.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 {
|
667
725
|
--tw-border-opacity: 1;
|
668
726
|
border-color: rgb(215 35 33 / var(--tw-border-opacity));
|
669
727
|
background-repeat: no-repeat;
|
670
728
|
padding-right: 2rem;
|
671
729
|
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjQiIHdpZHRoPSIyNCI+PHJlY3Qgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0ibm9uZSIvPjxnIGNsYXNzPSJjdXJyZW50TGF5ZXIiPjxwYXRoIGQ9Ik00LjQ3IDIxaDE1LjA2YzEuNTQgMCAyLjUtMS42NyAxLjczLTNMMTMuNzMgNC45OWMtLjc3LTEuMzMtMi42OS0xLjMzLTMuNDYgMEwyLjc0IDE4Yy0uNzcgMS4zMy4xOSAzIDEuNzMgM3pNMTIgMTRjLS41NSAwLTEtLjQ1LTEtMXYtMmMwLS41NS40NS0xIDEtMXMxIC40NSAxIDF2MmMwIC41NS0uNDUgMS0xIDF6bTEgNGgtMnYtMmgydjJ6IiBjbGFzcz0ic2VsZWN0ZWQiIGZpbGw9IiNkNzIzMjEiLz48L2c+PC9zdmc+);
|
672
|
-
background-position:
|
730
|
+
background-position: center right 0.25rem;
|
673
731
|
background-size: 1.5rem;
|
674
732
|
}
|
675
733
|
.squiz-fte-scope .squiz-fte-form-error {
|
@@ -901,6 +959,28 @@
|
|
901
959
|
.squiz-fte-scope .dropdown-button:focus {
|
902
960
|
background-color: rgba(0, 0, 0, 0.04);
|
903
961
|
}
|
962
|
+
.squiz-fte-scope .squiz-fte-checkbox {
|
963
|
+
--tw-text-opacity: 1;
|
964
|
+
color: rgb(61 61 61 / var(--tw-text-opacity));
|
965
|
+
font-size: 14px;
|
966
|
+
display: flex;
|
967
|
+
align-items: center;
|
968
|
+
margin-top: 0.75rem;
|
969
|
+
gap: 0.75rem;
|
970
|
+
}
|
971
|
+
.squiz-fte-scope .squiz-fte-checkbox .checkbox {
|
972
|
+
display: flex;
|
973
|
+
justify-content: center;
|
974
|
+
align-items: center;
|
975
|
+
width: 1.25rem;
|
976
|
+
height: 1.25rem;
|
977
|
+
background-color: #fff;
|
978
|
+
border: 2px solid #e0e0e0;
|
979
|
+
border-radius: 4px;
|
980
|
+
}
|
981
|
+
.squiz-fte-scope .squiz-fte-checkbox .checkbox svg {
|
982
|
+
width: 100%;
|
983
|
+
}
|
904
984
|
.squiz-fte-scope .squiz-fte-modal {
|
905
985
|
display: flex;
|
906
986
|
width: 100%;
|
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
|
+
};
|
@@ -0,0 +1,8 @@
|
|
1
|
+
export type CheckboxProps<TChecked, TUnchecked> = {
|
2
|
+
label: string;
|
3
|
+
onChange: (value: TChecked | TUnchecked) => void;
|
4
|
+
defaultChecked?: boolean;
|
5
|
+
unchecked: TUnchecked;
|
6
|
+
checked: TChecked;
|
7
|
+
};
|
8
|
+
export declare const Checkbox: <TChecked, TUnchecked>({ label, onChange, defaultChecked, unchecked, checked, }: CheckboxProps<TChecked, TUnchecked>) => JSX.Element;
|
@@ -0,0 +1,47 @@
|
|
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
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
27
|
+
};
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
29
|
+
exports.Checkbox = void 0;
|
30
|
+
const react_1 = __importStar(require("react"));
|
31
|
+
const CheckRounded_1 = __importDefault(require("@mui/icons-material/CheckRounded"));
|
32
|
+
const Checkbox = ({ label, onChange, defaultChecked = false, unchecked, checked, }) => {
|
33
|
+
const [toggled, setToggled] = (0, react_1.useState)(defaultChecked);
|
34
|
+
(0, react_1.useEffect)(() => {
|
35
|
+
if (toggled) {
|
36
|
+
onChange(checked);
|
37
|
+
}
|
38
|
+
else {
|
39
|
+
onChange(unchecked);
|
40
|
+
}
|
41
|
+
}, [toggled]);
|
42
|
+
const toggleCheckbox = () => setToggled(!toggled);
|
43
|
+
return (react_1.default.createElement("div", { className: "squiz-fte-checkbox" },
|
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, tabIndex: -1 }, label)));
|
46
|
+
};
|
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;
|
package/lib/ui/Modal/Modal.d.ts
CHANGED
package/lib/ui/Modal/Modal.js
CHANGED
@@ -31,7 +31,7 @@ const react_dom_1 = require("react-dom");
|
|
31
31
|
const CloseRounded_1 = __importDefault(require("@mui/icons-material/CloseRounded"));
|
32
32
|
const base_1 = require("@mui/base");
|
33
33
|
const clsx_1 = __importDefault(require("clsx"));
|
34
|
-
const Modal = ({ children, title, onCancel, onSubmit, className }, ref) => {
|
34
|
+
const Modal = ({ children, title, icon, onCancel, onSubmit, className }, ref) => {
|
35
35
|
const content = (0, react_1.useRef)(null);
|
36
36
|
const container = (0, react_1.useMemo)(() => {
|
37
37
|
const element = document.createElement('div');
|
@@ -65,7 +65,8 @@ const Modal = ({ children, title, onCancel, onSubmit, className }, ref) => {
|
|
65
65
|
react_1.default.createElement("div", { ref: ref, className: (0, clsx_1.default)('squiz-fte-modal-wrapper', className), tabIndex: -1 },
|
66
66
|
react_1.default.createElement("div", { className: "w-modal-sm my-6 mx-auto" },
|
67
67
|
react_1.default.createElement("div", { className: "squiz-fte-modal" },
|
68
|
-
react_1.default.createElement("div", { className: "squiz-fte-modal-header p-6 pb-
|
68
|
+
react_1.default.createElement("div", { className: "squiz-fte-modal-header p-6 pb-4" },
|
69
|
+
react_1.default.createElement("div", { className: "squiz-fte-modal-header-icon mr-1.5 mt-[-1px]" }, icon),
|
69
70
|
react_1.default.createElement("h2", { className: "font-semibold text-gray-900 text-heading-2" }, title),
|
70
71
|
react_1.default.createElement("button", { type: "button", className: "ml-auto -mr-3 -mt-3 bg-transparent border-0 text-gray-600 font-semibold outline-none focus:outline-none hover:text-color-gray-800", onClick: onCancel, "aria-label": "Close" },
|
71
72
|
react_1.default.createElement(CloseRounded_1.default, null))),
|
@@ -0,0 +1,10 @@
|
|
1
|
+
export type TabOptions = Record<string, TabOption>;
|
2
|
+
export type TabOption = {
|
3
|
+
label: string;
|
4
|
+
};
|
5
|
+
export type TabsProps = {
|
6
|
+
value: string;
|
7
|
+
options: TabOptions;
|
8
|
+
onChange?: (value: string) => void;
|
9
|
+
};
|
10
|
+
export declare const Tabs: ({ value, options, onChange }: TabsProps) => JSX.Element;
|
@@ -0,0 +1,46 @@
|
|
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
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
27
|
+
};
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
29
|
+
exports.Tabs = void 0;
|
30
|
+
const react_1 = require("@headlessui/react");
|
31
|
+
const react_2 = __importStar(require("react"));
|
32
|
+
const clsx_1 = __importDefault(require("clsx"));
|
33
|
+
const Tabs = ({ value, options, onChange }) => (react_2.default.createElement(react_1.Tab.Group
|
34
|
+
// Check what index the selected tab is, otherwise default to first tab
|
35
|
+
, {
|
36
|
+
// Check what index the selected tab is, otherwise default to first tab
|
37
|
+
defaultIndex: Object.keys(options).indexOf(value) || 0,
|
38
|
+
// Check what the selected tab key is and trigger onChange
|
39
|
+
onChange: (index) => {
|
40
|
+
const selectedTab = Object.keys(options)[index];
|
41
|
+
onChange?.(selectedTab);
|
42
|
+
} },
|
43
|
+
react_2.default.createElement(react_1.Tab.List, { className: "grid grid-flow-col h-10 border-b border-gray-300" }, Object.entries(options).map(([key, option]) => (react_2.default.createElement(react_1.Tab, { key: key, as: react_2.Fragment }, ({ selected }) => (react_2.default.createElement("div", { className: "flex flex-col justify-between", "data-testid": key, "aria-selected": selected },
|
44
|
+
react_2.default.createElement("button", { type: "button", className: (0, clsx_1.default)('mt-[7px] text-gray-800', selected && 'font-bold') }, option.label),
|
45
|
+
selected && react_2.default.createElement("span", { className: "h-[3px] bg-gray-800 w-11/12 self-center rounded-t-sm" })))))))));
|
46
|
+
exports.Tabs = Tabs;
|
@@ -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', () => {
|
@@ -1,26 +1,24 @@
|
|
1
|
-
import React
|
2
|
-
import { EditorContext } from './EditorContext';
|
1
|
+
import React from 'react';
|
2
|
+
import { EditorContext, EditorContextOptions } from './EditorContext';
|
3
3
|
import { render } from '@testing-library/react';
|
4
4
|
|
5
5
|
describe('EditorContext', () => {
|
6
|
-
const defaultContextFn = jest.fn();
|
7
|
-
const Component = () => {
|
8
|
-
defaultContextFn(useContext(EditorContext));
|
9
|
-
return null;
|
10
|
-
};
|
11
|
-
|
12
6
|
it('Has expected defaults', async () => {
|
13
|
-
|
7
|
+
let defaultContext: EditorContextOptions | null = null;
|
14
8
|
|
15
|
-
|
9
|
+
render(
|
10
|
+
<EditorContext.Consumer>
|
11
|
+
{(value) => {
|
12
|
+
defaultContext = value;
|
13
|
+
return null;
|
14
|
+
}}
|
15
|
+
</EditorContext.Consumer>,
|
16
|
+
);
|
16
17
|
|
17
18
|
expect(defaultContext).toEqual({
|
18
19
|
matrix: {
|
19
|
-
resolveMatrixAsset: expect.any(Function),
|
20
20
|
matrixDomain: '',
|
21
|
-
matrixIdentifier: '',
|
22
21
|
},
|
23
22
|
});
|
24
|
-
expect(await defaultContext.matrix.resolveMatrixAsset('fake-asset-id')).toBeNull();
|
25
23
|
});
|
26
24
|
});
|
@@ -1,25 +1,14 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
|
3
|
-
export type MatrixAsset = {
|
4
|
-
id: string;
|
5
|
-
type: string | 'image';
|
6
|
-
};
|
7
|
-
|
8
|
-
export type MatrixAssetResolver = (assetId: string) => Promise<MatrixAsset | null>;
|
9
|
-
|
10
3
|
export type EditorContextOptions = {
|
11
4
|
matrix: {
|
12
|
-
matrixIdentifier: string;
|
13
5
|
matrixDomain: string;
|
14
|
-
resolveMatrixAsset: MatrixAssetResolver;
|
15
6
|
};
|
16
7
|
};
|
17
8
|
|
18
9
|
export const defaultEditorContext: EditorContextOptions = {
|
19
10
|
matrix: {
|
20
|
-
matrixIdentifier: '',
|
21
11
|
matrixDomain: '',
|
22
|
-
resolveMatrixAsset: () => Promise.resolve(null),
|
23
12
|
},
|
24
13
|
};
|
25
14
|
|
@@ -3,6 +3,7 @@ import { render, screen, act, fireEvent } from '@testing-library/react';
|
|
3
3
|
import React from 'react';
|
4
4
|
import ImageForm from './ImageForm';
|
5
5
|
import { NodeName } from '../../../../Extensions/Extensions';
|
6
|
+
import { mockResourceBrowserContext } from '../../../../../tests';
|
6
7
|
|
7
8
|
describe('Image Form', () => {
|
8
9
|
const handleSubmit = jest.fn();
|
@@ -19,27 +20,43 @@ describe('Image Form', () => {
|
|
19
20
|
it('Renders the form with the relevant fields for arbitrary images', () => {
|
20
21
|
render(<ImageForm data={data} onSubmit={handleSubmit} />);
|
21
22
|
|
22
|
-
expect(
|
23
|
+
expect(document.querySelector('div[data-headlessui-state="selected"]')).toHaveTextContent('From URL');
|
23
24
|
expect(screen.getByLabelText('Source')).toHaveValue('https://httpcats.com/302.jpg');
|
24
25
|
expect(screen.getByLabelText('Alternative description')).toHaveValue('Cat with mouse in mouth');
|
25
26
|
expect(screen.getByLabelText('Width')).toHaveValue(1600);
|
26
27
|
expect(screen.getByLabelText('Height')).toHaveValue(1400);
|
27
28
|
});
|
28
29
|
|
29
|
-
it('Renders the form with the relevant fields for asset images', () => {
|
30
|
+
it('Renders the form with the relevant fields for asset images', async () => {
|
31
|
+
const { MockResourceBrowserContext } = mockResourceBrowserContext({
|
32
|
+
sources: [{ id: 'my-source-id' }],
|
33
|
+
resources: [
|
34
|
+
{
|
35
|
+
id: '100',
|
36
|
+
name: 'My selected image',
|
37
|
+
type: {
|
38
|
+
code: 'image',
|
39
|
+
name: 'Image',
|
40
|
+
},
|
41
|
+
},
|
42
|
+
],
|
43
|
+
});
|
44
|
+
|
30
45
|
render(
|
31
|
-
<
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
46
|
+
<MockResourceBrowserContext>
|
47
|
+
<ImageForm
|
48
|
+
data={{
|
49
|
+
...data,
|
50
|
+
imageType: NodeName.AssetImage,
|
51
|
+
assetImage: { matrixAssetId: '100', matrixIdentifier: 'matrix-identifier' },
|
52
|
+
}}
|
53
|
+
onSubmit={handleSubmit}
|
54
|
+
/>
|
55
|
+
</MockResourceBrowserContext>,
|
39
56
|
);
|
40
57
|
|
41
|
-
expect(
|
42
|
-
expect(screen.
|
58
|
+
expect(document.querySelector('div[data-headlessui-state="selected"]')).toHaveTextContent('From source');
|
59
|
+
expect(screen.getByText('My selected image')).toBeInTheDocument();
|
43
60
|
});
|
44
61
|
|
45
62
|
it('calculates the height when width changes and aspect ratio is locked', () => {
|