@jobber/components 6.113.1 → 6.114.1

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.
@@ -1,8 +1,9 @@
1
- import React__default, { useState, useRef, useEffect } from 'react';
1
+ import React__default, { createContext, useContext, useState, useRef, useEffect } from 'react';
2
2
  import { AnimatePresence, motion } from 'framer-motion';
3
3
  import ReactDOM__default from 'react-dom';
4
4
  import { useFocusTrap, useDebounce, useIsMounted, useRefocusOnActivator, useOnKeyDown, useBreakpoints } from '@jobber/hooks';
5
5
  import classnames from 'classnames';
6
+ import { n as noop } from './noop-es.js';
6
7
  import { B as ButtonDismiss } from './ButtonDismiss-es.js';
7
8
  import { T as Text } from './Text-es.js';
8
9
  import { B as Button } from './Button-es.js';
@@ -11,6 +12,11 @@ import { A as AtlantisThemeContextProvider } from './AtlantisThemeContext-es.js'
11
12
 
12
13
  var styles = {"backgroundImage":"i9Tw1T65W-k-","next":"Q8amcRaTGf0-","prev":"W9FVb24yJrk-","buttonHidden":"nsN0TPWsBXI-","buttonVisible":"dkLYp7AD2jE-","lightboxWrapper":"_5p2iAj4JfoE-","toolbar":"rMK4cKdOxFw-","closeButton":"_0m6vb11DgiA-","slideNumber":"kCc68gGuTgg-","image":"yYFVVScosfQ-","imageArea":"UskuwLHR6fg-","captionWrapper":"OGjhge-r-U4-","title":"tZU2g-NYdIs-","blurOverlay":"GKIdLTmvcvQ-","thumbnailBar":"_3TfQLQEE3GQ-","thumbnailImage":"eBMzUOlcfQ4-","thumbnail":"eapm2zruLn8-","selected":"PeLn2u-QB0k-","spinning":"_8tDoqjgfLcw-"};
13
14
 
15
+ // A little bit more than the transition's duration
16
+ // We're doing this to prevent a bug from framer-motion
17
+ // https://github.com/framer/motion/issues/1769
18
+ const BUTTON_DEBOUNCE_DELAY = 250;
19
+ const MOVEMENT_DEBOUNCE_DELAY = 1000;
14
20
  const swipeConfidenceThreshold = 10000;
15
21
  const swipePower = (offset, velocity) => {
16
22
  return Math.abs(offset) * velocity;
@@ -29,12 +35,26 @@ const slideVariants = {
29
35
  const imageTransition = {
30
36
  x: { duration: 0.65, ease: [0.42, 0, 0, 1.03] },
31
37
  };
32
- // A little bit more than the transition's duration
33
- // We're doing this to prevent a bug from framer-motion
34
- // https://github.com/framer/motion/issues/1769
35
- const BUTTON_DEBOUNCE_DELAY = 250;
36
- const MOVEMENT_DEBOUNCE_DELAY = 1000;
37
- function LightBox({ boxSizing = "content-box", open, images, imageIndex = 0, onRequestClose, }) {
38
+
39
+ /* eslint-disable max-statements */
40
+ const LightBoxContext = createContext({
41
+ open: false,
42
+ images: [],
43
+ currentImageIndex: 0,
44
+ mouseIsStationary: true,
45
+ boxSizing: "content-box",
46
+ directionRef: { current: 0 },
47
+ selectedThumbnailRef: { current: null },
48
+ lightboxRef: { current: null },
49
+ mounted: { current: false },
50
+ handleMouseMove: noop,
51
+ handleRequestClose: noop,
52
+ handleOnDragEnd: noop,
53
+ handleThumbnailClick: noop,
54
+ debouncedHandleNext: noop,
55
+ debouncedHandlePrevious: noop,
56
+ });
57
+ function LightBoxProvider({ open = true, images, imageIndex = 0, onRequestClose = noop, onImageChange = noop, boxSizing = "content-box", children, }) {
38
58
  const [currentImageIndex, setCurrentImageIndex] = useState(imageIndex);
39
59
  const directionRef = useRef(0);
40
60
  const [mouseIsStationary, setMouseIsStationary] = useState(true);
@@ -57,6 +77,7 @@ function LightBox({ boxSizing = "content-box", open, images, imageIndex = 0, onR
57
77
  });
58
78
  useEffect(() => {
59
79
  setCurrentImageIndex(imageIndex);
80
+ onImageChange(imageIndex);
60
81
  }, [imageIndex, open]);
61
82
  if (prevOpen.current !== open) {
62
83
  prevOpen.current = open;
@@ -70,57 +91,28 @@ function LightBox({ boxSizing = "content-box", open, images, imageIndex = 0, onR
70
91
  inline: "center",
71
92
  });
72
93
  }, [currentImageIndex]);
73
- const template = (React__default.createElement(React__default.Fragment, null, open && (React__default.createElement("div", { className: styles.lightboxWrapper, tabIndex: 0, "aria-label": "Lightbox", key: "Lightbox", ref: lightboxRef, onMouseMove: () => {
74
- if (mouseIsStationary) {
75
- setMouseIsStationary(false);
76
- }
77
- handleMouseMovement();
78
- } },
79
- React__default.createElement("div", { className: styles.backgroundImage, style: {
80
- backgroundImage: `url("${images[currentImageIndex].url}")`,
81
- } }),
82
- React__default.createElement("div", { className: styles.blurOverlay, onClick: handleRequestClose }),
83
- React__default.createElement(AtlantisThemeContextProvider, { dangerouslyOverrideTheme: "dark" },
84
- React__default.createElement("div", { className: styles.toolbar },
85
- React__default.createElement("div", { className: styles.slideNumber },
86
- React__default.createElement(Text, null, `${currentImageIndex + 1}/${images.length}`)),
87
- React__default.createElement("div", { className: styles.closeButton },
88
- React__default.createElement(ButtonDismiss, { ariaLabel: "Close", onClick: handleRequestClose })))),
89
- React__default.createElement("div", { className: styles.imageArea },
90
- React__default.createElement(AnimatePresence, { initial: false },
91
- React__default.createElement(motion.img, { key: currentImageIndex, variants: slideVariants, src: images[currentImageIndex].url, custom: directionRef, className: styles.image, initial: "enter", alt: images[currentImageIndex].alt ||
92
- images[currentImageIndex].title ||
93
- "", animate: "center", exit: "exit", transition: imageTransition, drag: "x", dragConstraints: { left: 0, right: 0 }, dragElastic: 1, onDragEnd: handleOnDragEnd }))),
94
- images.length > 1 && (React__default.createElement(React__default.Fragment, null,
95
- React__default.createElement(PreviousButton, { onClick: debouncedHandlePrevious, hideButton: mouseIsStationary }),
96
- React__default.createElement(NextButton, { onClick: debouncedHandleNext, hideButton: mouseIsStationary }))),
97
- (images[currentImageIndex].title ||
98
- images[currentImageIndex].caption) && (React__default.createElement("div", { className: styles.captionWrapper },
99
- React__default.createElement(AtlantisThemeContextProvider, { dangerouslyOverrideTheme: "dark" },
100
- images[currentImageIndex].title && (React__default.createElement("div", { className: styles.title },
101
- React__default.createElement(Heading, { level: 4 }, images[currentImageIndex].title))),
102
- images[currentImageIndex].caption && (React__default.createElement(Text, { size: "large" }, images[currentImageIndex].caption))))),
103
- images.length > 1 && (React__default.createElement("div", { className: styles.thumbnailBar, style: {
104
- "--lightbox--box-sizing": boxSizing,
105
- }, "data-testid": "ATL-Thumbnail-Bar" }, images.map((image, index) => (React__default.createElement("div", { key: index, className: classnames(styles.thumbnail, {
106
- [styles.selected]: index === currentImageIndex,
107
- }), onClick: () => handleThumbnailClick(index), ref: index === currentImageIndex ? selectedThumbnailRef : null },
108
- React__default.createElement("img", { key: index, src: image.url, alt: image.alt || image.title || "", className: styles.thumbnailImage }))))))))));
109
- return mounted.current
110
- ? ReactDOM__default.createPortal(template, document.body)
111
- : template;
94
+ function handleMouseMove() {
95
+ if (mouseIsStationary) {
96
+ setMouseIsStationary(false);
97
+ }
98
+ handleMouseMovement();
99
+ }
112
100
  function handleMovePrevious() {
113
101
  directionRef.current = -1;
114
- setCurrentImageIndex((currentImageIndex + images.length - 1) % images.length);
102
+ const newIndex = (currentImageIndex + images.length - 1) % images.length;
103
+ setCurrentImageIndex(newIndex);
104
+ onImageChange(newIndex);
115
105
  }
116
106
  function handleMoveNext() {
117
107
  directionRef.current = 1;
118
- setCurrentImageIndex((currentImageIndex + 1) % images.length);
108
+ const newIndex = (currentImageIndex + 1) % images.length;
109
+ setCurrentImageIndex(newIndex);
110
+ onImageChange(newIndex);
119
111
  }
120
112
  function handleRequestClose() {
121
113
  onRequestClose({ lastPosition: currentImageIndex });
122
114
  }
123
- function handleOnDragEnd(event, { offset, velocity }) {
115
+ function handleOnDragEnd(_event, { offset, velocity }) {
124
116
  const swipe = swipePower(offset.x, velocity.x);
125
117
  if (swipe < -swipeConfidenceThreshold) {
126
118
  handleMoveNext();
@@ -137,17 +129,28 @@ function LightBox({ boxSizing = "content-box", open, images, imageIndex = 0, onR
137
129
  directionRef.current = 1;
138
130
  }
139
131
  setCurrentImageIndex(index);
132
+ onImageChange(index);
140
133
  }
134
+ return (React__default.createElement(LightBoxContext.Provider, { value: {
135
+ open,
136
+ images,
137
+ currentImageIndex,
138
+ mouseIsStationary,
139
+ boxSizing,
140
+ directionRef,
141
+ selectedThumbnailRef,
142
+ lightboxRef,
143
+ mounted,
144
+ handleMouseMove,
145
+ handleRequestClose,
146
+ handleOnDragEnd,
147
+ handleThumbnailClick,
148
+ debouncedHandleNext,
149
+ debouncedHandlePrevious,
150
+ } }, children));
141
151
  }
142
- function PreviousButton({ onClick, hideButton }) {
143
- const { mediumAndUp } = useBreakpoints();
144
- return (React__default.createElement("div", { className: `${styles.prev} ${hideButton ? styles.buttonHidden : styles.buttonVisible}` },
145
- React__default.createElement(Button, { size: mediumAndUp ? "large" : "small", variation: "subtle", type: "secondary", icon: "arrowLeft", ariaLabel: "Previous image", onClick: onClick })));
146
- }
147
- function NextButton({ onClick, hideButton }) {
148
- const { mediumAndUp } = useBreakpoints();
149
- return (React__default.createElement("div", { className: `${styles.next} ${hideButton ? styles.buttonHidden : styles.buttonVisible}` },
150
- React__default.createElement(Button, { size: mediumAndUp ? "large" : "small", variation: "subtle", type: "secondary", icon: "arrowRight", ariaLabel: "Next image", onClick: onClick })));
152
+ function useLightBoxContext() {
153
+ return useContext(LightBoxContext);
151
154
  }
152
155
  function togglePrintStyles(open) {
153
156
  try {
@@ -163,4 +166,188 @@ function togglePrintStyles(open) {
163
166
  }
164
167
  }
165
168
 
166
- export { LightBox as L };
169
+ function LightBoxContent() {
170
+ const { open, lightboxRef, handleMouseMove } = useLightBoxContext();
171
+ const mounted = useIsMounted();
172
+ const template = (React__default.createElement(React__default.Fragment, null, open && (React__default.createElement("div", { className: styles.lightboxWrapper, tabIndex: 0, "aria-label": "Lightbox", key: "Lightbox", ref: lightboxRef, onMouseMove: handleMouseMove },
173
+ React__default.createElement(LightBoxBackground, null),
174
+ React__default.createElement(LightBoxOverlay, null),
175
+ React__default.createElement(LightBoxToolbar, null),
176
+ React__default.createElement(LightBoxSlides, null),
177
+ React__default.createElement(LightBoxNavigation, null),
178
+ React__default.createElement(LightBoxCaption, null),
179
+ React__default.createElement(LightBoxThumbnails, null)))));
180
+ return mounted.current
181
+ ? ReactDOM__default.createPortal(template, document.body)
182
+ : template;
183
+ }
184
+ function PreviousButton({ onClick, hideButton, className }) {
185
+ const { mediumAndUp } = useBreakpoints();
186
+ return (React__default.createElement("div", { className: `${className} ${hideButton ? styles.buttonHidden : styles.buttonVisible}` },
187
+ React__default.createElement(Button, { size: mediumAndUp ? "large" : "small", variation: "subtle", type: "secondary", icon: "arrowLeft", ariaLabel: "Previous image", onClick: onClick })));
188
+ }
189
+ function NextButton({ onClick, hideButton, className }) {
190
+ const { mediumAndUp } = useBreakpoints();
191
+ return (React__default.createElement("div", { className: `${className} ${hideButton ? styles.buttonHidden : styles.buttonVisible}` },
192
+ React__default.createElement(Button, { size: mediumAndUp ? "large" : "small", variation: "subtle", type: "secondary", icon: "arrowRight", ariaLabel: "Next image", onClick: onClick })));
193
+ }
194
+ /**
195
+ * Blurred, desaturated copy of the current image rendered as a full-bleed
196
+ * background behind the lightbox. Pass `className` to apply additional styles.
197
+ */
198
+ function LightBoxBackground({ className }) {
199
+ const { images, currentImageIndex } = useLightBoxContext();
200
+ return (React__default.createElement("div", { className: classnames(styles.backgroundImage, className), style: {
201
+ backgroundImage: `url("${images[currentImageIndex].url}")`,
202
+ } }));
203
+ }
204
+ /**
205
+ * Semi-transparent blur backdrop. Clicking it calls `onRequestClose`.
206
+ * Pass `className` to apply additional styles.
207
+ */
208
+ function LightBoxOverlay({ className }) {
209
+ const { handleRequestClose } = useLightBoxContext();
210
+ return (React__default.createElement("div", { className: classnames(styles.blurOverlay, className), onClick: handleRequestClose }));
211
+ }
212
+ /**
213
+ * Top bar showing the current image counter (`1/3`) and a close button.
214
+ * Styled for dark backgrounds.
215
+ */
216
+ function LightBoxToolbar() {
217
+ const { images, currentImageIndex, handleRequestClose } = useLightBoxContext();
218
+ return (React__default.createElement(AtlantisThemeContextProvider, { dangerouslyOverrideTheme: "dark" },
219
+ React__default.createElement("div", { className: styles.toolbar },
220
+ React__default.createElement("div", { className: styles.slideNumber },
221
+ React__default.createElement(Text, null, `${currentImageIndex + 1}/${images.length}`)),
222
+ React__default.createElement("div", { className: styles.closeButton },
223
+ React__default.createElement(ButtonDismiss, { ariaLabel: "Close", onClick: handleRequestClose })))));
224
+ }
225
+ /**
226
+ * The animated hero image with swipe-to-navigate and slide animation.
227
+ *
228
+ * Pass `className` to add styles to the image wrapper. Supports
229
+ * swipe-to-navigate (drag). Keyboard arrow navigation is handled by
230
+ * `LightBox.Provider`.
231
+ *
232
+ * @example
233
+ * ```tsx
234
+ * <LightBox.Slides className={styles.imageArea} />
235
+ * <LightBox.Navigation
236
+ * prevButtonClassName={styles.prev}
237
+ * nextButtonClassName={styles.next}
238
+ * />
239
+ * ```
240
+ */
241
+ function LightBoxSlides({ className }) {
242
+ const { images, currentImageIndex, directionRef, handleOnDragEnd } = useLightBoxContext();
243
+ return (React__default.createElement("div", { className: classnames(styles.imageArea, className) },
244
+ React__default.createElement(AnimatePresence, { initial: false },
245
+ React__default.createElement(motion.img, { key: currentImageIndex, variants: slideVariants, src: images[currentImageIndex].url, custom: directionRef, className: styles.image, initial: "enter", alt: images[currentImageIndex].alt ||
246
+ images[currentImageIndex].title ||
247
+ "", animate: "center", exit: "exit", transition: imageTransition, drag: "x", dragConstraints: { left: 0, right: 0 }, dragElastic: 1, onDragEnd: handleOnDragEnd }))));
248
+ }
249
+ /**
250
+ * Previous and next navigation buttons. Returns `null` when the image set
251
+ * has only one image.
252
+ *
253
+ * Use `prevButtonClassName` and `nextButtonClassName` to override the styles
254
+ * on each button's wrapper for custom layouts.
255
+ *
256
+ * @example
257
+ * ```tsx
258
+ * <LightBox.Navigation
259
+ * prevButtonClassName={styles.prev}
260
+ * nextButtonClassName={styles.next}
261
+ * />
262
+ * ```
263
+ */
264
+ function LightBoxNavigation({ prevButtonClassName, nextButtonClassName, }) {
265
+ const { images, mouseIsStationary, debouncedHandleNext, debouncedHandlePrevious, } = useLightBoxContext();
266
+ if (images.length <= 1)
267
+ return null;
268
+ return (React__default.createElement(React__default.Fragment, null,
269
+ React__default.createElement(PreviousButton, { onClick: debouncedHandlePrevious, hideButton: mouseIsStationary, className: classnames(styles.prev, prevButtonClassName) }),
270
+ React__default.createElement(NextButton, { onClick: debouncedHandleNext, hideButton: mouseIsStationary, className: classnames(styles.next, nextButtonClassName) })));
271
+ }
272
+ /**
273
+ * Title and caption text for the current image. Only renders when the current
274
+ * image has a `title` or `caption`. Styled for dark backgrounds.
275
+ */
276
+ function LightBoxCaption() {
277
+ const { images, currentImageIndex } = useLightBoxContext();
278
+ const { title, caption } = images[currentImageIndex];
279
+ if (!title && !caption)
280
+ return null;
281
+ return (React__default.createElement("div", { className: styles.captionWrapper },
282
+ React__default.createElement(AtlantisThemeContextProvider, { dangerouslyOverrideTheme: "dark" },
283
+ title && (React__default.createElement("div", { className: styles.title },
284
+ React__default.createElement(Heading, { level: 4 }, title))),
285
+ caption && React__default.createElement(Text, { size: "large" }, caption))));
286
+ }
287
+ /**
288
+ * Scrollable thumbnail strip. Only renders when there are two or more images.
289
+ */
290
+ function LightBoxThumbnails() {
291
+ const { images, currentImageIndex, boxSizing, selectedThumbnailRef, handleThumbnailClick, } = useLightBoxContext();
292
+ if (images.length <= 1)
293
+ return null;
294
+ return (React__default.createElement("div", { className: styles.thumbnailBar, style: { "--lightbox--box-sizing": boxSizing }, "data-testid": "ATL-Thumbnail-Bar" }, images.map((image, index) => (React__default.createElement("div", { key: index, className: classnames(styles.thumbnail, {
295
+ [styles.selected]: index === currentImageIndex,
296
+ }), onClick: () => handleThumbnailClick(index), ref: index === currentImageIndex ? selectedThumbnailRef : null },
297
+ React__default.createElement("img", { key: index, src: image.url, alt: image.alt || image.title || "", className: styles.thumbnailImage }))))));
298
+ }
299
+ /**
300
+ * LightBox displays images in a fullscreen overlay.
301
+ *
302
+ * **Self-contained (legacy) usage:**
303
+ * ```tsx
304
+ * <LightBox
305
+ * open={isOpen}
306
+ * images={images}
307
+ * imageIndex={imageIndex}
308
+ * onRequestClose={({ lastPosition }) => { setIsOpen(false); }}
309
+ * />
310
+ * ```
311
+ *
312
+ * **Full composable (fullscreen) usage:**
313
+ * ```tsx
314
+ * <LightBox.Provider open={isOpen} images={images} onRequestClose={onClose}>
315
+ * <LightBox.Content />
316
+ * </LightBox.Provider>
317
+ * ```
318
+ *
319
+ * **Inline gallery usage (no overlay, no close):**
320
+ * ```tsx
321
+ * <LightBox.Provider
322
+ * open={true}
323
+ * images={images}
324
+ * imageIndex={activeIndex}
325
+ * onImageChange={onImageChange}
326
+ * >
327
+ * <div className={styles.lightboxWrapper} onMouseMove={handleMouseMove}>
328
+ * <LightBox.Background className={styles.backgroundImage} />
329
+ * <LightBox.Overlay className={styles.blurOverlay} />
330
+ * <LightBox.Slides className={styles.imageArea} />
331
+ * <LightBox.Navigation
332
+ * prevButtonClassName={styles.prev}
333
+ * nextButtonClassName={styles.next}
334
+ * />
335
+ * </div>
336
+ * </LightBox.Provider>
337
+ * ```
338
+ */
339
+ function LightBox(props) {
340
+ return (React__default.createElement(LightBoxProvider, Object.assign({}, props),
341
+ React__default.createElement(LightBoxContent, null)));
342
+ }
343
+ LightBox.Provider = LightBoxProvider;
344
+ LightBox.Content = LightBoxContent;
345
+ LightBox.Background = LightBoxBackground;
346
+ LightBox.Overlay = LightBoxOverlay;
347
+ LightBox.Toolbar = LightBoxToolbar;
348
+ LightBox.Slides = LightBoxSlides;
349
+ LightBox.Navigation = LightBoxNavigation;
350
+ LightBox.Caption = LightBoxCaption;
351
+ LightBox.Thumbnails = LightBoxThumbnails;
352
+
353
+ export { LightBox as L, useLightBoxContext as u };
package/dist/index.cjs CHANGED
@@ -293,6 +293,7 @@ exports.InputText = InputText_index.InputText;
293
293
  exports.InputTime = InputTime_index.InputTime;
294
294
  exports.InputValidation = InputValidation.InputValidation;
295
295
  exports.LightBox = LightBox.LightBox;
296
+ exports.useLightBoxContext = LightBox.useLightBoxContext;
296
297
  exports.Link = Link.Link;
297
298
  exports.List = List.List;
298
299
  exports.ListItem = List.ListItem;
package/dist/index.mjs CHANGED
@@ -63,7 +63,7 @@ export { InputPhoneNumber } from './InputPhoneNumber/index.mjs';
63
63
  export { InputText } from './InputText/index.mjs';
64
64
  export { InputTime } from './InputTime/index.mjs';
65
65
  export { I as InputValidation } from './InputValidation-es.js';
66
- export { L as LightBox } from './LightBox-es.js';
66
+ export { L as LightBox, u as useLightBoxContext } from './LightBox-es.js';
67
67
  export { L as Link } from './Link-es.js';
68
68
  export { L as List, a as ListItem } from './List-es.js';
69
69
  export { M as Markdown } from './Markdown-es.js';
package/dist/styles.css CHANGED
@@ -7518,12 +7518,9 @@ h2.react-datepicker__current-month {
7518
7518
  width: 100%;
7519
7519
  max-width: 100%;
7520
7520
  }
7521
- .LDxKi0E-1rg- {
7522
- position: fixed;
7523
- top: 0;
7524
- left: 0;
7525
- z-index: 1001;
7526
- z-index: var(--elevation-modal);
7521
+ .OmFI-Bfdzgw- .react-datepicker-popper {
7522
+ z-index: 6;
7523
+ z-index: var(--elevation-datepicker);
7527
7524
  }
7528
7525
  .Ma55F5Y-XhE- .react-datepicker__header {
7529
7526
  padding: 0;
@@ -135,6 +135,15 @@
135
135
  "InputTime",
136
136
  "InputValidation",
137
137
  "LightBox",
138
+ "LightBox.Background",
139
+ "LightBox.Caption",
140
+ "LightBox.Content",
141
+ "LightBox.Navigation",
142
+ "LightBox.Overlay",
143
+ "LightBox.Provider",
144
+ "LightBox.Slides",
145
+ "LightBox.Thumbnails",
146
+ "LightBox.Toolbar",
138
147
  "Link",
139
148
  "List",
140
149
  "ListItem",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jobber/components",
3
- "version": "6.113.1",
3
+ "version": "6.114.1",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -538,5 +538,5 @@
538
538
  "> 1%",
539
539
  "IE 10"
540
540
  ],
541
- "gitHead": "45e47debd0c3f7e4f9c85be0c3a811803096cd26"
541
+ "gitHead": "8e79d0138c20e8e2b0eb8839296cd85cb9c8e403"
542
542
  }