@squiz/resource-browser 3.1.0 → 3.1.1
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/CHANGELOG.md +6 -0
- package/lib/ResourceBrowserInput/ResourceBrowserInput.d.ts +4 -7
- package/lib/ResourceBrowserInput/ResourceBrowserInput.js +2 -2
- package/lib/ResourcePicker/ResourcePicker.d.ts +2 -1
- package/lib/ResourcePicker/ResourcePicker.js +13 -3
- package/lib/index.js +9 -2
- package/package.json +1 -1
- package/src/Plugin/Plugin.spec.tsx +2 -0
- package/src/ResourceBrowserInput/ResourceBrowserInput.spec.tsx +1 -0
- package/src/ResourceBrowserInput/ResourceBrowserInput.tsx +5 -8
- package/src/ResourcePicker/ResourcePicker.spec.tsx +10 -0
- package/src/ResourcePicker/ResourcePicker.tsx +26 -2
- package/src/__mocks__/StorybookHelpers.tsx +4 -0
- package/src/index.spec.tsx +87 -7
- package/src/index.tsx +11 -0
package/CHANGELOG.md
CHANGED
@@ -1,15 +1,11 @@
|
|
1
1
|
import React from 'react';
|
2
|
-
import { ResourceBrowserPlugin, ResourceBrowserSource, ResourceBrowserUnresolvedResource, ResourceBrowserResource, ResourceBrowserSourceWithPlugin, PluginLaunchMode } from '../types';
|
2
|
+
import { ResourceBrowserPlugin, ResourceBrowserSource, ResourceBrowserUnresolvedResource, ResourceBrowserResource, ResourceBrowserSourceWithPlugin, PluginLaunchMode, useResolveResourceResponse } from '../types';
|
3
3
|
export type ResourceBrowserInputProps = {
|
4
4
|
modalTitle: string;
|
5
5
|
allowedTypes?: string[];
|
6
6
|
isDisabled?: boolean;
|
7
7
|
value: ResourceBrowserUnresolvedResource | null;
|
8
|
-
useResource(referenceId: string | null, source: ResourceBrowserSource | null):
|
9
|
-
data: ResourceBrowserResource | null;
|
10
|
-
error: Error | null;
|
11
|
-
isLoading: boolean;
|
12
|
-
};
|
8
|
+
useResource(referenceId: string | null, source: ResourceBrowserSource | null): useResolveResourceResponse;
|
13
9
|
onChange(resource: ResourceBrowserResource | null): void;
|
14
10
|
onClear?(): void;
|
15
11
|
plugin: ResourceBrowserPlugin | null;
|
@@ -18,9 +14,10 @@ export type ResourceBrowserInputProps = {
|
|
18
14
|
source: ResourceBrowserSource | null;
|
19
15
|
sources: ResourceBrowserSourceWithPlugin[];
|
20
16
|
isLoading: boolean;
|
17
|
+
isOtherSourceValue: boolean;
|
21
18
|
error: Error | null;
|
22
19
|
setSource(source: ResourceBrowserSource, mode?: PluginLaunchMode): void;
|
23
20
|
isModalOpen: boolean;
|
24
21
|
onModalStateChange(isOpen: boolean): void;
|
25
22
|
};
|
26
|
-
export declare const ResourceBrowserInput: ({ modalTitle, allowedTypes, onChange, value, useResource, isDisabled, onClear, plugin, pluginMode, searchEnabled, source, sources, isLoading, error, setSource, isModalOpen, onModalStateChange, }: ResourceBrowserInputProps) => React.JSX.Element;
|
23
|
+
export declare const ResourceBrowserInput: ({ modalTitle, allowedTypes, onChange, value, useResource, isDisabled, onClear, plugin, pluginMode, searchEnabled, source, sources, isLoading, isOtherSourceValue, error, setSource, isModalOpen, onModalStateChange, }: ResourceBrowserInputProps) => React.JSX.Element;
|
@@ -7,10 +7,10 @@ exports.ResourceBrowserInput = void 0;
|
|
7
7
|
const react_1 = __importDefault(require("react"));
|
8
8
|
const MainContainer_1 = __importDefault(require("../MainContainer/MainContainer"));
|
9
9
|
const ResourcePicker_1 = require("../ResourcePicker/ResourcePicker");
|
10
|
-
const ResourceBrowserInput = ({ modalTitle, allowedTypes, onChange, value, useResource, isDisabled, onClear, plugin, pluginMode, searchEnabled, source, sources, isLoading, error, setSource, isModalOpen, onModalStateChange, }) => {
|
10
|
+
const ResourceBrowserInput = ({ modalTitle, allowedTypes, onChange, value, useResource, isDisabled, onClear, plugin, pluginMode, searchEnabled, source, sources, isLoading, isOtherSourceValue, error, setSource, isModalOpen, onModalStateChange, }) => {
|
11
11
|
const { data: resource, error: resourceError, isLoading: isResourceLoading } = useResource(value?.resourceId || null, source);
|
12
12
|
const defaultOnClear = () => onChange(null);
|
13
13
|
const onClearFunction = onClear ?? defaultOnClear;
|
14
|
-
return (react_1.default.createElement(ResourcePicker_1.ResourcePicker, { resource: resource, plugin: plugin, allowedTypes: allowedTypes, error: resourceError || error, isLoading: isResourceLoading || isLoading, isDisabled: isDisabled, onClear: onClearFunction, isModalOpen: isModalOpen, onModalStateChange: onModalStateChange }, (onClose, titleProps) => (react_1.default.createElement(MainContainer_1.default, { selectedSource: source, sources: sources, preselectedResource: resource, plugin: plugin, pluginMode: pluginMode, searchEnabled: searchEnabled, title: modalTitle, titleAriaProps: titleProps, allowedTypes: allowedTypes, onSourceSelect: setSource, onClose: onClose, onChange: onChange }))));
|
14
|
+
return (react_1.default.createElement(ResourcePicker_1.ResourcePicker, { resource: resource, plugin: plugin, allowedTypes: allowedTypes, error: resourceError || error, isLoading: isResourceLoading || isLoading, isOtherSourceValue: isOtherSourceValue, isDisabled: isDisabled, onClear: onClearFunction, isModalOpen: isModalOpen, onModalStateChange: onModalStateChange }, (onClose, titleProps) => (react_1.default.createElement(MainContainer_1.default, { selectedSource: source, sources: sources, preselectedResource: resource, plugin: plugin, pluginMode: pluginMode, searchEnabled: searchEnabled, title: modalTitle, titleAriaProps: titleProps, allowedTypes: allowedTypes, onSourceSelect: setSource, onClose: onClose, onChange: onChange }))));
|
15
15
|
};
|
16
16
|
exports.ResourceBrowserInput = ResourceBrowserInput;
|
@@ -7,10 +7,11 @@ export type ResourcePickerProps = {
|
|
7
7
|
allowedTypes: string[] | undefined;
|
8
8
|
error: Error | null;
|
9
9
|
isLoading: boolean;
|
10
|
+
isOtherSourceValue: boolean;
|
10
11
|
isDisabled?: boolean;
|
11
12
|
children: (onClose: () => void, titleProps: DOMAttributes) => React.ReactElement;
|
12
13
|
onClear: () => void;
|
13
14
|
isModalOpen: boolean;
|
14
15
|
onModalStateChange(isOpen: boolean): void;
|
15
16
|
};
|
16
|
-
export declare const ResourcePicker: ({ resource, plugin, allowedTypes, error: externalError, isLoading: isExternalLoading, isDisabled, children, onClear, isModalOpen, onModalStateChange, }: ResourcePickerProps) => React.JSX.Element;
|
17
|
+
export declare const ResourcePicker: ({ resource, plugin, allowedTypes, error: externalError, isLoading: isExternalLoading, isOtherSourceValue, isDisabled, children, onClear, isModalOpen, onModalStateChange, }: ResourcePickerProps) => React.JSX.Element;
|
@@ -14,16 +14,26 @@ const Loading_1 = require("./States/Loading");
|
|
14
14
|
const Selected_1 = require("./States/Selected");
|
15
15
|
const useSelectedState_1 = require("../Hooks/useSelectedState");
|
16
16
|
const clsx_1 = __importDefault(require("clsx"));
|
17
|
-
const ResourcePicker = ({ resource, plugin, allowedTypes, error: externalError, isLoading: isExternalLoading, isDisabled, children, onClear, isModalOpen, onModalStateChange, }) => {
|
17
|
+
const ResourcePicker = ({ resource, plugin, allowedTypes, error: externalError, isLoading: isExternalLoading, isOtherSourceValue, isDisabled, children, onClear, isModalOpen, onModalStateChange, }) => {
|
18
18
|
const { data: selectedState, error, isLoading } = (0, useSelectedState_1.useSelectedState)({ resource, plugin });
|
19
19
|
const isImagePicker = allowedTypes && allowedTypes.length === 1 && allowedTypes.includes('image');
|
20
20
|
const isEmpty = resource === null && !isExternalLoading && !externalError;
|
21
21
|
return (react_1.default.createElement("div", { className: (0, clsx_1.default)('resource-picker', isDisabled && 'resource-picker--disabled') },
|
22
22
|
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" })),
|
23
|
-
|
23
|
+
isOtherSourceValue && (
|
24
|
+
// User is selecting a new image from a different source, render a loading spinner as we can't resolve the value
|
25
|
+
react_1.default.createElement("div", { className: "resource-picker-info" },
|
26
|
+
react_1.default.createElement("div", { className: "resource-picker-info__layout" },
|
27
|
+
react_1.default.createElement(Loading_1.LoadingState, null),
|
28
|
+
react_1.default.createElement(resource_browser_ui_lib_1.ModalTrigger, { overlayTriggerState: {
|
29
|
+
isOpen: isModalOpen,
|
30
|
+
onOpenChange: onModalStateChange,
|
31
|
+
}, showLabel: false, label: "", isDisabled: true, scope: "squiz-rb-scope" }, children)))),
|
32
|
+
isEmpty && !isOtherSourceValue && (react_1.default.createElement(resource_browser_ui_lib_1.ModalTrigger, { overlayTriggerState: {
|
24
33
|
isOpen: isModalOpen,
|
25
34
|
onOpenChange: onModalStateChange,
|
26
|
-
}, showLabel: true, label: isImagePicker ? `Choose image` : `Choose asset`, icon: react_1.default.createElement(AddCircleOutlineRounded_1.default, { "aria-hidden": true, className: `!w-4 !h-4 text-blue-300 ${isDisabled ? 'text-gray-600' : ''}` }), isDisabled: isDisabled, scope: "squiz-rb-scope" }, children))
|
35
|
+
}, showLabel: true, label: isImagePicker ? `Choose image` : `Choose asset`, icon: react_1.default.createElement(AddCircleOutlineRounded_1.default, { "aria-hidden": true, className: `!w-4 !h-4 text-blue-300 ${isDisabled ? 'text-gray-600' : ''}` }), isDisabled: isDisabled, scope: "squiz-rb-scope" }, children)),
|
36
|
+
!isEmpty && !isOtherSourceValue && (react_1.default.createElement("div", { className: "resource-picker-info" },
|
27
37
|
react_1.default.createElement("div", { className: "resource-picker-info__layout" },
|
28
38
|
(isExternalLoading || isLoading) && react_1.default.createElement(Loading_1.LoadingState, null),
|
29
39
|
(externalError || error) && (react_1.default.createElement(Error_1.ErrorState, { error: externalError || error, isDisabled: isDisabled, onClear: onClear })),
|
package/lib/index.js
CHANGED
@@ -98,12 +98,19 @@ const ResourceBrowser = (props) => {
|
|
98
98
|
}, [setIsModalOpen]);
|
99
99
|
// If the modal closes and we dont have a value clear the source state so it goes back to the launcher on re-open
|
100
100
|
(0, react_1.useEffect)(() => {
|
101
|
+
// If modal is closed and we dont have a value
|
101
102
|
if (!isModalOpen && !value && (sources?.length > 1 || searchEnabled)) {
|
102
103
|
setSource(null);
|
103
104
|
setMode(null);
|
104
105
|
}
|
105
106
|
else if (!isModalOpen) {
|
107
|
+
// Otherwise reset the RB mode
|
106
108
|
setMode(null);
|
109
|
+
// If there is a value passed in, reset the source so the preselected asset preview renders correctly
|
110
|
+
if (value && value.sourceId !== source?.id) {
|
111
|
+
const source = sources.find((source) => source.id === value?.sourceId) || null;
|
112
|
+
setSource(source);
|
113
|
+
}
|
107
114
|
}
|
108
115
|
}, [sources, isModalOpen]);
|
109
116
|
// Reset function to allow user manual reload if sources fail in inline usage
|
@@ -112,7 +119,7 @@ const ResourceBrowser = (props) => {
|
|
112
119
|
}, [reloadSources]);
|
113
120
|
// Render a default "plugin" and one for each item in the plugins array. They are conditionally rendered based on what is selected
|
114
121
|
return (react_1.default.createElement("div", { className: "squiz-rb-scope" },
|
115
|
-
react_1.default.createElement(Plugin_1.PluginRender, { key: "default", render: plugin === null, inline: !!inline, inlineType: inlineType, ...props, source: source, sources: sources, setSource: handleSourceSelect, isLoading: isLoading, error: sourcesError || error, plugin: plugin, pluginMode: mode, searchEnabled: searchEnabled, useResource: () => {
|
122
|
+
react_1.default.createElement(Plugin_1.PluginRender, { key: "default", render: plugin === null, inline: !!inline, inlineType: inlineType, ...props, source: source, sources: sources, setSource: handleSourceSelect, isLoading: isLoading, isOtherSourceValue: false, error: sourcesError || error, plugin: plugin, pluginMode: mode, searchEnabled: searchEnabled, useResource: () => {
|
116
123
|
return {
|
117
124
|
data: null,
|
118
125
|
error: null,
|
@@ -120,7 +127,7 @@ const ResourceBrowser = (props) => {
|
|
120
127
|
};
|
121
128
|
}, isModalOpen: isModalOpen, onModalStateChange: handleModalStateChange, onRetry: handleReset }),
|
122
129
|
plugins.map((thisPlugin) => {
|
123
|
-
return (react_1.default.createElement(Plugin_1.PluginRender, { key: thisPlugin.type, render: thisPlugin === plugin, inline: !!inline, inlineType: inlineType, ...props, source: source, sources: sources, setSource: handleSourceSelect, isLoading: isLoading, error: sourcesError || error, plugin: plugin, pluginMode: mode, searchEnabled: searchEnabled, useResource: thisPlugin.useResolveResource, isModalOpen: isModalOpen, onModalStateChange: handleModalStateChange, onRetry: handleReset }));
|
130
|
+
return (react_1.default.createElement(Plugin_1.PluginRender, { key: thisPlugin.type, render: thisPlugin === plugin, inline: !!inline, inlineType: inlineType, ...props, value: value && source ? (value.sourceId === source.id ? value : null) : null, isOtherSourceValue: value && source ? (value.sourceId !== source.id ? true : false) : false, source: source, sources: sources, setSource: handleSourceSelect, isLoading: isLoading, error: sourcesError || error, plugin: plugin, pluginMode: mode, searchEnabled: searchEnabled, useResource: thisPlugin.useResolveResource, isModalOpen: isModalOpen, onModalStateChange: handleModalStateChange, onRetry: handleReset }));
|
124
131
|
})));
|
125
132
|
};
|
126
133
|
exports.ResourceBrowser = ResourceBrowser;
|
package/package.json
CHANGED
@@ -21,6 +21,7 @@ describe('Plugin', () => {
|
|
21
21
|
const props = {
|
22
22
|
modalTitle: 'Asset picker',
|
23
23
|
value: null,
|
24
|
+
isOtherSourceValue: false,
|
24
25
|
onChange: jest.fn(),
|
25
26
|
onClear: jest.fn(),
|
26
27
|
useResource: () => {
|
@@ -53,6 +54,7 @@ describe('Plugin', () => {
|
|
53
54
|
const props = {
|
54
55
|
modalTitle: 'Asset picker',
|
55
56
|
value: null,
|
57
|
+
isOtherSourceValue: false,
|
56
58
|
onChange: jest.fn(),
|
57
59
|
onClear: jest.fn(),
|
58
60
|
useResource: () => {
|
@@ -8,6 +8,7 @@ import {
|
|
8
8
|
ResourceBrowserResource,
|
9
9
|
ResourceBrowserSourceWithPlugin,
|
10
10
|
PluginLaunchMode,
|
11
|
+
useResolveResourceResponse,
|
11
12
|
} from '../types';
|
12
13
|
|
13
14
|
export type ResourceBrowserInputProps = {
|
@@ -15,14 +16,7 @@ export type ResourceBrowserInputProps = {
|
|
15
16
|
allowedTypes?: string[];
|
16
17
|
isDisabled?: boolean;
|
17
18
|
value: ResourceBrowserUnresolvedResource | null;
|
18
|
-
useResource(
|
19
|
-
referenceId: string | null,
|
20
|
-
source: ResourceBrowserSource | null,
|
21
|
-
): {
|
22
|
-
data: ResourceBrowserResource | null;
|
23
|
-
error: Error | null;
|
24
|
-
isLoading: boolean;
|
25
|
-
};
|
19
|
+
useResource(referenceId: string | null, source: ResourceBrowserSource | null): useResolveResourceResponse;
|
26
20
|
onChange(resource: ResourceBrowserResource | null): void;
|
27
21
|
onClear?(): void;
|
28
22
|
plugin: ResourceBrowserPlugin | null;
|
@@ -31,6 +25,7 @@ export type ResourceBrowserInputProps = {
|
|
31
25
|
source: ResourceBrowserSource | null;
|
32
26
|
sources: ResourceBrowserSourceWithPlugin[];
|
33
27
|
isLoading: boolean;
|
28
|
+
isOtherSourceValue: boolean;
|
34
29
|
error: Error | null;
|
35
30
|
setSource(source: ResourceBrowserSource, mode?: PluginLaunchMode): void;
|
36
31
|
isModalOpen: boolean;
|
@@ -51,6 +46,7 @@ export const ResourceBrowserInput = ({
|
|
51
46
|
source,
|
52
47
|
sources,
|
53
48
|
isLoading,
|
49
|
+
isOtherSourceValue,
|
54
50
|
error,
|
55
51
|
setSource,
|
56
52
|
isModalOpen,
|
@@ -68,6 +64,7 @@ export const ResourceBrowserInput = ({
|
|
68
64
|
allowedTypes={allowedTypes}
|
69
65
|
error={resourceError || error}
|
70
66
|
isLoading={isResourceLoading || isLoading}
|
67
|
+
isOtherSourceValue={isOtherSourceValue}
|
71
68
|
isDisabled={isDisabled}
|
72
69
|
onClear={onClearFunction}
|
73
70
|
isModalOpen={isModalOpen}
|
@@ -10,6 +10,7 @@ const defaultProps: any = {
|
|
10
10
|
allowedTypes: undefined,
|
11
11
|
isLoading: false,
|
12
12
|
isError: false,
|
13
|
+
isOtherSourceValue: false,
|
13
14
|
};
|
14
15
|
|
15
16
|
describe('Resource picker', () => {
|
@@ -36,6 +37,15 @@ describe('Resource picker', () => {
|
|
36
37
|
expect(loadingLabel).toBeInTheDocument();
|
37
38
|
});
|
38
39
|
|
40
|
+
it('should render the loading state if isOtherSourceValue is set to true', () => {
|
41
|
+
render(<ResourcePicker {...defaultProps} isLoading={false} isOtherSourceValue={true} />);
|
42
|
+
const pickerLabel = screen.queryByText('Choose image');
|
43
|
+
const loadingLabel = screen.queryByLabelText('Loading selection');
|
44
|
+
|
45
|
+
expect(pickerLabel).not.toBeInTheDocument();
|
46
|
+
expect(loadingLabel).toBeInTheDocument();
|
47
|
+
});
|
48
|
+
|
39
49
|
it('should render the error state if set to true', () => {
|
40
50
|
const errorMessage = 'Failed to retrieve asset info due to a Component Service API key problem.';
|
41
51
|
|
@@ -18,6 +18,7 @@ export type ResourcePickerProps = {
|
|
18
18
|
allowedTypes: string[] | undefined;
|
19
19
|
error: Error | null;
|
20
20
|
isLoading: boolean;
|
21
|
+
isOtherSourceValue: boolean;
|
21
22
|
isDisabled?: boolean;
|
22
23
|
children: (onClose: () => void, titleProps: DOMAttributes) => React.ReactElement;
|
23
24
|
onClear: () => void;
|
@@ -31,6 +32,7 @@ export const ResourcePicker = ({
|
|
31
32
|
allowedTypes,
|
32
33
|
error: externalError,
|
33
34
|
isLoading: isExternalLoading,
|
35
|
+
isOtherSourceValue,
|
34
36
|
isDisabled,
|
35
37
|
children,
|
36
38
|
onClear,
|
@@ -49,7 +51,28 @@ export const ResourcePicker = ({
|
|
49
51
|
) : (
|
50
52
|
<AdsClickRoundedIcon aria-hidden className="w-6 h-6" />
|
51
53
|
)}
|
52
|
-
{
|
54
|
+
{isOtherSourceValue && (
|
55
|
+
// User is selecting a new image from a different source, render a loading spinner as we can't resolve the value
|
56
|
+
<div className="resource-picker-info">
|
57
|
+
<div className="resource-picker-info__layout">
|
58
|
+
<LoadingState />
|
59
|
+
{/* Need to render the ModalTrigger still as it renders the <Modal/> */}
|
60
|
+
<ModalTrigger
|
61
|
+
overlayTriggerState={{
|
62
|
+
isOpen: isModalOpen,
|
63
|
+
onOpenChange: onModalStateChange,
|
64
|
+
}}
|
65
|
+
showLabel={false}
|
66
|
+
label=""
|
67
|
+
isDisabled={true}
|
68
|
+
scope="squiz-rb-scope"
|
69
|
+
>
|
70
|
+
{children}
|
71
|
+
</ModalTrigger>
|
72
|
+
</div>
|
73
|
+
</div>
|
74
|
+
)}
|
75
|
+
{isEmpty && !isOtherSourceValue && (
|
53
76
|
<ModalTrigger
|
54
77
|
overlayTriggerState={{
|
55
78
|
isOpen: isModalOpen,
|
@@ -68,7 +91,8 @@ export const ResourcePicker = ({
|
|
68
91
|
>
|
69
92
|
{children}
|
70
93
|
</ModalTrigger>
|
71
|
-
)
|
94
|
+
)}
|
95
|
+
{!isEmpty && !isOtherSourceValue && (
|
72
96
|
<div className="resource-picker-info">
|
73
97
|
<div className="resource-picker-info__layout">
|
74
98
|
{(isExternalLoading || isLoading) && <LoadingState />}
|
@@ -93,6 +93,7 @@ export const createPlugins = (callbackWait: number, headerPortal = false, resour
|
|
93
93
|
className="col-start-2 col-end-2 flex flex-row gap-1 justify-self-start items-center font-normal text-sm"
|
94
94
|
>
|
95
95
|
<div>
|
96
|
+
<span>{type} plugin</span>
|
96
97
|
<dt className="hidden">Asset size</dt>
|
97
98
|
<dd className="text-gray-600">
|
98
99
|
{resource.squizImage && (
|
@@ -147,6 +148,9 @@ export const createPlugins = (callbackWait: number, headerPortal = false, resour
|
|
147
148
|
},
|
148
149
|
});
|
149
150
|
}, callbackWait);
|
151
|
+
} else {
|
152
|
+
setResource(null);
|
153
|
+
setIsLoading(false);
|
150
154
|
}
|
151
155
|
}, [unresolvedResource, setResource, setIsLoading]);
|
152
156
|
|
package/src/index.spec.tsx
CHANGED
@@ -154,7 +154,7 @@ describe('Resource browser input', () => {
|
|
154
154
|
});
|
155
155
|
});
|
156
156
|
|
157
|
-
it('onSourceSelect will set mode
|
157
|
+
it('onSourceSelect will set mode if provided', async () => {
|
158
158
|
const sourcesInput = [mockSource({ type: 'dam' }), mockSource()];
|
159
159
|
const calculatedSources = sourcesInput.map((source) => calculateExpectedSource(source));
|
160
160
|
mockRequestSources.mockResolvedValueOnce(sourcesInput);
|
@@ -214,6 +214,49 @@ describe('Resource browser input', () => {
|
|
214
214
|
});
|
215
215
|
});
|
216
216
|
|
217
|
+
it('Value will only be passed to ResourceBrowserInput if value source matches currently selected source', async () => {
|
218
|
+
const sourcesInput = [mockSource({ id: '1' }), mockSource({ id: '2' })];
|
219
|
+
const calculatedSources = sourcesInput.map((source) => calculateExpectedSource(source));
|
220
|
+
mockRequestSources.mockResolvedValueOnce(sourcesInput);
|
221
|
+
|
222
|
+
const value = { sourceId: sourcesInput[0].id, resourceId: '123456' };
|
223
|
+
|
224
|
+
renderComponent({ value });
|
225
|
+
|
226
|
+
await waitFor(() => {
|
227
|
+
expect(RBI.ResourceBrowserInput).toHaveBeenLastCalledWith(
|
228
|
+
expect.objectContaining({
|
229
|
+
value,
|
230
|
+
isOtherSourceValue: false,
|
231
|
+
source: calculatedSources[0],
|
232
|
+
}),
|
233
|
+
{},
|
234
|
+
);
|
235
|
+
});
|
236
|
+
|
237
|
+
const { onModalStateChange, setSource } = (RBI.ResourceBrowserInput as unknown as jest.SpyInstance).mock.calls[0][0];
|
238
|
+
// Invoke open the modal
|
239
|
+
act(() => {
|
240
|
+
onModalStateChange(true);
|
241
|
+
});
|
242
|
+
|
243
|
+
// Change the source
|
244
|
+
act(() => {
|
245
|
+
setSource(calculatedSources[1]);
|
246
|
+
});
|
247
|
+
|
248
|
+
await waitFor(() => {
|
249
|
+
expect(RBI.ResourceBrowserInput).toHaveBeenLastCalledWith(
|
250
|
+
expect.objectContaining({
|
251
|
+
value: null,
|
252
|
+
isOtherSourceValue: true,
|
253
|
+
source: calculatedSources[1],
|
254
|
+
}),
|
255
|
+
{},
|
256
|
+
);
|
257
|
+
});
|
258
|
+
});
|
259
|
+
|
217
260
|
it('onModalStateChange called with false will reset the Source and Plugin', async () => {
|
218
261
|
const sourcesInput = [mockSource({ type: 'dam' }), mockSource()];
|
219
262
|
const calculatedSources = sourcesInput.map((source) => calculateExpectedSource(source));
|
@@ -252,7 +295,13 @@ describe('Resource browser input', () => {
|
|
252
295
|
|
253
296
|
// Invoke modal close callback
|
254
297
|
const { onModalStateChange } = (RBI.ResourceBrowserInput as unknown as jest.SpyInstance).mock.calls[0][0];
|
255
|
-
|
298
|
+
// Invoke open and close the modal
|
299
|
+
act(() => {
|
300
|
+
onModalStateChange(true);
|
301
|
+
});
|
302
|
+
act(() => {
|
303
|
+
onModalStateChange(false);
|
304
|
+
});
|
256
305
|
|
257
306
|
// Expect no source or plugin
|
258
307
|
await waitFor(() => {
|
@@ -286,6 +335,9 @@ describe('Resource browser input', () => {
|
|
286
335
|
|
287
336
|
// Invoke modal close callback
|
288
337
|
const { onModalStateChange } = (RBI.ResourceBrowserInput as unknown as jest.SpyInstance).mock.calls[0][0];
|
338
|
+
act(() => {
|
339
|
+
onModalStateChange(true);
|
340
|
+
});
|
289
341
|
act(() => {
|
290
342
|
onModalStateChange(false);
|
291
343
|
});
|
@@ -339,7 +391,13 @@ describe('Resource browser input', () => {
|
|
339
391
|
|
340
392
|
// Invoke modal close callback
|
341
393
|
const { onModalStateChange } = (RBI.ResourceBrowserInput as unknown as jest.SpyInstance).mock.calls[0][0];
|
342
|
-
|
394
|
+
// Invoke open and close the modal
|
395
|
+
act(() => {
|
396
|
+
onModalStateChange(true);
|
397
|
+
});
|
398
|
+
act(() => {
|
399
|
+
onModalStateChange(false);
|
400
|
+
});
|
343
401
|
|
344
402
|
// Expect no source or plugin
|
345
403
|
await waitFor(() => {
|
@@ -355,8 +413,8 @@ describe('Resource browser input', () => {
|
|
355
413
|
});
|
356
414
|
});
|
357
415
|
|
358
|
-
it('onModalStateChange called with false will
|
359
|
-
const sourcesInput = [mockSource({
|
416
|
+
it('onModalStateChange called with false will reset the Source and Plugin to the value defaults if a value exists', async () => {
|
417
|
+
const sourcesInput = [mockSource({ id: '1' }), mockSource({ id: '2' })];
|
360
418
|
const calculatedSources = sourcesInput.map((source) => calculateExpectedSource(source));
|
361
419
|
mockRequestSources.mockResolvedValueOnce(sourcesInput);
|
362
420
|
|
@@ -373,8 +431,27 @@ describe('Resource browser input', () => {
|
|
373
431
|
);
|
374
432
|
});
|
375
433
|
|
376
|
-
|
377
|
-
|
434
|
+
const { onModalStateChange, setSource } = (RBI.ResourceBrowserInput as unknown as jest.SpyInstance).mock.calls[0][0];
|
435
|
+
// Invoke open and close the modal
|
436
|
+
act(() => {
|
437
|
+
onModalStateChange(true);
|
438
|
+
});
|
439
|
+
|
440
|
+
// Change the source
|
441
|
+
act(() => {
|
442
|
+
setSource(calculatedSources[1]);
|
443
|
+
});
|
444
|
+
|
445
|
+
await waitFor(() => {
|
446
|
+
expect(RBI.ResourceBrowserInput).toHaveBeenCalledWith(
|
447
|
+
expect.objectContaining({
|
448
|
+
source: calculatedSources[1],
|
449
|
+
plugin: mockDamPlugin,
|
450
|
+
}),
|
451
|
+
{},
|
452
|
+
);
|
453
|
+
});
|
454
|
+
|
378
455
|
act(() => {
|
379
456
|
onModalStateChange(false);
|
380
457
|
});
|
@@ -411,6 +488,9 @@ describe('Resource browser input', () => {
|
|
411
488
|
|
412
489
|
// Invoke modal close callback
|
413
490
|
const { onModalStateChange } = (RBI.ResourceBrowserInput as unknown as jest.SpyInstance).mock.calls[0][0];
|
491
|
+
act(() => {
|
492
|
+
onModalStateChange(true);
|
493
|
+
});
|
414
494
|
act(() => {
|
415
495
|
onModalStateChange(false);
|
416
496
|
});
|
package/src/index.tsx
CHANGED
@@ -103,11 +103,19 @@ export const ResourceBrowser = (props: ResourceBrowserProps) => {
|
|
103
103
|
|
104
104
|
// If the modal closes and we dont have a value clear the source state so it goes back to the launcher on re-open
|
105
105
|
useEffect(() => {
|
106
|
+
// If modal is closed and we dont have a value
|
106
107
|
if (!isModalOpen && !value && (sources?.length > 1 || searchEnabled)) {
|
107
108
|
setSource(null);
|
108
109
|
setMode(null);
|
109
110
|
} else if (!isModalOpen) {
|
111
|
+
// Otherwise reset the RB mode
|
110
112
|
setMode(null);
|
113
|
+
|
114
|
+
// If there is a value passed in, reset the source so the preselected asset preview renders correctly
|
115
|
+
if (value && value.sourceId !== source?.id) {
|
116
|
+
const source = sources.find((source) => source.id === value?.sourceId) || null;
|
117
|
+
setSource(source);
|
118
|
+
}
|
111
119
|
}
|
112
120
|
}, [sources, isModalOpen]);
|
113
121
|
|
@@ -129,6 +137,7 @@ export const ResourceBrowser = (props: ResourceBrowserProps) => {
|
|
129
137
|
sources={sources}
|
130
138
|
setSource={handleSourceSelect}
|
131
139
|
isLoading={isLoading}
|
140
|
+
isOtherSourceValue={false}
|
132
141
|
error={sourcesError || error}
|
133
142
|
plugin={plugin}
|
134
143
|
pluginMode={mode}
|
@@ -152,6 +161,8 @@ export const ResourceBrowser = (props: ResourceBrowserProps) => {
|
|
152
161
|
inline={!!inline}
|
153
162
|
inlineType={inlineType}
|
154
163
|
{...props}
|
164
|
+
value={value && source ? (value.sourceId === source.id ? value : null) : null} // Don't pass value if value isn't for selected source
|
165
|
+
isOtherSourceValue={value && source ? (value.sourceId !== source.id ? true : false) : false} // Block render of existing asset if not from this source
|
155
166
|
source={source}
|
156
167
|
sources={sources}
|
157
168
|
setSource={handleSourceSelect}
|