@comicrelief/component-library 8.53.2 → 8.54.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 (26) hide show
  1. package/dist/components/Atoms/Picture/Picture.js +1 -0
  2. package/dist/components/Molecules/SingleMessage/SingleMessage.js +12 -3
  3. package/dist/components/Molecules/SingleMessage/SingleMessage.md +5 -32
  4. package/dist/components/Molecules/SingleMessage/SingleMessage.style.js +38 -39
  5. package/dist/components/Molecules/SingleMessage/__snapshots__/SingleMessage.test.js.snap +27 -43
  6. package/dist/components/Organisms/DynamicGallery/DynamicGallery.js +43 -24
  7. package/dist/components/Organisms/DynamicGallery/DynamicGallery.md +1 -1
  8. package/dist/components/Organisms/DynamicGallery/DynamicGallery.style.js +29 -16
  9. package/dist/components/Organisms/DynamicGallery/_DynamicGalleryColumn.js +8 -3
  10. package/dist/components/Organisms/DynamicGallery/_Lightbox.js +45 -24
  11. package/dist/components/Organisms/DynamicGallery/_Lightbox.style.js +7 -11
  12. package/dist/components/Organisms/DynamicGallery/__snapshots__/DynamicGallery.test.js.snap +254 -216
  13. package/package.json +1 -1
  14. package/playwright/components/organisms/dynamicGallery.spec.js +222 -1
  15. package/src/components/Atoms/Picture/Picture.js +1 -0
  16. package/src/components/Molecules/SingleMessage/SingleMessage.js +14 -3
  17. package/src/components/Molecules/SingleMessage/SingleMessage.md +5 -32
  18. package/src/components/Molecules/SingleMessage/SingleMessage.style.js +11 -12
  19. package/src/components/Molecules/SingleMessage/__snapshots__/SingleMessage.test.js.snap +27 -43
  20. package/src/components/Organisms/DynamicGallery/DynamicGallery.js +48 -25
  21. package/src/components/Organisms/DynamicGallery/DynamicGallery.md +1 -1
  22. package/src/components/Organisms/DynamicGallery/DynamicGallery.style.js +23 -1
  23. package/src/components/Organisms/DynamicGallery/_DynamicGalleryColumn.js +8 -3
  24. package/src/components/Organisms/DynamicGallery/_Lightbox.js +36 -19
  25. package/src/components/Organisms/DynamicGallery/_Lightbox.style.js +16 -29
  26. package/src/components/Organisms/DynamicGallery/__snapshots__/DynamicGallery.test.js.snap +254 -216
@@ -4,12 +4,12 @@ var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWild
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.InteractiveGalleryNode = exports.ImageGrid = exports.ImageContainer = exports.GalleryNode = exports.EmptyMessage = exports.Details = exports.Container = exports.Column = void 0;
7
+ exports.ScreenReaderOnly = exports.InteractiveGalleryNode = exports.ImageGrid = exports.ImageContainer = exports.GalleryNode = exports.FocusTrap = exports.EmptyMessage = exports.Details = exports.Container = exports.Column = void 0;
8
8
  var _styledComponents = _interopRequireWildcard(require("styled-components"));
9
9
  const Container = exports.Container = _styledComponents.default.div.withConfig({
10
10
  displayName: "DynamicGallerystyle__Container",
11
11
  componentId: "sc-1kgt7yr-0"
12
- })(["display:flex;flex-direction:column;align-items:center;gap:1rem;max-width:", ";background:", ";", " color:", ";"], _ref => {
12
+ })(["display:flex;flex-direction:column;align-items:center;gap:1rem;position:relative;max-width:", ";background:", ";padding:", ";color:", ";@media ", "{gap:1rem;}"], _ref => {
13
13
  let {
14
14
  maxWidth
15
15
  } = _ref;
@@ -25,45 +25,50 @@ const Container = exports.Container = _styledComponents.default.div.withConfig({
25
25
  paddingTop,
26
26
  paddingBottom
27
27
  } = _ref3;
28
- return (0, _styledComponents.css)(["padding:", " 2rem ", ";"], paddingTop, paddingBottom);
28
+ return `${paddingTop} 1rem ${paddingBottom}`;
29
29
  }, _ref4 => {
30
30
  let {
31
31
  theme,
32
32
  textColour
33
33
  } = _ref4;
34
34
  return theme.color(textColour);
35
+ }, _ref5 => {
36
+ let {
37
+ theme
38
+ } = _ref5;
39
+ return theme.breakpoints2026('M');
35
40
  });
36
41
  const ImageGrid = exports.ImageGrid = _styledComponents.default.div.withConfig({
37
42
  displayName: "DynamicGallerystyle__ImageGrid",
38
43
  componentId: "sc-1kgt7yr-1"
39
- })(["display:flex;gap:1rem;width:100%;@media ", "{gap:2rem;}"], _ref5 => {
44
+ })(["display:flex;gap:1rem;width:100%;@media ", "{gap:2rem;}"], _ref6 => {
40
45
  let {
41
46
  theme
42
- } = _ref5;
47
+ } = _ref6;
43
48
  return theme.breakpoints2026('M');
44
49
  });
45
50
  const Column = exports.Column = _styledComponents.default.div.withConfig({
46
51
  displayName: "DynamicGallerystyle__Column",
47
52
  componentId: "sc-1kgt7yr-2"
48
- })(["flex:1;display:flex;flex-direction:column;gap:1.1rem;@media ", "{gap:2rem;}"], _ref6 => {
53
+ })(["flex:1;display:flex;flex-direction:column;gap:1.1rem;@media ", "{gap:2rem;}"], _ref7 => {
49
54
  let {
50
55
  theme
51
- } = _ref6;
56
+ } = _ref7;
52
57
  return theme.breakpoints2026('M');
53
58
  });
54
59
  const EmptyMessage = exports.EmptyMessage = _styledComponents.default.div.withConfig({
55
60
  displayName: "DynamicGallerystyle__EmptyMessage",
56
61
  componentId: "sc-1kgt7yr-3"
57
- })(["display:", ";"], _ref7 => {
62
+ })(["display:", ";"], _ref8 => {
58
63
  let {
59
64
  isEmpty
60
- } = _ref7;
65
+ } = _ref8;
61
66
  return isEmpty ? 'block' : 'none';
62
67
  });
63
- const GalleryNodeBase = (0, _styledComponents.css)(["display:flex;flex-direction:column;gap:0.9rem;padding:0;margin:0;background:none;border:none;text-align:left;&:focus-visible{outline:2px solid ", ";outline-offset:0.5rem;border-radius:1rem;}"], _ref8 => {
68
+ const GalleryNodeBase = (0, _styledComponents.css)(["display:flex;flex-direction:column;gap:0.9rem;padding:0;margin:0;background:none;border:none;text-align:left;&:focus-visible{outline:2px solid ", ";outline-offset:0.5rem;border-radius:1rem;}"], _ref9 => {
64
69
  let {
65
70
  focusOutlineColour
66
- } = _ref8;
71
+ } = _ref9;
67
72
  return focusOutlineColour;
68
73
  });
69
74
  const GalleryNode = exports.GalleryNode = _styledComponents.default.div.withConfig({
@@ -77,18 +82,26 @@ const InteractiveGalleryNode = exports.InteractiveGalleryNode = _styledComponent
77
82
  const ImageContainer = exports.ImageContainer = _styledComponents.default.div.withConfig({
78
83
  displayName: "DynamicGallerystyle__ImageContainer",
79
84
  componentId: "sc-1kgt7yr-6"
80
- })(["display:flex;height:auto;width:100%;min-height:", ";max-height:", ";overflow:hidden;border-radius:1rem;background:rgba(0,0,0,0.05);box-shadow:0px 2px 8px 0px rgba(0,0,0,0.2);img{height:100%;opacity:0;transition:opacity 0.1s ease-out 0.3s;}"], _ref9 => {
85
+ })(["display:flex;height:auto;width:100%;min-height:", ";max-height:", ";overflow:hidden;border-radius:1rem;background:rgba(0,0,0,0.05);box-shadow:0px 2px 8px 0px rgba(0,0,0,0.2);img{height:100%;opacity:0;transition:opacity 0.1s ease-out 0.3s;}"], _ref10 => {
81
86
  let {
82
87
  minHeight
83
- } = _ref9;
88
+ } = _ref10;
84
89
  return minHeight;
85
- }, _ref10 => {
90
+ }, _ref11 => {
86
91
  let {
87
92
  maxHeight
88
- } = _ref10;
93
+ } = _ref11;
89
94
  return maxHeight;
90
95
  });
91
96
  const Details = exports.Details = _styledComponents.default.div.withConfig({
92
97
  displayName: "DynamicGallerystyle__Details",
93
98
  componentId: "sc-1kgt7yr-7"
94
- })(["display:flex;flex-direction:column;gap:0.5rem;padding:0 1rem;"]);
99
+ })(["display:flex;flex-direction:column;gap:0.5rem;padding:0 1rem;"]);
100
+ const ScreenReaderOnly = exports.ScreenReaderOnly = _styledComponents.default.span.withConfig({
101
+ displayName: "DynamicGallerystyle__ScreenReaderOnly",
102
+ componentId: "sc-1kgt7yr-8"
103
+ })(["position:absolute;width:1px;height:1px;margin:-1px;border:0;padding:0;white-space:nowrap;clip-path:inset(100%);clip:rect(0 0 0 0);overflow:hidden;"]);
104
+ const FocusTrap = exports.FocusTrap = (0, _styledComponents.default)(ScreenReaderOnly).withConfig({
105
+ displayName: "DynamicGallerystyle__FocusTrap",
106
+ componentId: "sc-1kgt7yr-9"
107
+ })(["bottom:0;"]);
@@ -81,9 +81,15 @@ function DynamicGalleryColumn(_ref) {
81
81
  return /*#__PURE__*/_react.default.createElement(_DynamicGallery.Column, {
82
82
  ref: elRef,
83
83
  className: "gallery-column"
84
- }, nodes === null || nodes === void 0 ? void 0 : nodes.filter((_, nodeIndex) => nodeIndex % columnCount === columnIndex).map((node, nodeIndex) => {
84
+ }, nodes.map((node, nodeIndex) => {
85
+ // only render nodes that are in the current column;
86
+ // this lets us assign a unique index to each node
87
+ const columnNodeIndex = nodeIndex % columnCount;
88
+ if (columnNodeIndex !== columnIndex) return null;
85
89
  const bodyText = (0, _utils.extractNodeText)(node.gridBody);
86
- const key = String(nodeIndex) + bodyText;
90
+ // eslint prefers template literals for strings, but they break the compiler
91
+ // eslint-disable-next-line prefer-template
92
+ const key = String(nodeIndex) + ':' + bodyText + ':' + node.image;
87
93
  return /*#__PURE__*/_react.default.createElement(NodeComponent, {
88
94
  key: key,
89
95
  className: "gallery-node",
@@ -96,7 +102,6 @@ function DynamicGalleryColumn(_ref) {
96
102
  tabIndex: 0
97
103
  }, /*#__PURE__*/_react.default.createElement(_DynamicGallery.ImageContainer, {
98
104
  className: "gallery-node-image"
99
- // eslint prefers template literals for strings, but they break the compiler
100
105
  // eslint-disable-next-line prefer-template
101
106
  ,
102
107
  minHeight: String(minHeight) + 'px'
@@ -12,6 +12,7 @@ var _Arrow = _interopRequireDefault(require("../../Atoms/Icons/Arrow"));
12
12
  var _Cross = _interopRequireDefault(require("../../Atoms/Icons/Cross"));
13
13
  var _Picture = _interopRequireDefault(require("../../Atoms/Picture/Picture"));
14
14
  var _Lightbox = require("./_Lightbox.style");
15
+ var _DynamicGallery = require("./DynamicGallery.style");
15
16
  var _ScrollFix = _interopRequireDefault(require("./_ScrollFix"));
16
17
  var _utils = require("./_utils");
17
18
  /**
@@ -52,6 +53,19 @@ const Lightbox = () => {
52
53
  const hasNode = Boolean(selectedNode);
53
54
  const dialogRef = (0, _react.useRef)(null);
54
55
 
56
+ // handle interaction type
57
+ const interactionTypeRef = (0, _react.useRef)('keyboard');
58
+ (0, _react.useEffect)(() => {
59
+ function handlePointerDown() {
60
+ interactionTypeRef.current = 'pointer';
61
+ document.removeEventListener('pointerdown', handlePointerDown);
62
+ }
63
+ document.addEventListener('pointerdown', handlePointerDown);
64
+ return () => {
65
+ document.removeEventListener('pointerdown', handlePointerDown);
66
+ };
67
+ }, []);
68
+
55
69
  /**
56
70
  * handle keyboard events within the lightbox;
57
71
  * - trapped focus between UI elements
@@ -107,13 +121,15 @@ const Lightbox = () => {
107
121
  // handle focus management when dialog opens/closes
108
122
  (0, _react.useEffect)(() => {
109
123
  if (hasNode) {
110
- // move focus to the first focusable element in the dialog when it opens
111
- setTimeout(() => {
112
- const focusableElements = getFocusableElements(dialogRef.current);
113
- if (focusableElements.length > 0) {
114
- focusableElements[0].focus();
124
+ // when the lightbox opens, optionally focus the close button,
125
+ // but only if the user is interacting via the keyboard;
126
+ // we check interaction type because although focus-visible should handle this,
127
+ // Safari on iOS always shows the focus ring
128
+ requestAnimationFrame(() => {
129
+ if (interactionTypeRef.current === 'keyboard') {
130
+ dialogRef.current.querySelector('.close-button').focus();
115
131
  }
116
- }, 0);
132
+ });
117
133
  } else {
118
134
  // restore focus to the previously focused element when lightbox closes
119
135
  focusedNode === null || focusedNode === void 0 ? void 0 : focusedNode.focus();
@@ -150,8 +166,8 @@ const Lightbox = () => {
150
166
  const scaleX = maxWidth / imageWidth;
151
167
  const scaleY = maxHeight / imageHeight;
152
168
  const scale = Math.min(scaleX, scaleY);
153
- const width = imageWidth * scale;
154
- const height = imageHeight * scale;
169
+ const width = Math.round(imageWidth * scale);
170
+ const height = Math.round(imageHeight * scale);
155
171
 
156
172
  // set the width and height on the image element, and make it visible
157
173
  setImageDimensions({
@@ -182,33 +198,38 @@ const Lightbox = () => {
182
198
  width: imageDimensions.width,
183
199
  height: imageDimensions.height,
184
200
  objectFit: "contain",
185
- onLoad: event => onLoad(event)
186
- })), /*#__PURE__*/_react.default.createElement(_Lightbox.LightboxDetails, {
187
- id: "lightboxDescription",
188
- "aria-live": "polite",
189
- "aria-atomic": "true"
190
- }, (selectedNode === null || selectedNode === void 0 ? void 0 : selectedNode.lightboxBody) && /*#__PURE__*/_react.default.createElement("div", {
191
- id: "lightboxTitle"
192
- }, selectedNode.lightboxBody), (selectedNode === null || selectedNode === void 0 ? void 0 : selectedNode.lightboxCaption) && /*#__PURE__*/_react.default.createElement("div", null, selectedNode === null || selectedNode === void 0 ? void 0 : selectedNode.lightboxCaption)), /*#__PURE__*/_react.default.createElement(_Lightbox.CloseButton, {
193
- type: "button",
194
- onClick: () => setSelectedNode(null)
195
- }, /*#__PURE__*/_react.default.createElement(_Lightbox.ScreenReaderOnly, null, "Close"), /*#__PURE__*/_react.default.createElement(_Cross.default, {
196
- colour: "black",
197
- size: 16
198
- })), /*#__PURE__*/_react.default.createElement(_Lightbox.PreviousButton, {
201
+ onLoad: event => onLoad(event),
202
+ style: {
203
+ borderRadius: '0.6rem',
204
+ overflow: 'hidden'
205
+ }
206
+ }), /*#__PURE__*/_react.default.createElement(_Lightbox.PreviousButton, {
199
207
  type: "button",
200
208
  onClick: () => previousNode(selectedNode)
201
- }, /*#__PURE__*/_react.default.createElement(_Lightbox.ScreenReaderOnly, null, "Previous"), /*#__PURE__*/_react.default.createElement(_Arrow.default, {
209
+ }, /*#__PURE__*/_react.default.createElement(_DynamicGallery.ScreenReaderOnly, null, "Previous"), /*#__PURE__*/_react.default.createElement(_Arrow.default, {
202
210
  direction: "left",
203
211
  colour: "black",
204
212
  size: 16
205
213
  })), /*#__PURE__*/_react.default.createElement(_Lightbox.NextButton, {
206
214
  type: "button",
207
215
  onClick: () => nextNode(selectedNode)
208
- }, /*#__PURE__*/_react.default.createElement(_Lightbox.ScreenReaderOnly, null, "Next"), /*#__PURE__*/_react.default.createElement(_Arrow.default, {
216
+ }, /*#__PURE__*/_react.default.createElement(_DynamicGallery.ScreenReaderOnly, null, "Next"), /*#__PURE__*/_react.default.createElement(_Arrow.default, {
209
217
  direction: "right",
210
218
  colour: "black",
211
219
  size: 16
220
+ }))), /*#__PURE__*/_react.default.createElement(_Lightbox.LightboxDetails, {
221
+ id: "lightboxDescription",
222
+ "aria-live": "polite",
223
+ "aria-atomic": "true"
224
+ }, (selectedNode === null || selectedNode === void 0 ? void 0 : selectedNode.lightboxBody) && /*#__PURE__*/_react.default.createElement("div", {
225
+ id: "lightboxTitle"
226
+ }, selectedNode.lightboxBody), (selectedNode === null || selectedNode === void 0 ? void 0 : selectedNode.lightboxCaption) && /*#__PURE__*/_react.default.createElement("div", null, selectedNode === null || selectedNode === void 0 ? void 0 : selectedNode.lightboxCaption)), /*#__PURE__*/_react.default.createElement(_Lightbox.CloseButton, {
227
+ className: "close-button",
228
+ type: "button",
229
+ onClick: () => setSelectedNode(null)
230
+ }, /*#__PURE__*/_react.default.createElement(_DynamicGallery.ScreenReaderOnly, null, "Close"), /*#__PURE__*/_react.default.createElement(_Cross.default, {
231
+ colour: "black",
232
+ size: 16
212
233
  })))));
213
234
  };
214
235
  var _default = exports.default = Lightbox;
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.ScreenReaderOnly = exports.PreviousButton = exports.NextButton = exports.NavButton = exports.LightboxSpinner = exports.LightboxImage = exports.LightboxDetails = exports.LightboxContent = exports.Dialog = exports.Container = exports.CloseButton = exports.Backdrop = void 0;
7
+ exports.PreviousButton = exports.NextButton = exports.NavButton = exports.LightboxSpinner = exports.LightboxImage = exports.LightboxDetails = exports.LightboxContent = exports.Dialog = exports.Container = exports.CloseButton = exports.Backdrop = void 0;
8
8
  var _styledComponents = _interopRequireDefault(require("styled-components"));
9
9
  const Container = exports.Container = _styledComponents.default.div.withConfig({
10
10
  displayName: "_Lightboxstyle__Container",
@@ -35,7 +35,7 @@ const LightboxContent = exports.LightboxContent = _styledComponents.default.div.
35
35
  const LightboxImage = exports.LightboxImage = _styledComponents.default.div.withConfig({
36
36
  displayName: "_Lightboxstyle__LightboxImage",
37
37
  componentId: "sc-twdy7x-4"
38
- })(["position:relative;display:flex;align-items:center;justify-content:center;min-width:128px;min-height:32px;border-radius:0.6rem;overflow:hidden;& > div{display:flex;align-items:center;justify-content:center;transition:width 0.3s ease-in-out,height 0.3s ease-in-out;}& img{opacity:0;transition:opacity 0.1s ease-out 0.3s;}"]);
38
+ })(["position:relative;display:flex;align-items:center;justify-content:center;min-width:128px;min-height:32px;width:100%;& > div{display:flex;align-items:center;justify-content:center;transition:width 0.3s ease-in-out,height 0.3s ease-in-out;}& img{opacity:0;transition:opacity 0.1s ease-out 0.3s;}"]);
39
39
  const LightboxSpinner = exports.LightboxSpinner = _styledComponents.default.div.withConfig({
40
40
  displayName: "_Lightboxstyle__LightboxSpinner",
41
41
  componentId: "sc-twdy7x-5"
@@ -43,11 +43,11 @@ const LightboxSpinner = exports.LightboxSpinner = _styledComponents.default.div.
43
43
  const LightboxDetails = exports.LightboxDetails = _styledComponents.default.div.withConfig({
44
44
  displayName: "_Lightboxstyle__LightboxDetails",
45
45
  componentId: "sc-twdy7x-6"
46
- })(["display:flex;flex-direction:column;align-items:stretch;gap:0.5rem;width:100%;padding:0 1rem;"]);
46
+ })(["display:flex;flex-direction:column;align-items:stretch;gap:0.5rem;width:100%;max-width:1024px;padding:0 1rem;"]);
47
47
  const NavButton = exports.NavButton = _styledComponents.default.button.withConfig({
48
48
  displayName: "_Lightboxstyle__NavButton",
49
49
  componentId: "sc-twdy7x-7"
50
- })(["position:absolute;display:flex;align-items:center;justify-content:center;width:2.5rem;height:2.5rem;border-radius:0.5rem;border:none;background-color:white;cursor:pointer;z-index:10;svg{transition:all 0.1s ease-out;}&:hover{svg{fill:", ";}}&:focus-visible{outline:2px solid ", ";}"], _ref3 => {
50
+ })(["position:absolute;display:flex;align-items:center;justify-content:center;width:2.5rem;height:2.5rem;border-radius:0.5rem;border:none;background-color:white;cursor:pointer;z-index:10;svg{transition:fill 0.1s ease-out;}@media (hover:hover){&:hover{svg{fill:", ";}}}:focus-visible{outline:2px solid ", ";}"], _ref3 => {
51
51
  let {
52
52
  theme
53
53
  } = _ref3;
@@ -65,7 +65,7 @@ const CloseButton = exports.CloseButton = (0, _styledComponents.default)(NavButt
65
65
  const PreviousButton = exports.PreviousButton = (0, _styledComponents.default)(NavButton).withConfig({
66
66
  displayName: "_Lightboxstyle__PreviousButton",
67
67
  componentId: "sc-twdy7x-9"
68
- })(["top:30%;left:0;transform:translate(0,-50%);border-top-left-radius:0;border-bottom-left-radius:0;@media ", "{position:fixed;top:50%;}"], _ref5 => {
68
+ })(["top:50%;left:0;transform:translate(-1rem,-50%);@media ", "{position:fixed;transform:translate(1rem,-50%);top:50%;}"], _ref5 => {
69
69
  let {
70
70
  theme
71
71
  } = _ref5;
@@ -74,13 +74,9 @@ const PreviousButton = exports.PreviousButton = (0, _styledComponents.default)(N
74
74
  const NextButton = exports.NextButton = (0, _styledComponents.default)(NavButton).withConfig({
75
75
  displayName: "_Lightboxstyle__NextButton",
76
76
  componentId: "sc-twdy7x-10"
77
- })(["top:30%;right:0;transform:translate(0,-50%);border-top-right-radius:0;border-bottom-right-radius:0;@media ", "{position:fixed;top:50%;}"], _ref6 => {
77
+ })(["top:50%;right:0;transform:translate(1rem,-50%);@media ", "{position:fixed;transform:translate(-1rem,-50%);top:50%;}"], _ref6 => {
78
78
  let {
79
79
  theme
80
80
  } = _ref6;
81
81
  return theme.breakpoints2026('L');
82
- });
83
- const ScreenReaderOnly = exports.ScreenReaderOnly = _styledComponents.default.span.withConfig({
84
- displayName: "_Lightboxstyle__ScreenReaderOnly",
85
- componentId: "sc-twdy7x-11"
86
- })(["position:absolute;width:1px;height:1px;margin:-1px;border:0;padding:0;white-space:nowrap;clip-path:inset(100%);clip:rect(0 0 0 0);overflow:hidden;"]);
82
+ });