@squiz/resource-browser 1.32.1-alpha.27 → 1.32.1-alpha.29
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/lib/Modal/ModalTrigger.d.ts +2 -1
- package/lib/Modal/ModalTrigger.js +5 -4
- package/lib/PreviewPanel/PreviewPanel.d.ts +0 -1
- package/lib/PreviewPanel/details/MatrixResource.d.ts +0 -1
- package/lib/PreviewPanel/details/MatrixResource.js +2 -17
- package/lib/ResourceBreadcrumb/ResourceBreadcrumb.d.ts +0 -1
- package/lib/ResourceError/ResourceError.d.ts +0 -1
- package/lib/ResourceItem/ResourceItem.d.ts +0 -1
- package/lib/ResourceList/ResourceList.d.ts +0 -1
- package/lib/ResourcePickerContainer/ResourcePickerContainer.d.ts +0 -1
- package/lib/Skeleton/List/SkeletonList.d.ts +0 -1
- package/lib/Skeleton/ListItem/SkeletonListItem.d.ts +0 -1
- package/lib/SourceDropdown/SourceDropdown.d.ts +0 -1
- package/lib/SourceDropdown/SourceDropdown.js +1 -1
- package/lib/SourceList/SourceList.d.ts +0 -1
- package/lib/StatusIndicator/StatusIndicator.d.ts +6 -0
- package/lib/StatusIndicator/StatusIndicator.js +26 -0
- package/lib/index.css +110 -4
- package/lib/index.d.ts +2 -5
- package/lib/index.js +9 -3
- package/package.json +5 -3
- package/src/Icons/Icon.stories.tsx +5 -0
- package/src/Modal/Modal.spec.tsx +25 -0
- package/src/Modal/ModalTrigger.tsx +14 -2
- package/src/PreviewPanel/details/MatrixResource.tsx +2 -22
- package/src/ResourceError/ResourceError.spec.tsx +0 -4
- package/src/ResourceItem/ResourceItem.spec.tsx +0 -4
- package/src/ResourcePicker/ResetButton.tsx +14 -0
- package/src/ResourcePicker/ResourcePicker.spec.tsx +81 -0
- package/src/ResourcePicker/ResourcePicker.stories.tsx +62 -0
- package/src/ResourcePicker/ResourcePicker.tsx +55 -0
- package/src/ResourcePicker/States/Error.tsx +12 -0
- package/src/ResourcePicker/States/Loading.tsx +9 -0
- package/src/ResourcePicker/States/Selected.tsx +51 -0
- package/src/ResourcePicker/mock-image-resource.json +51 -0
- package/src/ResourcePicker/mock-resource.json +15 -0
- package/src/ResourcePicker/resource-picker.scss +13 -0
- package/src/ResourcePickerContainer/ResourcePickerContainer.stories.tsx +1 -1
- package/src/SourceDropdown/SourceDropdown.tsx +1 -1
- package/src/Spinner/Spinner.stories.tsx +1 -1
- package/src/Spinner/_spinner.scss +1 -1
- package/src/StatusIndicator/StatusIndicator.stories.tsx +83 -0
- package/src/StatusIndicator/StatusIndicator.tsx +35 -0
- package/src/index.scss +1 -0
- package/src/index.spec.tsx +44 -0
- package/src/index.stories.tsx +15 -17
- package/src/index.tsx +41 -20
- package/src/types.d.ts +5 -4
@@ -1,9 +1,10 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
import { DOMAttributes, FocusableElement } from '@react-types/shared';
|
3
|
-
declare function ModalTrigger({ label, showLabel, icon, children, ...props }: {
|
3
|
+
declare function ModalTrigger({ label, showLabel, icon, isDisabled, children, ...props }: {
|
4
4
|
label: string;
|
5
5
|
showLabel?: boolean;
|
6
6
|
icon?: React.ReactNode;
|
7
|
+
isDisabled?: boolean;
|
7
8
|
children: (onClose: () => void, titleProps: DOMAttributes<FocusableElement>) => React.ReactElement;
|
8
9
|
}): JSX.Element;
|
9
10
|
export default ModalTrigger;
|
@@ -8,7 +8,8 @@ const react_aria_1 = require("react-aria");
|
|
8
8
|
const react_stately_1 = require("react-stately");
|
9
9
|
const Modal_1 = __importDefault(require("./Modal"));
|
10
10
|
const ModalOpeningButton_1 = __importDefault(require("./ModalOpeningButton"));
|
11
|
-
|
11
|
+
const clsx_1 = __importDefault(require("clsx"));
|
12
|
+
function ModalTrigger({ label, showLabel, icon, isDisabled, children, ...props }) {
|
12
13
|
const state = (0, react_stately_1.useOverlayTriggerState)(props);
|
13
14
|
const { triggerProps, overlayProps } = (0, react_aria_1.useOverlayTrigger)({ type: 'dialog' }, state);
|
14
15
|
let ariaAttr = {};
|
@@ -16,9 +17,9 @@ function ModalTrigger({ label, showLabel, icon, children, ...props }) {
|
|
16
17
|
ariaAttr = { ...ariaAttr, 'aria-label': label };
|
17
18
|
}
|
18
19
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
19
|
-
react_1.default.createElement(ModalOpeningButton_1.default, { type: "button", ...triggerProps, ...ariaAttr },
|
20
|
-
|
21
|
-
|
20
|
+
react_1.default.createElement(ModalOpeningButton_1.default, { type: "button", ...triggerProps, ...ariaAttr, isDisabled: isDisabled, className: (0, clsx_1.default)('flex p-1 px-1.5 rounded mr-auto text-blue-300 hover:bg-blue-100 focus:bg-blue-100 focus:outline-none', isDisabled && 'hover:bg-transparent cursor-not-allowed text-gray-600') },
|
21
|
+
icon,
|
22
|
+
showLabel && react_1.default.createElement("span", { className: "ml-1 text-sm leading-4" }, label)),
|
22
23
|
state.isOpen && (react_1.default.createElement(Modal_1.default, { isDismissable: true, state: state, overlayProps: overlayProps }, (titleProps) => children(state.close, titleProps)))));
|
23
24
|
}
|
24
25
|
exports.default = ModalTrigger;
|
@@ -5,23 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
6
6
|
const react_1 = __importDefault(require("react"));
|
7
7
|
const Icon_1 = __importDefault(require("../../Icons/Icon"));
|
8
|
-
const
|
9
|
-
// Duplicated from the Matrix repository.
|
10
|
-
// src/Api/AssetManagementApi/Constants/AssetStatuses.php - contains a list of possible statuses.
|
11
|
-
// frontend/src/styles/common/status-colors.scss - contains the colours used for those statuses in Matrix.
|
12
|
-
unknown: '#ff0000',
|
13
|
-
archived: '#c98a67',
|
14
|
-
under_construction: '#94d1f9',
|
15
|
-
pending_approval: '#d0bbf0',
|
16
|
-
approved_to_go_live: '#f7eaa2',
|
17
|
-
live: '#bfe60a',
|
18
|
-
up_for_review: '#72cd32',
|
19
|
-
safe_editing: '#ff97b0',
|
20
|
-
safe_editing_pending_approval: '#d688db',
|
21
|
-
safe_edit_approved_to_go_live: '#ffb34a',
|
22
|
-
};
|
8
|
+
const StatusIndicator_1 = __importDefault(require("../../StatusIndicator/StatusIndicator"));
|
23
9
|
const MatrixResource = ({ resource: { id, type, name, status } }) => {
|
24
|
-
const color = statusColour[status.code] || statusColour.unknown;
|
25
10
|
return (react_1.default.createElement("div", null,
|
26
11
|
react_1.default.createElement("div", { className: "flex flex-col items-center text-gray-800 mt-7 mx-5 pb-4 border-b border-gray-300" },
|
27
12
|
react_1.default.createElement(Icon_1.default, { icon: type.code, resourceSource: "matrix", className: "w-14 h-14" }),
|
@@ -39,7 +24,7 @@ const MatrixResource = ({ resource: { id, type, name, status } }) => {
|
|
39
24
|
react_1.default.createElement("div", { className: "flex mb-2" },
|
40
25
|
react_1.default.createElement("dt", { className: "w-[60px] mr-4 text-gray-600" }, "Status"),
|
41
26
|
react_1.default.createElement("dd", { className: "flex items-center font-semibold" },
|
42
|
-
react_1.default.createElement(
|
27
|
+
react_1.default.createElement(StatusIndicator_1.default, { status: status }),
|
43
28
|
status.name))))));
|
44
29
|
};
|
45
30
|
exports.default = MatrixResource;
|
@@ -79,7 +79,7 @@ function SourceDropdown({ sources, selectedSource, isLoading, onRootSelect, onSo
|
|
79
79
|
react_1.default.createElement(Icon_1.default, { icon: 'root', "aria-hidden": true, className: "mr-2.5" }),
|
80
80
|
"All available sources")),
|
81
81
|
isLoading && (react_1.default.createElement("li", { className: "mt-6" },
|
82
|
-
react_1.default.createElement(Spinner_1.default, { size: "lg", label: "Loading sources" }))),
|
82
|
+
react_1.default.createElement(Spinner_1.default, { size: "lg", label: "Loading sources", className: "m-3" }))),
|
83
83
|
!isLoading &&
|
84
84
|
categorisedSources.map(({ key, label, sources }, index) => {
|
85
85
|
return (react_1.default.createElement("li", { key: key, className: `flex flex-col text-sm font-semibold text-grey-800 ${index > 0 ? 'mt-3' : ''}` },
|
@@ -0,0 +1,26 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
+
};
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
+
const react_1 = __importDefault(require("react"));
|
7
|
+
const statusColour = {
|
8
|
+
// Duplicated from the Matrix repository.
|
9
|
+
// src/Api/AssetManagementApi/Constants/AssetStatuses.php - contains a list of possible statuses.
|
10
|
+
// frontend/src/styles/common/status-colors.scss - contains the colours used for those statuses in Matrix.
|
11
|
+
unknown: '#ff0000',
|
12
|
+
archived: '#c98a67',
|
13
|
+
under_construction: '#94d1f9',
|
14
|
+
pending_approval: '#d0bbf0',
|
15
|
+
approved_to_go_live: '#f7eaa2',
|
16
|
+
live: '#bfe60a',
|
17
|
+
up_for_review: '#72cd32',
|
18
|
+
safe_editing: '#ff97b0',
|
19
|
+
safe_editing_pending_approval: '#d688db',
|
20
|
+
safe_edit_approved_to_go_live: '#ffb34a',
|
21
|
+
};
|
22
|
+
const StatusIndicator = ({ status }) => {
|
23
|
+
const color = statusColour[status.code] || statusColour.unknown;
|
24
|
+
return (react_1.default.createElement("span", { style: { backgroundColor: color }, className: "block rounded-full w-3 h-3 border border-solid border-black border-opacity-20" }));
|
25
|
+
};
|
26
|
+
exports.default = StatusIndicator;
|
package/lib/index.css
CHANGED
@@ -414,6 +414,18 @@
|
|
414
414
|
.squiz-rb-scope .z-\[9999\] {
|
415
415
|
z-index: 9999;
|
416
416
|
}
|
417
|
+
.squiz-rb-scope .col-start-2 {
|
418
|
+
grid-column-start: 2;
|
419
|
+
}
|
420
|
+
.squiz-rb-scope .col-end-2 {
|
421
|
+
grid-column-end: 2;
|
422
|
+
}
|
423
|
+
.squiz-rb-scope .m-2 {
|
424
|
+
margin: 0.5rem;
|
425
|
+
}
|
426
|
+
.squiz-rb-scope .m-3 {
|
427
|
+
margin: 0.75rem;
|
428
|
+
}
|
417
429
|
.squiz-rb-scope .m-5 {
|
418
430
|
margin: 1.25rem;
|
419
431
|
}
|
@@ -454,12 +466,12 @@
|
|
454
466
|
.squiz-rb-scope .ml-1 {
|
455
467
|
margin-left: 0.25rem;
|
456
468
|
}
|
469
|
+
.squiz-rb-scope .ml-4 {
|
470
|
+
margin-left: 1rem;
|
471
|
+
}
|
457
472
|
.squiz-rb-scope .ml-auto {
|
458
473
|
margin-left: auto;
|
459
474
|
}
|
460
|
-
.squiz-rb-scope .mr-1 {
|
461
|
-
margin-right: 0.25rem;
|
462
|
-
}
|
463
475
|
.squiz-rb-scope .mr-2 {
|
464
476
|
margin-right: 0.5rem;
|
465
477
|
}
|
@@ -478,6 +490,9 @@
|
|
478
490
|
.squiz-rb-scope .mr-7 {
|
479
491
|
margin-right: 1.75rem;
|
480
492
|
}
|
493
|
+
.squiz-rb-scope .mr-auto {
|
494
|
+
margin-right: auto;
|
495
|
+
}
|
481
496
|
.squiz-rb-scope .mt-2 {
|
482
497
|
margin-top: 0.5rem;
|
483
498
|
}
|
@@ -511,6 +526,9 @@
|
|
511
526
|
.squiz-rb-scope .hidden {
|
512
527
|
display: none;
|
513
528
|
}
|
529
|
+
.squiz-rb-scope .\!h-4 {
|
530
|
+
height: 1rem !important;
|
531
|
+
}
|
514
532
|
.squiz-rb-scope .h-14 {
|
515
533
|
height: 3.5rem;
|
516
534
|
}
|
@@ -547,6 +565,9 @@
|
|
547
565
|
.squiz-rb-scope .min-h-full {
|
548
566
|
min-height: 100%;
|
549
567
|
}
|
568
|
+
.squiz-rb-scope .\!w-4 {
|
569
|
+
width: 1rem !important;
|
570
|
+
}
|
550
571
|
.squiz-rb-scope .w-1\/2 {
|
551
572
|
width: 50%;
|
552
573
|
}
|
@@ -580,6 +601,9 @@
|
|
580
601
|
.squiz-rb-scope .w-\[119px\] {
|
581
602
|
width: 119px;
|
582
603
|
}
|
604
|
+
.squiz-rb-scope .w-\[400px\] {
|
605
|
+
width: 400px;
|
606
|
+
}
|
583
607
|
.squiz-rb-scope .w-\[60px\] {
|
584
608
|
width: 60px;
|
585
609
|
}
|
@@ -640,9 +664,18 @@
|
|
640
664
|
.squiz-rb-scope .justify-center {
|
641
665
|
justify-content: center;
|
642
666
|
}
|
667
|
+
.squiz-rb-scope .gap-1 {
|
668
|
+
gap: 0.25rem;
|
669
|
+
}
|
643
670
|
.squiz-rb-scope .gap-3 {
|
644
671
|
gap: 0.75rem;
|
645
672
|
}
|
673
|
+
.squiz-rb-scope .self-center {
|
674
|
+
align-self: center;
|
675
|
+
}
|
676
|
+
.squiz-rb-scope .justify-self-start {
|
677
|
+
justify-self: start;
|
678
|
+
}
|
646
679
|
.squiz-rb-scope .overflow-y-scroll {
|
647
680
|
overflow-y: scroll;
|
648
681
|
}
|
@@ -721,6 +754,10 @@
|
|
721
754
|
--tw-bg-opacity: 1;
|
722
755
|
background-color: rgb(237 237 237 / var(--tw-bg-opacity));
|
723
756
|
}
|
757
|
+
.squiz-rb-scope .bg-gray-300 {
|
758
|
+
--tw-bg-opacity: 1;
|
759
|
+
background-color: rgb(224 224 224 / var(--tw-bg-opacity));
|
760
|
+
}
|
724
761
|
.squiz-rb-scope .bg-white {
|
725
762
|
--tw-bg-opacity: 1;
|
726
763
|
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
@@ -743,6 +780,14 @@
|
|
743
780
|
.squiz-rb-scope .p-6 {
|
744
781
|
padding: 1.5rem;
|
745
782
|
}
|
783
|
+
.squiz-rb-scope .px-1 {
|
784
|
+
padding-left: 0.25rem;
|
785
|
+
padding-right: 0.25rem;
|
786
|
+
}
|
787
|
+
.squiz-rb-scope .px-1\.5 {
|
788
|
+
padding-left: 0.375rem;
|
789
|
+
padding-right: 0.375rem;
|
790
|
+
}
|
746
791
|
.squiz-rb-scope .px-2 {
|
747
792
|
padding-left: 0.5rem;
|
748
793
|
padding-right: 0.5rem;
|
@@ -805,6 +850,9 @@
|
|
805
850
|
.squiz-rb-scope .font-semibold {
|
806
851
|
font-weight: 600;
|
807
852
|
}
|
853
|
+
.squiz-rb-scope .leading-4 {
|
854
|
+
line-height: 1rem;
|
855
|
+
}
|
808
856
|
.squiz-rb-scope .leading-5 {
|
809
857
|
line-height: 1.25rem;
|
810
858
|
}
|
@@ -819,6 +867,10 @@
|
|
819
867
|
--tw-text-opacity: 1;
|
820
868
|
color: rgb(4 73 133 / var(--tw-text-opacity));
|
821
869
|
}
|
870
|
+
.squiz-rb-scope .text-gray-500 {
|
871
|
+
--tw-text-opacity: 1;
|
872
|
+
color: rgb(148 148 148 / var(--tw-text-opacity));
|
873
|
+
}
|
822
874
|
.squiz-rb-scope .text-gray-600 {
|
823
875
|
--tw-text-opacity: 1;
|
824
876
|
color: rgb(112 112 112 / var(--tw-text-opacity));
|
@@ -831,6 +883,10 @@
|
|
831
883
|
--tw-text-opacity: 1;
|
832
884
|
color: rgb(61 61 61 / var(--tw-text-opacity));
|
833
885
|
}
|
886
|
+
.squiz-rb-scope .text-red-300 {
|
887
|
+
--tw-text-opacity: 1;
|
888
|
+
color: rgb(215 35 33 / var(--tw-text-opacity));
|
889
|
+
}
|
834
890
|
.squiz-rb-scope .text-white {
|
835
891
|
--tw-text-opacity: 1;
|
836
892
|
color: rgb(255 255 255 / var(--tw-text-opacity));
|
@@ -869,7 +925,6 @@
|
|
869
925
|
}
|
870
926
|
}
|
871
927
|
.squiz-rb-scope .spinner__wrapper {
|
872
|
-
margin: 0.75rem;
|
873
928
|
display: flex;
|
874
929
|
align-items: center;
|
875
930
|
justify-content: center;
|
@@ -918,6 +973,35 @@
|
|
918
973
|
.squiz-rb-scope .resource-breadcrumb--expanded .resource-breadcrumb__item:last-child {
|
919
974
|
display: flex;
|
920
975
|
}
|
976
|
+
.squiz-rb-scope .resource-picker {
|
977
|
+
display: grid;
|
978
|
+
grid-template-columns: 24px 1fr;
|
979
|
+
gap: 0.5rem;
|
980
|
+
border-width: 2px;
|
981
|
+
--tw-border-opacity: 1;
|
982
|
+
border-color: rgb(224 224 224 / var(--tw-border-opacity));
|
983
|
+
border-radius: 4px;
|
984
|
+
padding: 0.5rem;
|
985
|
+
--tw-text-opacity: 1;
|
986
|
+
color: rgb(148 148 148 / var(--tw-text-opacity));
|
987
|
+
}
|
988
|
+
.squiz-rb-scope .resource-picker-info {
|
989
|
+
width: 100%;
|
990
|
+
border-radius: 6px;
|
991
|
+
--tw-bg-opacity: 1;
|
992
|
+
background-color: rgb(245 245 245 / var(--tw-bg-opacity));
|
993
|
+
padding: 0.5rem;
|
994
|
+
font-size: 0.875rem;
|
995
|
+
font-weight: 600;
|
996
|
+
--tw-text-opacity: 1;
|
997
|
+
color: rgb(43 43 43 / var(--tw-text-opacity));
|
998
|
+
}
|
999
|
+
.squiz-rb-scope .resource-picker-info__layout {
|
1000
|
+
display: grid;
|
1001
|
+
grid-template-columns: 24px 1fr 24px;
|
1002
|
+
gap: 0.5rem;
|
1003
|
+
justify-items: center;
|
1004
|
+
}
|
921
1005
|
.squiz-rb-scope .before\:fixed::before {
|
922
1006
|
content: var(--tw-content);
|
923
1007
|
position: fixed;
|
@@ -1027,6 +1111,13 @@
|
|
1027
1111
|
--tw-bg-opacity: 1;
|
1028
1112
|
background-color: rgb(245 245 245 / var(--tw-bg-opacity));
|
1029
1113
|
}
|
1114
|
+
.squiz-rb-scope .hover\:bg-transparent:hover {
|
1115
|
+
background-color: transparent;
|
1116
|
+
}
|
1117
|
+
.squiz-rb-scope .hover\:text-gray-800:hover {
|
1118
|
+
--tw-text-opacity: 1;
|
1119
|
+
color: rgb(61 61 61 / var(--tw-text-opacity));
|
1120
|
+
}
|
1030
1121
|
.squiz-rb-scope .focus\:bg-blue-100:focus {
|
1031
1122
|
--tw-bg-opacity: 1;
|
1032
1123
|
background-color: rgb(230 241 250 / var(--tw-bg-opacity));
|
@@ -1035,6 +1126,21 @@
|
|
1035
1126
|
--tw-bg-opacity: 1;
|
1036
1127
|
background-color: rgb(245 245 245 / var(--tw-bg-opacity));
|
1037
1128
|
}
|
1129
|
+
.squiz-rb-scope .focus\:text-gray-800:focus {
|
1130
|
+
--tw-text-opacity: 1;
|
1131
|
+
color: rgb(61 61 61 / var(--tw-text-opacity));
|
1132
|
+
}
|
1133
|
+
.squiz-rb-scope .focus\:outline-none:focus {
|
1134
|
+
outline: 2px solid transparent;
|
1135
|
+
outline-offset: 2px;
|
1136
|
+
}
|
1137
|
+
.squiz-rb-scope .disabled\:cursor-not-allowed:disabled {
|
1138
|
+
cursor: not-allowed;
|
1139
|
+
}
|
1140
|
+
.squiz-rb-scope .disabled\:text-gray-500:disabled {
|
1141
|
+
--tw-text-opacity: 1;
|
1142
|
+
color: rgb(148 148 148 / var(--tw-text-opacity));
|
1143
|
+
}
|
1038
1144
|
@media not all and (min-width: 768px) {
|
1039
1145
|
.squiz-rb-scope .max-md\:hidden {
|
1040
1146
|
display: none;
|
package/lib/index.d.ts
CHANGED
@@ -1,14 +1,11 @@
|
|
1
|
-
import React from 'react';
|
2
1
|
import { HydratedResourceReference, Resource, ResourceReference, Source } from './types';
|
3
2
|
export type { HydratedResourceReference, Resource, ResourceReference, Source };
|
4
|
-
export default function ComponentEditorContentBrowser({
|
5
|
-
showButtonLabel?: boolean;
|
6
|
-
buttonLabel: string;
|
7
|
-
buttonIcon: React.ReactNode;
|
3
|
+
export default function ComponentEditorContentBrowser({ modalTitle, allowedTypes, onRequestSources, onRequestChildren, onChange, isDisabled, }: {
|
8
4
|
modalTitle: string;
|
9
5
|
allowedTypes: string[] | undefined;
|
10
6
|
onRequestSources: () => Promise<Source[]>;
|
11
7
|
onRequestChildren(source: Source, resource: Resource | null): Promise<Resource[]>;
|
12
8
|
onRequestResource(reference: ResourceReference): Promise<Resource | null>;
|
13
9
|
onChange(resource: HydratedResourceReference | null): void;
|
10
|
+
isDisabled?: boolean;
|
14
11
|
}): JSX.Element;
|
package/lib/index.js
CHANGED
@@ -6,9 +6,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const react_1 = __importDefault(require("react"));
|
7
7
|
const ModalTrigger_1 = __importDefault(require("./Modal/ModalTrigger"));
|
8
8
|
const ResourcePickerContainer_1 = __importDefault(require("./ResourcePickerContainer/ResourcePickerContainer"));
|
9
|
-
|
10
|
-
|
9
|
+
const AdsClickRounded_1 = __importDefault(require("@mui/icons-material/AdsClickRounded"));
|
10
|
+
const AddCircleOutlineRounded_1 = __importDefault(require("@mui/icons-material/AddCircleOutlineRounded"));
|
11
|
+
const PhotoLibraryRounded_1 = __importDefault(require("@mui/icons-material/PhotoLibraryRounded"));
|
12
|
+
const clsx_1 = __importDefault(require("clsx"));
|
13
|
+
function ComponentEditorContentBrowser({ modalTitle, allowedTypes, onRequestSources, onRequestChildren, onChange, isDisabled, }) {
|
14
|
+
const isImagePicker = allowedTypes && allowedTypes.length === 1 && allowedTypes.includes('image');
|
11
15
|
return (react_1.default.createElement("div", { className: "squiz-rb-scope" },
|
12
|
-
react_1.default.createElement(
|
16
|
+
react_1.default.createElement("div", { className: (0, clsx_1.default)('resource-picker', isDisabled && 'bg-gray-300') },
|
17
|
+
isImagePicker ? (react_1.default.createElement(PhotoLibraryRounded_1.default, { "aria-hidden": true, className: "w-6 h-6" })) : (react_1.default.createElement(AdsClickRounded_1.default, { "aria-hidden": true, className: "w-6 h-6" })),
|
18
|
+
react_1.default.createElement(ModalTrigger_1.default, { showLabel: true, label: isImagePicker ? `Choose image` : `Choose asset`, icon: react_1.default.createElement(AddCircleOutlineRounded_1.default, { "aria-hidden": true, className: "!w-4 !h-4" }), isDisabled: isDisabled }, (onClose, titleProps) => (react_1.default.createElement(ResourcePickerContainer_1.default, { title: modalTitle, titleAriaProps: titleProps, allowedTypes: allowedTypes, onClose: onClose, onRequestSources: onRequestSources, onRequestChildren: onRequestChildren, onChange: onChange }))))));
|
13
19
|
}
|
14
20
|
exports.default = ComponentEditorContentBrowser;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@squiz/resource-browser",
|
3
|
-
"version": "1.32.1-alpha.
|
3
|
+
"version": "1.32.1-alpha.29",
|
4
4
|
"main": "lib/index.js",
|
5
5
|
"types": "lib/index.d.ts",
|
6
6
|
"scripts": {
|
@@ -14,7 +14,9 @@
|
|
14
14
|
"clean": "rimraf ./lib"
|
15
15
|
},
|
16
16
|
"dependencies": {
|
17
|
-
"@
|
17
|
+
"@mui/icons-material": "5.11.16",
|
18
|
+
"@squiz/dx-json-schema-lib": "1.32.1-alpha.29",
|
19
|
+
"pretty-bytes": "5.6.0",
|
18
20
|
"react-aria": "3.23.1",
|
19
21
|
"react-responsive": "9.0.2",
|
20
22
|
"react-stately": "3.21.0"
|
@@ -71,5 +73,5 @@
|
|
71
73
|
"volta": {
|
72
74
|
"node": "18.15.0"
|
73
75
|
},
|
74
|
-
"gitHead": "
|
76
|
+
"gitHead": "dd5931dd752cb79620662dc260e8c1df96fc63b1"
|
75
77
|
}
|
@@ -10,6 +10,11 @@ export default {
|
|
10
10
|
|
11
11
|
const Template: StoryFn<typeof Icon> = (props) => <Icon {...props} />;
|
12
12
|
|
13
|
+
export const Error = Template.bind({});
|
14
|
+
Error.args = {
|
15
|
+
icon: 'error',
|
16
|
+
};
|
17
|
+
|
13
18
|
export const ArrowRight = Template.bind({});
|
14
19
|
ArrowRight.args = {
|
15
20
|
icon: 'arrow-right',
|
package/src/Modal/Modal.spec.tsx
CHANGED
@@ -142,6 +142,31 @@ describe('Modal', () => {
|
|
142
142
|
});
|
143
143
|
});
|
144
144
|
|
145
|
+
it('Modal does not open if modal trigger button is disabled', async () => {
|
146
|
+
render(
|
147
|
+
<div>
|
148
|
+
<ModalTrigger label={'Open testing modal'} showLabel isDisabled={true}>
|
149
|
+
{(onClose, titleProps) => (
|
150
|
+
<div data-testid="modal">
|
151
|
+
<div {...titleProps}>Testing</div>
|
152
|
+
<button type="button" onClick={onClose}>
|
153
|
+
Close
|
154
|
+
</button>
|
155
|
+
</div>
|
156
|
+
)}
|
157
|
+
</ModalTrigger>
|
158
|
+
<div style={{ height: '150vh' }} />
|
159
|
+
</div>,
|
160
|
+
);
|
161
|
+
|
162
|
+
const user = userEvent.setup();
|
163
|
+
user.click(screen.getByText('Open testing modal'));
|
164
|
+
|
165
|
+
await waitFor(() => {
|
166
|
+
expect(screen.queryByTestId('modal')).not.toBeTruthy();
|
167
|
+
});
|
168
|
+
});
|
169
|
+
|
145
170
|
it('Focus is trapped within modal', async () => {
|
146
171
|
render(
|
147
172
|
<div>
|
@@ -6,17 +6,20 @@ import { DOMAttributes, FocusableElement } from '@react-types/shared';
|
|
6
6
|
|
7
7
|
import Modal from './Modal';
|
8
8
|
import ModalOpeningButton from './ModalOpeningButton';
|
9
|
+
import clsx from 'clsx';
|
9
10
|
|
10
11
|
function ModalTrigger({
|
11
12
|
label,
|
12
13
|
showLabel,
|
13
14
|
icon,
|
15
|
+
isDisabled,
|
14
16
|
children,
|
15
17
|
...props
|
16
18
|
}: {
|
17
19
|
label: string;
|
18
20
|
showLabel?: boolean;
|
19
21
|
icon?: React.ReactNode;
|
22
|
+
isDisabled?: boolean;
|
20
23
|
children: (onClose: () => void, titleProps: DOMAttributes<FocusableElement>) => React.ReactElement; // Child needs to be a functions which generates the 'content' so we can pass the onClose function and title aria props
|
21
24
|
}) {
|
22
25
|
const state = useOverlayTriggerState(props);
|
@@ -29,9 +32,18 @@ function ModalTrigger({
|
|
29
32
|
|
30
33
|
return (
|
31
34
|
<>
|
32
|
-
<ModalOpeningButton
|
33
|
-
|
35
|
+
<ModalOpeningButton
|
36
|
+
type="button"
|
37
|
+
{...triggerProps}
|
38
|
+
{...ariaAttr}
|
39
|
+
isDisabled={isDisabled}
|
40
|
+
className={clsx(
|
41
|
+
'flex p-1 px-1.5 rounded mr-auto text-blue-300 hover:bg-blue-100 focus:bg-blue-100 focus:outline-none',
|
42
|
+
isDisabled && 'hover:bg-transparent cursor-not-allowed text-gray-600',
|
43
|
+
)}
|
44
|
+
>
|
34
45
|
{icon}
|
46
|
+
{showLabel && <span className="ml-1 text-sm leading-4">{label}</span>}
|
35
47
|
</ModalOpeningButton>
|
36
48
|
{state.isOpen && (
|
37
49
|
<Modal isDismissable state={state} overlayProps={overlayProps}>
|
@@ -2,30 +2,13 @@ import React from 'react';
|
|
2
2
|
|
3
3
|
import { Resource } from '../../types';
|
4
4
|
import Icon, { IconOptions } from '../../Icons/Icon';
|
5
|
-
|
6
|
-
const statusColour = {
|
7
|
-
// Duplicated from the Matrix repository.
|
8
|
-
// src/Api/AssetManagementApi/Constants/AssetStatuses.php - contains a list of possible statuses.
|
9
|
-
// frontend/src/styles/common/status-colors.scss - contains the colours used for those statuses in Matrix.
|
10
|
-
unknown: '#ff0000',
|
11
|
-
archived: '#c98a67',
|
12
|
-
under_construction: '#94d1f9',
|
13
|
-
pending_approval: '#d0bbf0',
|
14
|
-
approved_to_go_live: '#f7eaa2',
|
15
|
-
live: '#bfe60a',
|
16
|
-
up_for_review: '#72cd32',
|
17
|
-
safe_editing: '#ff97b0',
|
18
|
-
safe_editing_pending_approval: '#d688db',
|
19
|
-
safe_edit_approved_to_go_live: '#ffb34a',
|
20
|
-
};
|
5
|
+
import StatusIndicator from '../../StatusIndicator/StatusIndicator';
|
21
6
|
|
22
7
|
type MatrixResourceProps = {
|
23
8
|
resource: Resource;
|
24
9
|
};
|
25
10
|
|
26
11
|
const MatrixResource = ({ resource: { id, type, name, status } }: MatrixResourceProps) => {
|
27
|
-
const color = statusColour[status.code as keyof typeof statusColour] || statusColour.unknown;
|
28
|
-
|
29
12
|
return (
|
30
13
|
<div>
|
31
14
|
<div className="flex flex-col items-center text-gray-800 mt-7 mx-5 pb-4 border-b border-gray-300">
|
@@ -47,10 +30,7 @@ const MatrixResource = ({ resource: { id, type, name, status } }: MatrixResource
|
|
47
30
|
<div className="flex mb-2">
|
48
31
|
<dt className="w-[60px] mr-4 text-gray-600">Status</dt>
|
49
32
|
<dd className="flex items-center font-semibold">
|
50
|
-
<
|
51
|
-
style={{ backgroundColor: color }}
|
52
|
-
className="block rounded-full w-3 h-3 mr-1 border border-solid border-black border-opacity-20"
|
53
|
-
></span>
|
33
|
+
<StatusIndicator status={status} />
|
54
34
|
{status.name}
|
55
35
|
</dd>
|
56
36
|
</div>
|
@@ -8,10 +8,6 @@ const defaultProps: any = {
|
|
8
8
|
};
|
9
9
|
|
10
10
|
describe('ResourceError', () => {
|
11
|
-
afterEach(() => {
|
12
|
-
jest.clearAllMocks();
|
13
|
-
});
|
14
|
-
|
15
11
|
it('should render the component with the correct error message', () => {
|
16
12
|
const { getByText } = render(<ResourceError {...defaultProps} />);
|
17
13
|
const errorMessage = getByText(defaultProps.errorMessage);
|
@@ -19,10 +19,6 @@ const defaultProps: any = {
|
|
19
19
|
};
|
20
20
|
|
21
21
|
describe('ResourceItem', () => {
|
22
|
-
afterEach(() => {
|
23
|
-
jest.clearAllMocks();
|
24
|
-
});
|
25
|
-
|
26
22
|
it('should render the component with the correct label', () => {
|
27
23
|
const { getByText } = render(<ResourceItem {...defaultProps} />);
|
28
24
|
const labelElement = getByText('My Resource');
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import CloseRoundedIcon from '@mui/icons-material/CloseRounded';
|
3
|
+
|
4
|
+
export const ResetButton = ({ isDisabled }: { isDisabled: boolean }) => (
|
5
|
+
<button
|
6
|
+
type="button"
|
7
|
+
aria-label={`Remove selection`}
|
8
|
+
title={`Remove selection`}
|
9
|
+
className="text-gray-500 hover:text-gray-800 focus:text-gray-800 w-6 h-6 disabled:text-gray-500 disabled:cursor-not-allowed"
|
10
|
+
disabled={isDisabled}
|
11
|
+
>
|
12
|
+
<CloseRoundedIcon />
|
13
|
+
</button>
|
14
|
+
);
|