uix-image-magnify 0.1.2 → 0.1.4
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/index.cjs +287 -79
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +32 -11
- package/dist/index.d.ts +32 -11
- package/dist/index.js +288 -80
- package/dist/index.js.map +1 -1
- package/dist/ssr/index.cjs +294 -80
- package/dist/ssr/index.cjs.map +1 -1
- package/dist/ssr/index.js +295 -81
- package/dist/ssr/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -5,18 +5,28 @@ var jsxRuntime = require('react/jsx-runtime');
|
|
|
5
5
|
|
|
6
6
|
// src/components/ImageMagnify.tsx
|
|
7
7
|
var clamp = (v, min, max) => Math.max(min, Math.min(max, v));
|
|
8
|
+
var useIsoLayoutEffect = typeof window !== "undefined" ? react.useLayoutEffect : react.useEffect;
|
|
8
9
|
function useImageMagnify(options = {}) {
|
|
9
10
|
const {
|
|
10
11
|
src,
|
|
11
12
|
zoomSrc,
|
|
12
13
|
zoomScale = 2,
|
|
14
|
+
minZoomScale = 1.5,
|
|
15
|
+
maxZoomScale = 5,
|
|
13
16
|
zoomType = "hover",
|
|
17
|
+
mode = "side-by-side",
|
|
18
|
+
dragMode = "follow",
|
|
14
19
|
lensSize = 150,
|
|
20
|
+
followOffset = 0,
|
|
15
21
|
zoomPreload = true,
|
|
22
|
+
disabled = false,
|
|
23
|
+
resetOnLeave = false,
|
|
16
24
|
onZoomStart,
|
|
17
|
-
onZoomEnd
|
|
25
|
+
onZoomEnd,
|
|
26
|
+
onZoomChange
|
|
18
27
|
} = options;
|
|
19
28
|
const [isZoomed, setIsZoomed] = react.useState(false);
|
|
29
|
+
const [currentScale, setCurrentScale] = react.useState(zoomScale);
|
|
20
30
|
const isZoomedRef = react.useRef(false);
|
|
21
31
|
const containerRef = react.useRef(null);
|
|
22
32
|
const imageRef = react.useRef(null);
|
|
@@ -25,18 +35,60 @@ function useImageMagnify(options = {}) {
|
|
|
25
35
|
const cursorRef = react.useRef(null);
|
|
26
36
|
const pointerRef = react.useRef({ x: 0, y: 0 });
|
|
27
37
|
const rafRef = react.useRef(0);
|
|
28
|
-
const
|
|
38
|
+
const scaleRef = react.useRef(zoomScale);
|
|
39
|
+
const modeRef = react.useRef(mode);
|
|
40
|
+
const lensSizeRef = react.useRef(lensSize);
|
|
41
|
+
const followOffsetRef = react.useRef(followOffset);
|
|
42
|
+
const dragModeRef = react.useRef(dragMode);
|
|
43
|
+
const txRef = react.useRef(0);
|
|
44
|
+
const tyRef = react.useRef(0);
|
|
45
|
+
const dragStartRef = react.useRef(null);
|
|
29
46
|
const bgImage = zoomSrc || src;
|
|
30
|
-
|
|
47
|
+
useIsoLayoutEffect(() => {
|
|
48
|
+
scaleRef.current = zoomScale;
|
|
49
|
+
setCurrentScale(zoomScale);
|
|
50
|
+
}, [zoomScale]);
|
|
51
|
+
useIsoLayoutEffect(() => {
|
|
52
|
+
modeRef.current = mode;
|
|
53
|
+
}, [mode]);
|
|
54
|
+
useIsoLayoutEffect(() => {
|
|
55
|
+
lensSizeRef.current = lensSize;
|
|
56
|
+
}, [lensSize]);
|
|
57
|
+
useIsoLayoutEffect(() => {
|
|
58
|
+
followOffsetRef.current = followOffset;
|
|
59
|
+
}, [followOffset]);
|
|
60
|
+
useIsoLayoutEffect(() => {
|
|
61
|
+
dragModeRef.current = dragMode;
|
|
62
|
+
}, [dragMode]);
|
|
63
|
+
const updatePointer = react.useCallback((clientX, clientY) => {
|
|
64
|
+
const container = containerRef.current;
|
|
65
|
+
if (!container) return;
|
|
66
|
+
const rect = container.getBoundingClientRect();
|
|
67
|
+
if (!rect.width || !rect.height) return;
|
|
68
|
+
pointerRef.current = {
|
|
69
|
+
x: clamp(clientX - rect.left, 0, rect.width),
|
|
70
|
+
y: clamp(clientY - rect.top, 0, rect.height)
|
|
71
|
+
};
|
|
72
|
+
}, []);
|
|
31
73
|
const setZoomed = react.useCallback(
|
|
32
74
|
(z) => {
|
|
75
|
+
if (disabled) return;
|
|
33
76
|
if (isZoomedRef.current === z) return;
|
|
34
77
|
isZoomedRef.current = z;
|
|
35
78
|
setIsZoomed(z);
|
|
36
|
-
if (z)
|
|
37
|
-
|
|
79
|
+
if (z) {
|
|
80
|
+
onZoomStart?.();
|
|
81
|
+
} else {
|
|
82
|
+
if (zoomType === "wheel") {
|
|
83
|
+
scaleRef.current = zoomScale;
|
|
84
|
+
setCurrentScale(zoomScale);
|
|
85
|
+
}
|
|
86
|
+
txRef.current = 0;
|
|
87
|
+
tyRef.current = 0;
|
|
88
|
+
onZoomEnd?.();
|
|
89
|
+
}
|
|
38
90
|
},
|
|
39
|
-
[onZoomStart, onZoomEnd]
|
|
91
|
+
[disabled, onZoomStart, onZoomEnd, zoomType, zoomScale]
|
|
40
92
|
);
|
|
41
93
|
const apply = react.useCallback(() => {
|
|
42
94
|
const container = containerRef.current;
|
|
@@ -44,27 +96,51 @@ function useImageMagnify(options = {}) {
|
|
|
44
96
|
const rect = container.getBoundingClientRect();
|
|
45
97
|
if (!rect.width || !rect.height) return;
|
|
46
98
|
const { x, y } = pointerRef.current;
|
|
47
|
-
const
|
|
48
|
-
const
|
|
99
|
+
const scale = scaleRef.current;
|
|
100
|
+
const ls = lensSizeRef.current;
|
|
101
|
+
const md = modeRef.current;
|
|
102
|
+
const fo = followOffsetRef.current;
|
|
103
|
+
const img = imageRef.current;
|
|
104
|
+
if (md === "inner" && img) {
|
|
105
|
+
if (!isZoomedRef.current) {
|
|
106
|
+
img.style.transform = "";
|
|
107
|
+
} else {
|
|
108
|
+
const minTx = rect.width * (1 - scale);
|
|
109
|
+
const minTy = rect.height * (1 - scale);
|
|
110
|
+
let tx;
|
|
111
|
+
let ty;
|
|
112
|
+
if (dragModeRef.current === "pan") {
|
|
113
|
+
tx = clamp(txRef.current, minTx, 0);
|
|
114
|
+
ty = clamp(tyRef.current, minTy, 0);
|
|
115
|
+
} else {
|
|
116
|
+
tx = x * (1 - scale);
|
|
117
|
+
ty = y * (1 - scale);
|
|
118
|
+
tx = clamp(tx, minTx, 0);
|
|
119
|
+
ty = clamp(ty, minTy, 0);
|
|
120
|
+
}
|
|
121
|
+
txRef.current = tx;
|
|
122
|
+
tyRef.current = ty;
|
|
123
|
+
img.style.transform = `translate3d(${tx}px, ${ty}px, 0) scale(${scale})`;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
49
126
|
const lens = lensRef.current;
|
|
50
127
|
if (lens) {
|
|
51
|
-
const maxX = Math.max(0, rect.width -
|
|
52
|
-
const maxY = Math.max(0, rect.height -
|
|
53
|
-
const
|
|
54
|
-
const
|
|
55
|
-
const
|
|
56
|
-
const cy = ly + lensSize / 2;
|
|
128
|
+
const maxX = Math.max(0, rect.width - ls);
|
|
129
|
+
const maxY = Math.max(0, rect.height - ls);
|
|
130
|
+
const offset = md === "follow" ? fo : 0;
|
|
131
|
+
const lx = clamp(x - ls / 2 + offset, 0, maxX);
|
|
132
|
+
const ly = clamp(y - ls / 2 + offset, 0, maxY);
|
|
57
133
|
lens.style.transform = `translate3d(${lx}px, ${ly}px, 0)`;
|
|
58
|
-
lens.style.backgroundPosition = `${
|
|
134
|
+
lens.style.backgroundPosition = `${ls / 2 - x * scale}px ${ls / 2 - y * scale}px`;
|
|
59
135
|
}
|
|
60
136
|
const pane = paneRef.current;
|
|
61
137
|
if (pane) {
|
|
62
138
|
const pw = pane.offsetWidth;
|
|
63
139
|
const ph = pane.offsetHeight;
|
|
64
|
-
const bgW = rect.width *
|
|
65
|
-
const bgH = rect.height *
|
|
66
|
-
let bgX = pw / 2 -
|
|
67
|
-
let bgY = ph / 2 -
|
|
140
|
+
const bgW = rect.width * scale;
|
|
141
|
+
const bgH = rect.height * scale;
|
|
142
|
+
let bgX = pw / 2 - x / rect.width * bgW;
|
|
143
|
+
let bgY = ph / 2 - y / rect.height * bgH;
|
|
68
144
|
if (bgW > pw) bgX = clamp(bgX, pw - bgW, 0);
|
|
69
145
|
else bgX = (pw - bgW) / 2;
|
|
70
146
|
if (bgH > ph) bgY = clamp(bgY, ph - bgH, 0);
|
|
@@ -75,7 +151,7 @@ function useImageMagnify(options = {}) {
|
|
|
75
151
|
if (cursor) {
|
|
76
152
|
cursor.style.transform = `translate3d(${x}px, ${y}px, 0)`;
|
|
77
153
|
}
|
|
78
|
-
}, [
|
|
154
|
+
}, []);
|
|
79
155
|
const schedule = react.useCallback(() => {
|
|
80
156
|
if (rafRef.current) return;
|
|
81
157
|
rafRef.current = requestAnimationFrame(() => {
|
|
@@ -83,9 +159,42 @@ function useImageMagnify(options = {}) {
|
|
|
83
159
|
apply();
|
|
84
160
|
});
|
|
85
161
|
}, [apply]);
|
|
162
|
+
const setScale = react.useCallback(
|
|
163
|
+
(next) => {
|
|
164
|
+
const clamped = clamp(next, minZoomScale, maxZoomScale);
|
|
165
|
+
if (scaleRef.current === clamped) return;
|
|
166
|
+
scaleRef.current = clamped;
|
|
167
|
+
setCurrentScale(clamped);
|
|
168
|
+
onZoomChange?.(clamped);
|
|
169
|
+
const container = containerRef.current;
|
|
170
|
+
if (container) {
|
|
171
|
+
const rect = container.getBoundingClientRect();
|
|
172
|
+
if (rect.width && rect.height) {
|
|
173
|
+
const size = `${rect.width * clamped}px ${rect.height * clamped}px`;
|
|
174
|
+
if (lensRef.current) lensRef.current.style.backgroundSize = size;
|
|
175
|
+
if (paneRef.current) paneRef.current.style.backgroundSize = size;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
schedule();
|
|
179
|
+
},
|
|
180
|
+
[minZoomScale, maxZoomScale, onZoomChange, schedule]
|
|
181
|
+
);
|
|
86
182
|
react.useEffect(() => {
|
|
87
|
-
if (isZoomed)
|
|
88
|
-
|
|
183
|
+
if (isZoomed) {
|
|
184
|
+
schedule();
|
|
185
|
+
} else if (mode === "inner" && imageRef.current) {
|
|
186
|
+
imageRef.current.style.transform = "";
|
|
187
|
+
txRef.current = 0;
|
|
188
|
+
tyRef.current = 0;
|
|
189
|
+
}
|
|
190
|
+
}, [isZoomed, schedule, mode]);
|
|
191
|
+
react.useEffect(() => {
|
|
192
|
+
if (disabled && isZoomedRef.current) {
|
|
193
|
+
isZoomedRef.current = false;
|
|
194
|
+
setIsZoomed(false);
|
|
195
|
+
onZoomEnd?.();
|
|
196
|
+
}
|
|
197
|
+
}, [disabled, onZoomEnd]);
|
|
89
198
|
react.useEffect(() => {
|
|
90
199
|
if (!bgImage) return;
|
|
91
200
|
const url = `url("${bgImage}")`;
|
|
@@ -98,7 +207,8 @@ function useImageMagnify(options = {}) {
|
|
|
98
207
|
const update = () => {
|
|
99
208
|
const rect = container.getBoundingClientRect();
|
|
100
209
|
if (!rect.width || !rect.height) return;
|
|
101
|
-
const
|
|
210
|
+
const s = scaleRef.current;
|
|
211
|
+
const size = `${rect.width * s}px ${rect.height * s}px`;
|
|
102
212
|
if (lensRef.current) lensRef.current.style.backgroundSize = size;
|
|
103
213
|
if (paneRef.current) paneRef.current.style.backgroundSize = size;
|
|
104
214
|
};
|
|
@@ -106,7 +216,7 @@ function useImageMagnify(options = {}) {
|
|
|
106
216
|
const ro = new ResizeObserver(update);
|
|
107
217
|
ro.observe(container);
|
|
108
218
|
return () => ro.disconnect();
|
|
109
|
-
}, [
|
|
219
|
+
}, [isZoomed, zoomScale]);
|
|
110
220
|
react.useEffect(() => {
|
|
111
221
|
if (!zoomPreload || !bgImage) return;
|
|
112
222
|
const img = new Image();
|
|
@@ -118,85 +228,155 @@ function useImageMagnify(options = {}) {
|
|
|
118
228
|
},
|
|
119
229
|
[]
|
|
120
230
|
);
|
|
121
|
-
|
|
231
|
+
react.useEffect(() => {
|
|
232
|
+
if (zoomType !== "wheel" || disabled) return;
|
|
122
233
|
const container = containerRef.current;
|
|
123
234
|
if (!container) return;
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
235
|
+
const onWheel = (e) => {
|
|
236
|
+
e.preventDefault();
|
|
237
|
+
updatePointer(e.clientX, e.clientY);
|
|
238
|
+
const factor = e.deltaY < 0 ? 1.1 : 1 / 1.1;
|
|
239
|
+
setScale(scaleRef.current * factor);
|
|
240
|
+
setZoomed(true);
|
|
241
|
+
};
|
|
242
|
+
container.addEventListener("wheel", onWheel, { passive: false });
|
|
243
|
+
return () => container.removeEventListener("wheel", onWheel);
|
|
244
|
+
}, [zoomType, disabled, setScale, setZoomed, updatePointer]);
|
|
245
|
+
const beginDrag = (e) => {
|
|
246
|
+
if (modeRef.current !== "inner" || dragModeRef.current !== "pan") return;
|
|
247
|
+
if (!isZoomedRef.current) return;
|
|
248
|
+
const el = e.currentTarget;
|
|
249
|
+
el.setPointerCapture?.(e.pointerId);
|
|
250
|
+
const rect = el.getBoundingClientRect();
|
|
251
|
+
const s = scaleRef.current;
|
|
252
|
+
dragStartRef.current = {
|
|
253
|
+
cursorX: e.clientX,
|
|
254
|
+
cursorY: e.clientY,
|
|
255
|
+
tx: clamp(txRef.current, rect.width * (1 - s), 0),
|
|
256
|
+
ty: clamp(tyRef.current, rect.height * (1 - s), 0)
|
|
129
257
|
};
|
|
130
258
|
};
|
|
131
259
|
const handlers = {
|
|
132
|
-
|
|
133
|
-
if (
|
|
260
|
+
onPointerEnter: (e) => {
|
|
261
|
+
if (disabled || e.pointerType === "touch") return;
|
|
134
262
|
updatePointer(e.clientX, e.clientY);
|
|
135
263
|
if (zoomType === "hover") setZoomed(true);
|
|
136
264
|
schedule();
|
|
137
265
|
},
|
|
138
|
-
|
|
139
|
-
if (
|
|
140
|
-
|
|
141
|
-
if (isZoomedRef.current) schedule();
|
|
142
|
-
},
|
|
143
|
-
onMouseLeave: () => {
|
|
144
|
-
if (isRecentTouch()) return;
|
|
266
|
+
onPointerLeave: (e) => {
|
|
267
|
+
if (disabled || e.pointerType === "touch") return;
|
|
268
|
+
if (dragStartRef.current) return;
|
|
145
269
|
if (zoomType === "hover") setZoomed(false);
|
|
270
|
+
else if (resetOnLeave) setZoomed(false);
|
|
146
271
|
},
|
|
147
|
-
|
|
148
|
-
if (
|
|
149
|
-
if (zoomType !== "click") return;
|
|
272
|
+
onPointerDown: (e) => {
|
|
273
|
+
if (disabled) return;
|
|
150
274
|
updatePointer(e.clientX, e.clientY);
|
|
151
|
-
|
|
275
|
+
const isTouch = e.pointerType === "touch";
|
|
276
|
+
if (isZoomedRef.current) {
|
|
277
|
+
beginDrag(e);
|
|
278
|
+
if (dragStartRef.current) return;
|
|
279
|
+
}
|
|
280
|
+
if (zoomType === "hold") {
|
|
281
|
+
setZoomed(true);
|
|
282
|
+
} else if (isTouch) {
|
|
283
|
+
setZoomed(!isZoomedRef.current);
|
|
284
|
+
} else if (zoomType === "click") {
|
|
285
|
+
setZoomed(!isZoomedRef.current);
|
|
286
|
+
} else if (zoomType === "wheel") {
|
|
287
|
+
setZoomed(!isZoomedRef.current);
|
|
288
|
+
}
|
|
152
289
|
schedule();
|
|
153
290
|
},
|
|
154
|
-
|
|
155
|
-
if (
|
|
156
|
-
if (
|
|
291
|
+
onPointerMove: (e) => {
|
|
292
|
+
if (disabled) return;
|
|
293
|
+
if (dragStartRef.current) {
|
|
294
|
+
const container = containerRef.current;
|
|
295
|
+
if (!container) return;
|
|
296
|
+
const rect = container.getBoundingClientRect();
|
|
297
|
+
const s = scaleRef.current;
|
|
298
|
+
const dx = e.clientX - dragStartRef.current.cursorX;
|
|
299
|
+
const dy = e.clientY - dragStartRef.current.cursorY;
|
|
300
|
+
txRef.current = clamp(
|
|
301
|
+
dragStartRef.current.tx + dx,
|
|
302
|
+
rect.width * (1 - s),
|
|
303
|
+
0
|
|
304
|
+
);
|
|
305
|
+
tyRef.current = clamp(
|
|
306
|
+
dragStartRef.current.ty + dy,
|
|
307
|
+
rect.height * (1 - s),
|
|
308
|
+
0
|
|
309
|
+
);
|
|
310
|
+
schedule();
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
157
313
|
updatePointer(e.clientX, e.clientY);
|
|
158
|
-
|
|
159
|
-
schedule();
|
|
314
|
+
if (isZoomedRef.current) schedule();
|
|
160
315
|
},
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
if (zoomType === "
|
|
167
|
-
else setZoomed(!isZoomedRef.current);
|
|
168
|
-
schedule();
|
|
316
|
+
onPointerUp: (e) => {
|
|
317
|
+
if (dragStartRef.current) {
|
|
318
|
+
e.currentTarget.releasePointerCapture?.(e.pointerId);
|
|
319
|
+
dragStartRef.current = null;
|
|
320
|
+
}
|
|
321
|
+
if (zoomType === "hold") setZoomed(false);
|
|
169
322
|
},
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
if (!t) return;
|
|
174
|
-
updatePointer(t.clientX, t.clientY);
|
|
175
|
-
schedule();
|
|
323
|
+
onPointerCancel: () => {
|
|
324
|
+
dragStartRef.current = null;
|
|
325
|
+
if (zoomType === "hold") setZoomed(false);
|
|
176
326
|
},
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
327
|
+
onDoubleClick: (e) => {
|
|
328
|
+
if (disabled || zoomType !== "double-click") return;
|
|
329
|
+
updatePointer(e.clientX, e.clientY);
|
|
330
|
+
setZoomed(!isZoomedRef.current);
|
|
331
|
+
schedule();
|
|
180
332
|
},
|
|
181
333
|
onKeyDown: (e) => {
|
|
334
|
+
if (disabled) return;
|
|
182
335
|
const container = containerRef.current;
|
|
183
336
|
if (!container) return;
|
|
184
337
|
const rect = container.getBoundingClientRect();
|
|
185
338
|
const step = 20;
|
|
186
|
-
|
|
339
|
+
if (!isZoomedRef.current && pointerRef.current.x === 0 && pointerRef.current.y === 0) {
|
|
340
|
+
pointerRef.current.x = rect.width / 2;
|
|
341
|
+
pointerRef.current.y = rect.height / 2;
|
|
342
|
+
}
|
|
187
343
|
let handled = true;
|
|
188
344
|
switch (e.key) {
|
|
189
345
|
case "ArrowLeft":
|
|
190
|
-
pointerRef.current.x = clamp(
|
|
346
|
+
pointerRef.current.x = clamp(
|
|
347
|
+
pointerRef.current.x - step,
|
|
348
|
+
0,
|
|
349
|
+
rect.width
|
|
350
|
+
);
|
|
191
351
|
break;
|
|
192
352
|
case "ArrowRight":
|
|
193
|
-
pointerRef.current.x = clamp(
|
|
353
|
+
pointerRef.current.x = clamp(
|
|
354
|
+
pointerRef.current.x + step,
|
|
355
|
+
0,
|
|
356
|
+
rect.width
|
|
357
|
+
);
|
|
194
358
|
break;
|
|
195
359
|
case "ArrowUp":
|
|
196
|
-
pointerRef.current.y = clamp(
|
|
360
|
+
pointerRef.current.y = clamp(
|
|
361
|
+
pointerRef.current.y - step,
|
|
362
|
+
0,
|
|
363
|
+
rect.height
|
|
364
|
+
);
|
|
197
365
|
break;
|
|
198
366
|
case "ArrowDown":
|
|
199
|
-
pointerRef.current.y = clamp(
|
|
367
|
+
pointerRef.current.y = clamp(
|
|
368
|
+
pointerRef.current.y + step,
|
|
369
|
+
0,
|
|
370
|
+
rect.height
|
|
371
|
+
);
|
|
372
|
+
break;
|
|
373
|
+
case "+":
|
|
374
|
+
case "=":
|
|
375
|
+
if (zoomType === "wheel") setScale(scaleRef.current * 1.2);
|
|
376
|
+
break;
|
|
377
|
+
case "-":
|
|
378
|
+
case "_":
|
|
379
|
+
if (zoomType === "wheel") setScale(scaleRef.current / 1.2);
|
|
200
380
|
break;
|
|
201
381
|
case "Enter":
|
|
202
382
|
case " ":
|
|
@@ -214,7 +394,7 @@ function useImageMagnify(options = {}) {
|
|
|
214
394
|
}
|
|
215
395
|
},
|
|
216
396
|
onFocus: () => {
|
|
217
|
-
if (
|
|
397
|
+
if (disabled) return;
|
|
218
398
|
if (zoomType === "hover") setZoomed(true);
|
|
219
399
|
},
|
|
220
400
|
onBlur: () => {
|
|
@@ -223,6 +403,8 @@ function useImageMagnify(options = {}) {
|
|
|
223
403
|
};
|
|
224
404
|
return {
|
|
225
405
|
isZoomed,
|
|
406
|
+
zoomScale: currentScale,
|
|
407
|
+
bgImage,
|
|
226
408
|
containerRef,
|
|
227
409
|
imageRef,
|
|
228
410
|
lensRef,
|
|
@@ -253,18 +435,29 @@ var ImageMagnify = react.forwardRef(
|
|
|
253
435
|
lensSize = 150,
|
|
254
436
|
lensShape = "circle",
|
|
255
437
|
zoomType = "hover",
|
|
438
|
+
disabled,
|
|
439
|
+
imageProps,
|
|
440
|
+
onLoad,
|
|
441
|
+
onError,
|
|
256
442
|
...hookOptions
|
|
257
443
|
} = props;
|
|
258
444
|
const {
|
|
259
445
|
isZoomed,
|
|
446
|
+
bgImage,
|
|
260
447
|
containerRef,
|
|
261
448
|
imageRef,
|
|
262
449
|
lensRef,
|
|
263
450
|
paneRef,
|
|
264
451
|
cursorRef,
|
|
265
452
|
handlers
|
|
266
|
-
} = useImageMagnify({
|
|
267
|
-
|
|
453
|
+
} = useImageMagnify({
|
|
454
|
+
src,
|
|
455
|
+
zoomType,
|
|
456
|
+
lensSize,
|
|
457
|
+
mode,
|
|
458
|
+
disabled,
|
|
459
|
+
...hookOptions
|
|
460
|
+
});
|
|
268
461
|
const paneOffset = {};
|
|
269
462
|
if (panePosition === "right") {
|
|
270
463
|
paneOffset.left = "calc(100% + 12px)";
|
|
@@ -279,6 +472,11 @@ var ImageMagnify = react.forwardRef(
|
|
|
279
472
|
paneOffset.left = 0;
|
|
280
473
|
paneOffset.top = "calc(100% + 12px)";
|
|
281
474
|
}
|
|
475
|
+
const isInner = mode === "inner";
|
|
476
|
+
const showLens = (mode === "lens" || mode === "follow") && isZoomed;
|
|
477
|
+
const showPane = mode === "side-by-side" && isZoomed;
|
|
478
|
+
const showCursor = mode === "side-by-side" && isZoomed;
|
|
479
|
+
const cursorStyle = disabled ? "default" : zoomType === "hover" || zoomType === "hold" || zoomType === "wheel" ? "crosshair" : isZoomed ? "zoom-out" : "zoom-in";
|
|
282
480
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
283
481
|
"div",
|
|
284
482
|
{
|
|
@@ -299,12 +497,14 @@ var ImageMagnify = react.forwardRef(
|
|
|
299
497
|
tabIndex: 0,
|
|
300
498
|
role: "img",
|
|
301
499
|
"aria-label": alt,
|
|
500
|
+
"aria-disabled": disabled || void 0,
|
|
302
501
|
style: {
|
|
303
502
|
position: "relative",
|
|
304
503
|
overflow: "hidden",
|
|
305
504
|
width: "100%",
|
|
306
|
-
cursor:
|
|
307
|
-
|
|
505
|
+
cursor: cursorStyle,
|
|
506
|
+
// Only block scrolling while zoomed so page scrolling still works.
|
|
507
|
+
touchAction: isZoomed ? "none" : "pan-y",
|
|
308
508
|
outline: "none",
|
|
309
509
|
lineHeight: 0
|
|
310
510
|
},
|
|
@@ -313,27 +513,34 @@ var ImageMagnify = react.forwardRef(
|
|
|
313
513
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
314
514
|
"img",
|
|
315
515
|
{
|
|
516
|
+
...imageProps,
|
|
316
517
|
ref: imageRef,
|
|
317
518
|
src,
|
|
318
|
-
alt,
|
|
519
|
+
alt: "",
|
|
520
|
+
"aria-hidden": "true",
|
|
319
521
|
loading: lazy ? "lazy" : void 0,
|
|
320
522
|
draggable: false,
|
|
321
523
|
className: imageClassName,
|
|
524
|
+
onLoad,
|
|
525
|
+
onError,
|
|
322
526
|
style: {
|
|
323
527
|
display: "block",
|
|
324
528
|
width: "100%",
|
|
325
529
|
height: "auto",
|
|
326
530
|
userSelect: "none",
|
|
327
531
|
pointerEvents: "none",
|
|
532
|
+
transformOrigin: "0 0",
|
|
533
|
+
willChange: isInner ? "transform" : void 0,
|
|
328
534
|
...imageStyle
|
|
329
535
|
}
|
|
330
536
|
}
|
|
331
537
|
),
|
|
332
|
-
|
|
538
|
+
showLens && /* @__PURE__ */ jsxRuntime.jsx(
|
|
333
539
|
"div",
|
|
334
540
|
{
|
|
335
541
|
ref: lensRef,
|
|
336
542
|
className: lensClassName,
|
|
543
|
+
"aria-hidden": "true",
|
|
337
544
|
style: {
|
|
338
545
|
position: "absolute",
|
|
339
546
|
top: 0,
|
|
@@ -351,10 +558,11 @@ var ImageMagnify = react.forwardRef(
|
|
|
351
558
|
}
|
|
352
559
|
}
|
|
353
560
|
),
|
|
354
|
-
|
|
561
|
+
showCursor && /* @__PURE__ */ jsxRuntime.jsx(
|
|
355
562
|
"div",
|
|
356
563
|
{
|
|
357
564
|
ref: cursorRef,
|
|
565
|
+
"aria-hidden": "true",
|
|
358
566
|
style: {
|
|
359
567
|
position: "absolute",
|
|
360
568
|
top: 0,
|
|
@@ -375,7 +583,7 @@ var ImageMagnify = react.forwardRef(
|
|
|
375
583
|
]
|
|
376
584
|
}
|
|
377
585
|
),
|
|
378
|
-
|
|
586
|
+
showPane && /* @__PURE__ */ jsxRuntime.jsx(
|
|
379
587
|
"div",
|
|
380
588
|
{
|
|
381
589
|
ref: paneRef,
|