@squiz/resource-browser 1.69.1 → 2.1.8-rc.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.
Files changed (141) hide show
  1. package/CHANGELOG.md +88 -35
  2. package/LICENSE.md +15 -0
  3. package/README.md +9 -0
  4. package/jest.config.ts +22 -21
  5. package/lib/Hooks/useSelectedState.d.ts +15 -0
  6. package/lib/Hooks/useSelectedState.js +16 -0
  7. package/lib/Hooks/useSources.d.ts +5 -4
  8. package/lib/Hooks/useSources.js +25 -1
  9. package/lib/MainContainer/MainContainer.d.ts +17 -0
  10. package/lib/MainContainer/MainContainer.js +61 -0
  11. package/lib/Plugin/Plugin.d.ts +13 -0
  12. package/lib/Plugin/Plugin.js +17 -0
  13. package/lib/ResourceBrowserContext/ResourceBrowserContext.d.ts +2 -3
  14. package/lib/ResourceBrowserContext/ResourceBrowserContext.js +4 -17
  15. package/lib/ResourceBrowserInput/ResourceBrowserInput.d.ts +24 -0
  16. package/lib/ResourceBrowserInput/ResourceBrowserInput.js +16 -0
  17. package/lib/ResourcePicker/ResourcePicker.d.ts +6 -4
  18. package/lib/ResourcePicker/ResourcePicker.js +14 -8
  19. package/lib/ResourcePicker/States/Selected.d.ts +10 -4
  20. package/lib/ResourcePicker/States/Selected.js +11 -32
  21. package/lib/SourceDropdown/SourceDropdown.d.ts +5 -11
  22. package/lib/SourceDropdown/SourceDropdown.js +20 -99
  23. package/lib/SourceList/SourceList.d.ts +5 -16
  24. package/lib/SourceList/SourceList.js +14 -75
  25. package/lib/index.css +42 -202
  26. package/lib/index.d.ts +7 -7
  27. package/lib/index.js +69 -13
  28. package/lib/types.d.ts +41 -59
  29. package/package.json +82 -80
  30. package/src/Hooks/useSelectedState.spec.ts +46 -0
  31. package/src/Hooks/useSelectedState.ts +22 -0
  32. package/src/Hooks/useSources.spec.ts +30 -12
  33. package/src/Hooks/useSources.ts +33 -4
  34. package/src/Icons/CircledLoopIcon.tsx +8 -8
  35. package/src/MainContainer/MainContainer.spec.tsx +203 -0
  36. package/src/MainContainer/MainContainer.stories.tsx +62 -0
  37. package/src/MainContainer/MainContainer.tsx +101 -0
  38. package/src/Plugin/Plugin.spec.tsx +46 -0
  39. package/src/Plugin/Plugin.tsx +20 -0
  40. package/src/ResourceBrowserContext/ResourceBrowserContext.spec.tsx +65 -106
  41. package/src/ResourceBrowserContext/ResourceBrowserContext.tsx +24 -39
  42. package/src/ResourceBrowserInput/ResourceBrowserInput.spec.tsx +192 -0
  43. package/src/ResourceBrowserInput/ResourceBrowserInput.tsx +81 -0
  44. package/src/ResourcePicker/ResourcePicker.spec.tsx +159 -116
  45. package/src/ResourcePicker/ResourcePicker.stories.tsx +28 -24
  46. package/src/ResourcePicker/ResourcePicker.tsx +79 -59
  47. package/src/ResourcePicker/States/Error.tsx +8 -8
  48. package/src/ResourcePicker/States/Loading.tsx +3 -3
  49. package/src/ResourcePicker/States/Selected.tsx +66 -73
  50. package/src/ResourcePicker/mock-image-resource.json +25 -47
  51. package/src/ResourcePicker/mock-resource.json +11 -13
  52. package/src/ResourcePicker/resource-picker.scss +13 -13
  53. package/src/SourceDropdown/SourceDropdown.spec.tsx +65 -391
  54. package/src/SourceDropdown/SourceDropdown.stories.tsx +21 -24
  55. package/src/SourceDropdown/SourceDropdown.tsx +80 -258
  56. package/src/SourceList/SourceList.spec.tsx +37 -430
  57. package/src/SourceList/SourceList.stories.tsx +17 -37
  58. package/src/SourceList/SourceList.tsx +28 -155
  59. package/src/__mocks__/MockModels.ts +56 -25
  60. package/src/__mocks__/PluginExample.tsx +98 -0
  61. package/src/__mocks__/StorybookHelpers.tsx +141 -0
  62. package/src/__mocks__/renderWithContext.tsx +14 -18
  63. package/src/__mocks__/sample-sources.json +32 -0
  64. package/src/index.scss +18 -8
  65. package/src/index.spec.tsx +277 -99
  66. package/src/index.stories.tsx +65 -39
  67. package/src/index.tsx +119 -57
  68. package/src/types.ts +54 -63
  69. package/tailwind.config.cjs +92 -92
  70. package/vite.config.js +12 -12
  71. package/lib/Hooks/useCategorisedSources.d.ts +0 -14
  72. package/lib/Hooks/useCategorisedSources.js +0 -38
  73. package/lib/Hooks/useChildResources.d.ts +0 -16
  74. package/lib/Hooks/useChildResources.js +0 -13
  75. package/lib/Hooks/usePreselectedResourcePath.d.ts +0 -20
  76. package/lib/Hooks/usePreselectedResourcePath.js +0 -31
  77. package/lib/Hooks/useRecentLocations.d.ts +0 -5
  78. package/lib/Hooks/useRecentLocations.js +0 -38
  79. package/lib/Hooks/useRecentResourcesPaths.d.ts +0 -20
  80. package/lib/Hooks/useRecentResourcesPaths.js +0 -30
  81. package/lib/Hooks/useResource.d.ts +0 -28
  82. package/lib/Hooks/useResource.js +0 -23
  83. package/lib/Hooks/useResourcePath.d.ts +0 -16
  84. package/lib/Hooks/useResourcePath.js +0 -64
  85. package/lib/Icons/HistoryIcon.d.ts +0 -4
  86. package/lib/Icons/HistoryIcon.js +0 -13
  87. package/lib/PreviewPanel/PreviewPanel.d.ts +0 -5
  88. package/lib/PreviewPanel/PreviewPanel.js +0 -8
  89. package/lib/PreviewPanel/details/MatrixResource.d.ts +0 -7
  90. package/lib/PreviewPanel/details/MatrixResource.js +0 -35
  91. package/lib/ResourceBreadcrumb/ResourceBreadcrumb.d.ts +0 -9
  92. package/lib/ResourceBreadcrumb/ResourceBreadcrumb.js +0 -54
  93. package/lib/ResourceList/ResourceList.d.ts +0 -18
  94. package/lib/ResourceList/ResourceList.js +0 -49
  95. package/lib/ResourcePickerContainer/ResourcePickerContainer.d.ts +0 -17
  96. package/lib/ResourcePickerContainer/ResourcePickerContainer.js +0 -166
  97. package/lib/StatusIndicator/StatusIndicator.d.ts +0 -8
  98. package/lib/StatusIndicator/StatusIndicator.js +0 -27
  99. package/lib/utils/findBestMatchLineage.d.ts +0 -2
  100. package/lib/utils/findBestMatchLineage.js +0 -28
  101. package/lib/utils/uuid.d.ts +0 -1
  102. package/lib/utils/uuid.js +0 -6
  103. package/src/Hooks/useCategorisedSources.spec.ts +0 -39
  104. package/src/Hooks/useCategorisedSources.ts +0 -46
  105. package/src/Hooks/useChildResources.spec.ts +0 -29
  106. package/src/Hooks/useChildResources.ts +0 -21
  107. package/src/Hooks/usePreselectedResourcePath.ts +0 -54
  108. package/src/Hooks/useRecentLocations.spec.ts +0 -81
  109. package/src/Hooks/useRecentLocations.ts +0 -44
  110. package/src/Hooks/useRecentResourcesPaths.ts +0 -54
  111. package/src/Hooks/useResource.spec.ts +0 -61
  112. package/src/Hooks/useResource.ts +0 -38
  113. package/src/Hooks/useResourcePath.spec.ts +0 -120
  114. package/src/Hooks/useResourcePath.ts +0 -76
  115. package/src/Icons/HistoryIcon.tsx +0 -17
  116. package/src/PreviewPanel/PreviewPanel.spec.tsx +0 -198
  117. package/src/PreviewPanel/PreviewPanel.stories.tsx +0 -76
  118. package/src/PreviewPanel/PreviewPanel.tsx +0 -6
  119. package/src/PreviewPanel/details/MatrixResource.tsx +0 -54
  120. package/src/PreviewPanel/details/matrix-resource.scss +0 -16
  121. package/src/ResourceBreadcrumb/ResourceBreadcrumb.spec.tsx +0 -133
  122. package/src/ResourceBreadcrumb/ResourceBreadcrumb.stories.tsx +0 -24
  123. package/src/ResourceBreadcrumb/ResourceBreadcrumb.tsx +0 -79
  124. package/src/ResourceBreadcrumb/resource-breadcrumb.scss +0 -28
  125. package/src/ResourceBreadcrumb/sample-hierarchy.json +0 -27
  126. package/src/ResourceList/ResourceList.spec.tsx +0 -202
  127. package/src/ResourceList/ResourceList.stories.tsx +0 -40
  128. package/src/ResourceList/ResourceList.tsx +0 -83
  129. package/src/ResourceList/sample-resources.json +0 -851
  130. package/src/ResourcePickerContainer/ResourcePickerContainer.spec.tsx +0 -780
  131. package/src/ResourcePickerContainer/ResourcePickerContainer.stories.tsx +0 -45
  132. package/src/ResourcePickerContainer/ResourcePickerContainer.tsx +0 -290
  133. package/src/SourceList/sample-sources.json +0 -251
  134. package/src/StatusIndicator/StatusIndicator.stories.tsx +0 -83
  135. package/src/StatusIndicator/StatusIndicator.tsx +0 -38
  136. package/src/__mocks__/JestHelpers.ts +0 -65
  137. package/src/__mocks__/StorybookHelpers.ts +0 -128
  138. package/src/__mocks__/jestHelpers.spec.ts +0 -38
  139. package/src/utils/findBestMatchLineage.spec.ts +0 -81
  140. package/src/utils/findBestMatchLineage.ts +0 -30
  141. package/src/utils/uuid.ts +0 -5
@@ -1,65 +0,0 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- import sass from 'sass';
4
- import postcss, { Root, AcceptedPlugin, Processor } from 'postcss';
5
- import { fileURLToPath } from 'url';
6
-
7
- const removeLayerDirectivePlugin = {
8
- postcssPlugin: 'remove-layer-directive',
9
- OnceExit(root: Root) {
10
- // Remove the @layer directive while keeping the contents
11
- root.walkAtRules('layer', (rule) => {
12
- rule.replaceWith(rule.nodes);
13
- });
14
- },
15
- } as AcceptedPlugin;
16
-
17
- function removeLayerDirective(scss: string) {
18
- const { css } = postcss({
19
- plugins: [removeLayerDirectivePlugin],
20
- } as Processor).process(scss, {
21
- from: undefined,
22
- });
23
-
24
- return css;
25
- }
26
-
27
- function readAndParseScss({ relativePath, dirname }: { relativePath: string; dirname: string }) {
28
- const cssFileContents = fs.readFileSync(path.resolve(dirname, relativePath), 'utf8');
29
- const compiledCSS = sass.compileString(cssFileContents, {
30
- importers: [
31
- {
32
- canonicalize(url) {
33
- // This function converts the relative path to an absolute path
34
- const filePath = path.resolve(dirname, url);
35
-
36
- return new URL(`file://${filePath}`);
37
- },
38
- load(canonicalUrl) {
39
- // This function loads the returns the file in the expected format
40
- return {
41
- contents: fs.readFileSync(fileURLToPath(`${canonicalUrl}.scss`), 'utf8'),
42
- syntax: 'scss',
43
- };
44
- },
45
- },
46
- ],
47
- }).css;
48
-
49
- return removeLayerDirective(compiledCSS);
50
- }
51
-
52
- function loadCss({ container, cssFileContents }: { container: HTMLElement; cssFileContents: string }) {
53
- const style = window.document.createElement('style');
54
- style.type = 'text/css';
55
- style.innerHTML = cssFileContents;
56
- container.append(style);
57
- }
58
-
59
- const resizeWindow = (x: number, y: number) => {
60
- window.innerWidth = x;
61
- window.innerHeight = y;
62
- window.dispatchEvent(new Event('resize'));
63
- };
64
-
65
- export { readAndParseScss, loadCss, resizeWindow };
@@ -1,128 +0,0 @@
1
- import sampleSources from '../SourceList/sample-sources.json';
2
- import { HydratedResourceReference, Resource, ResourceReference, Source } from '../types';
3
- import sampleResources from '../ResourceList/sample-resources.json';
4
-
5
- type CreateCallbacksProps = Partial<{
6
- delay: number;
7
- sourceIsLoading: boolean;
8
- resourceIsLoading: boolean;
9
- error?: string;
10
- }>;
11
-
12
- const indexSources = (sources: Source[]) => {
13
- const indexed: Record<string, Resource> = {};
14
- const pending: Resource[] = [];
15
-
16
- sources.forEach((source) => {
17
- if (source && 'nodes' in source) {
18
- pending.push(...source.nodes);
19
- }
20
- });
21
-
22
- while (pending.length > 0) {
23
- const resource = pending.shift();
24
-
25
- if (!resource) {
26
- continue;
27
- }
28
-
29
- indexed[resource.id] = resource;
30
- }
31
-
32
- return indexed;
33
- };
34
-
35
- const indexResources = (resources: Resource[]) => {
36
- const indexed: Record<string, Resource> = {};
37
- const pending = [...resources];
38
-
39
- while (pending.length > 0) {
40
- const resource = pending.shift();
41
-
42
- if (!resource) {
43
- continue;
44
- }
45
-
46
- indexed[resource.id] = resource;
47
-
48
- if (resource && '_children' in resource) {
49
- pending.push(...(resource._children as Resource[]));
50
- }
51
- }
52
-
53
- return indexed;
54
- };
55
-
56
- export const createResourceBrowserCallbacks = ({
57
- delay = 500,
58
- sourceIsLoading = false,
59
- resourceIsLoading = false,
60
- error,
61
- }: CreateCallbacksProps = {}) => {
62
- const indexSourceResources = indexSources(sampleSources as Source[]);
63
- const indexedResources = indexResources(sampleResources as Resource[]);
64
-
65
- return {
66
- onRequestSources: () => {
67
- console.log('onRequestSources');
68
-
69
- return new Promise((resolve, reject) => {
70
- if (!sourceIsLoading) {
71
- setTimeout(() => {
72
- if (error && Math.random() > 0.5) {
73
- reject(new Error(error));
74
- } else {
75
- resolve(sampleSources);
76
- }
77
- }, delay);
78
- }
79
- });
80
- },
81
- onRequestChildren: (source: Source, resource: Resource | null) => {
82
- console.log('onRequestChildren', source, resource);
83
-
84
- return new Promise((resolve, reject) => {
85
- if (!resourceIsLoading) {
86
- setTimeout(() => {
87
- if (error && Math.random() > 0.5) {
88
- reject(new Error(error));
89
- } else {
90
- resolve(resource ? (indexedResources[resource.id] as any)?._children || [] : sampleResources);
91
- }
92
- }, delay);
93
- }
94
- });
95
- },
96
- onRequestResource: (reference: ResourceReference) => {
97
- console.log('onRequestResource', reference);
98
-
99
- return new Promise((resolve, reject) => {
100
- if (!resourceIsLoading) {
101
- setTimeout(() => {
102
- if (error && Math.random() > 0.5) {
103
- reject(new Error(error));
104
- } else {
105
- const foundResource = indexedResources[reference.resource];
106
- const foundSourceResource = indexSourceResources[reference.resource];
107
- if (foundResource) {
108
- resolve(foundResource);
109
- }
110
- resolve(foundSourceResource);
111
- }
112
- }, delay);
113
- }
114
- });
115
- },
116
- onChange: (reference: HydratedResourceReference | null) => {
117
- if (reference) {
118
- const { resource, source } = reference;
119
-
120
- alert(
121
- `Resource Browser has selected resource #${resource.id} (${resource.name}) from source #${source.id} (${source.name}).`,
122
- );
123
- } else {
124
- alert(`Resource Browser has cleared selected resource.`);
125
- }
126
- },
127
- };
128
- };
@@ -1,38 +0,0 @@
1
- import { loadCss, resizeWindow } from './JestHelpers';
2
-
3
- describe('loadCss', () => {
4
- it('should load the css', () => {
5
- const container = document.createElement('div');
6
- container.setAttribute('id', 'test');
7
-
8
- const cssFileContents = `
9
- .test {
10
- color: red;
11
- }
12
- `;
13
-
14
- loadCss({ container, cssFileContents });
15
-
16
- // Expect that the css is loaded into the container as a style tag
17
- expect(container.innerHTML).toBe(`<style type="text/css">${cssFileContents}</style>`);
18
- });
19
- });
20
-
21
- describe('resizeWindow', () => {
22
- it('should resize the window', () => {
23
- resizeWindow(100, 100);
24
-
25
- // Expect that the window has been resized
26
- expect(window.innerWidth).toBe(100);
27
- expect(window.innerHeight).toBe(100);
28
- });
29
-
30
- it('should dispatch a resize event', () => {
31
- const resizeSpy = jest.spyOn(window, 'dispatchEvent');
32
-
33
- resizeWindow(100, 100);
34
-
35
- // Expect that the window has been resized
36
- expect(resizeSpy).toHaveBeenCalled();
37
- });
38
- });
@@ -1,81 +0,0 @@
1
- import { Resource } from '../types';
2
- import { findBestMatchLineage } from './findBestMatchLineage';
3
- import { mockResource, mockSource } from '../__mocks__/MockModels';
4
-
5
- describe('findBestMatchLineage', () => {
6
- it.each([
7
- [
8
- 'Resource lineage is not returned',
9
- mockResource({
10
- lineages: undefined,
11
- }),
12
- [],
13
- ],
14
- [
15
- 'Resource has no lineages',
16
- mockResource({
17
- lineages: [],
18
- }),
19
- [],
20
- ],
21
- [
22
- 'Resource does not have lineage which is beneath a configured root node',
23
- mockResource({
24
- id: '3000',
25
- lineages: [{ resourceIds: ['1', '30', '300', '3000'] }],
26
- }),
27
- [],
28
- ],
29
- [
30
- 'Resource has a lineage under one of the root nodes',
31
- mockResource({
32
- id: '100',
33
- lineages: [{ resourceIds: ['1', '20', '200', '2000'] }],
34
- }),
35
- ['20', '200', '2000'],
36
- ],
37
- [
38
- 'Resource has a lineage beneath multiple of the root nodes',
39
- mockResource({
40
- id: '1000',
41
- lineages: [{ resourceIds: ['1', '10', '100', '1000'] }, { resourceIds: ['1', '20', '200', '1000'] }],
42
- }),
43
- // first match is returned.
44
- ['10', '100', '1000'],
45
- ],
46
- [
47
- 'Resource has multiple lineages under a single configured root node',
48
- mockResource({
49
- id: '1000',
50
- lineages: [{ resourceIds: ['1', '10', '100', '1000'] }, { resourceIds: ['1', '10', '101', '1000'] }],
51
- }),
52
- // first match is returned.
53
- ['10', '100', '1000'],
54
- ],
55
- [
56
- 'Resource ID is a configured root node',
57
- mockResource({
58
- id: '10',
59
- lineages: [{ resourceIds: ['1', '10'] }],
60
- }),
61
- [],
62
- ],
63
- [
64
- 'Resource ID is a configured root node and also nested under a root node',
65
- mockResource({
66
- id: '10',
67
- lineages: [{ resourceIds: ['1', '10'] }, { resourceIds: ['1', '20', '10'] }],
68
- }),
69
- ['20', '10'],
70
- ],
71
- ])(
72
- 'Returns best match lineage which can be identified from provided source - %s',
73
- (description: string, resource: Resource, expected: string[]) => {
74
- const source = mockSource({
75
- nodes: [mockResource({ id: '10' }), mockResource({ id: '20' })],
76
- });
77
-
78
- expect(findBestMatchLineage(source, resource)).toEqual(expected);
79
- },
80
- );
81
- });
@@ -1,30 +0,0 @@
1
- import { Source, Resource } from '../types';
2
-
3
- export const findBestMatchLineage = (source: Source, resource: Resource): string[] => {
4
- if (resource.lineages) {
5
- for (const lineage of resource.lineages) {
6
- // Lineage must:
7
- // 1. Appear beneath the root node.
8
- // 2. Not be the root node itself (root nodes can't be selected, to be changed in FEAAS-760).
9
- // TODO: FEAAS-760 update as necessary so the lineage will be returned even if it ends at the root node, eg:
10
- // const rootNode = source.nodes.find(node => lineage.resourceIds.includes(node.id));
11
- const rootNode = source.nodes.find((node) => {
12
- const index = lineage.resourceIds.indexOf(node.id);
13
-
14
- return index >= 0 && index < lineage.resourceIds.length - 1;
15
- });
16
-
17
- if (rootNode) {
18
- const rootNodeIndex = lineage.resourceIds.indexOf(rootNode.id);
19
-
20
- // Return the lineage starting from the root node. eg.
21
- // * Full lineage is: 1 > 10 > 100 > 1000 > 10000
22
- // * The source has a node with an ID of: 100
23
- // * The returned lineage will be: 100 > 1000 > 10000
24
- return lineage.resourceIds.slice(rootNodeIndex);
25
- }
26
- }
27
- }
28
-
29
- return [];
30
- };
package/src/utils/uuid.ts DELETED
@@ -1,5 +0,0 @@
1
- export default function uuid(): string {
2
- return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, (c) =>
3
- (Number(c) ^ (window.crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (Number(c) / 4)))).toString(16),
4
- );
5
- }