@squiz/resource-browser 2.4.12 → 3.0.0-pre-alpha.0
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/README.md +4 -0
- package/lib/BrowseToSource/BrowseToSource.d.ts +8 -0
- package/lib/BrowseToSource/BrowseToSource.js +50 -0
- package/lib/Hooks/useAuth.js +11 -15
- package/lib/Hooks/useSelectedState.js +3 -7
- package/lib/Hooks/useSources.d.ts +2 -2
- package/lib/Hooks/useSources.js +19 -9
- package/lib/Icons/AdsClickIcon.d.ts +4 -0
- package/lib/Icons/AdsClickIcon.js +5 -0
- package/lib/Icons/ArrowDownIcon.d.ts +4 -0
- package/lib/Icons/ArrowDownIcon.js +5 -0
- package/lib/Icons/CircledLoopIcon.js +4 -11
- package/lib/MainContainer/MainContainer.d.ts +6 -4
- package/lib/MainContainer/MainContainer.js +33 -52
- package/lib/Plugin/Plugin.js +7 -14
- package/lib/ResourceBrowserContext/AuthProvider.js +9 -37
- package/lib/ResourceBrowserContext/ResourceBrowserContext.d.ts +1 -0
- package/lib/ResourceBrowserContext/ResourceBrowserContext.js +10 -39
- package/lib/ResourceBrowserInput/ResourceBrowserInput.d.ts +6 -4
- package/lib/ResourceBrowserInput/ResourceBrowserInput.js +5 -12
- package/lib/ResourceLauncher/ResourceLauncher.d.ts +8 -0
- package/lib/ResourceLauncher/ResourceLauncher.js +11 -0
- package/lib/ResourcePicker/ResourcePicker.js +20 -27
- package/lib/ResourcePicker/States/Error.js +6 -13
- package/lib/ResourcePicker/States/Loading.js +4 -11
- package/lib/ResourcePicker/States/Selected.js +12 -19
- package/lib/SourceDropdown/SourceDropdown.d.ts +2 -2
- package/lib/SourceDropdown/SourceDropdown.js +22 -48
- package/lib/SourceDropdownContainer/SourceDropdownContainer.d.ts +5 -0
- package/lib/SourceDropdownContainer/SourceDropdownContainer.js +12 -0
- package/lib/SourceList/SourceList.js +11 -16
- package/lib/index.css +102 -26
- package/lib/index.d.ts +4 -1
- package/lib/index.js +40 -66
- package/lib/types.d.ts +35 -3
- package/lib/types.js +5 -2
- package/lib/utils/authUtils.js +9 -16
- package/lib-esm/BrowseToSource/BrowseToSource.d.ts +8 -0
- package/lib-esm/BrowseToSource/BrowseToSource.js +50 -0
- package/lib-esm/Hooks/useAuth.d.ts +7 -0
- package/lib-esm/Hooks/useAuth.js +54 -0
- package/lib-esm/Hooks/useSelectedState.d.ts +15 -0
- package/lib-esm/Hooks/useSelectedState.js +12 -0
- package/lib-esm/Hooks/useSources.d.ts +14 -0
- package/lib-esm/Hooks/useSources.js +44 -0
- package/lib-esm/Icons/AdsClickIcon.d.ts +4 -0
- package/lib-esm/Icons/AdsClickIcon.js +5 -0
- package/lib-esm/Icons/ArrowDownIcon.d.ts +4 -0
- package/lib-esm/Icons/ArrowDownIcon.js +5 -0
- package/lib-esm/Icons/CircledLoopIcon.d.ts +4 -0
- package/lib-esm/Icons/CircledLoopIcon.js +5 -0
- package/lib-esm/MainContainer/MainContainer.d.ts +19 -0
- package/lib-esm/MainContainer/MainContainer.js +43 -0
- package/lib-esm/Plugin/Plugin.d.ts +13 -0
- package/lib-esm/Plugin/Plugin.js +12 -0
- package/lib-esm/ResourceBrowserContext/AuthProvider.d.ts +16 -0
- package/lib-esm/ResourceBrowserContext/AuthProvider.js +18 -0
- package/lib-esm/ResourceBrowserContext/ResourceBrowserContext.d.ts +15 -0
- package/lib-esm/ResourceBrowserContext/ResourceBrowserContext.js +26 -0
- package/lib-esm/ResourceBrowserInput/ResourceBrowserInput.d.ts +26 -0
- package/lib-esm/ResourceBrowserInput/ResourceBrowserInput.js +9 -0
- package/lib-esm/ResourceLauncher/ResourceLauncher.d.ts +8 -0
- package/lib-esm/ResourceLauncher/ResourceLauncher.js +11 -0
- package/lib-esm/ResourcePicker/ResourcePicker.d.ts +16 -0
- package/lib-esm/ResourcePicker/ResourcePicker.js +25 -0
- package/lib-esm/ResourcePicker/States/Error.d.ts +7 -0
- package/lib-esm/ResourcePicker/States/Error.js +6 -0
- package/lib-esm/ResourcePicker/States/Loading.d.ts +2 -0
- package/lib-esm/ResourcePicker/States/Loading.js +4 -0
- package/lib-esm/ResourcePicker/States/Selected.d.ts +15 -0
- package/lib-esm/ResourcePicker/States/Selected.js +20 -0
- package/lib-esm/SourceDropdown/SourceDropdown.d.ts +7 -0
- package/lib-esm/SourceDropdown/SourceDropdown.js +46 -0
- package/lib-esm/SourceDropdownContainer/SourceDropdownContainer.d.ts +5 -0
- package/lib-esm/SourceDropdownContainer/SourceDropdownContainer.js +12 -0
- package/lib-esm/SourceList/SourceList.d.ts +8 -0
- package/lib-esm/SourceList/SourceList.js +16 -0
- package/lib-esm/index.d.ts +18 -0
- package/lib-esm/index.js +79 -0
- package/lib-esm/types.d.ts +97 -0
- package/lib-esm/types.js +5 -0
- package/lib-esm/utils/authUtils.d.ts +5 -0
- package/lib-esm/utils/authUtils.js +31 -0
- package/package.json +18 -6
- package/src/BrowseToSource/BrowseToSource.spec.tsx +111 -0
- package/src/BrowseToSource/BrowseToSource.stories.tsx +29 -0
- package/src/BrowseToSource/BrowseToSource.tsx +111 -0
- package/src/Hooks/useSources.spec.ts +8 -4
- package/src/Hooks/useSources.ts +28 -13
- package/src/Icons/AdsClickIcon.tsx +11 -0
- package/src/Icons/ArrowDownIcon.tsx +11 -0
- package/src/MainContainer/MainContainer.spec.tsx +322 -108
- package/src/MainContainer/MainContainer.tsx +67 -27
- package/src/Plugin/Plugin.spec.tsx +2 -0
- package/src/ResourceBrowserContext/ResourceBrowserContext.spec.tsx +3 -0
- package/src/ResourceBrowserContext/ResourceBrowserContext.tsx +2 -0
- package/src/ResourceBrowserInput/ResourceBrowserInput.spec.tsx +7 -0
- package/src/ResourceBrowserInput/ResourceBrowserInput.tsx +16 -3
- package/src/ResourceLauncher/ResourceLauncher.spec.tsx +65 -0
- package/src/ResourceLauncher/ResourceLauncher.tsx +31 -0
- package/src/SourceDropdown/SourceDropdown.stories.tsx +1 -2
- package/src/SourceDropdown/SourceDropdown.tsx +8 -8
- package/src/SourceDropdownContainer/SourceDropdownContainer.spec.tsx +50 -0
- package/src/SourceDropdownContainer/SourceDropdownContainer.stories.tsx +62 -0
- package/src/SourceDropdownContainer/SourceDropdownContainer.tsx +27 -0
- package/src/__mocks__/MockModels.ts +16 -2
- package/src/__mocks__/PluginExample.tsx +8 -0
- package/src/__mocks__/StorybookHelpers.tsx +37 -1
- package/src/__mocks__/renderWithContext.tsx +1 -0
- package/src/index.spec.tsx +135 -41
- package/src/index.stories.tsx +12 -1
- package/src/index.tsx +45 -16
- package/src/types.ts +43 -3
- package/.eslintrc +0 -40
- package/.storybook/main.ts +0 -23
- package/.storybook/preview-body.html +0 -1
- package/.storybook/preview-head.html +0 -12
- package/.storybook/preview.ts +0 -16
- package/CHANGELOG.md +0 -244
- package/LICENSE.md +0 -15
- package/build.js +0 -21
- package/jest.config.ts +0 -30
- package/postcss.config.js +0 -21
- package/tailwind.config.cjs +0 -98
- package/tsconfig.json +0 -22
- package/tsconfig.storybook.json +0 -4
- package/tsconfig.test.json +0 -12
- package/vite.config.js +0 -20
package/lib/index.js
CHANGED
@@ -1,57 +1,29 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
|
26
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
27
|
-
};
|
28
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
29
|
-
exports.ResourceBrowser = exports.AuthContext = exports.AuthProvider = exports.useAuthContext = exports.ResourceBrowserContextProvider = exports.ResourceBrowserContext = void 0;
|
30
|
-
const react_1 = __importStar(require("react"));
|
31
|
-
const ResourceBrowserContext_1 = require("./ResourceBrowserContext/ResourceBrowserContext");
|
32
|
-
Object.defineProperty(exports, "ResourceBrowserContext", { enumerable: true, get: function () { return ResourceBrowserContext_1.ResourceBrowserContext; } });
|
33
|
-
Object.defineProperty(exports, "ResourceBrowserContextProvider", { enumerable: true, get: function () { return ResourceBrowserContext_1.ResourceBrowserContextProvider; } });
|
34
|
-
const useSources_1 = require("./Hooks/useSources");
|
35
|
-
const Plugin_1 = require("./Plugin/Plugin");
|
36
|
-
const AuthProvider_1 = require("./ResourceBrowserContext/AuthProvider");
|
37
|
-
Object.defineProperty(exports, "AuthProvider", { enumerable: true, get: function () { return AuthProvider_1.AuthProvider; } });
|
38
|
-
Object.defineProperty(exports, "useAuthContext", { enumerable: true, get: function () { return AuthProvider_1.useAuthContext; } });
|
39
|
-
Object.defineProperty(exports, "AuthContext", { enumerable: true, get: function () { return AuthProvider_1.AuthContext; } });
|
40
|
-
__exportStar(require("./types"), exports);
|
41
|
-
const ResourceBrowser = (props) => {
|
1
|
+
import React, { useState, useContext, useEffect, useCallback } from 'react';
|
2
|
+
import { ResourceBrowserContext, ResourceBrowserContextProvider } from './ResourceBrowserContext/ResourceBrowserContext';
|
3
|
+
import { useSources } from './Hooks/useSources';
|
4
|
+
import { PluginRender } from './Plugin/Plugin';
|
5
|
+
import { AuthProvider, useAuthContext, AuthContext } from './ResourceBrowserContext/AuthProvider';
|
6
|
+
import BrowseToSource from './BrowseToSource/BrowseToSource';
|
7
|
+
import SourceDropdown from './SourceDropdown/SourceDropdown';
|
8
|
+
import SourceDropdownContainer from './SourceDropdownContainer/SourceDropdownContainer';
|
9
|
+
export { ResourceBrowserContext, ResourceBrowserContextProvider, useAuthContext, AuthProvider, AuthContext, BrowseToSource, SourceDropdown, SourceDropdownContainer, };
|
10
|
+
export * from './types';
|
11
|
+
export const ResourceBrowser = (props) => {
|
42
12
|
const { value } = props;
|
43
|
-
const [error, setError] =
|
44
|
-
const { onRequestSources, plugins } =
|
45
|
-
const [isModalOpen, setIsModalOpen] =
|
46
|
-
const [source, setSource] =
|
47
|
-
const
|
48
|
-
const
|
13
|
+
const [error, setError] = useState(null);
|
14
|
+
const { onRequestSources, searchEnabled, plugins } = useContext(ResourceBrowserContext);
|
15
|
+
const [isModalOpen, setIsModalOpen] = useState(false);
|
16
|
+
const [source, setSource] = useState(null);
|
17
|
+
const [mode, setMode] = useState(null);
|
18
|
+
const { data: sources, isLoading, error: sourcesError } = useSources({ onRequestSources, plugins });
|
19
|
+
const [plugin, setPlugin] = useState(null);
|
49
20
|
// MainContainer will render a list of sources of one is not provided to it, callback to allow it to set the source once a user selects
|
50
|
-
const handleSourceSelect =
|
21
|
+
const handleSourceSelect = useCallback((source, mode) => {
|
51
22
|
setSource(source);
|
52
|
-
|
53
|
-
|
54
|
-
|
23
|
+
setMode(mode || null);
|
24
|
+
}, [setSource, setMode]);
|
25
|
+
// If an existing resource is passed in auto select its source
|
26
|
+
useEffect(() => {
|
55
27
|
let source = null;
|
56
28
|
setError(null);
|
57
29
|
// If there is a provided value try to use its source
|
@@ -64,34 +36,37 @@ const ResourceBrowser = (props) => {
|
|
64
36
|
setError(new Error('Unable to find resource source.'));
|
65
37
|
}
|
66
38
|
}
|
67
|
-
else if (sources?.length === 1) {
|
68
|
-
// If only one source is passed
|
39
|
+
else if (sources?.length === 1 && !searchEnabled) {
|
40
|
+
// If only one source is passed and search is not enabled select it automatically
|
69
41
|
source = sources[0];
|
70
42
|
}
|
71
43
|
setSource(source);
|
44
|
+
setMode(null); // Passed in resource will always use the default mode
|
72
45
|
}, [value, isLoading, sources, setSource, setError]);
|
73
|
-
(
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
setPlugin(plugin || null);
|
46
|
+
// When a source is selected update our plugin reference to match (legacy support)
|
47
|
+
// the plugin is now attached to the source directly when fetched from the context so use that instead when possible
|
48
|
+
useEffect(() => {
|
49
|
+
if (source?.plugin) {
|
50
|
+
setPlugin(source.plugin);
|
79
51
|
}
|
80
52
|
else {
|
81
53
|
setPlugin(null);
|
82
54
|
}
|
83
55
|
}, [plugins, source]);
|
84
|
-
|
56
|
+
// The modal has some control over it own open/closed state (for WCAG reasons) so keep this in sync with our state
|
57
|
+
const handleModalStateChange = useCallback((isOpen) => {
|
85
58
|
setIsModalOpen(isOpen);
|
86
59
|
}, [setIsModalOpen]);
|
87
|
-
|
88
|
-
|
60
|
+
// If the modal closes and we dont have a value clear the source state so it goes back to the launcher on re-open
|
61
|
+
useEffect(() => {
|
62
|
+
if (!isModalOpen && !value && (sources?.length > 1 || searchEnabled)) {
|
89
63
|
setSource(null);
|
64
|
+
setMode(null);
|
90
65
|
}
|
91
66
|
}, [sources, isModalOpen]);
|
92
67
|
// Render a default "plugin" and one for each item in the plugins array. They are conditionally rendered based on what is selected
|
93
|
-
return (
|
94
|
-
|
68
|
+
return (React.createElement("div", { className: "squiz-rb-scope" },
|
69
|
+
React.createElement(PluginRender, { key: "default", render: plugin === null, ...props, source: source, sources: sources, setSource: handleSourceSelect, isLoading: isLoading, error: sourcesError || error, plugin: plugin, pluginMode: mode, searchEnabled: searchEnabled, useResource: () => {
|
95
70
|
return {
|
96
71
|
data: null,
|
97
72
|
error: null,
|
@@ -99,7 +74,6 @@ const ResourceBrowser = (props) => {
|
|
99
74
|
};
|
100
75
|
}, isModalOpen: isModalOpen, onModalStateChange: handleModalStateChange }),
|
101
76
|
plugins.map((thisPlugin) => {
|
102
|
-
return (
|
77
|
+
return (React.createElement(PluginRender, { key: thisPlugin.type, render: thisPlugin === plugin, ...props, source: source, sources: sources, setSource: handleSourceSelect, isLoading: isLoading, error: error, plugin: plugin, pluginMode: mode, searchEnabled: searchEnabled, useResource: thisPlugin.useResolveResource, isModalOpen: isModalOpen, onModalStateChange: handleModalStateChange }));
|
103
78
|
})));
|
104
79
|
};
|
105
|
-
exports.ResourceBrowser = ResourceBrowser;
|
package/lib/types.d.ts
CHANGED
@@ -13,9 +13,20 @@ export interface ResourceBrowserSource {
|
|
13
13
|
id: string;
|
14
14
|
type: ResourceBrowserPluginType;
|
15
15
|
}
|
16
|
+
export interface ResourceBrowserSourceWithPlugin extends ResourceBrowserSource {
|
17
|
+
plugin: ResourceBrowserPlugin;
|
18
|
+
}
|
16
19
|
export interface ResourceBrowserSourceWithConfig extends ResourceBrowserSource {
|
17
20
|
configuration?: AuthenticationConfiguration;
|
18
21
|
}
|
22
|
+
export declare enum PluginLaunchModeType {
|
23
|
+
'Browse' = "browse",
|
24
|
+
'Search' = "search"
|
25
|
+
}
|
26
|
+
export type PluginLaunchMode = {
|
27
|
+
type: PluginLaunchModeType;
|
28
|
+
args?: ResourceBrowserSearchUIArgs | ResourceBrowserUIArgs;
|
29
|
+
};
|
19
30
|
export type ResourceBrowserUnresolvedResource = {
|
20
31
|
sourceId: string;
|
21
32
|
resourceId: string;
|
@@ -37,12 +48,28 @@ export type ResourceBrowserSelectedState = {
|
|
37
48
|
label: string;
|
38
49
|
description: Array<ReactElement>;
|
39
50
|
};
|
40
|
-
|
51
|
+
type ResourceBrowserProps = {
|
41
52
|
source: ResourceBrowserSource;
|
53
|
+
onSourceSelect(source: ResourceBrowserSource, mode?: PluginLaunchMode): void;
|
54
|
+
sources: ResourceBrowserSourceWithPlugin[];
|
42
55
|
allowedTypes?: string[];
|
43
56
|
headerPortal?: Element;
|
44
|
-
preselectedResource?: ResourceBrowserResource;
|
45
57
|
onSelected: (resource: ResourceBrowserResource) => void;
|
58
|
+
searchEnabled: boolean;
|
59
|
+
};
|
60
|
+
export type ResourceBrowserUIArgs = {
|
61
|
+
preselectedResource?: ResourceBrowserResource;
|
62
|
+
browseTo?: ResourceBrowserUnresolvedResource;
|
63
|
+
};
|
64
|
+
export type ResourceBrowserUIProps = ResourceBrowserProps & ResourceBrowserUIArgs;
|
65
|
+
export type ResourceBrowserSearchUIArgs = {
|
66
|
+
query?: string;
|
67
|
+
};
|
68
|
+
export type ResourceBrowserSearchUIProps = ResourceBrowserProps & ResourceBrowserSearchUIArgs;
|
69
|
+
export type ResourceBrowserLauncherProps = {
|
70
|
+
source: ResourceBrowserSource;
|
71
|
+
onSearch: (query: string) => void;
|
72
|
+
onBrowse: (browseTo?: ResourceBrowserUnresolvedResource) => void;
|
46
73
|
};
|
47
74
|
export type useResolveResourceResponse = {
|
48
75
|
data: ResourceBrowserResource | null;
|
@@ -56,10 +83,15 @@ export interface ResourceBrowserPlugin {
|
|
56
83
|
/** Datasource type this plugin should be used for */
|
57
84
|
type: ResourceBrowserPluginType;
|
58
85
|
createHeaderPortal?: boolean;
|
59
|
-
/** React Functional Component to provde the UI to render to allow a user to
|
86
|
+
/** React Functional Component to provde the UI to render to allow a user to browse for resource to use */
|
60
87
|
sourceBrowserComponent: () => React.FunctionComponent<ResourceBrowserUIProps>;
|
88
|
+
/** React Functional Component to provde the UI to render to allow a user to search for resource to use */
|
89
|
+
sourceSearchComponent: () => React.FunctionComponent<ResourceBrowserSearchUIProps>;
|
90
|
+
/** React Functional Component to provde the sources launcher view */
|
91
|
+
renderResourceLauncher: () => React.FunctionComponent<ResourceBrowserLauncherProps>;
|
61
92
|
/** Function to provde the the summary information to show what resource is currently selected */
|
62
93
|
renderSelectedResource: (resource: ResourceBrowserResource) => Promise<ResourceBrowserSelectedState>;
|
63
94
|
/** Function to resolve a resource and source id into a fully resolved output reference */
|
64
95
|
useResolveResource: (resourceId: string | null, source: ResourceBrowserSource | null) => useResolveResourceResponse;
|
65
96
|
}
|
97
|
+
export {};
|
package/lib/types.js
CHANGED
@@ -1,2 +1,5 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
export var PluginLaunchModeType;
|
2
|
+
(function (PluginLaunchModeType) {
|
3
|
+
PluginLaunchModeType["Browse"] = "browse";
|
4
|
+
PluginLaunchModeType["Search"] = "search";
|
5
|
+
})(PluginLaunchModeType || (PluginLaunchModeType = {}));
|
package/lib/utils/authUtils.js
CHANGED
@@ -1,25 +1,19 @@
|
|
1
|
-
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.refreshAccessToken = exports.logout = exports.setCookieValue = exports.getCookieValue = void 0;
|
4
|
-
const getCookieValue = (name) => {
|
1
|
+
export const getCookieValue = (name) => {
|
5
2
|
const match = document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]+)');
|
6
3
|
return match ? match.pop() : null;
|
7
4
|
};
|
8
|
-
|
9
|
-
const setCookieValue = (name, value) => {
|
5
|
+
export const setCookieValue = (name, value) => {
|
10
6
|
document.cookie = `${name}=${value}; Path=/;`;
|
11
7
|
};
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
(0, exports.setCookieValue)('refreshToken', '');
|
8
|
+
export const logout = () => {
|
9
|
+
setCookieValue('authToken', '');
|
10
|
+
setCookieValue('refreshToken', '');
|
16
11
|
};
|
17
|
-
|
18
|
-
const refreshAccessToken = async (authConfig) => {
|
12
|
+
export const refreshAccessToken = async (authConfig) => {
|
19
13
|
if (!authConfig) {
|
20
14
|
throw new Error('No auth configuration available');
|
21
15
|
}
|
22
|
-
const refreshToken =
|
16
|
+
const refreshToken = getCookieValue('refreshToken');
|
23
17
|
if (!refreshToken) {
|
24
18
|
throw new Error('You are not logged in');
|
25
19
|
}
|
@@ -28,11 +22,10 @@ const refreshAccessToken = async (authConfig) => {
|
|
28
22
|
credentials: 'include',
|
29
23
|
});
|
30
24
|
if (!response.ok) {
|
31
|
-
|
25
|
+
logout();
|
32
26
|
throw new Error('Failed to refresh token');
|
33
27
|
}
|
34
28
|
const data = await response.json();
|
35
|
-
|
29
|
+
setCookieValue('authToken', data.access_token);
|
36
30
|
return data.access_token;
|
37
31
|
};
|
38
|
-
exports.refreshAccessToken = refreshAccessToken;
|
@@ -0,0 +1,8 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { ResourceBrowserSource, PluginLaunchMode } from '../types';
|
3
|
+
export default function BrowseToSource({ sources, selectedSource, onSourceSelect, className, }: {
|
4
|
+
sources: ResourceBrowserSource[];
|
5
|
+
selectedSource: ResourceBrowserSource;
|
6
|
+
onSourceSelect(source: ResourceBrowserSource, mode?: PluginLaunchMode): void;
|
7
|
+
className?: string;
|
8
|
+
}): React.JSX.Element;
|
@@ -0,0 +1,50 @@
|
|
1
|
+
import React, { useRef, useState } from 'react';
|
2
|
+
import { Icon, uuid } from '@squiz/generic-browser-lib';
|
3
|
+
import { useFocusWithin, useKeyboard } from 'react-aria';
|
4
|
+
import { AdsClickIcon } from '../Icons/AdsClickIcon';
|
5
|
+
import { ArrowDownIcon } from '../Icons/ArrowDownIcon';
|
6
|
+
export default function BrowseToSource({ sources, selectedSource, onSourceSelect, className = '', }) {
|
7
|
+
const [uniqueId] = useState(uuid());
|
8
|
+
const buttonRef = useRef(null);
|
9
|
+
const [isOpen, setIsOpen] = useState(false);
|
10
|
+
// Watch the focus and blur on the menu and close if focus leaves the control
|
11
|
+
const { focusWithinProps } = useFocusWithin({
|
12
|
+
onBlurWithin: () => {
|
13
|
+
setIsOpen(false);
|
14
|
+
},
|
15
|
+
});
|
16
|
+
// Listen for Esc key within this element
|
17
|
+
const { keyboardProps } = useKeyboard({
|
18
|
+
onKeyDown: (e) => {
|
19
|
+
if (isOpen && e.key === 'Escape') {
|
20
|
+
setIsOpen(false);
|
21
|
+
buttonRef.current?.focus(); // Restore focus to the element which opened the menu
|
22
|
+
}
|
23
|
+
},
|
24
|
+
});
|
25
|
+
const handleSourceClick = (source) => {
|
26
|
+
setIsOpen(false);
|
27
|
+
buttonRef.current?.focus();
|
28
|
+
onSourceSelect(source);
|
29
|
+
};
|
30
|
+
if (!sources.length) {
|
31
|
+
return React.createElement(React.Fragment, null);
|
32
|
+
}
|
33
|
+
return (React.createElement("div", { className: `inline-block ${isOpen ? 'flex items-center border-2 border-gray-200 rounded-lg px-1 py-0.5 w-[350px]' : 'p-0'} ${className}` },
|
34
|
+
isOpen && React.createElement(AdsClickIcon, { "aria-hidden": true, className: "ml-1 mr-2 shrink-0" }),
|
35
|
+
sources.length > 1 && (React.createElement("div", { ...focusWithinProps, ...keyboardProps, className: `relative w-full ${isOpen && 'border-l border-gray-400 pl-1 '}` },
|
36
|
+
React.createElement("button", { ref: buttonRef, type: "button", "aria-label": "Source quick select", "aria-expanded": isOpen, "aria-controls": `${uniqueId}-button-menu`, onClick: () => setIsOpen(!isOpen), className: `relative flex items-center p-2 w-full rounded-lg ${!isOpen && 'border-2 border-gray-200 hover:bg-gray-100'}` }, isOpen ? (React.createElement(React.Fragment, null,
|
37
|
+
React.createElement("span", { className: "text-gray-700 text-md leading-5 mr-2" }, "Browse to ..."),
|
38
|
+
React.createElement(ArrowDownIcon, { "aria-hidden": true, className: "absolute right-3" }))) : (React.createElement(React.Fragment, null,
|
39
|
+
React.createElement(AdsClickIcon, { "aria-hidden": true, className: "ml-[6px] mr-2" }),
|
40
|
+
React.createElement("span", { className: "text-gray-700 text-md font-semibold leading-5 mr-[6px]" }, "Browse")))),
|
41
|
+
React.createElement("ul", { id: `${uniqueId}-button-menu`, "aria-hidden": !isOpen, className: `absolute z-50 top-[calc(100%+8px)] left-1 w-[calc(100%-2px)] bg-gray-100 border-1 shadow-md rounded border-gray-300 p-2 pb-0 overflow-y-auto max-h-80 ${!isOpen ? 'hidden' : ''}` }, sources.map((source) => {
|
42
|
+
const { id, name, type } = source;
|
43
|
+
const isSelectedSource = id === selectedSource.id;
|
44
|
+
return (React.createElement("li", { key: id, className: "flex items-center text-sm font-semibold mb-2 bg-white rounded" },
|
45
|
+
React.createElement("button", { type: "button", onClick: () => handleSourceClick(source), className: `relative grow flex items-center p-2 border-1 border-white rounded hover:bg-gray-50 hover:border-gray-300 focus:bg-gray-100` },
|
46
|
+
React.createElement(Icon, { icon: type, "aria-label": type, className: "shrink-0 mr-2.5" }),
|
47
|
+
React.createElement("span", { className: "text-left mr-7" }, name),
|
48
|
+
isSelectedSource && (React.createElement(Icon, { icon: 'selected', "aria-label": "selected", className: "absolute right-4" })))));
|
49
|
+
}))))));
|
50
|
+
}
|
@@ -0,0 +1,7 @@
|
|
1
|
+
import { AuthenticationConfiguration } from '../types';
|
2
|
+
export declare const useAuth: (authConfig: AuthenticationConfiguration | undefined) => {
|
3
|
+
authToken: string | null;
|
4
|
+
isAuthenticated: boolean;
|
5
|
+
login: () => void;
|
6
|
+
refreshAccessToken: () => Promise<string>;
|
7
|
+
};
|
@@ -0,0 +1,54 @@
|
|
1
|
+
/* eslint-disable no-console */
|
2
|
+
import { useState, useCallback, useEffect } from 'react';
|
3
|
+
import { getCookieValue, refreshAccessToken as refreshTokenUtil } from '../utils/authUtils';
|
4
|
+
export const useAuth = (authConfig) => {
|
5
|
+
const [authToken, setAuthToken] = useState(getCookieValue('authToken'));
|
6
|
+
const [isAuthenticated, setIsAuthenticated] = useState(!!getCookieValue('authToken'));
|
7
|
+
const refreshAccessToken = useCallback(async () => {
|
8
|
+
const newToken = await refreshTokenUtil(authConfig);
|
9
|
+
setAuthToken(newToken);
|
10
|
+
setIsAuthenticated(!!newToken);
|
11
|
+
return newToken;
|
12
|
+
}, [authConfig]);
|
13
|
+
const handleLogin = useCallback(() => {
|
14
|
+
if (!authConfig?.redirectUrl && !authConfig?.authUrl && !authConfig?.scope) {
|
15
|
+
console.error('Auth config is misconfigured');
|
16
|
+
return;
|
17
|
+
}
|
18
|
+
const encodedRedirectUrl = encodeURIComponent(authConfig.redirectUrl);
|
19
|
+
const loginUrl = `${authConfig?.authUrl}?client_id=${authConfig?.clientId}&scope=${authConfig?.scope}&redirect_uri=${encodedRedirectUrl}&response_type=code&state=state`;
|
20
|
+
const popup = window.open(loginUrl, 'Login', 'width=600,height=600');
|
21
|
+
if (!popup) {
|
22
|
+
console.error('Popup failed to open');
|
23
|
+
return;
|
24
|
+
}
|
25
|
+
const checkPopup = setInterval(() => {
|
26
|
+
try {
|
27
|
+
if (getCookieValue('authToken') && getCookieValue('refreshToken')) {
|
28
|
+
clearInterval(checkPopup);
|
29
|
+
popup.close();
|
30
|
+
setAuthToken(getCookieValue('authToken'));
|
31
|
+
setIsAuthenticated(true);
|
32
|
+
}
|
33
|
+
}
|
34
|
+
catch (error) {
|
35
|
+
// Ignore cross-origin access errors
|
36
|
+
}
|
37
|
+
if (popup.closed) {
|
38
|
+
clearInterval(checkPopup);
|
39
|
+
console.error('Popup closed before authentication');
|
40
|
+
}
|
41
|
+
}, 1000); // Check every second
|
42
|
+
}, [authConfig]);
|
43
|
+
useEffect(() => {
|
44
|
+
refreshAccessToken().catch(() => {
|
45
|
+
setIsAuthenticated(false);
|
46
|
+
});
|
47
|
+
}, [authConfig, refreshAccessToken]);
|
48
|
+
return {
|
49
|
+
authToken,
|
50
|
+
isAuthenticated,
|
51
|
+
login: handleLogin,
|
52
|
+
refreshAccessToken,
|
53
|
+
};
|
54
|
+
};
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import { ResourceBrowserPlugin, ResourceBrowserResource } from '../types';
|
2
|
+
type UseResourceProps = {
|
3
|
+
plugin: ResourceBrowserPlugin | null;
|
4
|
+
resource: ResourceBrowserResource | null;
|
5
|
+
};
|
6
|
+
/**
|
7
|
+
* Loads the selected state for the provided resource
|
8
|
+
*/
|
9
|
+
export declare const useSelectedState: ({ plugin, resource }: UseResourceProps) => {
|
10
|
+
data: import("../types").ResourceBrowserSelectedState | null;
|
11
|
+
error: Error | null;
|
12
|
+
isLoading: boolean;
|
13
|
+
reload: () => void;
|
14
|
+
};
|
15
|
+
export {};
|
@@ -0,0 +1,12 @@
|
|
1
|
+
import { useAsync } from '@squiz/generic-browser-lib';
|
2
|
+
/**
|
3
|
+
* Loads the selected state for the provided resource
|
4
|
+
*/
|
5
|
+
export const useSelectedState = ({ plugin, resource }) => {
|
6
|
+
// Find the resolver for this resource
|
7
|
+
const renderSelectedResource = resource && plugin?.renderSelectedResource;
|
8
|
+
return useAsync({
|
9
|
+
callback: () => (resource && renderSelectedResource ? renderSelectedResource(resource) : null),
|
10
|
+
defaultValue: null,
|
11
|
+
}, [resource]);
|
12
|
+
};
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import { ResourceBrowserSource, ResourceBrowserPlugin, ResourceBrowserSourceWithPlugin } from '../types';
|
2
|
+
export type UseSourcesProps = {
|
3
|
+
onRequestSources: () => Promise<ResourceBrowserSource[]>;
|
4
|
+
plugins: Array<ResourceBrowserPlugin>;
|
5
|
+
};
|
6
|
+
/**
|
7
|
+
* Loads and caches the source list when a component using the hook is mounted.
|
8
|
+
*/
|
9
|
+
export declare const useSources: ({ onRequestSources, plugins }: UseSourcesProps) => {
|
10
|
+
data: ResourceBrowserSourceWithPlugin[];
|
11
|
+
error: Error | null;
|
12
|
+
isLoading: boolean;
|
13
|
+
reload: () => void;
|
14
|
+
};
|
@@ -0,0 +1,44 @@
|
|
1
|
+
import { useAsync } from '@squiz/generic-browser-lib';
|
2
|
+
/**
|
3
|
+
* Loads and caches the source list when a component using the hook is mounted.
|
4
|
+
*/
|
5
|
+
export const useSources = ({ onRequestSources, plugins }) => {
|
6
|
+
const pluginsKey = plugins.reduce((acc, plugin) => acc + plugin.type, '');
|
7
|
+
return useAsync({
|
8
|
+
callback: () => {
|
9
|
+
return new Promise((resolve, reject) => {
|
10
|
+
// Get all the sources from the outer context
|
11
|
+
onRequestSources()
|
12
|
+
.then((sources) => {
|
13
|
+
// Remove any sources which we don't have a plugin to handle
|
14
|
+
const filteredSources = sources.filter((source) => {
|
15
|
+
return !!plugins.find((plugin) => {
|
16
|
+
if (plugin.type === source.type) {
|
17
|
+
return true;
|
18
|
+
}
|
19
|
+
return false;
|
20
|
+
});
|
21
|
+
});
|
22
|
+
// Attach the plugin to the source so it can be quickly used later
|
23
|
+
const combinedSources = filteredSources.map((source) => {
|
24
|
+
const plugin = plugins.find((plugin) => {
|
25
|
+
if (plugin.type === source.type) {
|
26
|
+
return true;
|
27
|
+
}
|
28
|
+
return false;
|
29
|
+
});
|
30
|
+
return {
|
31
|
+
...source,
|
32
|
+
plugin,
|
33
|
+
};
|
34
|
+
});
|
35
|
+
resolve(combinedSources);
|
36
|
+
})
|
37
|
+
.catch((e) => {
|
38
|
+
reject(e);
|
39
|
+
});
|
40
|
+
});
|
41
|
+
},
|
42
|
+
defaultValue: [],
|
43
|
+
}, [onRequestSources, pluginsKey]);
|
44
|
+
};
|
@@ -0,0 +1,5 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
export const AdsClickIcon = (props) => {
|
3
|
+
return (React.createElement("svg", { fill: "#4f4f4f", height: "24", width: "24", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg", ...props },
|
4
|
+
React.createElement("path", { d: "M11.56 17.845C8.38001 17.695 5.85001 15.075 5.85001 11.855C5.85001 8.54501 8.54001 5.85501 11.85 5.85501C15.07 5.85501 17.69 8.38501 17.84 11.565L15.74 10.935C15.33 9.16501 13.74 7.85501 11.85 7.85501C9.64001 7.85501 7.85001 9.64501 7.85001 11.855C7.85001 13.745 9.16001 15.335 10.93 15.745L11.56 17.845ZM21.85 11.855C21.85 12.155 21.84 12.455 21.81 12.755L19.84 12.165C19.85 12.065 19.85 11.955 19.85 11.855C19.85 7.43501 16.27 3.85501 11.85 3.85501C7.43001 3.85501 3.85001 7.43501 3.85001 11.855C3.85001 16.275 7.43001 19.855 11.85 19.855C11.95 19.855 12.06 19.855 12.16 19.845L12.75 21.815C12.45 21.845 12.15 21.855 11.85 21.855C6.33001 21.855 1.85001 17.375 1.85001 11.855C1.85001 6.33501 6.33001 1.85501 11.85 1.85501C17.37 1.85501 21.85 6.33501 21.85 11.855ZM18.08 16.115L20.35 15.355C20.81 15.205 20.8 14.545 20.34 14.405L12.74 12.125C12.36 12.015 12 12.365 12.12 12.745L14.4 20.345C14.54 20.815 15.2 20.825 15.35 20.355L16.11 18.085L20.02 21.995C20.22 22.195 20.53 22.195 20.73 21.995L22 20.725C22.2 20.525 22.2 20.215 22 20.015L18.08 16.115Z" })));
|
5
|
+
};
|
@@ -0,0 +1,5 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
export const ArrowDownIcon = (props) => {
|
3
|
+
return (React.createElement("svg", { fill: "#4f4f4f", height: "25", width: "24", viewBox: "0 0 24 25", xmlns: "http://www.w3.org/2000/svg", ...props },
|
4
|
+
React.createElement("path", { d: "M8.12459 9.49953L12.0046 13.3795L15.8846 9.49953C16.2746 9.10953 16.9046 9.10953 17.2946 9.49953C17.6846 9.88953 17.6846 10.5195 17.2946 10.9095L12.7046 15.4995C12.3146 15.8895 11.6846 15.8895 11.2946 15.4995L6.70459 10.9095C6.51734 10.7227 6.41211 10.469 6.41211 10.2045C6.41211 9.94001 6.51734 9.68636 6.70459 9.49953C7.09459 9.11953 7.73459 9.10953 8.12459 9.49953Z" })));
|
5
|
+
};
|
@@ -0,0 +1,5 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
export const CircledLoopIcon = (props) => {
|
3
|
+
return (React.createElement("svg", { fill: "none", height: "16", viewBox: "0 0 16 16", width: "16", xmlns: "http://www.w3.org/2000/svg", ...props },
|
4
|
+
React.createElement("path", { d: "M8 0.5C3.86 0.5 0.5 3.86 0.5 8C0.5 12.14 3.86 15.5 8 15.5C12.14 15.5 15.5 12.14 15.5 8C15.5 3.86 12.14 0.5 8 0.5ZM8 14C4.6925 14 2 11.3075 2 8C2 4.6925 4.6925 2 8 2C11.3075 2 14 4.6925 14 8C14 11.3075 11.3075 14 8 14ZM11.1275 10.07L10.3025 9.245C10.835 8.2475 10.7 6.9875 9.86 6.1475C9.3425 5.63 8.675 5.375 8 5.375C7.9775 5.375 7.955 5.3825 7.9325 5.3825L8.75 6.2L7.955 6.995L5.8325 4.8725L7.955 2.75L8.75 3.545L8.03 4.265C8.9825 4.2725 9.9275 4.625 10.655 5.345C11.93 6.6275 12.0875 8.615 11.1275 10.07ZM10.1675 11.1275L8.045 13.25L7.25 12.455L7.9625 11.7425C7.0175 11.735 6.0725 11.3675 5.3525 10.6475C4.07 9.365 3.9125 7.385 4.8725 5.93L5.6975 6.755C5.165 7.7525 5.3 9.0125 6.14 9.8525C6.665 10.3775 7.3625 10.6325 8.06 10.61L7.25 9.8L8.045 9.005L10.1675 11.1275Z", fill: "#949494" })));
|
5
|
+
};
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { DOMAttributes, FocusableElement } from '@react-types/shared';
|
3
|
+
import { ResourceBrowserPlugin, ResourceBrowserSource, ResourceBrowserResource, ResourceBrowserSourceWithPlugin, PluginLaunchMode } from '../types';
|
4
|
+
interface MainContainerProps {
|
5
|
+
title: string;
|
6
|
+
titleAriaProps: DOMAttributes<FocusableElement>;
|
7
|
+
allowedTypes: string[] | undefined;
|
8
|
+
sources: ResourceBrowserSourceWithPlugin[];
|
9
|
+
selectedSource: ResourceBrowserSource | null;
|
10
|
+
onSourceSelect(source: ResourceBrowserSource, mode?: PluginLaunchMode): void;
|
11
|
+
onChange(resource: ResourceBrowserResource | null): void;
|
12
|
+
onClose: () => void;
|
13
|
+
preselectedResource?: ResourceBrowserResource | null;
|
14
|
+
plugin: ResourceBrowserPlugin | null;
|
15
|
+
pluginMode: PluginLaunchMode | null;
|
16
|
+
searchEnabled: boolean;
|
17
|
+
}
|
18
|
+
declare function MainContainer({ title, titleAriaProps, allowedTypes, sources, selectedSource, onSourceSelect, onChange, onClose, preselectedResource, plugin, pluginMode, searchEnabled, }: MainContainerProps): React.JSX.Element;
|
19
|
+
export default MainContainer;
|
@@ -0,0 +1,43 @@
|
|
1
|
+
import React, { useCallback, useState } from 'react';
|
2
|
+
import SourceList from '../SourceList/SourceList';
|
3
|
+
import ResourceLauncher from '../ResourceLauncher/ResourceLauncher';
|
4
|
+
import SourceDropdownContainer from '../SourceDropdownContainer/SourceDropdownContainer';
|
5
|
+
import SourceDropdown from '../SourceDropdown/SourceDropdown';
|
6
|
+
import { PluginLaunchModeType, } from '../types';
|
7
|
+
function MainContainer({ title, titleAriaProps, allowedTypes, sources, selectedSource, onSourceSelect, onChange, onClose, preselectedResource, plugin, pluginMode, searchEnabled, }) {
|
8
|
+
const [headerPortal, setHeaderPortal] = useState(null);
|
9
|
+
const pluginToRender = pluginMode ? pluginMode.type : PluginLaunchModeType.Browse; // Cant default a 'null' property in signature so set it here
|
10
|
+
const SourceBrowser = plugin?.sourceBrowserComponent();
|
11
|
+
const SourceSearch = plugin?.sourceSearchComponent();
|
12
|
+
// Can't use a useRef as it wont update on change when a source is selected, so need to use a ref callback to store in state
|
13
|
+
const setHeaderPortalRef = useCallback((node) => {
|
14
|
+
if (node !== null) {
|
15
|
+
setHeaderPortal(node);
|
16
|
+
}
|
17
|
+
}, [setHeaderPortal]);
|
18
|
+
// MainContainer will either render the source list view if no source is set or the plugins UI if a source has been selected
|
19
|
+
return (React.createElement("div", { className: "relative flex flex-col h-full text-gray-800" },
|
20
|
+
React.createElement("div", { className: "flex items-center py-3 pl-6 pr-10 min-h-[68px]" },
|
21
|
+
React.createElement("h2", { ...titleAriaProps, className: "text-xl leading-6 text-gray-800 font-semibold mr-6" }, title),
|
22
|
+
plugin && selectedSource && (React.createElement(React.Fragment, null,
|
23
|
+
plugin.createHeaderPortal && React.createElement("div", { ref: setHeaderPortalRef, className: "squiz-rb-plugin" }),
|
24
|
+
!plugin.createHeaderPortal && sources.length > 1 && (React.createElement(SourceDropdownContainer, { isCollapsed: false, onExpand: () => { } },
|
25
|
+
React.createElement("div", { className: `border-l border-blue-200 pl-1 w-[204px]` },
|
26
|
+
React.createElement(SourceDropdown, { sources: sources, selectedSource: selectedSource, onSourceSelect: onSourceSelect })))))),
|
27
|
+
React.createElement("button", { type: "button", "aria-label": `Close ${title} dialog`, onClick: onClose, className: "absolute top-2 right-2 p-2.5 rounded hover:bg-blue-100 focus:bg-blue-100" },
|
28
|
+
React.createElement("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", xmlns: "http://www.w3.org/2000/svg" },
|
29
|
+
React.createElement("path", { d: "M13.3 0.710017C13.1131 0.522765 12.8595 0.417532 12.595 0.417532C12.3305 0.417532 12.0768 0.522765 11.89 0.710017L6.99997 5.59002L2.10997 0.700017C1.92314 0.512765 1.66949 0.407532 1.40497 0.407532C1.14045 0.407532 0.886802 0.512765 0.699971 0.700017C0.309971 1.09002 0.309971 1.72002 0.699971 2.11002L5.58997 7.00002L0.699971 11.89C0.309971 12.28 0.309971 12.91 0.699971 13.3C1.08997 13.69 1.71997 13.69 2.10997 13.3L6.99997 8.41002L11.89 13.3C12.28 13.69 12.91 13.69 13.3 13.3C13.69 12.91 13.69 12.28 13.3 11.89L8.40997 7.00002L13.3 2.11002C13.68 1.73002 13.68 1.09002 13.3 0.710017Z", fill: "currentColor" })))),
|
30
|
+
React.createElement("div", { className: "border-t border-gray-300 overflow-y-hidden" },
|
31
|
+
plugin && selectedSource && (React.createElement("div", { className: `squiz-rb-plugin squiz-rb-plugin--${pluginMode?.type}` },
|
32
|
+
pluginToRender === PluginLaunchModeType.Browse && SourceBrowser && (React.createElement(SourceBrowser, { source: selectedSource, sources: sources, onSourceSelect: onSourceSelect, allowedTypes: allowedTypes, headerPortal: plugin.createHeaderPortal && headerPortal ? headerPortal : undefined, searchEnabled: searchEnabled, preselectedResource: preselectedResource || undefined, browseTo: pluginMode?.args?.browseTo, onSelected: (resource) => {
|
33
|
+
onChange(resource);
|
34
|
+
onClose();
|
35
|
+
} })),
|
36
|
+
pluginToRender === PluginLaunchModeType.Search && SourceSearch && (React.createElement(SourceSearch, { source: selectedSource, sources: sources, onSourceSelect: onSourceSelect, allowedTypes: allowedTypes, headerPortal: plugin.createHeaderPortal && headerPortal ? headerPortal : undefined, searchEnabled: searchEnabled, query: pluginMode?.args?.query, onSelected: (resource) => {
|
37
|
+
onChange(resource);
|
38
|
+
onClose();
|
39
|
+
} })))),
|
40
|
+
!selectedSource && searchEnabled && React.createElement(ResourceLauncher, { sources: sources, onSourceSelect: onSourceSelect }),
|
41
|
+
!selectedSource && !searchEnabled && React.createElement(SourceList, { sources: sources, onSourceSelect: onSourceSelect }))));
|
42
|
+
}
|
43
|
+
export default MainContainer;
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { ResourceBrowserInputProps } from '../ResourceBrowserInput/ResourceBrowserInput';
|
3
|
+
/**
|
4
|
+
* This plugin component exsits to deal with React rules of Hooks stupidity.
|
5
|
+
*
|
6
|
+
* For it to not freak out when we want to change from one plugin to another we have to render
|
7
|
+
* something to the ReactDom for each plugin and 'activate' that component when that plugin
|
8
|
+
* needs to render its UI etc.
|
9
|
+
*/
|
10
|
+
export type PluginRenderType = ResourceBrowserInputProps & {
|
11
|
+
render: boolean;
|
12
|
+
};
|
13
|
+
export declare const PluginRender: ({ render, ...props }: PluginRenderType) => React.JSX.Element;
|
@@ -0,0 +1,12 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { ResourceBrowserInput } from '../ResourceBrowserInput/ResourceBrowserInput';
|
3
|
+
import { AuthProvider } from '../ResourceBrowserContext/AuthProvider';
|
4
|
+
export const PluginRender = ({ render, ...props }) => {
|
5
|
+
if (render) {
|
6
|
+
return (React.createElement(AuthProvider, { authConfig: props.source },
|
7
|
+
React.createElement(ResourceBrowserInput, { ...props })));
|
8
|
+
}
|
9
|
+
else {
|
10
|
+
return React.createElement(React.Fragment, null);
|
11
|
+
}
|
12
|
+
};
|