yet-another-react-lightbox 3.24.0 → 3.26.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.
- package/README.md +1 -1
- package/dist/index.js +1 -1
- package/dist/plugins/captions/captions.css +1 -1
- package/dist/plugins/zoom/index.d.ts +4 -0
- package/dist/plugins/zoom/index.js +40 -23
- package/package.json +2 -6
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ extendable.
|
|
|
9
9
|
[](https://bundlephobia.com/package/yet-another-react-lightbox)
|
|
10
10
|
[](https://github.com/igordanchenko/yet-another-react-lightbox/blob/main/LICENSE)
|
|
11
11
|
|
|
12
|
-
- **Built for React:** works with React 18, 17 and 16.8.0+
|
|
12
|
+
- **Built for React:** works with React 19, 18, 17 and 16.8.0+
|
|
13
13
|
- **UX:** supports keyboard, mouse, touchpad and touchscreen navigation
|
|
14
14
|
- **Preloading:** never displays partially downloaded images
|
|
15
15
|
- **Performance:** preloads limited number of images without compromising
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
"use client";
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { IMAGE_FIT_COVER, IMAGE_FIT_CONTAIN, ACTION_CLOSE, MODULE_CONTROLLER, UNKNOWN_ACTION_TYPE, ELEMENT_BUTTON, ELEMENT_ICON, EVENT_ON_WHEEL, EVENT_ON_KEY_UP, EVENT_ON_KEY_DOWN, EVENT_ON_POINTER_CANCEL, EVENT_ON_POINTER_LEAVE, EVENT_ON_POINTER_UP, EVENT_ON_POINTER_MOVE, EVENT_ON_POINTER_DOWN, SLIDE_STATUS_LOADING, activeSlideStatus, SLIDE_STATUS_COMPLETE, SLIDE_STATUS_ERROR, SLIDE_STATUS_PLACEHOLDER, CLASS_SLIDE, CLASS_SLIDE_WRAPPER, ACTION_PREV, ACTION_NEXT, ACTION_SWIPE, MODULE_PORTAL, CLASS_FLEX_CENTER, MODULE_CAROUSEL, VK_ARROW_RIGHT, VK_ARROW_LEFT, VK_ESCAPE, MODULE_NAVIGATION, CLASS_NO_SCROLL, CLASS_NO_SCROLL_PADDING, MODULE_NO_SCROLL, MODULE_ROOT, MODULE_TOOLBAR } from './types.js';
|
|
4
4
|
import { createPortal } from 'react-dom';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.yarl__slide_captions_container{background:var(--yarl__slide_captions_container_background,rgba(0,0,0,.5));left:var(--yarl__slide_captions_container_left,0);padding:var(--yarl__slide_captions_container_padding,16px);position:absolute;right:var(--yarl__slide_captions_container_right,0);-webkit-transform:translateZ(0)}.yarl__slide_title{color:var(--yarl__slide_title_color,#fff);font-size:var(--yarl__slide_title_font_size,125%);font-weight:var(--yarl__slide_title_font_weight,bolder);max-width:calc(100% - var(--yarl__toolbar_width, 0px));overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.yarl__slide_title_container{top:var(--yarl__slide_title_container_top,0)}.yarl__slide_description{display:-webkit-box
|
|
1
|
+
.yarl__slide_captions_container{background:var(--yarl__slide_captions_container_background,rgba(0,0,0,.5));left:var(--yarl__slide_captions_container_left,0);padding:var(--yarl__slide_captions_container_padding,16px);position:absolute;right:var(--yarl__slide_captions_container_right,0);-webkit-transform:translateZ(0)}.yarl__slide_title{color:var(--yarl__slide_title_color,#fff);font-size:var(--yarl__slide_title_font_size,125%);font-weight:var(--yarl__slide_title_font_weight,bolder);max-width:calc(100% - var(--yarl__toolbar_width, 0px));overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.yarl__slide_title_container{top:var(--yarl__slide_title_container_top,0)}.yarl__slide_description{display:-webkit-box;hyphens:auto;overflow:hidden;-webkit-box-orient:vertical;color:var(--yarl__slide_description_color,#fff);-webkit-line-clamp:var(--yarl__slide_description_max_lines,3);text-align:var(--yarl__slide_description_text_align,start)}.yarl__slide_description_container{bottom:var(--yarl__slide_description_container_bottom,0)}
|
|
@@ -10,6 +10,8 @@ declare module "yet-another-react-lightbox" {
|
|
|
10
10
|
zoom?: {
|
|
11
11
|
/** Zoom plugin ref */
|
|
12
12
|
ref?: React.ForwardedRef<ZoomRef>;
|
|
13
|
+
/** override minimum zoom level (default: 1.0) */
|
|
14
|
+
minZoom?: number;
|
|
13
15
|
/** ratio of image pixels to physical pixels at maximum zoom level */
|
|
14
16
|
maxZoomPixelRatio?: number;
|
|
15
17
|
/** zoom-in multiplier */
|
|
@@ -70,6 +72,8 @@ declare module "yet-another-react-lightbox" {
|
|
|
70
72
|
interface ZoomRef {
|
|
71
73
|
/** current zoom level */
|
|
72
74
|
zoom: number;
|
|
75
|
+
/** minimum zoom level */
|
|
76
|
+
minZoom: number;
|
|
73
77
|
/** maximum zoom level */
|
|
74
78
|
maxZoom: number;
|
|
75
79
|
/** horizontal offset */
|
|
@@ -3,6 +3,7 @@ import { useLightboxProps, useMotionPreference, useEventCallback, useLayoutEffec
|
|
|
3
3
|
import { EVENT_ON_KEY_DOWN, EVENT_ON_WHEEL, UNKNOWN_ACTION_TYPE, CLASS_FULLSIZE, CLASS_FLEX_CENTER, CLASS_SLIDE_WRAPPER, CLASS_SLIDE_WRAPPER_INTERACTIVE, PLUGIN_ZOOM } from '../../types.js';
|
|
4
4
|
|
|
5
5
|
const defaultZoomProps = {
|
|
6
|
+
minZoom: 1,
|
|
6
7
|
maxZoomPixelRatio: 1,
|
|
7
8
|
zoomInMultiplier: 2,
|
|
8
9
|
doubleTapDelay: 300,
|
|
@@ -13,10 +14,13 @@ const defaultZoomProps = {
|
|
|
13
14
|
pinchZoomDistanceFactor: 100,
|
|
14
15
|
scrollToZoom: false,
|
|
15
16
|
};
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
function validateMinZoom(minZoom) {
|
|
18
|
+
return Math.min(Math.max(minZoom, Number.EPSILON), 1);
|
|
19
|
+
}
|
|
20
|
+
function resolveZoomProps(zoom) {
|
|
21
|
+
const { minZoom, ...rest } = { ...defaultZoomProps, ...zoom };
|
|
22
|
+
return { minZoom: validateMinZoom(minZoom), ...rest };
|
|
23
|
+
}
|
|
20
24
|
|
|
21
25
|
function useZoomAnimation(zoom, offsetX, offsetY, zoomWrapperRef) {
|
|
22
26
|
const zoomAnimation = React.useRef(undefined);
|
|
@@ -118,7 +122,7 @@ function distance(pointerA, pointerB) {
|
|
|
118
122
|
function scaleZoom(value, delta, factor = 100, clamp = 2) {
|
|
119
123
|
return value * Math.min(1 + Math.abs(delta / factor), clamp) ** Math.sign(delta);
|
|
120
124
|
}
|
|
121
|
-
function useZoomSensors(zoom, maxZoom, disabled, changeZoom, changeOffsets, zoomWrapperRef) {
|
|
125
|
+
function useZoomSensors(zoom, minZoom, maxZoom, disabled, zoomIn, zoomOut, changeZoom, changeOffsets, zoomWrapperRef) {
|
|
122
126
|
const activePointers = React.useRef([]);
|
|
123
127
|
const lastPointerDown = React.useRef(0);
|
|
124
128
|
const pinchZoomDistance = React.useRef(undefined);
|
|
@@ -160,18 +164,17 @@ function useZoomSensors(zoom, maxZoom, disabled, changeZoom, changeOffsets, zoom
|
|
|
160
164
|
move(keyboardMoveDistance, 0);
|
|
161
165
|
}
|
|
162
166
|
}
|
|
163
|
-
const handleChangeZoom = (zoomValue) => {
|
|
164
|
-
preventDefault();
|
|
165
|
-
changeZoom(zoomValue);
|
|
166
|
-
};
|
|
167
167
|
if (key === "+" || (meta && key === "=")) {
|
|
168
|
-
|
|
168
|
+
preventDefault();
|
|
169
|
+
zoomIn();
|
|
169
170
|
}
|
|
170
171
|
else if (key === "-" || (meta && key === "_")) {
|
|
171
|
-
|
|
172
|
+
preventDefault();
|
|
173
|
+
zoomOut();
|
|
172
174
|
}
|
|
173
175
|
else if (meta && key === "0") {
|
|
174
|
-
|
|
176
|
+
preventDefault();
|
|
177
|
+
changeZoom(1);
|
|
175
178
|
}
|
|
176
179
|
});
|
|
177
180
|
const onWheel = useEventCallback((event) => {
|
|
@@ -212,7 +215,14 @@ function useZoomSensors(zoom, maxZoom, disabled, changeZoom, changeOffsets, zoom
|
|
|
212
215
|
if (pointers.length === 0 &&
|
|
213
216
|
timeStamp - lastPointerDown.current < (event.pointerType === "touch" ? doubleTapDelay : doubleClickDelay)) {
|
|
214
217
|
lastPointerDown.current = 0;
|
|
215
|
-
|
|
218
|
+
const targetZoom = zoom >= 1
|
|
219
|
+
? zoom !== maxZoom
|
|
220
|
+
? zoom * Math.max(maxZoom ** (1 / doubleClickMaxStops), zoomInMultiplier)
|
|
221
|
+
: 1
|
|
222
|
+
: zoom !== minZoom
|
|
223
|
+
? zoom / Math.max(minZoom ** (-1 / doubleClickMaxStops), zoomInMultiplier)
|
|
224
|
+
: 1;
|
|
225
|
+
changeZoom(targetZoom, false, ...translateCoordinates(event));
|
|
216
226
|
}
|
|
217
227
|
else {
|
|
218
228
|
lastPointerDown.current = timeStamp;
|
|
@@ -278,7 +288,7 @@ function useZoomState(imageRect, maxZoom, zoomWrapperRef) {
|
|
|
278
288
|
const animate = useZoomAnimation(zoom, offsetX, offsetY, zoomWrapperRef);
|
|
279
289
|
const { currentSlide, globalIndex } = useLightboxState();
|
|
280
290
|
const { containerRect, slideRect } = useController();
|
|
281
|
-
const { zoomInMultiplier } = useZoomProps();
|
|
291
|
+
const { minZoom, zoomInMultiplier } = useZoomProps();
|
|
282
292
|
const currentSource = currentSlide && isImageSlide(currentSlide) ? currentSlide.src : undefined;
|
|
283
293
|
const disabled = !currentSource || !(zoomWrapperRef === null || zoomWrapperRef === void 0 ? void 0 : zoomWrapperRef.current);
|
|
284
294
|
useLayoutEffect(() => {
|
|
@@ -296,7 +306,7 @@ function useZoomState(imageRect, maxZoom, zoomWrapperRef) {
|
|
|
296
306
|
setOffsetY(Math.min(Math.abs(newOffsetY), Math.max(maxOffsetY, 0)) * Math.sign(newOffsetY));
|
|
297
307
|
}, [zoom, offsetX, offsetY, slideRect, imageRect.width, imageRect.height]);
|
|
298
308
|
const changeZoom = React.useCallback((targetZoom, rapid, dx, dy) => {
|
|
299
|
-
const newZoom = round(Math.min(Math.max(targetZoom + 0.001 < maxZoom ? targetZoom : maxZoom,
|
|
309
|
+
const newZoom = round(Math.min(Math.max(targetZoom + 0.001 < maxZoom ? targetZoom : maxZoom, minZoom), maxZoom), 5);
|
|
300
310
|
if (newZoom === zoom)
|
|
301
311
|
return;
|
|
302
312
|
if (!rapid) {
|
|
@@ -304,7 +314,7 @@ function useZoomState(imageRect, maxZoom, zoomWrapperRef) {
|
|
|
304
314
|
}
|
|
305
315
|
changeOffsets(dx ? dx * (1 / zoom - 1 / newZoom) : 0, dy ? dy * (1 / zoom - 1 / newZoom) : 0, newZoom);
|
|
306
316
|
setZoom(newZoom);
|
|
307
|
-
}, [zoom, maxZoom, changeOffsets, animate]);
|
|
317
|
+
}, [zoom, minZoom, maxZoom, changeOffsets, animate]);
|
|
308
318
|
const handleControllerRectChange = useEventCallback(() => {
|
|
309
319
|
if (zoom > 1) {
|
|
310
320
|
if (zoom > maxZoom) {
|
|
@@ -314,8 +324,14 @@ function useZoomState(imageRect, maxZoom, zoomWrapperRef) {
|
|
|
314
324
|
}
|
|
315
325
|
});
|
|
316
326
|
useLayoutEffect(handleControllerRectChange, [containerRect.width, containerRect.height, handleControllerRectChange]);
|
|
317
|
-
const zoomIn = React.useCallback(() =>
|
|
318
|
-
|
|
327
|
+
const zoomIn = React.useCallback(() => {
|
|
328
|
+
const targetZoom = zoom * zoomInMultiplier;
|
|
329
|
+
changeZoom(zoom < 1 && targetZoom > 1 ? 1 : targetZoom);
|
|
330
|
+
}, [zoom, zoomInMultiplier, changeZoom]);
|
|
331
|
+
const zoomOut = React.useCallback(() => {
|
|
332
|
+
const targetZoom = zoom / zoomInMultiplier;
|
|
333
|
+
changeZoom(zoom > 1 && targetZoom < 1 ? 1 : targetZoom);
|
|
334
|
+
}, [zoom, zoomInMultiplier, changeZoom]);
|
|
319
335
|
return { zoom, offsetX, offsetY, disabled, changeOffsets, changeZoom, zoomIn, zoomOut };
|
|
320
336
|
}
|
|
321
337
|
|
|
@@ -324,12 +340,13 @@ const useZoom = makeUseContext("useZoom", "ZoomControllerContext", ZoomControlle
|
|
|
324
340
|
function ZoomContextProvider({ children }) {
|
|
325
341
|
const [zoomWrapper, setZoomWrapper] = React.useState();
|
|
326
342
|
const { slideRect } = useController();
|
|
343
|
+
const { ref, minZoom } = useZoomProps();
|
|
327
344
|
const { imageRect, maxZoom } = useZoomImageRect(slideRect, zoomWrapper === null || zoomWrapper === void 0 ? void 0 : zoomWrapper.imageDimensions);
|
|
328
345
|
const { zoom, offsetX, offsetY, disabled, changeZoom, changeOffsets, zoomIn, zoomOut } = useZoomState(imageRect, maxZoom, zoomWrapper === null || zoomWrapper === void 0 ? void 0 : zoomWrapper.zoomWrapperRef);
|
|
329
346
|
useZoomCallback(zoom, disabled);
|
|
330
|
-
useZoomSensors(zoom, maxZoom, disabled, changeZoom, changeOffsets, zoomWrapper === null || zoomWrapper === void 0 ? void 0 : zoomWrapper.zoomWrapperRef);
|
|
331
|
-
const zoomRef = React.useMemo(() => ({ zoom, maxZoom, offsetX, offsetY, disabled, zoomIn, zoomOut, changeZoom }), [zoom, maxZoom, offsetX, offsetY, disabled, zoomIn, zoomOut, changeZoom]);
|
|
332
|
-
React.useImperativeHandle(
|
|
347
|
+
useZoomSensors(zoom, minZoom, maxZoom, disabled, zoomIn, zoomOut, changeZoom, changeOffsets, zoomWrapper === null || zoomWrapper === void 0 ? void 0 : zoomWrapper.zoomWrapperRef);
|
|
348
|
+
const zoomRef = React.useMemo(() => ({ zoom, minZoom, maxZoom, offsetX, offsetY, disabled, zoomIn, zoomOut, changeZoom }), [zoom, minZoom, maxZoom, offsetX, offsetY, disabled, zoomIn, zoomOut, changeZoom]);
|
|
349
|
+
React.useImperativeHandle(ref, () => zoomRef, [zoomRef]);
|
|
333
350
|
const context = React.useMemo(() => ({ ...zoomRef, setZoomWrapper }), [zoomRef, setZoomWrapper]);
|
|
334
351
|
return React.createElement(ZoomControllerContext.Provider, { value: context }, children);
|
|
335
352
|
}
|
|
@@ -341,9 +358,9 @@ const ZoomOutIcon = createIcon("ZoomOut", React.createElement("path", { d: "M15.
|
|
|
341
358
|
const ZoomButton = React.forwardRef(function ZoomButton({ zoomIn, onLoseFocus }, ref) {
|
|
342
359
|
const wasEnabled = React.useRef(false);
|
|
343
360
|
const wasFocused = React.useRef(false);
|
|
344
|
-
const { zoom, maxZoom, zoomIn: zoomInCallback, zoomOut: zoomOutCallback, disabled: zoomDisabled } = useZoom();
|
|
361
|
+
const { zoom, minZoom, maxZoom, zoomIn: zoomInCallback, zoomOut: zoomOutCallback, disabled: zoomDisabled, } = useZoom();
|
|
345
362
|
const { render } = useLightboxProps();
|
|
346
|
-
const disabled = zoomDisabled || (zoomIn ? zoom >= maxZoom : zoom <=
|
|
363
|
+
const disabled = zoomDisabled || (zoomIn ? zoom >= maxZoom : zoom <= minZoom);
|
|
347
364
|
React.useEffect(() => {
|
|
348
365
|
if (disabled && wasEnabled.current && wasFocused.current) {
|
|
349
366
|
onLoseFocus();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yet-another-react-lightbox",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.26.0",
|
|
4
4
|
"description": "Modern React lightbox component",
|
|
5
5
|
"author": "Igor Danchenko",
|
|
6
6
|
"license": "MIT",
|
|
@@ -141,7 +141,7 @@
|
|
|
141
141
|
"homepage": "https://yet-another-react-lightbox.com",
|
|
142
142
|
"repository": {
|
|
143
143
|
"type": "git",
|
|
144
|
-
"url": "https://github.com/igordanchenko/yet-another-react-lightbox.git"
|
|
144
|
+
"url": "git+https://github.com/igordanchenko/yet-another-react-lightbox.git"
|
|
145
145
|
},
|
|
146
146
|
"bugs": {
|
|
147
147
|
"url": "https://github.com/igordanchenko/yet-another-react-lightbox/issues"
|
|
@@ -149,10 +149,6 @@
|
|
|
149
149
|
"engines": {
|
|
150
150
|
"node": ">=14"
|
|
151
151
|
},
|
|
152
|
-
"publishConfig": {
|
|
153
|
-
"access": "public",
|
|
154
|
-
"provenance": true
|
|
155
|
-
},
|
|
156
152
|
"peerDependencies": {
|
|
157
153
|
"@types/react": "^16 || ^17 || ^18 || ^19",
|
|
158
154
|
"@types/react-dom": "^16 || ^17 || ^18 || ^19",
|