yet-another-react-lightbox 1.7.1 → 1.9.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.
@@ -0,0 +1,423 @@
1
+ import * as React from "react";
2
+ import { adjustDevicePixelRatio, cleanup, clsx, createIcon, createModule, cssClass, IconButton, ImageSlide, label, makeUseContext, round, useContainerRect, useController, useEnhancedEffect, useEvents, useMotionPreference, } from "../core/index.js";
3
+ const defaultZoomProps = {
4
+ maxZoomPixelRatio: 1,
5
+ zoomInMultiplier: 2,
6
+ doubleTapDelay: 300,
7
+ doubleClickDelay: 500,
8
+ doubleClickMaxStops: 2,
9
+ keyboardMoveDistance: 50,
10
+ wheelZoomDistanceFactor: 100,
11
+ pinchZoomDistanceFactor: 100,
12
+ };
13
+ const ZoomInIcon = createIcon("ZoomIn", React.createElement(React.Fragment, null,
14
+ React.createElement("path", { d: "M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" }),
15
+ React.createElement("path", { d: "M12 10h-2v2H9v-2H7V9h2V7h1v2h2v1z" })));
16
+ const ZoomOutIcon = createIcon("ZoomOut", React.createElement("path", { d: "M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14zM7 9h5v1H7z" }));
17
+ const ZoomContext = React.createContext(null);
18
+ const useZoom = makeUseContext("useZoom", "ZoomContext", ZoomContext);
19
+ const ZoomContextProvider = ({ children }) => {
20
+ const [minZoom, setMinZoom] = React.useState(false);
21
+ const [maxZoom, setMaxZoom] = React.useState(false);
22
+ const [zoomSupported, setZoomSupported] = React.useState(false);
23
+ const context = React.useMemo(() => ({
24
+ minZoom,
25
+ maxZoom,
26
+ zoomSupported,
27
+ setMinZoom,
28
+ setMaxZoom,
29
+ setZoomSupported,
30
+ }), [minZoom, maxZoom, zoomSupported]);
31
+ return React.createElement(ZoomContext.Provider, { value: context }, children);
32
+ };
33
+ const ZoomButton = React.forwardRef(({ labels, render, zoomIn, onLoseFocus }, ref) => {
34
+ const wasEnabled = React.useRef(false);
35
+ const wasFocused = React.useRef(false);
36
+ const { zoomSupported, minZoom, maxZoom } = useZoom();
37
+ const { publish } = useEvents();
38
+ const disabled = !zoomSupported || (zoomIn ? maxZoom : minZoom);
39
+ const onClick = () => publish(zoomIn ? "zoom-in" : "zoom-out");
40
+ const onFocus = React.useCallback(() => {
41
+ wasFocused.current = true;
42
+ }, []);
43
+ const onBlur = React.useCallback(() => {
44
+ wasFocused.current = false;
45
+ }, []);
46
+ React.useEffect(() => {
47
+ if (disabled && wasEnabled.current && wasFocused.current) {
48
+ onLoseFocus();
49
+ }
50
+ if (!disabled) {
51
+ wasEnabled.current = true;
52
+ }
53
+ }, [disabled, onLoseFocus]);
54
+ if (zoomIn && render.buttonZoomIn)
55
+ return (React.createElement(React.Fragment, null, render.buttonZoomIn({
56
+ ref,
57
+ labels,
58
+ disabled,
59
+ onClick,
60
+ onFocus,
61
+ onBlur,
62
+ })));
63
+ if (zoomIn && render.buttonZoomOut)
64
+ return (React.createElement(React.Fragment, null, render.buttonZoomOut({
65
+ ref,
66
+ labels,
67
+ disabled,
68
+ onClick,
69
+ onFocus,
70
+ onBlur,
71
+ })));
72
+ return (React.createElement(IconButton, { ref: ref, label: label(labels, zoomIn ? "Zoom in" : "Zoom out"), icon: zoomIn ? ZoomInIcon : ZoomOutIcon, renderIcon: zoomIn ? render.iconZoomIn : render.iconZoomOut, disabled: disabled, onClick: onClick, onFocus: onFocus, onBlur: onBlur }));
73
+ });
74
+ ZoomButton.displayName = "ZoomButton";
75
+ const ZoomButtonsGroup = ({ labels, render }) => {
76
+ const zoomInRef = React.useRef(null);
77
+ const zoomOutRef = React.useRef(null);
78
+ const { transferFocus } = useController();
79
+ const focusSibling = React.useCallback((sibling) => {
80
+ var _a, _b;
81
+ if (!((_a = sibling.current) === null || _a === void 0 ? void 0 : _a.disabled)) {
82
+ (_b = sibling.current) === null || _b === void 0 ? void 0 : _b.focus();
83
+ }
84
+ else {
85
+ transferFocus();
86
+ }
87
+ }, [transferFocus]);
88
+ const focusZoomIn = React.useCallback(() => focusSibling(zoomInRef), [focusSibling]);
89
+ const focusZoomOut = React.useCallback(() => focusSibling(zoomOutRef), [focusSibling]);
90
+ return (React.createElement(React.Fragment, null,
91
+ React.createElement(ZoomButton, { ref: zoomInRef, key: "zoomIn", zoomIn: true, labels: labels, render: render, onLoseFocus: focusZoomOut }),
92
+ React.createElement(ZoomButton, { ref: zoomOutRef, key: "zoomOut", labels: labels, render: render, onLoseFocus: focusZoomIn })));
93
+ };
94
+ const getSlideRects = (slide, cover, maxZoomPixelRatio, rect) => {
95
+ var _a, _b;
96
+ let slideRect = { width: 0, height: 0 };
97
+ let maxSlideRect = { width: 0, height: 0 };
98
+ if (rect && !("type" in slide) && "src" in slide) {
99
+ const width = Math.max(...(((_a = slide.srcSet) === null || _a === void 0 ? void 0 : _a.map((x) => x.width)) || []), ...[...(slide.width ? [slide.width] : [])]);
100
+ const height = Math.max(...(((_b = slide.srcSet) === null || _b === void 0 ? void 0 : _b.map((x) => x.width)) || (slide.aspectRatio ? [width / slide.aspectRatio] : [])), ...[...(slide.height ? [slide.height] : [])]);
101
+ if (width > 0 && height > 0 && rect.width > 0 && rect.height > 0) {
102
+ maxSlideRect = cover
103
+ ? {
104
+ width: Math.round(Math.min(width, (rect.width / rect.height) * height)),
105
+ height: Math.round(Math.min(height, (rect.height / rect.width) * width)),
106
+ }
107
+ : { width, height };
108
+ maxSlideRect = {
109
+ width: adjustDevicePixelRatio(maxSlideRect.width) * maxZoomPixelRatio,
110
+ height: adjustDevicePixelRatio(maxSlideRect.height) * maxZoomPixelRatio,
111
+ };
112
+ slideRect = cover
113
+ ? {
114
+ width: Math.min(rect.width, maxSlideRect.width),
115
+ height: Math.min(rect.height, maxSlideRect.height),
116
+ }
117
+ : {
118
+ width: Math.round(Math.min(rect.width, (rect.height / height) * width)),
119
+ height: Math.round(Math.min(rect.height, (rect.width / width) * height)),
120
+ };
121
+ }
122
+ }
123
+ return { slideRect, maxSlideRect };
124
+ };
125
+ const distance = (pointerA, pointerB) => ((pointerA.clientX - pointerB.clientX) ** 2 + (pointerA.clientY - pointerB.clientY) ** 2) ** 0.5;
126
+ const ZoomContainer = ({ slide, offset, rect, render, carousel, animation, zoom: originalZoomProps }) => {
127
+ var _a;
128
+ const zoomProps = { ...defaultZoomProps, ...originalZoomProps };
129
+ const { setMinZoom: currentSetMinZoom, setMaxZoom: currentSetMaxZoom } = useZoom();
130
+ const { setContainerRef, containerRef: currentContainerRef, containerRect: currentContainerRect, } = useContainerRect();
131
+ const { subscribeSensors, containerRef: currentControllerRef, containerRect: currentControllerRect, } = useController();
132
+ const { subscribe } = useEvents();
133
+ const currentReduceMotion = useMotionPreference();
134
+ const { slideRect: currentSlideRect, maxSlideRect: currentMaxSlideRect } = getSlideRects(slide, carousel.imageFit === "cover" || ("imageFit" in slide && slide.imageFit === "cover"), zoomProps.maxZoomPixelRatio, currentContainerRect);
135
+ const currentMaxZoom = currentSlideRect.width ? round(currentMaxSlideRect.width / currentSlideRect.width, 3) : 1;
136
+ const [state, setState] = React.useState({ zoom: 1, offsetX: 0, offsetY: 0 });
137
+ const refs = React.useRef({
138
+ state,
139
+ slideRect: currentSlideRect,
140
+ containerRef: currentContainerRef,
141
+ controllerRef: currentControllerRef,
142
+ containerRect: currentContainerRect,
143
+ controllerRect: currentControllerRect,
144
+ maxZoom: currentMaxZoom,
145
+ reduceMotion: currentReduceMotion,
146
+ setMinZoom: currentSetMinZoom,
147
+ setMaxZoom: currentSetMaxZoom,
148
+ activePointers: [],
149
+ lastPointerDown: 0,
150
+ zoomProps,
151
+ });
152
+ refs.current.state = state;
153
+ refs.current.slideRect = currentSlideRect;
154
+ refs.current.containerRef = currentContainerRef;
155
+ refs.current.controllerRef = currentControllerRef;
156
+ refs.current.containerRect = currentContainerRect;
157
+ refs.current.controllerRect = currentControllerRect;
158
+ refs.current.maxZoom = currentMaxZoom;
159
+ refs.current.reduceMotion = currentReduceMotion;
160
+ refs.current.setMinZoom = currentSetMinZoom;
161
+ refs.current.setMaxZoom = currentSetMaxZoom;
162
+ refs.current.zoomAnimationDuration = animation.zoom;
163
+ refs.current.zoomProps = zoomProps;
164
+ const changeOffsets = React.useCallback((dx, dy, newZoom) => {
165
+ const { state: { zoom, offsetX, offsetY }, containerRect, slideRect, } = refs.current;
166
+ const targetZoom = newZoom || zoom;
167
+ const newOffsetX = offsetX - (dx || 0);
168
+ const newOffsetY = offsetY - (dy || 0);
169
+ const maxOffsetX = containerRect ? (slideRect.width * targetZoom - containerRect.width) / 2 / targetZoom : 0;
170
+ const maxOffsetY = containerRect ? (slideRect.height * targetZoom - containerRect.height) / 2 / targetZoom : 0;
171
+ setState((prev) => ({
172
+ ...prev,
173
+ offsetX: Math.min(Math.abs(newOffsetX), Math.max(maxOffsetX, 0)) * Math.sign(newOffsetX),
174
+ offsetY: Math.min(Math.abs(newOffsetY), Math.max(maxOffsetY, 0)) * Math.sign(newOffsetY),
175
+ }));
176
+ }, []);
177
+ useEnhancedEffect(() => {
178
+ if (refs.current.state.zoom > 1) {
179
+ changeOffsets();
180
+ }
181
+ }, [currentControllerRect.width, currentControllerRect.height, changeOffsets]);
182
+ useEnhancedEffect(() => {
183
+ var _a, _b;
184
+ const { current } = refs;
185
+ const { zoomAnimation, zoomAnimationStart, zoomAnimationDuration, reduceMotion, containerRef } = current;
186
+ zoomAnimation === null || zoomAnimation === void 0 ? void 0 : zoomAnimation.cancel();
187
+ if (zoomAnimationStart && containerRef.current) {
188
+ current.zoomAnimation = (_b = (_a = containerRef.current).animate) === null || _b === void 0 ? void 0 : _b.call(_a, [
189
+ { transform: zoomAnimationStart },
190
+ {
191
+ transform: `scale(${state.zoom}) translate3d(${state.offsetX}px, ${state.offsetY}px, 0)`,
192
+ },
193
+ ], {
194
+ duration: reduceMotion ? 0 : zoomAnimationDuration !== null && zoomAnimationDuration !== void 0 ? zoomAnimationDuration : 500,
195
+ easing: zoomAnimation ? "ease-out" : "ease-in-out",
196
+ });
197
+ current.zoomAnimationStart = undefined;
198
+ if (current.zoomAnimation) {
199
+ current.zoomAnimation.onfinish = () => {
200
+ current.zoomAnimation = undefined;
201
+ };
202
+ }
203
+ }
204
+ }, [state.zoom, state.offsetX, state.offsetY]);
205
+ useEnhancedEffect(() => {
206
+ if (offset === 0) {
207
+ const { setMinZoom, setMaxZoom, maxZoom } = refs.current;
208
+ setMinZoom(state.zoom <= 1);
209
+ setMaxZoom(state.zoom >= maxZoom);
210
+ }
211
+ }, [offset, state.zoom]);
212
+ useEnhancedEffect(() => {
213
+ if (offset === 0) {
214
+ const { setMinZoom, setMaxZoom } = refs.current;
215
+ const resetZoom = () => {
216
+ setState({ zoom: 1, offsetX: 0, offsetY: 0 });
217
+ setMinZoom(true);
218
+ setMaxZoom(false);
219
+ };
220
+ resetZoom();
221
+ return () => {
222
+ resetZoom();
223
+ };
224
+ }
225
+ return () => { };
226
+ }, [offset]);
227
+ const changeZoom = React.useCallback((value, rapid, dx, dy) => {
228
+ const { current } = refs;
229
+ const { state: { zoom }, containerRef, containerRect, maxZoom, } = current;
230
+ if (!containerRef.current || !containerRect)
231
+ return;
232
+ const newZoom = round(Math.min(Math.max(value, 1), maxZoom), 5);
233
+ if (newZoom === zoom)
234
+ return;
235
+ if (!rapid) {
236
+ current.zoomAnimationStart = window.getComputedStyle(containerRef.current).transform;
237
+ }
238
+ changeOffsets(dx ? dx * (1 / zoom - 1 / newZoom) : 0, dy ? dy * (1 / zoom - 1 / newZoom) : 0, newZoom);
239
+ setState((prev) => ({ ...prev, zoom: newZoom }));
240
+ }, [changeOffsets]);
241
+ const translateCoordinates = React.useCallback((event) => {
242
+ const { controllerRef } = refs.current;
243
+ if (controllerRef.current) {
244
+ const { pageX, pageY } = event;
245
+ const { scrollX, scrollY } = window;
246
+ const { left, top, width, height } = controllerRef.current.getBoundingClientRect();
247
+ return [pageX - left - scrollX - width / 2, pageY - top - scrollY - height / 2];
248
+ }
249
+ return [];
250
+ }, []);
251
+ const onKeyDown = React.useCallback((event) => {
252
+ const { state: { zoom }, zoomProps: { keyboardMoveDistance, zoomInMultiplier }, } = refs.current;
253
+ if (zoom > 1) {
254
+ const move = (deltaX, deltaY) => {
255
+ event.stopPropagation();
256
+ changeOffsets(deltaX, deltaY);
257
+ };
258
+ if (event.key === "ArrowDown") {
259
+ move(0, keyboardMoveDistance);
260
+ }
261
+ else if (event.key === "ArrowUp") {
262
+ move(0, -keyboardMoveDistance);
263
+ }
264
+ else if (event.key === "ArrowLeft") {
265
+ move(-keyboardMoveDistance, 0);
266
+ }
267
+ else if (event.key === "ArrowRight") {
268
+ move(keyboardMoveDistance, 0);
269
+ }
270
+ }
271
+ if (event.key === "+" || (event.key === "=" && event.metaKey)) {
272
+ changeZoom(zoom * zoomInMultiplier);
273
+ }
274
+ else if (event.key === "-" || (event.key === "_" && event.metaKey)) {
275
+ changeZoom(zoom / zoomInMultiplier);
276
+ }
277
+ else if (event.key === "0" && event.metaKey) {
278
+ changeZoom(1);
279
+ }
280
+ }, [changeZoom, changeOffsets]);
281
+ const onWheel = React.useCallback((event) => {
282
+ const { state: { zoom }, zoomProps: { wheelZoomDistanceFactor }, } = refs.current;
283
+ if (event.ctrlKey) {
284
+ event.stopPropagation();
285
+ if (Math.abs(event.deltaY) > Math.abs(event.deltaX)) {
286
+ changeZoom(zoom * (1 - event.deltaY / wheelZoomDistanceFactor), true, ...translateCoordinates(event));
287
+ }
288
+ return;
289
+ }
290
+ if (zoom > 1) {
291
+ event.stopPropagation();
292
+ changeOffsets(event.deltaX, event.deltaY);
293
+ }
294
+ }, [changeZoom, changeOffsets, translateCoordinates]);
295
+ const clearPointer = React.useCallback((event) => {
296
+ const { activePointers } = refs.current;
297
+ activePointers.splice(0, activePointers.length, ...activePointers.filter((p) => p.pointerId !== event.pointerId));
298
+ }, []);
299
+ const replacePointer = React.useCallback((event) => {
300
+ clearPointer(event);
301
+ refs.current.activePointers.push(event);
302
+ }, [clearPointer]);
303
+ const onPointerDown = React.useCallback((event) => {
304
+ var _a;
305
+ const { current } = refs;
306
+ const { state: { zoom }, containerRef, activePointers, lastPointerDown, maxZoom, zoomProps: { doubleTapDelay, doubleClickDelay, zoomInMultiplier, doubleClickMaxStops }, } = current;
307
+ if (!((_a = containerRef.current) === null || _a === void 0 ? void 0 : _a.contains(event.target))) {
308
+ return;
309
+ }
310
+ if (zoom > 1) {
311
+ event.stopPropagation();
312
+ }
313
+ const { timeStamp } = event;
314
+ if (activePointers.length === 0 &&
315
+ timeStamp - lastPointerDown < (event.pointerType === "touch" ? doubleTapDelay : doubleClickDelay)) {
316
+ current.lastPointerDown = 0;
317
+ changeZoom(zoom !== maxZoom ? zoom * Math.max(maxZoom ** (1 / doubleClickMaxStops), zoomInMultiplier) : 1, false, ...translateCoordinates(event));
318
+ }
319
+ else {
320
+ current.lastPointerDown = timeStamp;
321
+ }
322
+ replacePointer(event);
323
+ if (activePointers.length === 2) {
324
+ current.pinchZoomDistance = distance(activePointers[0], activePointers[1]);
325
+ }
326
+ }, [changeZoom, replacePointer, translateCoordinates]);
327
+ const onPointerMove = React.useCallback((event) => {
328
+ const { current } = refs;
329
+ const { state: { zoom }, activePointers, pinchZoomDistance, zoomProps: { pinchZoomDistanceFactor }, } = current;
330
+ const activePointer = activePointers.find((p) => p.pointerId === event.pointerId);
331
+ if (activePointers.length === 2 && pinchZoomDistance) {
332
+ event.stopPropagation();
333
+ replacePointer(event);
334
+ const currentDistance = distance(activePointers[0], activePointers[1]);
335
+ const delta = currentDistance - pinchZoomDistance;
336
+ if (Math.abs(delta) > 0) {
337
+ changeZoom(zoom * (1 + delta / pinchZoomDistanceFactor), true, ...activePointers
338
+ .map((x) => translateCoordinates(x))
339
+ .reduce((acc, coordinate) => coordinate.map((x, i) => acc[i] + x / 2)));
340
+ current.pinchZoomDistance = currentDistance;
341
+ }
342
+ return;
343
+ }
344
+ if (zoom > 1) {
345
+ event.stopPropagation();
346
+ if (activePointer) {
347
+ if (activePointers.length === 1) {
348
+ changeOffsets((activePointer.clientX - event.clientX) / zoom, (activePointer.clientY - event.clientY) / zoom);
349
+ }
350
+ replacePointer(event);
351
+ }
352
+ }
353
+ }, [changeOffsets, replacePointer, changeZoom, translateCoordinates]);
354
+ const onPointerUp = React.useCallback((event) => {
355
+ const { current } = refs;
356
+ const { activePointers } = current;
357
+ if (activePointers.length === 2 && activePointers.find((p) => p.pointerId === event.pointerId)) {
358
+ current.pinchZoomDistance = undefined;
359
+ }
360
+ clearPointer(event);
361
+ }, [clearPointer]);
362
+ React.useEffect(() => offset === 0
363
+ ? cleanup(subscribe("zoom-in", () => changeZoom(refs.current.state.zoom * refs.current.zoomProps.zoomInMultiplier)), subscribe("zoom-out", () => changeZoom(refs.current.state.zoom / refs.current.zoomProps.zoomInMultiplier)), subscribeSensors("onKeyDown", onKeyDown), subscribeSensors("onWheel", onWheel), subscribeSensors("onPointerDown", onPointerDown), subscribeSensors("onPointerMove", onPointerMove), subscribeSensors("onPointerUp", onPointerUp), subscribeSensors("onPointerLeave", onPointerUp), subscribeSensors("onPointerCancel", onPointerUp))
364
+ : () => { }, [offset, subscribe, subscribeSensors, onKeyDown, onPointerDown, onPointerMove, onPointerUp, onWheel, changeZoom]);
365
+ const { state: { zoom, offsetX, offsetY }, } = refs.current;
366
+ const scaledRect = offset === 0
367
+ ? {
368
+ width: rect.width * zoom,
369
+ height: rect.height * zoom,
370
+ }
371
+ : rect;
372
+ let rendered = (_a = render.slide) === null || _a === void 0 ? void 0 : _a.call(render, slide, offset, scaledRect);
373
+ if (!rendered && !("type" in slide) && "src" in slide) {
374
+ rendered = (React.createElement(ImageSlide, { slide: slide, offset: offset, rect: scaledRect, render: render, imageFit: carousel.imageFit }));
375
+ }
376
+ return rendered ? (React.createElement("div", { ref: setContainerRef, className: clsx(cssClass("fullsize"), cssClass("flex_center")), ...(offset === 0
377
+ ? { style: { transform: `scale(${zoom}) translate3d(${offsetX}px, ${offsetY}px, 0)` } }
378
+ : null) }, rendered)) : null;
379
+ };
380
+ const ZoomWrapper = ({ slide, offset, rect, render, carousel, animation }) => {
381
+ var _a;
382
+ const { setZoomSupported } = useZoom();
383
+ const imageSlide = !("type" in slide);
384
+ const zoomSupported = imageSlide && ("srcSet" in slide || ("width" in slide && "height" in slide));
385
+ React.useEffect(() => {
386
+ if (offset === 0) {
387
+ setZoomSupported(zoomSupported);
388
+ }
389
+ }, [offset, zoomSupported, setZoomSupported]);
390
+ if (zoomSupported) {
391
+ return (React.createElement(ZoomContainer, { slide: slide, offset: offset, rect: rect, render: render, carousel: carousel, animation: animation }));
392
+ }
393
+ const rendered = (_a = render.slide) === null || _a === void 0 ? void 0 : _a.call(render, slide, offset, rect);
394
+ if (rendered) {
395
+ return React.createElement(React.Fragment, null, rendered);
396
+ }
397
+ if (imageSlide) {
398
+ return React.createElement(ImageSlide, { slide: slide, offset: offset, rect: rect, render: render, imageFit: carousel.imageFit });
399
+ }
400
+ return null;
401
+ };
402
+ export const ZoomModule = createModule("zoom", ZoomContextProvider);
403
+ export const Zoom = ({ augment, append }) => {
404
+ augment(({ toolbar: { buttons, ...restToolbar }, render, carousel, animation, zoom, ...restProps }) => ({
405
+ toolbar: {
406
+ buttons: [React.createElement(ZoomButtonsGroup, { key: "zoom", labels: restProps.labels, render: render }), ...buttons],
407
+ ...restToolbar,
408
+ },
409
+ render: {
410
+ ...render,
411
+ slide: (slide, offset, rect) => (React.createElement(ZoomWrapper, { slide: slide, offset: offset, rect: rect, render: render, carousel: carousel, animation: animation })),
412
+ },
413
+ zoom: {
414
+ ...defaultZoomProps,
415
+ ...zoom,
416
+ },
417
+ carousel,
418
+ animation,
419
+ ...restProps,
420
+ }));
421
+ append("controller", ZoomModule);
422
+ };
423
+ export default Zoom;
@@ -22,7 +22,6 @@
22
22
  font-weight: 500;
23
23
  overflow: hidden;
24
24
  -webkit-hyphens: auto;
25
- -ms-hyphens: auto;
26
25
  hyphens: auto;
27
26
  display: -webkit-box;
28
27
  -webkit-box-orient: vertical;
@@ -2,4 +2,6 @@ export * from "./Captions.js";
2
2
  export * from "./Fullscreen.js";
3
3
  export * from "./Inline.js";
4
4
  export * from "./Slideshow.js";
5
+ export * from "./Thumbnails.js";
5
6
  export * from "./Video.js";
7
+ export * from "./Zoom.js";
@@ -2,4 +2,6 @@ export * from "./Captions.js";
2
2
  export * from "./Fullscreen.js";
3
3
  export * from "./Inline.js";
4
4
  export * from "./Slideshow.js";
5
+ export * from "./Thumbnails.js";
5
6
  export * from "./Video.js";
7
+ export * from "./Zoom.js";
@@ -0,0 +1,150 @@
1
+ .yarl__thumbnails {
2
+ display: flex;
3
+ }
4
+ .yarl__thumbnails_top, .yarl__thumbnails_bottom {
5
+ flex-flow: column nowrap;
6
+ }
7
+ .yarl__thumbnails_top .yarl__thumbnails_track, .yarl__thumbnails_bottom .yarl__thumbnails_track {
8
+ flex-flow: row nowrap;
9
+ }
10
+ .yarl__thumbnails_start, .yarl__thumbnails_end {
11
+ flex-flow: row nowrap;
12
+ }
13
+ .yarl__thumbnails_start .yarl__thumbnails_track, .yarl__thumbnails_end .yarl__thumbnails_track {
14
+ flex-flow: column nowrap;
15
+ }
16
+ .yarl__thumbnails_wrapper {
17
+ flex-grow: 1;
18
+ position: relative;
19
+ }
20
+ .yarl__thumbnails_container {
21
+ color: #fff;
22
+ background-color: #000;
23
+ overflow: hidden;
24
+ padding: 16px;
25
+ position: relative;
26
+ z-index: 0;
27
+ -webkit-user-select: none;
28
+ -moz-user-select: none;
29
+ user-select: none;
30
+ -webkit-touch-callout: none;
31
+ }
32
+ .yarl__thumbnails_container::before, .yarl__thumbnails_container::after {
33
+ content: "";
34
+ position: absolute;
35
+ z-index: 1;
36
+ }
37
+ .yarl__thumbnails_top .yarl__thumbnails_container::before, .yarl__thumbnails_bottom .yarl__thumbnails_container::before {
38
+ left: 0;
39
+ background: linear-gradient(to left, transparent, #000);
40
+ }
41
+ .yarl__thumbnails_top .yarl__thumbnails_container::after, .yarl__thumbnails_bottom .yarl__thumbnails_container::after {
42
+ right: 0;
43
+ background: linear-gradient(to right, transparent, #000);
44
+ }
45
+ .yarl__thumbnails_top .yarl__thumbnails_container::before, .yarl__thumbnails_top .yarl__thumbnails_container::after, .yarl__thumbnails_bottom .yarl__thumbnails_container::before, .yarl__thumbnails_bottom .yarl__thumbnails_container::after {
46
+ top: 0;
47
+ bottom: 0;
48
+ width: 60px;
49
+ }
50
+ .yarl__thumbnails_start .yarl__thumbnails_container::before, .yarl__thumbnails_end .yarl__thumbnails_container::before {
51
+ top: 0;
52
+ background: linear-gradient(to top, transparent, #000);
53
+ }
54
+ .yarl__thumbnails_start .yarl__thumbnails_container::after, .yarl__thumbnails_end .yarl__thumbnails_container::after {
55
+ bottom: 0;
56
+ background: linear-gradient(to bottom, transparent, #000);
57
+ }
58
+ .yarl__thumbnails_start .yarl__thumbnails_container::before, .yarl__thumbnails_start .yarl__thumbnails_container::after, .yarl__thumbnails_end .yarl__thumbnails_container::before, .yarl__thumbnails_end .yarl__thumbnails_container::after {
59
+ left: 0;
60
+ right: 0;
61
+ height: 60px;
62
+ }
63
+ .yarl__thumbnails_track {
64
+ display: flex;
65
+ gap: var(--yarl__thumbnails_thumbnail_gap, 16px);
66
+ }
67
+ .yarl__thumbnails_thumbnail {
68
+ cursor: pointer;
69
+ -webkit-appearance: none;
70
+ -moz-appearance: none;
71
+ appearance: none;
72
+ background: transparent;
73
+ border: var(--yarl__thumbnails_thumbnail_border, 1px) solid rgba(255, 255, 255, 0.8);
74
+ border-radius: var(--yarl__thumbnails_thumbnail_border_radius, 4px);
75
+ -webkit-tap-highlight-color: transparent;
76
+ flex-shrink: 0;
77
+ position: relative;
78
+ overflow: hidden;
79
+ padding: var(--yarl__thumbnails_thumbnail_padding, 4px);
80
+ width: var(--yarl__thumbnails_thumbnail_width, 120px);
81
+ height: var(--yarl__thumbnails_thumbnail_height, 80px);
82
+ box-sizing: content-box;
83
+ }
84
+ .yarl__thumbnails_thumbnail_active {
85
+ border-color: #fff;
86
+ }
87
+ .yarl__thumbnails_thumbnail_fadein {
88
+ opacity: 0;
89
+ -webkit-animation: yarl__thumbnails_thumbnail_fadein var(--yarl__thumbnails_thumbnail_fadein_duration, 0.5s) ease-in-out var(--yarl__thumbnails_thumbnail_fadein_delay, 0s) forwards;
90
+ animation: yarl__thumbnails_thumbnail_fadein var(--yarl__thumbnails_thumbnail_fadein_duration, 0.5s) ease-in-out var(--yarl__thumbnails_thumbnail_fadein_delay, 0s) forwards;
91
+ }
92
+ .yarl__thumbnails_thumbnail_fadeout {
93
+ -webkit-animation: yarl__thumbnails_thumbnail_fadeout var(--yarl__thumbnails_thumbnail_fadeout_duration, 0.5s) ease-in-out var(--yarl__thumbnails_thumbnail_fadeout_delay, 0s) forwards;
94
+ animation: yarl__thumbnails_thumbnail_fadeout var(--yarl__thumbnails_thumbnail_fadeout_duration, 0.5s) ease-in-out var(--yarl__thumbnails_thumbnail_fadeout_delay, 0s) forwards;
95
+ cursor: unset;
96
+ }
97
+ .yarl__thumbnails_thumbnail_placeholder {
98
+ visibility: hidden;
99
+ cursor: unset;
100
+ }
101
+ .yarl__thumbnails_thumbnail_icon {
102
+ color: rgba(255, 255, 255, 0.8);
103
+ -webkit-filter: drop-shadow(2px 2px 2px rgba(0, 0, 0, 0.8));
104
+ filter: drop-shadow(2px 2px 2px rgba(0, 0, 0, 0.8));
105
+ position: absolute;
106
+ top: 50%;
107
+ left: 50%;
108
+ -webkit-transform: translate3d(-50%, -50%, 0);
109
+ transform: translate3d(-50%, -50%, 0);
110
+ width: 32px;
111
+ height: 32px;
112
+ }
113
+ .yarl__thumbnails_contain_image {
114
+ -o-object-fit: contain;
115
+ object-fit: contain;
116
+ }
117
+
118
+ @-webkit-keyframes yarl__thumbnails_thumbnail_fadein {
119
+ from {
120
+ opacity: 0;
121
+ }
122
+ to {
123
+ opacity: 1;
124
+ }
125
+ }
126
+
127
+ @keyframes yarl__thumbnails_thumbnail_fadein {
128
+ from {
129
+ opacity: 0;
130
+ }
131
+ to {
132
+ opacity: 1;
133
+ }
134
+ }
135
+ @-webkit-keyframes yarl__thumbnails_thumbnail_fadeout {
136
+ from {
137
+ opacity: 1;
138
+ }
139
+ to {
140
+ opacity: 0;
141
+ }
142
+ }
143
+ @keyframes yarl__thumbnails_thumbnail_fadeout {
144
+ from {
145
+ opacity: 1;
146
+ }
147
+ to {
148
+ opacity: 0;
149
+ }
150
+ }
package/dist/styles.css CHANGED
@@ -1,3 +1,7 @@
1
+ .yarl__fullsize {
2
+ width: 100%;
3
+ height: 100%;
4
+ }
1
5
  .yarl__portal {
2
6
  position: fixed;
3
7
  inset: 0;
@@ -12,13 +16,10 @@
12
16
  .yarl__container {
13
17
  -webkit-user-select: none;
14
18
  -moz-user-select: none;
15
- -ms-user-select: none;
16
19
  user-select: none;
17
20
  touch-action: var(--yarl__controller_touch_action, none);
18
21
  }
19
22
  .yarl__container {
20
- width: 100%;
21
- height: 100%;
22
23
  position: relative;
23
24
  overflow: hidden;
24
25
  color: #fff;
@@ -56,12 +57,9 @@
56
57
  transition: unset;
57
58
  }
58
59
  .yarl__slide_image {
59
- width: 100%;
60
- height: 100%;
61
60
  -o-object-fit: contain;
62
61
  object-fit: contain;
63
62
  -moz-user-select: none;
64
- -ms-user-select: none;
65
63
  user-select: none;
66
64
  -webkit-user-select: none;
67
65
  -webkit-touch-callout: none;
@@ -144,7 +142,6 @@
144
142
  display: flex;
145
143
  justify-content: flex-end;
146
144
  padding: 8px;
147
- gap: 8px;
148
145
  }
149
146
  [dir=rtl] .yarl__toolbar {
150
147
  inset: 0 auto auto 0;
@@ -215,6 +212,7 @@
215
212
  .yarl__no_scroll {
216
213
  height: 100%;
217
214
  overflow: hidden;
215
+ overscroll-behavior: none;
218
216
  }
219
217
  .yarl__pad_scrollbar {
220
218
  padding-right: var(--yarl__scrollbar_padding, 17px);