@squiz/resource-browser 1.32.1-alpha.28 → 1.32.1-alpha.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/lib/Modal/ModalTrigger.d.ts +2 -1
  2. package/lib/Modal/ModalTrigger.js +5 -4
  3. package/lib/PreviewPanel/PreviewPanel.d.ts +0 -1
  4. package/lib/PreviewPanel/details/MatrixResource.d.ts +0 -1
  5. package/lib/PreviewPanel/details/MatrixResource.js +2 -17
  6. package/lib/ResourceBreadcrumb/ResourceBreadcrumb.d.ts +0 -1
  7. package/lib/ResourceError/ResourceError.d.ts +0 -1
  8. package/lib/ResourceItem/ResourceItem.d.ts +0 -1
  9. package/lib/ResourceItem/ResourceItem.js +7 -6
  10. package/lib/ResourceList/ResourceList.d.ts +0 -1
  11. package/lib/ResourcePickerContainer/ResourcePickerContainer.d.ts +0 -1
  12. package/lib/ResourcePickerContainer/ResourcePickerContainer.js +4 -4
  13. package/lib/Skeleton/List/SkeletonList.d.ts +0 -1
  14. package/lib/Skeleton/ListItem/SkeletonListItem.d.ts +0 -1
  15. package/lib/Skeleton/ListItem/SkeletonListItem.js +1 -1
  16. package/lib/SourceDropdown/SourceDropdown.d.ts +0 -1
  17. package/lib/SourceDropdown/SourceDropdown.js +5 -5
  18. package/lib/SourceList/SourceList.d.ts +0 -1
  19. package/lib/Spinner/Spinner.d.ts +1 -1
  20. package/lib/Spinner/Spinner.js +1 -1
  21. package/lib/StatusIndicator/StatusIndicator.d.ts +6 -0
  22. package/lib/StatusIndicator/StatusIndicator.js +26 -0
  23. package/lib/index.css +187 -23
  24. package/lib/index.d.ts +2 -5
  25. package/lib/index.js +9 -3
  26. package/package.json +5 -3
  27. package/src/Icons/Icon.stories.tsx +5 -0
  28. package/src/Modal/Modal.spec.tsx +25 -0
  29. package/src/Modal/ModalTrigger.tsx +14 -2
  30. package/src/PreviewPanel/details/MatrixResource.tsx +2 -22
  31. package/src/ResourceError/ResourceError.spec.tsx +0 -4
  32. package/src/ResourceItem/ResourceItem.spec.tsx +0 -4
  33. package/src/ResourceItem/ResourceItem.tsx +9 -7
  34. package/src/ResourcePicker/ResetButton.tsx +14 -0
  35. package/src/ResourcePicker/ResourcePicker.spec.tsx +81 -0
  36. package/src/ResourcePicker/ResourcePicker.stories.tsx +62 -0
  37. package/src/ResourcePicker/ResourcePicker.tsx +55 -0
  38. package/src/ResourcePicker/States/Error.tsx +12 -0
  39. package/src/ResourcePicker/States/Loading.tsx +9 -0
  40. package/src/ResourcePicker/States/Selected.tsx +51 -0
  41. package/src/ResourcePicker/mock-image-resource.json +51 -0
  42. package/src/ResourcePicker/mock-resource.json +15 -0
  43. package/src/ResourcePicker/resource-picker.scss +13 -0
  44. package/src/ResourcePickerContainer/ResourcePickerContainer.stories.tsx +1 -1
  45. package/src/ResourcePickerContainer/ResourcePickerContainer.tsx +4 -4
  46. package/src/Skeleton/ListItem/SkeletonListItem.tsx +1 -1
  47. package/src/Skeleton/_skeleton.scss +15 -0
  48. package/src/SourceDropdown/SourceDropdown.tsx +5 -7
  49. package/src/Spinner/Spinner.stories.tsx +2 -2
  50. package/src/Spinner/Spinner.tsx +2 -2
  51. package/src/Spinner/_spinner.scss +8 -5
  52. package/src/StatusIndicator/StatusIndicator.stories.tsx +83 -0
  53. package/src/StatusIndicator/StatusIndicator.tsx +35 -0
  54. package/src/index.scss +15 -0
  55. package/src/index.spec.tsx +44 -0
  56. package/src/index.stories.tsx +15 -17
  57. package/src/index.tsx +41 -20
  58. package/src/types.d.ts +5 -4
package/lib/index.css CHANGED
@@ -378,6 +378,9 @@
378
378
  .squiz-rb-scope .-left-0\.5 {
379
379
  left: -0.125rem;
380
380
  }
381
+ .squiz-rb-scope .-right-8 {
382
+ right: -2rem;
383
+ }
381
384
  .squiz-rb-scope .bottom-0 {
382
385
  bottom: 0px;
383
386
  }
@@ -390,9 +393,6 @@
390
393
  .squiz-rb-scope .right-4 {
391
394
  right: 1rem;
392
395
  }
393
- .squiz-rb-scope .right-5 {
394
- right: 1.25rem;
395
- }
396
396
  .squiz-rb-scope .top-2 {
397
397
  top: 0.5rem;
398
398
  }
@@ -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,12 @@
478
490
  .squiz-rb-scope .mr-7 {
479
491
  margin-right: 1.75rem;
480
492
  }
493
+ .squiz-rb-scope .mr-8 {
494
+ margin-right: 2rem;
495
+ }
496
+ .squiz-rb-scope .mr-auto {
497
+ margin-right: auto;
498
+ }
481
499
  .squiz-rb-scope .mt-2 {
482
500
  margin-top: 0.5rem;
483
501
  }
@@ -496,6 +514,12 @@
496
514
  .squiz-rb-scope .mt-7 {
497
515
  margin-top: 1.75rem;
498
516
  }
517
+ .squiz-rb-scope .line-clamp-2 {
518
+ overflow: hidden;
519
+ display: -webkit-box;
520
+ -webkit-box-orient: vertical;
521
+ -webkit-line-clamp: 2;
522
+ }
499
523
  .squiz-rb-scope .block {
500
524
  display: block;
501
525
  }
@@ -511,6 +535,9 @@
511
535
  .squiz-rb-scope .hidden {
512
536
  display: none;
513
537
  }
538
+ .squiz-rb-scope .\!h-4 {
539
+ height: 1rem !important;
540
+ }
514
541
  .squiz-rb-scope .h-14 {
515
542
  height: 3.5rem;
516
543
  }
@@ -532,11 +559,14 @@
532
559
  .squiz-rb-scope .h-9 {
533
560
  height: 2.25rem;
534
561
  }
562
+ .squiz-rb-scope .h-\[20px\] {
563
+ height: 20px;
564
+ }
535
565
  .squiz-rb-scope .h-\[50vh\] {
536
566
  height: 50vh;
537
567
  }
538
- .squiz-rb-scope .h-\[calc\(100\%-92px\)\] {
539
- height: calc(100% - 92px);
568
+ .squiz-rb-scope .h-\[calc\(100\%-72px\)\] {
569
+ height: calc(100% - 72px);
540
570
  }
541
571
  .squiz-rb-scope .h-full {
542
572
  height: 100%;
@@ -544,15 +574,18 @@
544
574
  .squiz-rb-scope .h-screen {
545
575
  height: 100vh;
546
576
  }
577
+ .squiz-rb-scope .min-h-\[64px\] {
578
+ min-height: 64px;
579
+ }
547
580
  .squiz-rb-scope .min-h-full {
548
581
  min-height: 100%;
549
582
  }
583
+ .squiz-rb-scope .\!w-4 {
584
+ width: 1rem !important;
585
+ }
550
586
  .squiz-rb-scope .w-1\/2 {
551
587
  width: 50%;
552
588
  }
553
- .squiz-rb-scope .w-10 {
554
- width: 2.5rem;
555
- }
556
589
  .squiz-rb-scope .w-12 {
557
590
  width: 3rem;
558
591
  }
@@ -580,6 +613,12 @@
580
613
  .squiz-rb-scope .w-\[119px\] {
581
614
  width: 119px;
582
615
  }
616
+ .squiz-rb-scope .w-\[20px\] {
617
+ width: 20px;
618
+ }
619
+ .squiz-rb-scope .w-\[400px\] {
620
+ width: 400px;
621
+ }
583
622
  .squiz-rb-scope .w-\[60px\] {
584
623
  width: 60px;
585
624
  }
@@ -640,9 +679,18 @@
640
679
  .squiz-rb-scope .justify-center {
641
680
  justify-content: center;
642
681
  }
682
+ .squiz-rb-scope .gap-1 {
683
+ gap: 0.25rem;
684
+ }
643
685
  .squiz-rb-scope .gap-3 {
644
686
  gap: 0.75rem;
645
687
  }
688
+ .squiz-rb-scope .self-center {
689
+ align-self: center;
690
+ }
691
+ .squiz-rb-scope .justify-self-start {
692
+ justify-self: start;
693
+ }
646
694
  .squiz-rb-scope .overflow-y-scroll {
647
695
  overflow-y: scroll;
648
696
  }
@@ -651,9 +699,6 @@
651
699
  text-overflow: ellipsis;
652
700
  white-space: nowrap;
653
701
  }
654
- .squiz-rb-scope .break-all {
655
- word-break: break-all;
656
- }
657
702
  .squiz-rb-scope .rounded {
658
703
  border-radius: 4px;
659
704
  }
@@ -721,6 +766,10 @@
721
766
  --tw-bg-opacity: 1;
722
767
  background-color: rgb(237 237 237 / var(--tw-bg-opacity));
723
768
  }
769
+ .squiz-rb-scope .bg-gray-300 {
770
+ --tw-bg-opacity: 1;
771
+ background-color: rgb(224 224 224 / var(--tw-bg-opacity));
772
+ }
724
773
  .squiz-rb-scope .bg-white {
725
774
  --tw-bg-opacity: 1;
726
775
  background-color: rgb(255 255 255 / var(--tw-bg-opacity));
@@ -731,6 +780,9 @@
731
780
  .squiz-rb-scope .p-1 {
732
781
  padding: 0.25rem;
733
782
  }
783
+ .squiz-rb-scope .p-1\.5 {
784
+ padding: 0.375rem;
785
+ }
734
786
  .squiz-rb-scope .p-2 {
735
787
  padding: 0.5rem;
736
788
  }
@@ -740,8 +792,13 @@
740
792
  .squiz-rb-scope .p-4 {
741
793
  padding: 1rem;
742
794
  }
743
- .squiz-rb-scope .p-6 {
744
- padding: 1.5rem;
795
+ .squiz-rb-scope .px-1 {
796
+ padding-left: 0.25rem;
797
+ padding-right: 0.25rem;
798
+ }
799
+ .squiz-rb-scope .px-1\.5 {
800
+ padding-left: 0.375rem;
801
+ padding-right: 0.375rem;
745
802
  }
746
803
  .squiz-rb-scope .px-2 {
747
804
  padding-left: 0.5rem;
@@ -755,6 +812,10 @@
755
812
  padding-left: 0.75rem;
756
813
  padding-right: 0.75rem;
757
814
  }
815
+ .squiz-rb-scope .px-4 {
816
+ padding-left: 1rem;
817
+ padding-right: 1rem;
818
+ }
758
819
  .squiz-rb-scope .px-7 {
759
820
  padding-left: 1.75rem;
760
821
  padding-right: 1.75rem;
@@ -805,6 +866,9 @@
805
866
  .squiz-rb-scope .font-semibold {
806
867
  font-weight: 600;
807
868
  }
869
+ .squiz-rb-scope .leading-4 {
870
+ line-height: 1rem;
871
+ }
808
872
  .squiz-rb-scope .leading-5 {
809
873
  line-height: 1.25rem;
810
874
  }
@@ -819,6 +883,10 @@
819
883
  --tw-text-opacity: 1;
820
884
  color: rgb(4 73 133 / var(--tw-text-opacity));
821
885
  }
886
+ .squiz-rb-scope .text-gray-500 {
887
+ --tw-text-opacity: 1;
888
+ color: rgb(148 148 148 / var(--tw-text-opacity));
889
+ }
822
890
  .squiz-rb-scope .text-gray-600 {
823
891
  --tw-text-opacity: 1;
824
892
  color: rgb(112 112 112 / var(--tw-text-opacity));
@@ -831,23 +899,32 @@
831
899
  --tw-text-opacity: 1;
832
900
  color: rgb(61 61 61 / var(--tw-text-opacity));
833
901
  }
902
+ .squiz-rb-scope .text-red-300 {
903
+ --tw-text-opacity: 1;
904
+ color: rgb(215 35 33 / var(--tw-text-opacity));
905
+ }
834
906
  .squiz-rb-scope .text-white {
835
907
  --tw-text-opacity: 1;
836
908
  color: rgb(255 255 255 / var(--tw-text-opacity));
837
909
  }
910
+ .squiz-rb-scope .antialiased {
911
+ -webkit-font-smoothing: antialiased;
912
+ -moz-osx-font-smoothing: grayscale;
913
+ }
838
914
  .squiz-rb-scope .opacity-40 {
839
915
  opacity: 0.4;
840
916
  }
917
+ .squiz-rb-scope .outline-0 {
918
+ outline-width: 0px;
919
+ }
841
920
  .squiz-rb-scope .blur {
842
921
  --tw-blur: blur(8px);
843
922
  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);
844
923
  }
845
924
  .squiz-rb-scope .spinner {
846
925
  display: inline-block;
847
- height: 2rem;
848
- width: 2rem;
849
926
  border-radius: 9999px;
850
- border-width: 4px;
927
+ border-width: 2px;
851
928
  border-style: solid;
852
929
  border-color: currentColor;
853
930
  border-right-color: transparent;
@@ -868,17 +945,34 @@
868
945
  animation: spin 1.5s linear infinite;
869
946
  }
870
947
  }
948
+ .squiz-rb-scope .spinner {
949
+ height: 20px;
950
+ width: 20px;
951
+ }
871
952
  .squiz-rb-scope .spinner__wrapper {
872
- margin: 0.75rem;
873
953
  display: flex;
874
954
  align-items: center;
875
955
  justify-content: center;
876
956
  --tw-text-opacity: 1;
877
957
  color: rgb(224 224 224 / var(--tw-text-opacity));
878
958
  }
879
- .squiz-rb-scope .spinner--lg {
880
- height: 3rem;
881
- width: 3rem;
959
+ .squiz-rb-scope .spinner--md {
960
+ height: 32px;
961
+ width: 32px;
962
+ }
963
+ .squiz-rb-scope .animate-skeleton-pulse {
964
+ animation: pulse 2s linear infinite;
965
+ }
966
+ @keyframes pulse {
967
+ 0% {
968
+ opacity: 1;
969
+ }
970
+ 50% {
971
+ opacity: 0.45;
972
+ }
973
+ 100% {
974
+ opacity: 1;
975
+ }
882
976
  }
883
977
  .squiz-rb-scope .resource-breadcrumb--collapsed .resource-breadcrumb__label {
884
978
  max-width: 250px;
@@ -918,6 +1012,46 @@
918
1012
  .squiz-rb-scope .resource-breadcrumb--expanded .resource-breadcrumb__item:last-child {
919
1013
  display: flex;
920
1014
  }
1015
+ .squiz-rb-scope .resource-picker {
1016
+ display: grid;
1017
+ grid-template-columns: 24px 1fr;
1018
+ gap: 0.5rem;
1019
+ border-width: 2px;
1020
+ --tw-border-opacity: 1;
1021
+ border-color: rgb(224 224 224 / var(--tw-border-opacity));
1022
+ border-radius: 4px;
1023
+ padding: 0.5rem;
1024
+ --tw-text-opacity: 1;
1025
+ color: rgb(148 148 148 / var(--tw-text-opacity));
1026
+ }
1027
+ .squiz-rb-scope .resource-picker-info {
1028
+ width: 100%;
1029
+ border-radius: 6px;
1030
+ --tw-bg-opacity: 1;
1031
+ background-color: rgb(245 245 245 / var(--tw-bg-opacity));
1032
+ padding: 0.5rem;
1033
+ font-size: 0.875rem;
1034
+ font-weight: 600;
1035
+ --tw-text-opacity: 1;
1036
+ color: rgb(43 43 43 / var(--tw-text-opacity));
1037
+ }
1038
+ .squiz-rb-scope .resource-picker-info__layout {
1039
+ display: grid;
1040
+ grid-template-columns: 24px 1fr 24px;
1041
+ gap: 0.5rem;
1042
+ justify-items: center;
1043
+ }
1044
+ .squiz-rb-scope *,
1045
+ .squiz-rb-scope button {
1046
+ letter-spacing: -0.02em;
1047
+ }
1048
+ .squiz-rb-scope svg {
1049
+ --tw-text-opacity: 1;
1050
+ color: rgb(112 112 112 / var(--tw-text-opacity));
1051
+ }
1052
+ .squiz-rb-scope .p-4\.5 {
1053
+ padding: 18px;
1054
+ }
921
1055
  .squiz-rb-scope .before\:fixed::before {
922
1056
  content: var(--tw-content);
923
1057
  position: fixed;
@@ -1027,6 +1161,17 @@
1027
1161
  --tw-bg-opacity: 1;
1028
1162
  background-color: rgb(245 245 245 / var(--tw-bg-opacity));
1029
1163
  }
1164
+ .squiz-rb-scope .hover\:bg-gray-50:hover {
1165
+ --tw-bg-opacity: 1;
1166
+ background-color: rgb(247 247 247 / var(--tw-bg-opacity));
1167
+ }
1168
+ .squiz-rb-scope .hover\:bg-transparent:hover {
1169
+ background-color: transparent;
1170
+ }
1171
+ .squiz-rb-scope .hover\:text-gray-800:hover {
1172
+ --tw-text-opacity: 1;
1173
+ color: rgb(61 61 61 / var(--tw-text-opacity));
1174
+ }
1030
1175
  .squiz-rb-scope .focus\:bg-blue-100:focus {
1031
1176
  --tw-bg-opacity: 1;
1032
1177
  background-color: rgb(230 241 250 / var(--tw-bg-opacity));
@@ -1035,6 +1180,25 @@
1035
1180
  --tw-bg-opacity: 1;
1036
1181
  background-color: rgb(245 245 245 / var(--tw-bg-opacity));
1037
1182
  }
1183
+ .squiz-rb-scope .focus\:bg-gray-50:focus {
1184
+ --tw-bg-opacity: 1;
1185
+ background-color: rgb(247 247 247 / var(--tw-bg-opacity));
1186
+ }
1187
+ .squiz-rb-scope .focus\:text-gray-800:focus {
1188
+ --tw-text-opacity: 1;
1189
+ color: rgb(61 61 61 / var(--tw-text-opacity));
1190
+ }
1191
+ .squiz-rb-scope .focus\:outline-none:focus {
1192
+ outline: 2px solid transparent;
1193
+ outline-offset: 2px;
1194
+ }
1195
+ .squiz-rb-scope .disabled\:cursor-not-allowed:disabled {
1196
+ cursor: not-allowed;
1197
+ }
1198
+ .squiz-rb-scope .disabled\:text-gray-500:disabled {
1199
+ --tw-text-opacity: 1;
1200
+ color: rgb(148 148 148 / var(--tw-text-opacity));
1201
+ }
1038
1202
  @media not all and (min-width: 768px) {
1039
1203
  .squiz-rb-scope .max-md\:hidden {
1040
1204
  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({ showButtonLabel, buttonLabel, buttonIcon, modalTitle, allowedTypes, onRequestSources, onRequestChildren, onChange, }: {
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
- function ComponentEditorContentBrowser({ showButtonLabel, buttonLabel, buttonIcon, modalTitle, allowedTypes, onRequestSources, onRequestChildren, onChange, }) {
10
- const showLabel = showButtonLabel || false;
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(ModalTrigger_1.default, { showLabel: showLabel, label: buttonLabel, icon: buttonIcon }, (onClose, titleProps) => (react_1.default.createElement(ResourcePickerContainer_1.default, { title: modalTitle, titleAriaProps: titleProps, allowedTypes: allowedTypes, onClose: onClose, onRequestSources: onRequestSources, onRequestChildren: onRequestChildren, onChange: onChange })))));
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.28",
3
+ "version": "1.32.1-alpha.30",
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
- "@squiz/dx-json-schema-lib": "1.32.1-alpha.28",
17
+ "@mui/icons-material": "5.11.16",
18
+ "@squiz/dx-json-schema-lib": "1.32.1-alpha.30",
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": "affbfe3733cbad5b594b3e298329cc1c62727f36"
76
+ "gitHead": "d7dd20646acc571cdcf3b95629c004fa8892f8b6"
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',
@@ -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 type="button" {...triggerProps} {...ariaAttr}>
33
- {showLabel && label}
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
- <span
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');
@@ -36,16 +36,16 @@ const ResourceItem = <T,>({
36
36
  const title = isDisabled ? "You can't select this item" : label;
37
37
 
38
38
  return (
39
- <li className={`flex items-stretch p-1 bg-white border border-grey-200 ${className}`}>
39
+ <li className={`flex items-stretch p-1 bg-white border border-grey-200 min-h-[64px] ${className}`}>
40
40
  <ModalOpeningButton
41
41
  type="button"
42
42
  {...triggerProps}
43
43
  isDisabled={isDisabled}
44
44
  onPress={() => onSelect(item, overlayProps)}
45
45
  className={`
46
- relative grow flex items-center p-4 rounded ${selected ? 'bg-blue-100 text-blue-400' : ''} ${
46
+ relative grow flex items-center px-4 py-2 rounded outline-0 ${selected ? 'bg-blue-100 text-blue-400' : ''} ${
47
47
  childCount > 0 ? 'mr-2' : ''
48
- } ${isDisabled ? 'font-normal text-gray-600 cursor-not-allowed' : 'hover:bg-gray-100 focus:bg-gray-100'}
48
+ } ${isDisabled ? 'font-normal text-gray-600 cursor-not-allowed' : 'hover:bg-gray-50 focus:bg-gray-50'}
49
49
  `}
50
50
  title={title}
51
51
  >
@@ -55,18 +55,20 @@ const ResourceItem = <T,>({
55
55
  aria-label={type}
56
56
  className={`mr-4 shrink-0 ${isDisabled && 'opacity-40'}`}
57
57
  />
58
- <span className="text-left break-all">{label}</span>
59
- {childCount <= 0 && <Icon icon={'arrow-right' as IconOptions} className="absolute right-5" />}
58
+ <span className={`relative flex items-center ${selected ? 'mr-8' : ''}`}>
59
+ <span className="line-clamp-2 text-left break-word">{label}</span>
60
+ {selected && <Icon icon={'selected' as IconOptions} aria-label="selected" className="absolute -right-8" />}
61
+ </span>
60
62
  </ModalOpeningButton>
61
63
  {childCount > 0 && (
62
64
  <button
63
65
  type="button"
64
66
  aria-label={`Drill down to ${label} children`}
65
67
  onClick={() => onDrillDown(item)}
66
- className={`relative shrink-0 flex items-center p-4 rounded before:w-px before:h-[calc(100%-0.75rem)] before:bg-gray-200 before:absolute before:top-1.5 before:-left-1 hover:bg-gray-100 focus:bg-gray-100`}
68
+ className={`relative shrink-0 flex items-center p-4 rounded outline-0 before:w-px before:h-[calc(100%-0.75rem)] before:bg-gray-200 before:absolute before:top-1.5 before:-left-1 hover:bg-gray-50 focus:bg-gray-50`}
67
69
  >
68
70
  <span className="ml-auto flex items-center">
69
- <span className="truncate w-10 text-right" title={String(childCount)}>
71
+ <span className="truncate w-14 text-right" title={String(childCount)}>
70
72
  {childCount}
71
73
  </span>
72
74
  <Icon icon={'arrow-right' as IconOptions} className="ml-1" />
@@ -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
+ );