uix-image-magnify 0.1.4 → 0.2.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.
- package/dist/ImageMagnify-DssaU7jS.d.cts +88 -0
- package/dist/ImageMagnify-DssaU7jS.d.ts +88 -0
- package/dist/index.cjs +377 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +61 -83
- package/dist/index.d.ts +61 -83
- package/dist/index.js +378 -20
- package/dist/index.js.map +1 -1
- package/dist/ssr/index.cjs +44 -17
- package/dist/ssr/index.cjs.map +1 -1
- package/dist/ssr/index.d.cts +2 -2
- package/dist/ssr/index.d.ts +2 -2
- package/dist/ssr/index.js +44 -17
- package/dist/ssr/index.js.map +1 -1
- package/package.json +4 -10
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { CSSProperties, ImgHTMLAttributes } from 'react';
|
|
3
|
+
|
|
4
|
+
type ZoomType = "hover" | "click" | "double-click" | "hold" | "wheel" | "none";
|
|
5
|
+
type PanePosition = "left" | "right" | "top" | "bottom";
|
|
6
|
+
type LensShape = "circle" | "square";
|
|
7
|
+
type MagnifyMode = "lens" | "side-by-side" | "inner" | "follow";
|
|
8
|
+
type DragMode = "follow" | "pan";
|
|
9
|
+
interface UseImageMagnifyOptions {
|
|
10
|
+
/** Base image URL (required when used standalone). */
|
|
11
|
+
src?: string;
|
|
12
|
+
/** High-resolution image used for the zoomed view. Defaults to `src`. */
|
|
13
|
+
zoomSrc?: string;
|
|
14
|
+
/** Magnification factor (2 = 200%). */
|
|
15
|
+
zoomScale?: number;
|
|
16
|
+
/** Minimum scale for wheel/keyboard zoom. Default `1.5`. */
|
|
17
|
+
minZoomScale?: number;
|
|
18
|
+
/** Maximum scale for wheel/keyboard zoom. Default `5`. */
|
|
19
|
+
maxZoomScale?: number;
|
|
20
|
+
/** Interaction that activates zoom. */
|
|
21
|
+
zoomType?: ZoomType;
|
|
22
|
+
/** How the zoomed content is displayed. */
|
|
23
|
+
mode?: MagnifyMode;
|
|
24
|
+
/** Drag interaction for `inner` mode. */
|
|
25
|
+
dragMode?: DragMode;
|
|
26
|
+
/** Where the side-by-side pane sits relative to the image. */
|
|
27
|
+
panePosition?: PanePosition;
|
|
28
|
+
/** Diameter / side length of the lens in px. */
|
|
29
|
+
lensSize?: number;
|
|
30
|
+
/** Lens shape. */
|
|
31
|
+
lensShape?: LensShape;
|
|
32
|
+
/** Offset (both axes, px) for `mode="follow"`. */
|
|
33
|
+
followOffset?: number;
|
|
34
|
+
/** Disable all interaction. */
|
|
35
|
+
disabled?: boolean;
|
|
36
|
+
/** Preload the high-res image to avoid a flash. */
|
|
37
|
+
zoomPreload?: boolean;
|
|
38
|
+
/** Reset zoom when the pointer leaves the container. */
|
|
39
|
+
resetOnLeave?: boolean;
|
|
40
|
+
onZoomStart?: () => void;
|
|
41
|
+
onZoomEnd?: () => void;
|
|
42
|
+
onZoomChange?: (scale: number) => void;
|
|
43
|
+
}
|
|
44
|
+
declare function useImageMagnify(options?: UseImageMagnifyOptions): {
|
|
45
|
+
isZoomed: boolean;
|
|
46
|
+
zoomScale: number;
|
|
47
|
+
bgImage: string | undefined;
|
|
48
|
+
containerRef: React.RefObject<HTMLDivElement>;
|
|
49
|
+
imageRef: React.RefObject<HTMLImageElement>;
|
|
50
|
+
lensRef: React.RefObject<HTMLDivElement>;
|
|
51
|
+
paneRef: React.RefObject<HTMLDivElement>;
|
|
52
|
+
cursorRef: React.RefObject<HTMLDivElement>;
|
|
53
|
+
handlers: {
|
|
54
|
+
onPointerEnter: (e: React.PointerEvent) => void;
|
|
55
|
+
onPointerLeave: (e: React.PointerEvent) => void;
|
|
56
|
+
onPointerDown: (e: React.PointerEvent) => void;
|
|
57
|
+
onPointerMove: (e: React.PointerEvent) => void;
|
|
58
|
+
onPointerUp: (e: React.PointerEvent) => void;
|
|
59
|
+
onPointerCancel: () => void;
|
|
60
|
+
onDoubleClick: (e: React.MouseEvent) => void;
|
|
61
|
+
onKeyDown: (e: React.KeyboardEvent) => void;
|
|
62
|
+
onFocus: () => void;
|
|
63
|
+
onBlur: () => void;
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
interface ImageMagnifyProps extends UseImageMagnifyOptions {
|
|
68
|
+
src: string;
|
|
69
|
+
alt: string;
|
|
70
|
+
width?: number | string;
|
|
71
|
+
className?: string;
|
|
72
|
+
style?: CSSProperties;
|
|
73
|
+
imageClassName?: string;
|
|
74
|
+
imageStyle?: CSSProperties;
|
|
75
|
+
lensClassName?: string;
|
|
76
|
+
lensStyle?: CSSProperties;
|
|
77
|
+
paneClassName?: string;
|
|
78
|
+
paneStyle?: CSSProperties;
|
|
79
|
+
paneWidth?: number | string;
|
|
80
|
+
paneHeight?: number | string;
|
|
81
|
+
lazy?: boolean;
|
|
82
|
+
imageProps?: Omit<ImgHTMLAttributes<HTMLImageElement>, "src" | "alt" | "style">;
|
|
83
|
+
onLoad?: ImgHTMLAttributes<HTMLImageElement>["onLoad"];
|
|
84
|
+
onError?: ImgHTMLAttributes<HTMLImageElement>["onError"];
|
|
85
|
+
}
|
|
86
|
+
declare const ImageMagnify: React.ForwardRefExoticComponent<ImageMagnifyProps & React.RefAttributes<HTMLDivElement>>;
|
|
87
|
+
|
|
88
|
+
export { type DragMode as D, type ImageMagnifyProps as I, type LensShape as L, type MagnifyMode as M, type PanePosition as P, type UseImageMagnifyOptions as U, type ZoomType as Z, ImageMagnify as a, useImageMagnify as u };
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { CSSProperties, ImgHTMLAttributes } from 'react';
|
|
3
|
+
|
|
4
|
+
type ZoomType = "hover" | "click" | "double-click" | "hold" | "wheel" | "none";
|
|
5
|
+
type PanePosition = "left" | "right" | "top" | "bottom";
|
|
6
|
+
type LensShape = "circle" | "square";
|
|
7
|
+
type MagnifyMode = "lens" | "side-by-side" | "inner" | "follow";
|
|
8
|
+
type DragMode = "follow" | "pan";
|
|
9
|
+
interface UseImageMagnifyOptions {
|
|
10
|
+
/** Base image URL (required when used standalone). */
|
|
11
|
+
src?: string;
|
|
12
|
+
/** High-resolution image used for the zoomed view. Defaults to `src`. */
|
|
13
|
+
zoomSrc?: string;
|
|
14
|
+
/** Magnification factor (2 = 200%). */
|
|
15
|
+
zoomScale?: number;
|
|
16
|
+
/** Minimum scale for wheel/keyboard zoom. Default `1.5`. */
|
|
17
|
+
minZoomScale?: number;
|
|
18
|
+
/** Maximum scale for wheel/keyboard zoom. Default `5`. */
|
|
19
|
+
maxZoomScale?: number;
|
|
20
|
+
/** Interaction that activates zoom. */
|
|
21
|
+
zoomType?: ZoomType;
|
|
22
|
+
/** How the zoomed content is displayed. */
|
|
23
|
+
mode?: MagnifyMode;
|
|
24
|
+
/** Drag interaction for `inner` mode. */
|
|
25
|
+
dragMode?: DragMode;
|
|
26
|
+
/** Where the side-by-side pane sits relative to the image. */
|
|
27
|
+
panePosition?: PanePosition;
|
|
28
|
+
/** Diameter / side length of the lens in px. */
|
|
29
|
+
lensSize?: number;
|
|
30
|
+
/** Lens shape. */
|
|
31
|
+
lensShape?: LensShape;
|
|
32
|
+
/** Offset (both axes, px) for `mode="follow"`. */
|
|
33
|
+
followOffset?: number;
|
|
34
|
+
/** Disable all interaction. */
|
|
35
|
+
disabled?: boolean;
|
|
36
|
+
/** Preload the high-res image to avoid a flash. */
|
|
37
|
+
zoomPreload?: boolean;
|
|
38
|
+
/** Reset zoom when the pointer leaves the container. */
|
|
39
|
+
resetOnLeave?: boolean;
|
|
40
|
+
onZoomStart?: () => void;
|
|
41
|
+
onZoomEnd?: () => void;
|
|
42
|
+
onZoomChange?: (scale: number) => void;
|
|
43
|
+
}
|
|
44
|
+
declare function useImageMagnify(options?: UseImageMagnifyOptions): {
|
|
45
|
+
isZoomed: boolean;
|
|
46
|
+
zoomScale: number;
|
|
47
|
+
bgImage: string | undefined;
|
|
48
|
+
containerRef: React.RefObject<HTMLDivElement>;
|
|
49
|
+
imageRef: React.RefObject<HTMLImageElement>;
|
|
50
|
+
lensRef: React.RefObject<HTMLDivElement>;
|
|
51
|
+
paneRef: React.RefObject<HTMLDivElement>;
|
|
52
|
+
cursorRef: React.RefObject<HTMLDivElement>;
|
|
53
|
+
handlers: {
|
|
54
|
+
onPointerEnter: (e: React.PointerEvent) => void;
|
|
55
|
+
onPointerLeave: (e: React.PointerEvent) => void;
|
|
56
|
+
onPointerDown: (e: React.PointerEvent) => void;
|
|
57
|
+
onPointerMove: (e: React.PointerEvent) => void;
|
|
58
|
+
onPointerUp: (e: React.PointerEvent) => void;
|
|
59
|
+
onPointerCancel: () => void;
|
|
60
|
+
onDoubleClick: (e: React.MouseEvent) => void;
|
|
61
|
+
onKeyDown: (e: React.KeyboardEvent) => void;
|
|
62
|
+
onFocus: () => void;
|
|
63
|
+
onBlur: () => void;
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
interface ImageMagnifyProps extends UseImageMagnifyOptions {
|
|
68
|
+
src: string;
|
|
69
|
+
alt: string;
|
|
70
|
+
width?: number | string;
|
|
71
|
+
className?: string;
|
|
72
|
+
style?: CSSProperties;
|
|
73
|
+
imageClassName?: string;
|
|
74
|
+
imageStyle?: CSSProperties;
|
|
75
|
+
lensClassName?: string;
|
|
76
|
+
lensStyle?: CSSProperties;
|
|
77
|
+
paneClassName?: string;
|
|
78
|
+
paneStyle?: CSSProperties;
|
|
79
|
+
paneWidth?: number | string;
|
|
80
|
+
paneHeight?: number | string;
|
|
81
|
+
lazy?: boolean;
|
|
82
|
+
imageProps?: Omit<ImgHTMLAttributes<HTMLImageElement>, "src" | "alt" | "style">;
|
|
83
|
+
onLoad?: ImgHTMLAttributes<HTMLImageElement>["onLoad"];
|
|
84
|
+
onError?: ImgHTMLAttributes<HTMLImageElement>["onError"];
|
|
85
|
+
}
|
|
86
|
+
declare const ImageMagnify: React.ForwardRefExoticComponent<ImageMagnifyProps & React.RefAttributes<HTMLDivElement>>;
|
|
87
|
+
|
|
88
|
+
export { type DragMode as D, type ImageMagnifyProps as I, type LensShape as L, type MagnifyMode as M, type PanePosition as P, type UseImageMagnifyOptions as U, type ZoomType as Z, ImageMagnify as a, useImageMagnify as u };
|
package/dist/index.cjs
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
var react = require('react');
|
|
4
4
|
var jsxRuntime = require('react/jsx-runtime');
|
|
5
|
+
var react$1 = require('swiper/react');
|
|
6
|
+
var modules = require('swiper/modules');
|
|
7
|
+
require('swiper/css');
|
|
8
|
+
require('swiper/css/navigation');
|
|
9
|
+
require('swiper/css/thumbs');
|
|
5
10
|
|
|
6
11
|
// src/components/ImageMagnify.tsx
|
|
7
12
|
var clamp = (v, min, max) => Math.max(min, Math.min(max, v));
|
|
@@ -413,6 +418,19 @@ function useImageMagnify(options = {}) {
|
|
|
413
418
|
handlers
|
|
414
419
|
};
|
|
415
420
|
}
|
|
421
|
+
var useIsoLayoutEffect2 = typeof window !== "undefined" ? react.useLayoutEffect : react.useEffect;
|
|
422
|
+
function useMediaQuery(query) {
|
|
423
|
+
const [matches, setMatches] = react.useState(false);
|
|
424
|
+
useIsoLayoutEffect2(() => {
|
|
425
|
+
const media = window.matchMedia(query);
|
|
426
|
+
const listener = () => setMatches(media.matches);
|
|
427
|
+
listener();
|
|
428
|
+
media.addEventListener("change", listener);
|
|
429
|
+
return () => media.removeEventListener("change", listener);
|
|
430
|
+
}, [query]);
|
|
431
|
+
return matches;
|
|
432
|
+
}
|
|
433
|
+
var MOBILE_QUERY = "(max-width: 768px)";
|
|
416
434
|
var ImageMagnify = react.forwardRef(
|
|
417
435
|
(props, ref) => {
|
|
418
436
|
const {
|
|
@@ -441,6 +459,8 @@ var ImageMagnify = react.forwardRef(
|
|
|
441
459
|
onError,
|
|
442
460
|
...hookOptions
|
|
443
461
|
} = props;
|
|
462
|
+
const isMobile = useMediaQuery(MOBILE_QUERY);
|
|
463
|
+
const responsivePanePosition = isMobile ? "bottom" : panePosition;
|
|
444
464
|
const {
|
|
445
465
|
isZoomed,
|
|
446
466
|
bgImage,
|
|
@@ -458,25 +478,36 @@ var ImageMagnify = react.forwardRef(
|
|
|
458
478
|
disabled,
|
|
459
479
|
...hookOptions
|
|
460
480
|
});
|
|
461
|
-
const
|
|
462
|
-
if (
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
481
|
+
const panePositionStyle = {};
|
|
482
|
+
if (responsivePanePosition === "right") {
|
|
483
|
+
panePositionStyle.position = "absolute";
|
|
484
|
+
panePositionStyle.left = "calc(100% + 12px)";
|
|
485
|
+
panePositionStyle.top = 0;
|
|
486
|
+
} else if (responsivePanePosition === "left") {
|
|
487
|
+
panePositionStyle.position = "absolute";
|
|
488
|
+
panePositionStyle.right = "calc(100% + 12px)";
|
|
489
|
+
panePositionStyle.top = 0;
|
|
490
|
+
} else if (responsivePanePosition === "top") {
|
|
491
|
+
panePositionStyle.position = "absolute";
|
|
492
|
+
panePositionStyle.left = 0;
|
|
493
|
+
panePositionStyle.bottom = "calc(100% + 12px)";
|
|
494
|
+
} else if (isMobile) {
|
|
495
|
+
panePositionStyle.position = "static";
|
|
496
|
+
panePositionStyle.display = "block";
|
|
497
|
+
panePositionStyle.marginTop = 12;
|
|
498
|
+
panePositionStyle.width = "100%";
|
|
499
|
+
panePositionStyle.boxSizing = "border-box";
|
|
471
500
|
} else {
|
|
472
|
-
|
|
473
|
-
|
|
501
|
+
panePositionStyle.position = "absolute";
|
|
502
|
+
panePositionStyle.left = 0;
|
|
503
|
+
panePositionStyle.top = "calc(100% + 12px)";
|
|
474
504
|
}
|
|
475
505
|
const isInner = mode === "inner";
|
|
476
506
|
const showLens = (mode === "lens" || mode === "follow") && isZoomed;
|
|
477
507
|
const showPane = mode === "side-by-side" && isZoomed;
|
|
478
508
|
const showCursor = mode === "side-by-side" && isZoomed;
|
|
479
509
|
const cursorStyle = disabled ? "default" : zoomType === "hover" || zoomType === "hold" || zoomType === "wheel" ? "crosshair" : isZoomed ? "zoom-out" : "zoom-in";
|
|
510
|
+
const outerWidth = isMobile ? "100%" : width;
|
|
480
511
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
481
512
|
"div",
|
|
482
513
|
{
|
|
@@ -486,7 +517,8 @@ var ImageMagnify = react.forwardRef(
|
|
|
486
517
|
position: "relative",
|
|
487
518
|
display: "inline-block",
|
|
488
519
|
lineHeight: 0,
|
|
489
|
-
width,
|
|
520
|
+
width: outerWidth,
|
|
521
|
+
maxWidth: "100%",
|
|
490
522
|
...style
|
|
491
523
|
},
|
|
492
524
|
children: [
|
|
@@ -503,7 +535,6 @@ var ImageMagnify = react.forwardRef(
|
|
|
503
535
|
overflow: "hidden",
|
|
504
536
|
width: "100%",
|
|
505
537
|
cursor: cursorStyle,
|
|
506
|
-
// Only block scrolling while zoomed so page scrolling still works.
|
|
507
538
|
touchAction: isZoomed ? "none" : "pan-y",
|
|
508
539
|
outline: "none",
|
|
509
540
|
lineHeight: 0
|
|
@@ -590,16 +621,17 @@ var ImageMagnify = react.forwardRef(
|
|
|
590
621
|
className: paneClassName,
|
|
591
622
|
"aria-hidden": "true",
|
|
592
623
|
style: {
|
|
593
|
-
|
|
594
|
-
width: paneWidth,
|
|
624
|
+
width: isMobile && responsivePanePosition === "bottom" ? "100%" : paneWidth,
|
|
595
625
|
height: paneHeight,
|
|
626
|
+
maxWidth: "100%",
|
|
627
|
+
boxSizing: "border-box",
|
|
596
628
|
backgroundImage: bgImage ? `url("${bgImage}")` : void 0,
|
|
597
629
|
backgroundRepeat: "no-repeat",
|
|
598
630
|
border: "1px solid #e5e5e5",
|
|
599
631
|
borderRadius: 4,
|
|
600
632
|
boxShadow: "0 8px 24px rgba(0,0,0,0.12)",
|
|
601
633
|
pointerEvents: "none",
|
|
602
|
-
...
|
|
634
|
+
...panePositionStyle,
|
|
603
635
|
...paneStyle
|
|
604
636
|
}
|
|
605
637
|
}
|
|
@@ -610,8 +642,336 @@ var ImageMagnify = react.forwardRef(
|
|
|
610
642
|
}
|
|
611
643
|
);
|
|
612
644
|
ImageMagnify.displayName = "ImageMagnify";
|
|
645
|
+
var ArrowLeftIcon = () => /* @__PURE__ */ jsxRuntime.jsx(
|
|
646
|
+
"svg",
|
|
647
|
+
{
|
|
648
|
+
viewBox: "0 0 24 24",
|
|
649
|
+
width: "20",
|
|
650
|
+
height: "20",
|
|
651
|
+
fill: "none",
|
|
652
|
+
stroke: "currentColor",
|
|
653
|
+
strokeWidth: "2",
|
|
654
|
+
strokeLinecap: "round",
|
|
655
|
+
strokeLinejoin: "round",
|
|
656
|
+
"aria-hidden": "true",
|
|
657
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "15 18 9 12 15 6" })
|
|
658
|
+
}
|
|
659
|
+
);
|
|
660
|
+
var ArrowRightIcon = () => /* @__PURE__ */ jsxRuntime.jsx(
|
|
661
|
+
"svg",
|
|
662
|
+
{
|
|
663
|
+
viewBox: "0 0 24 24",
|
|
664
|
+
width: "20",
|
|
665
|
+
height: "20",
|
|
666
|
+
fill: "none",
|
|
667
|
+
stroke: "currentColor",
|
|
668
|
+
strokeWidth: "2",
|
|
669
|
+
strokeLinecap: "round",
|
|
670
|
+
strokeLinejoin: "round",
|
|
671
|
+
"aria-hidden": "true",
|
|
672
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "9 18 15 12 9 6" })
|
|
673
|
+
}
|
|
674
|
+
);
|
|
675
|
+
var defaultArrowBaseStyle = {
|
|
676
|
+
position: "absolute",
|
|
677
|
+
top: "50%",
|
|
678
|
+
transform: "translateY(-50%)",
|
|
679
|
+
width: 40,
|
|
680
|
+
height: 40,
|
|
681
|
+
display: "inline-flex",
|
|
682
|
+
alignItems: "center",
|
|
683
|
+
justifyContent: "center",
|
|
684
|
+
background: "rgba(255,255,255,0.85)",
|
|
685
|
+
border: "1px solid rgba(0,0,0,0.12)",
|
|
686
|
+
borderRadius: 9999,
|
|
687
|
+
boxShadow: "0 4px 12px rgba(0,0,0,0.15)",
|
|
688
|
+
cursor: "pointer",
|
|
689
|
+
zIndex: 10,
|
|
690
|
+
color: "#111",
|
|
691
|
+
padding: 0,
|
|
692
|
+
transition: "background 0.15s ease",
|
|
693
|
+
backdropFilter: "blur(4px)",
|
|
694
|
+
WebkitBackdropFilter: "blur(4px)"
|
|
695
|
+
};
|
|
696
|
+
var visuallyHidden = {
|
|
697
|
+
position: "absolute",
|
|
698
|
+
width: 1,
|
|
699
|
+
height: 1,
|
|
700
|
+
padding: 0,
|
|
701
|
+
margin: -1,
|
|
702
|
+
overflow: "hidden",
|
|
703
|
+
clip: "rect(0,0,0,0)",
|
|
704
|
+
whiteSpace: "nowrap",
|
|
705
|
+
border: 0
|
|
706
|
+
};
|
|
707
|
+
var ImageMagnifyGallery = react.forwardRef((props, ref) => {
|
|
708
|
+
const {
|
|
709
|
+
images,
|
|
710
|
+
alt,
|
|
711
|
+
activeIndex: controlledActiveIndex,
|
|
712
|
+
defaultIndex = 0,
|
|
713
|
+
onIndexChange,
|
|
714
|
+
showArrows = true,
|
|
715
|
+
showThumbnails = true,
|
|
716
|
+
showCounter = false,
|
|
717
|
+
loop = true,
|
|
718
|
+
enableKeyboard = true,
|
|
719
|
+
preloadAdjacent = true,
|
|
720
|
+
className,
|
|
721
|
+
style,
|
|
722
|
+
viewportClassName,
|
|
723
|
+
viewportStyle,
|
|
724
|
+
thumbnailContainerClassName,
|
|
725
|
+
thumbnailContainerStyle,
|
|
726
|
+
thumbnailClassName,
|
|
727
|
+
thumbnailActiveClassName,
|
|
728
|
+
thumbnailStyle,
|
|
729
|
+
thumbnailActiveStyle,
|
|
730
|
+
arrowClassName,
|
|
731
|
+
arrowStyle,
|
|
732
|
+
thumbnailSize = 80,
|
|
733
|
+
thumbnailGap = 8,
|
|
734
|
+
prevArrow,
|
|
735
|
+
nextArrow,
|
|
736
|
+
width,
|
|
737
|
+
...magnifyProps
|
|
738
|
+
} = props;
|
|
739
|
+
const [swiper, setSwiper] = react.useState(null);
|
|
740
|
+
const [thumbsSwiper, setThumbsSwiper] = react.useState(null);
|
|
741
|
+
const [localIndex, setLocalIndex] = react.useState(defaultIndex);
|
|
742
|
+
const prevRef = react.useRef(null);
|
|
743
|
+
const nextRef = react.useRef(null);
|
|
744
|
+
const isControlled = controlledActiveIndex !== void 0;
|
|
745
|
+
const activeIndex = isControlled ? controlledActiveIndex : localIndex;
|
|
746
|
+
const hasMultiple = images.length > 1;
|
|
747
|
+
react.useEffect(() => {
|
|
748
|
+
if (!swiper || swiper.destroyed) return;
|
|
749
|
+
if (isControlled && swiper.activeIndex !== controlledActiveIndex) {
|
|
750
|
+
swiper.slideTo(controlledActiveIndex);
|
|
751
|
+
}
|
|
752
|
+
}, [isControlled, controlledActiveIndex, swiper]);
|
|
753
|
+
react.useEffect(() => {
|
|
754
|
+
if (!preloadAdjacent || typeof window === "undefined" || images.length <= 1)
|
|
755
|
+
return;
|
|
756
|
+
const targets = /* @__PURE__ */ new Set([
|
|
757
|
+
(activeIndex + 1) % images.length,
|
|
758
|
+
(activeIndex - 1 + images.length) % images.length
|
|
759
|
+
]);
|
|
760
|
+
targets.forEach((i) => {
|
|
761
|
+
if (images[i]) {
|
|
762
|
+
const img = new Image();
|
|
763
|
+
img.src = images[i];
|
|
764
|
+
}
|
|
765
|
+
});
|
|
766
|
+
}, [activeIndex, images, preloadAdjacent]);
|
|
767
|
+
const modules$1 = react.useMemo(() => {
|
|
768
|
+
const m = [modules.Navigation, modules.Thumbs];
|
|
769
|
+
if (enableKeyboard) m.push(modules.Keyboard);
|
|
770
|
+
return m;
|
|
771
|
+
}, [enableKeyboard]);
|
|
772
|
+
if (images.length === 0) {
|
|
773
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className, style });
|
|
774
|
+
}
|
|
775
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
776
|
+
"div",
|
|
777
|
+
{
|
|
778
|
+
ref,
|
|
779
|
+
className,
|
|
780
|
+
style: { maxWidth: "100%", width, ...style },
|
|
781
|
+
role: "region",
|
|
782
|
+
"aria-roledescription": "carousel",
|
|
783
|
+
"aria-label": `${alt} \u2014 image gallery`,
|
|
784
|
+
children: [
|
|
785
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
786
|
+
"div",
|
|
787
|
+
{
|
|
788
|
+
className: viewportClassName,
|
|
789
|
+
style: { position: "relative", width: "100%", ...viewportStyle },
|
|
790
|
+
children: [
|
|
791
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
792
|
+
react$1.Swiper,
|
|
793
|
+
{
|
|
794
|
+
modules: modules$1,
|
|
795
|
+
onSwiper: setSwiper,
|
|
796
|
+
initialSlide: isControlled ? controlledActiveIndex : defaultIndex,
|
|
797
|
+
onSlideChange: (s) => {
|
|
798
|
+
if (!isControlled) setLocalIndex(s.activeIndex);
|
|
799
|
+
onIndexChange?.(s.activeIndex);
|
|
800
|
+
},
|
|
801
|
+
onBeforeInit: (s) => {
|
|
802
|
+
if (!showArrows || !hasMultiple) return;
|
|
803
|
+
if (s.params.navigation && typeof s.params.navigation === "object") {
|
|
804
|
+
s.params.navigation.prevEl = prevRef.current;
|
|
805
|
+
s.params.navigation.nextEl = nextRef.current;
|
|
806
|
+
}
|
|
807
|
+
},
|
|
808
|
+
navigation: showArrows && hasMultiple ? {} : false,
|
|
809
|
+
keyboard: enableKeyboard ? { enabled: true } : void 0,
|
|
810
|
+
thumbs: {
|
|
811
|
+
swiper: thumbsSwiper && !thumbsSwiper.destroyed ? thumbsSwiper : null
|
|
812
|
+
},
|
|
813
|
+
loop: loop && hasMultiple,
|
|
814
|
+
autoHeight: true,
|
|
815
|
+
spaceBetween: 10,
|
|
816
|
+
style: {
|
|
817
|
+
width: "100%",
|
|
818
|
+
"--swiper-navigation-size": "20px",
|
|
819
|
+
...arrowStyle
|
|
820
|
+
},
|
|
821
|
+
children: images.map((src, idx) => /* @__PURE__ */ jsxRuntime.jsx(react$1.SwiperSlide, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
822
|
+
ImageMagnify,
|
|
823
|
+
{
|
|
824
|
+
...magnifyProps,
|
|
825
|
+
src,
|
|
826
|
+
alt,
|
|
827
|
+
width: "100%"
|
|
828
|
+
}
|
|
829
|
+
) }, idx))
|
|
830
|
+
}
|
|
831
|
+
),
|
|
832
|
+
showArrows && hasMultiple && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
833
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
834
|
+
"button",
|
|
835
|
+
{
|
|
836
|
+
ref: prevRef,
|
|
837
|
+
type: "button",
|
|
838
|
+
className: arrowClassName,
|
|
839
|
+
style: { ...defaultArrowBaseStyle, left: 12 },
|
|
840
|
+
"aria-label": "Previous image",
|
|
841
|
+
children: prevArrow ?? /* @__PURE__ */ jsxRuntime.jsx(ArrowLeftIcon, {})
|
|
842
|
+
}
|
|
843
|
+
),
|
|
844
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
845
|
+
"button",
|
|
846
|
+
{
|
|
847
|
+
ref: nextRef,
|
|
848
|
+
type: "button",
|
|
849
|
+
className: arrowClassName,
|
|
850
|
+
style: { ...defaultArrowBaseStyle, right: 12 },
|
|
851
|
+
"aria-label": "Next image",
|
|
852
|
+
children: nextArrow ?? /* @__PURE__ */ jsxRuntime.jsx(ArrowRightIcon, {})
|
|
853
|
+
}
|
|
854
|
+
)
|
|
855
|
+
] }),
|
|
856
|
+
showCounter && hasMultiple && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
857
|
+
"div",
|
|
858
|
+
{
|
|
859
|
+
"aria-hidden": "true",
|
|
860
|
+
style: {
|
|
861
|
+
position: "absolute",
|
|
862
|
+
top: 12,
|
|
863
|
+
right: 12,
|
|
864
|
+
background: "rgba(0,0,0,0.6)",
|
|
865
|
+
color: "#fff",
|
|
866
|
+
fontSize: 12,
|
|
867
|
+
fontWeight: 600,
|
|
868
|
+
padding: "4px 8px",
|
|
869
|
+
borderRadius: 4,
|
|
870
|
+
zIndex: 10,
|
|
871
|
+
pointerEvents: "none"
|
|
872
|
+
},
|
|
873
|
+
children: [
|
|
874
|
+
activeIndex + 1,
|
|
875
|
+
" / ",
|
|
876
|
+
images.length
|
|
877
|
+
]
|
|
878
|
+
}
|
|
879
|
+
),
|
|
880
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { "aria-live": "polite", "aria-atomic": "true", style: visuallyHidden, children: [
|
|
881
|
+
"Image ",
|
|
882
|
+
activeIndex + 1,
|
|
883
|
+
" of ",
|
|
884
|
+
images.length
|
|
885
|
+
] })
|
|
886
|
+
]
|
|
887
|
+
}
|
|
888
|
+
),
|
|
889
|
+
showThumbnails && hasMultiple && /* @__PURE__ */ jsxRuntime.jsx(
|
|
890
|
+
react$1.Swiper,
|
|
891
|
+
{
|
|
892
|
+
modules: modules$1,
|
|
893
|
+
onSwiper: setSwiper,
|
|
894
|
+
initialSlide: isControlled ? controlledActiveIndex : defaultIndex,
|
|
895
|
+
onSlideChange: (s) => {
|
|
896
|
+
if (!isControlled) setLocalIndex(s.activeIndex);
|
|
897
|
+
onIndexChange?.(s.activeIndex);
|
|
898
|
+
},
|
|
899
|
+
onBeforeInit: (s) => {
|
|
900
|
+
if (!showArrows || !hasMultiple) return;
|
|
901
|
+
const nav = s.params.navigation;
|
|
902
|
+
if (nav && typeof nav === "object") {
|
|
903
|
+
nav.prevEl = prevRef.current;
|
|
904
|
+
nav.nextEl = nextRef.current;
|
|
905
|
+
}
|
|
906
|
+
},
|
|
907
|
+
navigation: showArrows && hasMultiple ? {} : false,
|
|
908
|
+
keyboard: enableKeyboard ? { enabled: true } : void 0,
|
|
909
|
+
thumbs: {
|
|
910
|
+
swiper: thumbsSwiper && !thumbsSwiper.destroyed ? thumbsSwiper : null
|
|
911
|
+
},
|
|
912
|
+
loop: loop && hasMultiple,
|
|
913
|
+
autoHeight: true,
|
|
914
|
+
spaceBetween: 10,
|
|
915
|
+
style: { width: "100%" },
|
|
916
|
+
children: images.map((src, idx) => /* @__PURE__ */ jsxRuntime.jsx(react$1.SwiperSlide, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
917
|
+
ImageMagnify,
|
|
918
|
+
{
|
|
919
|
+
...magnifyProps,
|
|
920
|
+
src,
|
|
921
|
+
alt,
|
|
922
|
+
width: "100%"
|
|
923
|
+
}
|
|
924
|
+
) }, idx))
|
|
925
|
+
}
|
|
926
|
+
)
|
|
927
|
+
]
|
|
928
|
+
}
|
|
929
|
+
);
|
|
930
|
+
});
|
|
931
|
+
ImageMagnifyGallery.displayName = "ImageMagnifyGallery";
|
|
932
|
+
function useImageSlider({
|
|
933
|
+
length,
|
|
934
|
+
defaultIndex = 0,
|
|
935
|
+
index: controlledIndex,
|
|
936
|
+
onIndexChange,
|
|
937
|
+
loop = true
|
|
938
|
+
}) {
|
|
939
|
+
const [internalIndex, setInternalIndex] = react.useState(defaultIndex);
|
|
940
|
+
const safeLength = Math.max(1, length);
|
|
941
|
+
const rawIndex = controlledIndex ?? internalIndex;
|
|
942
|
+
const index = Math.max(0, Math.min(safeLength - 1, rawIndex));
|
|
943
|
+
const setIndex = react.useCallback(
|
|
944
|
+
(next2) => {
|
|
945
|
+
if (length <= 0) return;
|
|
946
|
+
let resolved;
|
|
947
|
+
if (loop) {
|
|
948
|
+
resolved = (next2 % safeLength + safeLength) % safeLength;
|
|
949
|
+
} else {
|
|
950
|
+
resolved = Math.max(0, Math.min(safeLength - 1, next2));
|
|
951
|
+
}
|
|
952
|
+
if (resolved === index) return;
|
|
953
|
+
if (controlledIndex === void 0) {
|
|
954
|
+
setInternalIndex(resolved);
|
|
955
|
+
}
|
|
956
|
+
onIndexChange?.(resolved);
|
|
957
|
+
},
|
|
958
|
+
[length, safeLength, loop, index, controlledIndex, onIndexChange]
|
|
959
|
+
);
|
|
960
|
+
const prev = react.useCallback(() => setIndex(index - 1), [setIndex, index]);
|
|
961
|
+
const next = react.useCallback(() => setIndex(index + 1), [setIndex, index]);
|
|
962
|
+
return {
|
|
963
|
+
index,
|
|
964
|
+
canPrev: loop || index > 0,
|
|
965
|
+
canNext: loop || index < safeLength - 1,
|
|
966
|
+
setIndex,
|
|
967
|
+
prev,
|
|
968
|
+
next
|
|
969
|
+
};
|
|
970
|
+
}
|
|
613
971
|
|
|
614
972
|
exports.ImageMagnify = ImageMagnify;
|
|
973
|
+
exports.ImageMagnifyGallery = ImageMagnifyGallery;
|
|
615
974
|
exports.useImageMagnify = useImageMagnify;
|
|
975
|
+
exports.useImageSlider = useImageSlider;
|
|
616
976
|
//# sourceMappingURL=index.cjs.map
|
|
617
977
|
//# sourceMappingURL=index.cjs.map
|