@squiz/resource-browser 1.32.1-alpha.15 → 1.32.1-alpha.16

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 (90) hide show
  1. package/jest.config.ts +12 -1
  2. package/lib/Hooks/useCategorisedSources.d.ts +14 -0
  3. package/lib/Hooks/useCategorisedSources.js +38 -0
  4. package/lib/Hooks/useChildResources.d.ts +19 -0
  5. package/lib/Hooks/useChildResources.js +35 -0
  6. package/lib/Hooks/useResourcePath.d.ts +16 -0
  7. package/lib/Hooks/useResourcePath.js +64 -0
  8. package/lib/Hooks/useSources.d.ts +16 -0
  9. package/lib/Hooks/useSources.js +29 -0
  10. package/lib/Icons/Icon.d.ts +7 -7
  11. package/lib/Icons/Icon.js +7 -9
  12. package/lib/Icons/MatrixResources/Audio.js +1 -1
  13. package/lib/Icons/MatrixResources/Excel.js +1 -1
  14. package/lib/Icons/MatrixResources/MatrixResourceMap.d.ts +6 -6
  15. package/lib/Icons/MatrixResources/MatrixResourceMap.js +6 -6
  16. package/lib/Icons/MatrixResources/Pdf.js +1 -1
  17. package/lib/Icons/MatrixResources/Powerpoint.js +1 -1
  18. package/lib/Icons/MatrixResources/Video.js +1 -1
  19. package/lib/Icons/MatrixResources/Word.js +1 -1
  20. package/lib/Modal/Modal.js +1 -1
  21. package/lib/PreviewPanel/PreviewModal.js +1 -1
  22. package/lib/PreviewPanel/PreviewPanel.d.ts +4 -6
  23. package/lib/PreviewPanel/PreviewPanel.js +11 -39
  24. package/lib/PreviewPanel/details/MatrixResource.d.ts +4 -9
  25. package/lib/PreviewPanel/details/MatrixResource.js +20 -16
  26. package/lib/ResourceBreadcrumb/ResourceBreadcrumb.d.ts +5 -5
  27. package/lib/ResourceBreadcrumb/ResourceBreadcrumb.js +3 -3
  28. package/lib/ResourceItem/ResourceItem.d.ts +6 -8
  29. package/lib/ResourceItem/ResourceItem.js +3 -3
  30. package/lib/ResourceList/ResourceList.d.ts +5 -4
  31. package/lib/ResourceList/ResourceList.js +3 -3
  32. package/lib/ResourcePickerContainer/ResourcePickerContainer.d.ts +4 -5
  33. package/lib/ResourcePickerContainer/ResourcePickerContainer.js +34 -89
  34. package/lib/SourceDropdown/SourceDropdown.d.ts +5 -5
  35. package/lib/SourceDropdown/SourceDropdown.js +19 -27
  36. package/lib/SourceList/SourceList.d.ts +4 -4
  37. package/lib/SourceList/SourceList.js +7 -5
  38. package/lib/index.css +6 -0
  39. package/lib/index.d.ts +6 -29
  40. package/lib/index.js +2 -3
  41. package/lib/uuid.js +1 -3
  42. package/package.json +3 -2
  43. package/src/Hooks/useCategorisedSources.spec.ts +39 -0
  44. package/src/Hooks/useCategorisedSources.ts +46 -0
  45. package/src/Hooks/useChildResources.spec.ts +49 -0
  46. package/src/Hooks/useChildResources.ts +43 -0
  47. package/src/Hooks/useResourcePath.spec.ts +124 -0
  48. package/src/Hooks/useResourcePath.ts +76 -0
  49. package/src/Hooks/useSources.spec.ts +33 -0
  50. package/src/Hooks/useSources.ts +33 -0
  51. package/src/Icons/Icon.stories.tsx +7 -7
  52. package/src/Icons/Icon.tsx +9 -14
  53. package/src/Icons/MatrixResources/Audio.tsx +1 -1
  54. package/src/Icons/MatrixResources/Excel.tsx +1 -1
  55. package/src/Icons/MatrixResources/MatrixResourceMap.ts +7 -7
  56. package/src/Icons/MatrixResources/Pdf.tsx +1 -1
  57. package/src/Icons/MatrixResources/Powerpoint.tsx +1 -1
  58. package/src/Icons/MatrixResources/Video.tsx +1 -1
  59. package/src/Icons/MatrixResources/Word.tsx +1 -1
  60. package/src/Modal/Modal.tsx +1 -1
  61. package/src/PreviewPanel/PreviewModal.tsx +1 -1
  62. package/src/PreviewPanel/PreviewPanel.spec.tsx +20 -62
  63. package/src/PreviewPanel/PreviewPanel.stories.tsx +16 -24
  64. package/src/PreviewPanel/PreviewPanel.tsx +15 -51
  65. package/src/PreviewPanel/details/MatrixResource.tsx +23 -19
  66. package/src/ResourceBreadcrumb/ResourceBreadcrumb.spec.tsx +13 -23
  67. package/src/ResourceBreadcrumb/ResourceBreadcrumb.stories.tsx +1 -1
  68. package/src/ResourceBreadcrumb/ResourceBreadcrumb.tsx +8 -9
  69. package/src/ResourceBreadcrumb/sample-hierarchy.json +15 -25
  70. package/src/ResourceItem/ResourceItem.tsx +10 -12
  71. package/src/ResourceList/ResourceList.spec.tsx +8 -53
  72. package/src/ResourceList/ResourceList.stories.tsx +2 -2
  73. package/src/ResourceList/ResourceList.tsx +12 -10
  74. package/src/ResourceList/sample-resources.json +551 -49
  75. package/src/ResourcePickerContainer/ResourcePickerContainer.spec.tsx +196 -315
  76. package/src/ResourcePickerContainer/ResourcePickerContainer.stories.tsx +7 -29
  77. package/src/ResourcePickerContainer/ResourcePickerContainer.tsx +63 -127
  78. package/src/SourceDropdown/SourceDropdown.spec.tsx +63 -60
  79. package/src/SourceDropdown/SourceDropdown.stories.tsx +4 -7
  80. package/src/SourceDropdown/SourceDropdown.tsx +34 -41
  81. package/src/SourceList/SourceList.spec.tsx +38 -32
  82. package/src/SourceList/SourceList.tsx +17 -19
  83. package/src/SourceList/sample-sources.json +186 -77
  84. package/src/__mocks__/MockModels.ts +30 -0
  85. package/src/__mocks__/StorybookHelpers.ts +46 -0
  86. package/src/index.stories.tsx +13 -38
  87. package/src/index.tsx +5 -29
  88. package/src/types.d.ts +71 -0
  89. package/src/uuid.ts +2 -4
  90. package/src/SourceDropdown/sample-sources.json +0 -110
@@ -0,0 +1,46 @@
1
+ import { ScopedSource, Source } from '../types';
2
+ import { useMemo } from 'react';
3
+
4
+ export type CategorisedSource = {
5
+ key: string;
6
+ label: string;
7
+ sources: ScopedSource[];
8
+ };
9
+
10
+ /**
11
+ * Groups a list of source into scoped/un-scoped for rendering in the source list.
12
+ *
13
+ * @param {Source[]} sources
14
+ *
15
+ * @return {SourceList}
16
+ */
17
+ export const useCategorisedSources = (sources: Source[]): CategorisedSource[] => {
18
+ return useMemo(() => {
19
+ const categorised: CategorisedSource[] = [];
20
+ const uncategorised: ScopedSource[] = [];
21
+
22
+ sources.forEach((source) => {
23
+ if (source.nodes.length > 0) {
24
+ const category: CategorisedSource = { key: source.id, label: source.name, sources: [] };
25
+
26
+ source.nodes.forEach((resource) => {
27
+ category.sources.push({ source, resource });
28
+ });
29
+
30
+ categorised.push(category);
31
+ } else {
32
+ uncategorised.push({ source, resource: null });
33
+ }
34
+ });
35
+
36
+ if (uncategorised.length > 0) {
37
+ categorised.push({
38
+ key: 'other',
39
+ label: 'Other systems',
40
+ sources: uncategorised,
41
+ });
42
+ }
43
+
44
+ return categorised;
45
+ }, [sources]);
46
+ };
@@ -0,0 +1,49 @@
1
+ import { renderHook, waitFor } from '@testing-library/react';
2
+ import { mockResource, mockScopedSource } from '../__mocks__/MockModels';
3
+ import { useChildResources } from './useChildResources';
4
+
5
+ describe('useChildResources', () => {
6
+ it('Should trigger and return the loaded child resources', async () => {
7
+ const source = mockScopedSource();
8
+ const currentResource = mockResource({ name: 'Current resource' });
9
+ const children = [mockResource({ name: 'Child 1' })];
10
+ const onRequestChildren = jest.fn().mockResolvedValue(children);
11
+ const { result } = renderHook(() =>
12
+ useChildResources({
13
+ source,
14
+ currentResource,
15
+ onRequestChildren,
16
+ }),
17
+ );
18
+
19
+ expect(result.current.isLoading).toBe(true);
20
+ expect(result.current.error).toBe(null);
21
+ expect(result.current.resources).toEqual([]);
22
+
23
+ await waitFor(() => expect(result.current.isLoading).toBe(false));
24
+
25
+ expect(result.current.isLoading).toBe(false);
26
+ expect(result.current.error).toBe(null);
27
+ expect(result.current.resources).toBe(children);
28
+ });
29
+
30
+ it('Should return the error if loading resources fails', async () => {
31
+ const source = mockScopedSource();
32
+ const currentResource = mockResource({ name: 'Current resource' });
33
+ const error = new Error('Loading the resources failed.');
34
+ const onRequestChildren = jest.fn().mockRejectedValue(error);
35
+ const { result } = renderHook(() =>
36
+ useChildResources({
37
+ source,
38
+ currentResource,
39
+ onRequestChildren,
40
+ }),
41
+ );
42
+
43
+ await waitFor(() => expect(result.current.isLoading).toBe(false));
44
+
45
+ expect(result.current.isLoading).toBe(false);
46
+ expect(result.current.error).toBe(error);
47
+ expect(result.current.resources).toEqual([]);
48
+ });
49
+ });
@@ -0,0 +1,43 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { Resource, ScopedSource, Source } from '../types';
3
+
4
+ type UseChildResourcesProps = {
5
+ source: ScopedSource | null;
6
+ currentResource: Resource | null;
7
+ onRequestChildren: (source: Source, resource: Resource | null) => Promise<Resource[]>;
8
+ };
9
+
10
+ /**
11
+ * Triggers a reload of the child resources when the source or current resource change.
12
+ *
13
+ * @param {ScopedSource|null} source
14
+ * @param {Resource|null} currentResource
15
+ * @param {Function} onRequestChildren
16
+ */
17
+ export const useChildResources = ({ source, currentResource, onRequestChildren }: UseChildResourcesProps) => {
18
+ const [isLoading, setIsLoading] = useState(false);
19
+ const [error, setError] = useState<Error | null>(null);
20
+ const [resources, setResources] = useState<Resource[]>([]);
21
+
22
+ // trigger a reload of the resources when the source or the current resource changes.
23
+ useEffect(() => {
24
+ setError(null);
25
+ setResources([]);
26
+
27
+ if (source) {
28
+ setIsLoading(true);
29
+
30
+ onRequestChildren(source.source, currentResource)
31
+ .then((resources: Array<Resource>) => {
32
+ setResources(resources);
33
+ setIsLoading(false);
34
+ })
35
+ .catch((e) => {
36
+ setError(e);
37
+ setIsLoading(false);
38
+ });
39
+ }
40
+ }, [source, currentResource]);
41
+
42
+ return { isLoading, error, resources };
43
+ };
@@ -0,0 +1,124 @@
1
+ import { act, renderHook } from '@testing-library/react';
2
+ import { mockScopedSource, mockResource } from '../__mocks__/MockModels';
3
+ import { useResourcePath } from './useResourcePath';
4
+ import { Resource, Hierarchy, ScopedSource } from '../types';
5
+
6
+ describe('useResourcePath', () => {
7
+ it('Should return expected initial state', () => {
8
+ const {
9
+ result: { current: result },
10
+ } = renderHook(() => useResourcePath());
11
+
12
+ expect(result).toEqual({
13
+ source: null,
14
+ currentResource: null,
15
+ hierarchy: [],
16
+ setSource: expect.any(Function),
17
+ push: expect.any(Function),
18
+ popUntil: expect.any(Function),
19
+ });
20
+ });
21
+
22
+ it('setSource should update the source and clear the current hierarchy', async () => {
23
+ const { result } = renderHook(() => useResourcePath());
24
+ const source = mockScopedSource({
25
+ source: { id: '1', name: 'Test source' },
26
+ resource: { id: '2', name: 'Test resource' },
27
+ });
28
+ const resource = mockResource({ id: '3', name: 'Test resource 2' });
29
+
30
+ await act(() => result.current.setSource(source));
31
+ await act(() => result.current.push(resource));
32
+
33
+ // make sure the current resource/hierarchy is populated
34
+ expect(result.current.currentResource).toBe(resource);
35
+ expect(result.current.hierarchy).toHaveLength(2);
36
+
37
+ // set the source again
38
+ await act(() => result.current.setSource(source));
39
+
40
+ // make sure the current resource and hierarchy are reset
41
+ expect(result.current.source).toBe(source);
42
+ expect(result.current.currentResource).toBe(null);
43
+ expect(result.current.hierarchy).toEqual([{ key: 'source:1-resource:2', label: 'Test resource', node: source }]);
44
+ });
45
+
46
+ it('push should add the node to the hierarchy', async () => {
47
+ const { result } = renderHook(() => useResourcePath());
48
+ const source = mockScopedSource({ source: { id: '1' } });
49
+ const site = mockResource({ id: '1', type: { code: 'site', name: 'Site' }, name: 'My site' });
50
+ const page = mockResource({ id: '2', type: { code: 'page', name: 'Page' }, name: 'My page' });
51
+
52
+ await act(() => result.current.setSource(source));
53
+ await act(() => result.current.push(site));
54
+ await act(() => result.current.push(page));
55
+
56
+ expect(result.current.source).toBe(source);
57
+ expect(result.current.currentResource).toBe(page);
58
+ expect(result.current.hierarchy).toEqual([
59
+ { key: 'source:1-resource:unscoped', label: source.source.name, node: source },
60
+ { key: '1', label: site.name, node: site },
61
+ { key: '2', label: page.name, node: page },
62
+ ]);
63
+ });
64
+
65
+ it.each([
66
+ [
67
+ 'popping to the last node should remove nothing',
68
+ mockResource({ id: '3' }),
69
+ [
70
+ { key: 'source:1-resource:unscoped', label: 'Test source', node: mockScopedSource({ source: { id: '1' } }) },
71
+ { key: '1', label: 'Resource 1', node: mockResource({ id: '1', name: 'Resource 1' }) },
72
+ { key: '2', label: 'Resource 2', node: mockResource({ id: '2', name: 'Resource 2' }) },
73
+ { key: '3', label: 'Resource 3', node: mockResource({ id: '3', name: 'Resource 3' }) },
74
+ ],
75
+ ],
76
+ [
77
+ 'popping to a node not in the hierarchy should remove everything',
78
+ mockResource({ id: 'resource-not-in-hierarchy' }),
79
+ [],
80
+ ],
81
+ [
82
+ 'popping to the source should remove everything except the source',
83
+ mockScopedSource({ source: { id: '1' } }),
84
+ [{ key: 'source:1-resource:unscoped', label: 'Test source', node: mockScopedSource({ source: { id: '1' } }) }],
85
+ ],
86
+ [
87
+ 'popping to a resource node should remove the resources after it',
88
+ mockResource({ id: '2' }),
89
+ [
90
+ { key: 'source:1-resource:unscoped', label: 'Test source', node: mockScopedSource({ source: { id: '1' } }) },
91
+ { key: '1', label: 'Resource 1', node: mockResource({ id: '1', name: 'Resource 1' }) },
92
+ { key: '2', label: 'Resource 2', node: mockResource({ id: '2', name: 'Resource 2' }) },
93
+ ],
94
+ ],
95
+ ])(
96
+ 'popUntil should remove from the hierarchy until the node being popped to is hit - %s',
97
+ async (
98
+ description: string,
99
+ node: ScopedSource | Resource,
100
+ expectedHierarchy: Hierarchy<ScopedSource | Resource>,
101
+ ) => {
102
+ const { result } = renderHook(() => useResourcePath());
103
+ const source = mockScopedSource({ source: { id: '1' } });
104
+ const mockResources = [
105
+ mockResource({ id: '1', name: 'Resource 1' }),
106
+ mockResource({ id: '2', name: 'Resource 2' }),
107
+ mockResource({ id: '3', name: 'Resource 3' }),
108
+ ];
109
+
110
+ await act(() => result.current.setSource(source));
111
+ await act(() => result.current.push(mockResources[0]));
112
+ await act(() => result.current.push(mockResources[1]));
113
+ await act(() => result.current.push(mockResources[2]));
114
+
115
+ // make sure hierarchy has expected length before popping
116
+ expect(result.current.source).toBe(source);
117
+ expect(result.current.hierarchy).toHaveLength(4);
118
+
119
+ await act(() => result.current.popUntil(node));
120
+
121
+ expect(result.current.hierarchy).toEqual(expectedHierarchy);
122
+ },
123
+ );
124
+ });
@@ -0,0 +1,76 @@
1
+ import { useCallback, useMemo, useState } from 'react';
2
+ import { Hierarchy, ScopedSource, Resource } from '../types';
3
+
4
+ /**
5
+ * Retains the state relating to where in the resource tree we are.
6
+ *
7
+ * Including:
8
+ * * The source.
9
+ * * A full path from the source to the leaf resource being browser.
10
+ */
11
+ export const useResourcePath = () => {
12
+ const [source, setSourceInternal] = useState<ScopedSource | null>(null);
13
+ const [resourceStack, setResourceStack] = useState<Array<Resource>>([]);
14
+
15
+ const setSource = useCallback((source: ScopedSource | null) => {
16
+ setSourceInternal(source);
17
+ setResourceStack([]);
18
+ }, []);
19
+
20
+ const push = useCallback(
21
+ (resource: Resource) => {
22
+ setResourceStack([...resourceStack, resource]);
23
+ },
24
+ [resourceStack],
25
+ );
26
+
27
+ const popUntil = useCallback(
28
+ (node: ScopedSource | Resource) => {
29
+ if ('source' in node) {
30
+ // source node selected, just switch to the source
31
+ setSource(node);
32
+ return;
33
+ }
34
+
35
+ // resource node selected
36
+ const newResourceStack = [...resourceStack];
37
+
38
+ // pop until we reach the node that was selected in the breadcrumb
39
+ while (newResourceStack.length > 0 && newResourceStack[newResourceStack.length - 1].id !== node?.id) {
40
+ newResourceStack.pop();
41
+ }
42
+
43
+ if (newResourceStack.length === 0) {
44
+ // if we didn't find the node clear the source to push the user back to the root
45
+ setSource(null);
46
+ } else {
47
+ setResourceStack(newResourceStack);
48
+ }
49
+ },
50
+ [source, resourceStack],
51
+ );
52
+
53
+ const hierarchy = useMemo<Hierarchy<ScopedSource | Resource>>(() => {
54
+ if (!source) {
55
+ return [];
56
+ }
57
+
58
+ return [
59
+ {
60
+ key: `source:${source.source.id}-resource:${source.resource?.id || 'unscoped'}`,
61
+ label: source.resource?.name || source.source.name,
62
+ node: source,
63
+ },
64
+ ...resourceStack.map((resource) => ({ key: resource.id, node: resource, label: resource.name })),
65
+ ];
66
+ }, [source, resourceStack]);
67
+
68
+ return {
69
+ source,
70
+ currentResource: (resourceStack[resourceStack.length - 1] || null) as Resource | null,
71
+ hierarchy,
72
+ setSource,
73
+ push,
74
+ popUntil,
75
+ };
76
+ };
@@ -0,0 +1,33 @@
1
+ import { renderHook, waitFor } from '@testing-library/react';
2
+ import { mockSource } from '../__mocks__/MockModels';
3
+ import { useSources } from './useSources';
4
+
5
+ describe('useSources', () => {
6
+ it('Should trigger and load the sources', async () => {
7
+ const sources = [mockSource()];
8
+ const onRequestSources = jest.fn().mockResolvedValue(sources);
9
+ const { result } = renderHook(() => useSources({ onRequestSources }));
10
+
11
+ expect(result.current.isLoading).toBe(true);
12
+ expect(result.current.error).toBe(null);
13
+ expect(result.current.sources).toEqual([]);
14
+
15
+ await waitFor(() => expect(result.current.isLoading).toBe(false));
16
+
17
+ expect(result.current.isLoading).toBe(false);
18
+ expect(result.current.error).toBe(null);
19
+ expect(result.current.sources).toBe(sources);
20
+ });
21
+
22
+ it('Should return the error if loading resources fails', async () => {
23
+ const error = new Error('Loading the sources failed.');
24
+ const onRequestSources = jest.fn().mockRejectedValue(error);
25
+ const { result } = renderHook(() => useSources({ onRequestSources }));
26
+
27
+ await waitFor(() => expect(result.current.isLoading).toBe(false));
28
+
29
+ expect(result.current.isLoading).toBe(false);
30
+ expect(result.current.error).toBe(error);
31
+ expect(result.current.sources).toEqual([]);
32
+ });
33
+ });
@@ -0,0 +1,33 @@
1
+ import { useCallback, useEffect, useState } from 'react';
2
+ import { Source } from '../types';
3
+
4
+ type UseSourcesProps = {
5
+ onRequestSources: () => Promise<Source[]>;
6
+ };
7
+
8
+ /**
9
+ * Loads and caches the source list when a component using the hook is mounted.
10
+ *
11
+ * @param {Function} onRequestSources
12
+ */
13
+ export const useSources = ({ onRequestSources }: UseSourcesProps) => {
14
+ const [isLoading, setIsLoading] = useState(true);
15
+ const [error, setError] = useState<Error | null>(null);
16
+ const [sources, setSources] = useState<Source[]>([]);
17
+ const loadSources = useCallback(() => {
18
+ onRequestSources()
19
+ .then((sources) => {
20
+ setIsLoading(false);
21
+ setSources(sources);
22
+ })
23
+ .catch((error) => {
24
+ setIsLoading(false);
25
+ setError(error);
26
+ });
27
+ }, []);
28
+
29
+ // trigger a load of the sources when the component using the hook is initially rendered.
30
+ useEffect(loadSources, []);
31
+
32
+ return { isLoading, error, sources, reload: loadSources };
33
+ };
@@ -27,13 +27,13 @@ Root.args = {
27
27
 
28
28
  export const Audio = Template.bind({});
29
29
  Audio.args = {
30
- icon: 'audio',
30
+ icon: 'audio_file',
31
31
  resourceSource: 'matrix',
32
32
  };
33
33
 
34
34
  export const Excel = Template.bind({});
35
35
  Excel.args = {
36
- icon: 'excel',
36
+ icon: 'excel_doc',
37
37
  resourceSource: 'matrix',
38
38
  };
39
39
 
@@ -57,19 +57,19 @@ Image.args = {
57
57
 
58
58
  export const Page = Template.bind({});
59
59
  Page.args = {
60
- icon: 'page',
60
+ icon: 'page_standard',
61
61
  resourceSource: 'matrix',
62
62
  };
63
63
 
64
64
  export const Pdf = Template.bind({});
65
65
  Pdf.args = {
66
- icon: 'pdf',
66
+ icon: 'pdf_file',
67
67
  resourceSource: 'matrix',
68
68
  };
69
69
 
70
70
  export const Powerpoint = Template.bind({});
71
71
  Powerpoint.args = {
72
- icon: 'powerpoint',
72
+ icon: 'powerpoint_doc',
73
73
  resourceSource: 'matrix',
74
74
  };
75
75
 
@@ -81,13 +81,13 @@ Site.args = {
81
81
 
82
82
  export const Video = Template.bind({});
83
83
  Video.args = {
84
- icon: 'video',
84
+ icon: 'video_file',
85
85
  resourceSource: 'matrix',
86
86
  };
87
87
 
88
88
  export const Word = Template.bind({});
89
89
  Word.args = {
90
- icon: 'word',
90
+ icon: 'word_doc',
91
91
  resourceSource: 'matrix',
92
92
  };
93
93
 
@@ -9,9 +9,7 @@ export const iconSources = {
9
9
 
10
10
  // The resource sources options
11
11
  export type ResourceSources = keyof typeof iconSources;
12
-
13
- // Get the list of possible icons from the icon sources
14
- export type IconOptions = keyof (typeof iconSources)[ResourceSources];
12
+ export type IconOptions = string;
15
13
 
16
14
  /**
17
15
  * Renders an icon based on the resource source and the icon name
@@ -39,18 +37,15 @@ function Icon({
39
37
  isDecorative?: boolean;
40
38
  } & React.HTMLAttributes<HTMLElement> &
41
39
  React.SVGAttributes<SVGElement>) {
42
- // Loop through the resource sources
43
- for (const source in iconSources) {
44
- // If the resource source is the current source and the icon is in the current source map, render the icon
45
- if (resourceSource === source && icon && icon in iconSources[source]) {
46
- // Get the icon from the current source map
47
- const Icon = iconSources[source][icon] as React.FunctionComponent<
48
- { isDecorative: boolean } & React.SVGProps<SVGSVGElement>
49
- >;
40
+ const icons = (iconSources[resourceSource] as any) || null;
41
+
42
+ // If the resource source is the current source and the icon is in the current source map, render the icon
43
+ if (icons && icon && icon in icons) {
44
+ // Get the icon from the current source map
45
+ const Icon = icons[icon] as React.FunctionComponent<{ isDecorative: boolean } & React.SVGProps<SVGSVGElement>>;
50
46
 
51
- // Render the icon
52
- return <Icon isDecorative={isDecorative} {...props} />;
53
- }
47
+ // Render the icon
48
+ return <Icon isDecorative={isDecorative} {...props} />;
54
49
  }
55
50
 
56
51
  // If the icon is not defined, render the default icon
@@ -24,7 +24,7 @@ export default function Audio({ isDecorative, ...props }: { isDecorative: boolea
24
24
  <circle cx="7.5" cy="16.5" fill="#73c0cb" r="2" stroke="#057e91" />
25
25
  <path d="m16 7 1 .32v7.18c0 .2761-.2239.5-.5.5s-.5-.2239-.5-.5z" fill="#057e91" />
26
26
  <circle cx="14.5" cy="14.5" fill="#73c0cb" r="2" stroke="#057e91" />
27
- {!isDecorative && <title>audio icon</title>}
27
+ {!isDecorative && <title>audio file icon</title>}
28
28
  </svg>
29
29
  );
30
30
  }
@@ -23,7 +23,7 @@ export default function Excel({ isDecorative, ...props }: { isDecorative: boolea
23
23
  <rect y="8" width="12" height="12" rx="2" fill="#4FAD6F" />
24
24
  <path d="M3.5 11.5L8.5 16.5" stroke="white" strokeLinecap="round" />
25
25
  <path d="M8.5 11.5L3.5 16.5" stroke="white" strokeLinecap="round" />
26
- {!isDecorative && <title>excel icon</title>}
26
+ {!isDecorative && <title>excel doc icon</title>}
27
27
  </svg>
28
28
  );
29
29
  }
@@ -2,17 +2,17 @@ import { Audio, Excel, Folder, GenericFile, Image, Page, Pdf, Powerpoint, Site,
2
2
 
3
3
  // Define our map of matrix types to icons
4
4
  const MatrixResourceMap = {
5
- audio: Audio,
6
- excel: Excel,
5
+ audio_file: Audio,
6
+ excel_doc: Excel,
7
7
  folder: Folder,
8
- generic_file: GenericFile,
8
+ generic_file: GenericFile, // fallback when a type doesn't match.
9
9
  image: Image,
10
10
  page_standard: Page,
11
- pdf: Pdf,
12
- powerpoint: Powerpoint,
11
+ pdf_file: Pdf,
12
+ powerpoint_doc: Powerpoint,
13
13
  site: Site,
14
- video: Video,
15
- word: Word,
14
+ video_file: Video,
15
+ word_doc: Word,
16
16
  };
17
17
 
18
18
  // Export our map
@@ -28,7 +28,7 @@ export default function Pdf({ isDecorative, ...props }: { isDecorative: boolean
28
28
  <path d="m11.5 17.5v-3.8c0-.1105.0895-.2.2-.2h1.8" />
29
29
  <path d="m11.5 15.5h1" />
30
30
  </g>
31
- {!isDecorative && <title>pdf icon</title>}
31
+ {!isDecorative && <title>pdf file icon</title>}
32
32
  </svg>
33
33
  );
34
34
  }
@@ -28,7 +28,7 @@ export default function Powerpoint({
28
28
  <path d="m3.5 11.5v5" />
29
29
  <path d="m3.5 11.5h3.5c.33333 0 1.5 0 1.5 1.5s-1.16667 1.5-1.5 1.5h-3" />
30
30
  </g>
31
- {!isDecorative && <title>powerpoint icon</title>}
31
+ {!isDecorative && <title>powerpoint doc icon</title>}
32
32
  </svg>
33
33
  );
34
34
  }
@@ -21,7 +21,7 @@ export default function Video({ isDecorative, ...props }: { isDecorative: boolea
21
21
  stroke="#6b47b4"
22
22
  strokeLinecap="round"
23
23
  />
24
- {!isDecorative && <title>video icon</title>}
24
+ {!isDecorative && <title>video file icon</title>}
25
25
  </svg>
26
26
  );
27
27
  }
@@ -24,7 +24,7 @@ export default function Word({ isDecorative, ...props }: { isDecorative: boolean
24
24
  <path d="m14.5 3v3.5c0 .55228.4477 1 1 1h3.5" stroke="#bcbcbc" />
25
25
  <rect fill="#0774d2" height="12" rx="2" width="12" y="8" />
26
26
  <path d="m2.5 11.5 1.5 5 2-5 2 5 1.5-5" stroke="#fff" strokeLinecap="round" strokeLinejoin="round" />
27
- {!isDecorative && <title>word icon</title>}
27
+ {!isDecorative && <title>word doc icon</title>}
28
28
  </svg>
29
29
  );
30
30
  }
@@ -44,7 +44,7 @@ function Modal({ isDismissable, state, overlayProps, children, ...props }: Modal
44
44
  <div className="squiz-rb-scope">
45
45
  <div
46
46
  {...underlayProps}
47
- className="h-full z-[9999] fixed inset-0 before:z-40 before:fixed before:inset-0 before:bg-black before:bg-opacity-25"
47
+ className="h-full z-[9998] fixed inset-0 before:z-40 before:fixed before:inset-0 before:bg-black before:bg-opacity-25"
48
48
  >
49
49
  <div {...modalProps} ref={ref} className="h-full flex items-center justify-center">
50
50
  <ModalContent {...overlayProps}>{(titleProps) => children(titleProps)}</ModalContent>
@@ -77,7 +77,7 @@ function PreviewModal({ state, overlayProps, children, onClose, ...props }: Prev
77
77
  ref={modalRef}
78
78
  {...underlayProps}
79
79
  {...keyboardProps}
80
- className="fixed z-50 overflow-y-scroll bottom-0 w-full h-[50vh] bg-white border-t border-gray-300"
80
+ className="fixed z-[9999] overflow-y-scroll bottom-0 w-full h-[50vh] bg-white border-t border-gray-300"
81
81
  >
82
82
  <div ref={overlayRef} {...modalProps} className="h-full">
83
83
  <PreviewModalContent {...overlayProps} onClose={onClose}>