@comicrelief/component-library 8.52.1 → 8.52.2
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/dist/components/Organisms/DynamicGallery/DynamicGallery.js +9 -3
- package/dist/components/Organisms/DynamicGallery/DynamicGallery.style.js +13 -16
- package/dist/components/Organisms/DynamicGallery/_DynamicGalleryColumn.js +37 -28
- package/dist/components/Organisms/DynamicGallery/_Lightbox.js +14 -18
- package/dist/components/Organisms/DynamicGallery/__snapshots__/DynamicGallery.test.js.snap +64 -111
- package/dist/components/Organisms/DynamicGallery/_types.js +4 -3
- package/dist/components/Organisms/DynamicGallery/_utils.js +29 -3
- package/package.json +1 -1
- package/src/components/Organisms/DynamicGallery/DynamicGallery.js +8 -2
- package/src/components/Organisms/DynamicGallery/DynamicGallery.style.js +7 -15
- package/src/components/Organisms/DynamicGallery/_DynamicGalleryColumn.js +49 -41
- package/src/components/Organisms/DynamicGallery/_Lightbox.js +21 -26
- package/src/components/Organisms/DynamicGallery/__snapshots__/DynamicGallery.test.js.snap +64 -111
- package/src/components/Organisms/DynamicGallery/_types.js +4 -3
- package/src/components/Organisms/DynamicGallery/_utils.js +40 -3
|
@@ -10,21 +10,21 @@ import React, {
|
|
|
10
10
|
import Picture from '../../Atoms/Picture/Picture';
|
|
11
11
|
import { LightboxContext } from './_Lightbox';
|
|
12
12
|
import {
|
|
13
|
-
Caption,
|
|
14
13
|
Column,
|
|
15
14
|
Details,
|
|
16
15
|
GalleryNode,
|
|
17
16
|
ImageContainer,
|
|
18
|
-
InteractiveGalleryNode
|
|
19
|
-
Title
|
|
17
|
+
InteractiveGalleryNode
|
|
20
18
|
} from './DynamicGallery.style';
|
|
21
19
|
import { GalleryNodeType } from './_types';
|
|
20
|
+
import { extractNodeText } from './_utils';
|
|
22
21
|
|
|
23
22
|
/**
|
|
24
23
|
* a separate component to handle columns of images;
|
|
25
24
|
* this component handles aspect ratio calculations to enfore a min/max ratio for its images
|
|
26
25
|
*/
|
|
27
26
|
export default function DynamicGalleryColumn({
|
|
27
|
+
focusOutlineColour,
|
|
28
28
|
updateTabOrder,
|
|
29
29
|
nodes,
|
|
30
30
|
imageRatio,
|
|
@@ -92,45 +92,52 @@ export default function DynamicGalleryColumn({
|
|
|
92
92
|
<Column ref={elRef} className="gallery-column">
|
|
93
93
|
{nodes
|
|
94
94
|
?.filter((_, nodeIndex) => nodeIndex % columnCount === columnIndex)
|
|
95
|
-
.map((node, nodeIndex) =>
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
// eslint-disable-next-line prefer-template
|
|
110
|
-
maxHeight={String(maxHeight) + 'px'}
|
|
95
|
+
.map((node, nodeIndex) => {
|
|
96
|
+
const bodyText = extractNodeText(node.gridBody);
|
|
97
|
+
const key = String(nodeIndex) + bodyText;
|
|
98
|
+
return (
|
|
99
|
+
<NodeComponent
|
|
100
|
+
key={key}
|
|
101
|
+
className="gallery-node"
|
|
102
|
+
caption={bodyText}
|
|
103
|
+
aria-label={bodyText}
|
|
104
|
+
title={bodyText}
|
|
105
|
+
data-node-index={nodeIndex}
|
|
106
|
+
focusOutlineColour={focusOutlineColour}
|
|
107
|
+
onPointerUp={useLightbox ? () => handlePointerUp(node) : undefined}
|
|
108
|
+
tabIndex={0}
|
|
111
109
|
>
|
|
112
|
-
<
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
110
|
+
<ImageContainer
|
|
111
|
+
className="gallery-node-image"
|
|
112
|
+
// eslint prefers template literals for strings, but they break the compiler
|
|
113
|
+
// eslint-disable-next-line prefer-template
|
|
114
|
+
minHeight={String(minHeight) + 'px'}
|
|
115
|
+
// eslint-disable-next-line prefer-template
|
|
116
|
+
maxHeight={String(maxHeight) + 'px'}
|
|
117
|
+
>
|
|
118
|
+
<Picture
|
|
119
|
+
image={node.image}
|
|
120
|
+
objectFit="cover"
|
|
121
|
+
alt={bodyText}
|
|
122
|
+
// animate image in on load
|
|
123
|
+
onLoad={event => {
|
|
124
|
+
event.target
|
|
125
|
+
.closest('.gallery-node-image')
|
|
126
|
+
.querySelector('img')
|
|
127
|
+
.style.setProperty('opacity', '1');
|
|
122
128
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
129
|
+
// update tab order once the image has loaded
|
|
130
|
+
updateTabOrder();
|
|
131
|
+
}}
|
|
132
|
+
/>
|
|
133
|
+
</ImageContainer>
|
|
134
|
+
<Details>
|
|
135
|
+
{node.gridBody && <div>{node.gridBody}</div>}
|
|
136
|
+
{node.gridCaption && <div>{node.gridCaption}</div>}
|
|
137
|
+
</Details>
|
|
138
|
+
</NodeComponent>
|
|
139
|
+
);
|
|
140
|
+
})}
|
|
134
141
|
</Column>
|
|
135
142
|
);
|
|
136
143
|
}
|
|
@@ -140,5 +147,6 @@ DynamicGalleryColumn.propTypes = {
|
|
|
140
147
|
imageRatio: PropTypes.oneOf(['dynamic', '4:3']),
|
|
141
148
|
columnIndex: PropTypes.number,
|
|
142
149
|
columnCount: PropTypes.number,
|
|
143
|
-
updateTabOrder: PropTypes.func
|
|
150
|
+
updateTabOrder: PropTypes.func,
|
|
151
|
+
focusOutlineColour: PropTypes.string
|
|
144
152
|
};
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
ScreenReaderOnly
|
|
20
20
|
} from './_Lightbox.style';
|
|
21
21
|
import ScrollFix from './_ScrollFix';
|
|
22
|
+
import { extractNodeText } from './_utils';
|
|
22
23
|
|
|
23
24
|
/**
|
|
24
25
|
* lightbox context:
|
|
@@ -59,12 +60,13 @@ const Lightbox = () => {
|
|
|
59
60
|
selectedNode,
|
|
60
61
|
setSelectedNode,
|
|
61
62
|
nextNode,
|
|
62
|
-
previousNode
|
|
63
|
+
previousNode,
|
|
64
|
+
focusedNode,
|
|
65
|
+
setFocusedNode
|
|
63
66
|
} = useContext(LightboxContext);
|
|
64
67
|
|
|
65
68
|
const hasNode = Boolean(selectedNode);
|
|
66
69
|
const dialogRef = useRef(null);
|
|
67
|
-
const previousFocusRef = useRef(null);
|
|
68
70
|
|
|
69
71
|
/**
|
|
70
72
|
* handle keyboard events within the lightbox;
|
|
@@ -125,30 +127,20 @@ const Lightbox = () => {
|
|
|
125
127
|
|
|
126
128
|
// handle focus management when dialog opens/closes
|
|
127
129
|
useEffect(() => {
|
|
128
|
-
// when the lightbox is opened, store the previously focused element
|
|
129
|
-
// and move focus to the first focusable element in the dialog
|
|
130
130
|
if (hasNode) {
|
|
131
|
-
//
|
|
132
|
-
previousFocusRef.current = document.activeElement;
|
|
133
|
-
// move focus to the first focusable element in the dialog
|
|
131
|
+
// move focus to the first focusable element in the dialog when it opens
|
|
134
132
|
setTimeout(() => {
|
|
135
133
|
const focusableElements = getFocusableElements(dialogRef.current);
|
|
136
134
|
if (focusableElements.length > 0) {
|
|
137
135
|
focusableElements[0].focus();
|
|
138
136
|
}
|
|
139
137
|
}, 0);
|
|
140
|
-
|
|
138
|
+
} else {
|
|
139
|
+
// restore focus to the previously focused element when lightbox closes
|
|
140
|
+
focusedNode?.focus();
|
|
141
|
+
setFocusedNode(null);
|
|
141
142
|
}
|
|
142
|
-
|
|
143
|
-
// when the lightbox is closed, restore focus to the previously focused element
|
|
144
|
-
if (
|
|
145
|
-
previousFocusRef.current
|
|
146
|
-
&& typeof previousFocusRef.current.focus === 'function'
|
|
147
|
-
) {
|
|
148
|
-
previousFocusRef.current.focus();
|
|
149
|
-
previousFocusRef.current = null;
|
|
150
|
-
}
|
|
151
|
-
}, [hasNode]);
|
|
143
|
+
}, [hasNode, focusedNode, setFocusedNode]);
|
|
152
144
|
|
|
153
145
|
/**
|
|
154
146
|
* close the lightbox when the backdrop is clicked
|
|
@@ -182,9 +174,13 @@ const Lightbox = () => {
|
|
|
182
174
|
target.style.opacity = '1';
|
|
183
175
|
}
|
|
184
176
|
|
|
177
|
+
const bodyText = extractNodeText(selectedNode?.lightboxBody);
|
|
178
|
+
|
|
185
179
|
return (
|
|
186
180
|
<Container isOpen={hasNode}>
|
|
187
|
-
<Backdrop
|
|
181
|
+
<Backdrop
|
|
182
|
+
onPointerUp={() => handleBackdropClick()}
|
|
183
|
+
/>
|
|
188
184
|
<Dialog
|
|
189
185
|
ref={dialogRef}
|
|
190
186
|
aria-labelledby="lightboxTitle"
|
|
@@ -199,7 +195,7 @@ const Lightbox = () => {
|
|
|
199
195
|
{hasNode && (
|
|
200
196
|
<Picture
|
|
201
197
|
key={selectedNode?.image}
|
|
202
|
-
alt={
|
|
198
|
+
alt={bodyText}
|
|
203
199
|
image={selectedNode?.image}
|
|
204
200
|
width={imageDimensions.width}
|
|
205
201
|
height={imageDimensions.height}
|
|
@@ -209,15 +205,14 @@ const Lightbox = () => {
|
|
|
209
205
|
)}
|
|
210
206
|
</LightboxImage>
|
|
211
207
|
<LightboxDetails id="lightboxDescription" aria-live="polite" aria-atomic="true">
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
{selectedNode?.caption}
|
|
208
|
+
{selectedNode?.lightboxBody && (
|
|
209
|
+
<div id="lightboxTitle">
|
|
210
|
+
{selectedNode.lightboxBody}
|
|
216
211
|
</div>
|
|
217
212
|
)}
|
|
218
|
-
{selectedNode?.
|
|
213
|
+
{selectedNode?.lightboxCaption && (
|
|
219
214
|
<div>
|
|
220
|
-
{selectedNode
|
|
215
|
+
{selectedNode?.lightboxCaption}
|
|
221
216
|
</div>
|
|
222
217
|
)}
|
|
223
218
|
</LightboxDetails>
|