@sitebytom/use-zoom-pan 0.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.
package/dist/index.js ADDED
@@ -0,0 +1,648 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+
5
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
6
+
7
+ var React__default = /*#__PURE__*/_interopDefault(React);
8
+
9
+ // src/useZoomPan.ts
10
+ var DEFAULT_OPTIONS = {
11
+ minScale: 1,
12
+ maxScale: 6,
13
+ zoomSensitivity: 2e-3,
14
+ clickZoomScale: 2.5,
15
+ dragThresholdMouse: 5,
16
+ dragThresholdTouch: 10,
17
+ swipeThreshold: 50,
18
+ boundsBuffer: 80,
19
+ manageCursor: true,
20
+ enableSwipe: true,
21
+ initialScale: void 0,
22
+ initialPosition: void 0
23
+ };
24
+ var TRANSITION_DURATION = 400;
25
+ var TRANSITION_CURVE = "cubic-bezier(0.2, 0, 0, 1)";
26
+ var calculateBounds = (targetScale, container, element, boundsBuffer) => {
27
+ if (!container || !element) return { xLimit: 0, yLimit: 0 };
28
+ const containerWidth = container.clientWidth;
29
+ const containerHeight = container.clientHeight;
30
+ const elementWidth = element.offsetWidth || containerWidth;
31
+ const elementHeight = element.offsetHeight || containerHeight;
32
+ const scaledWidth = elementWidth * targetScale;
33
+ const scaledHeight = elementHeight * targetScale;
34
+ const xLimit = (scaledWidth <= containerWidth ? 0 : (scaledWidth - containerWidth) / 2) + boundsBuffer;
35
+ const yLimit = (scaledHeight <= containerHeight ? 0 : (scaledHeight - containerHeight) / 2) + boundsBuffer;
36
+ return { xLimit, yLimit };
37
+ };
38
+ var clampPosition = (pos, targetScale, container, element, boundsBuffer) => {
39
+ const { xLimit, yLimit } = calculateBounds(targetScale, container, element, boundsBuffer);
40
+ return {
41
+ x: Math.max(-xLimit, Math.min(xLimit, pos.x)),
42
+ y: Math.max(-yLimit, Math.min(yLimit, pos.y))
43
+ };
44
+ };
45
+ var normalizeWheelDelta = (e, sensitivity) => {
46
+ const factor = e.deltaMode === 1 ? 20 : 1;
47
+ return -e.deltaY * factor * sensitivity;
48
+ };
49
+ var useZoomPan = ({
50
+ containerRef,
51
+ enableZoom = true,
52
+ onNext,
53
+ onPrev,
54
+ options = {}
55
+ }) => {
56
+ const config = React__default.default.useMemo(() => ({
57
+ ...DEFAULT_OPTIONS,
58
+ ...options
59
+ }), [
60
+ options.minScale,
61
+ options.maxScale,
62
+ options.zoomSensitivity,
63
+ options.clickZoomScale,
64
+ options.dragThresholdMouse,
65
+ options.dragThresholdTouch,
66
+ options.swipeThreshold,
67
+ options.boundsBuffer,
68
+ options.manageCursor,
69
+ options.initialScale,
70
+ options.initialPosition
71
+ ]);
72
+ const contentRef = React__default.default.useRef(null);
73
+ const getContentElement = React.useCallback(() => {
74
+ return contentRef.current || containerRef.current?.firstElementChild;
75
+ }, [containerRef]);
76
+ const [scale, setScale] = React.useState(config.initialScale ?? config.minScale);
77
+ const [position, setPosition] = React.useState(config.initialPosition ?? { x: 0, y: 0 });
78
+ const [isDragging, setIsDragging] = React.useState(false);
79
+ const [isTransitioning, setIsTransitioning] = React.useState(false);
80
+ const dragStartRef = React.useRef({
81
+ x: 0,
82
+ y: 0,
83
+ hasDragged: false,
84
+ startX: 0,
85
+ startY: 0
86
+ });
87
+ const pinchRef = React.useRef({
88
+ startDist: 0,
89
+ initialScale: config.minScale,
90
+ startX: 0,
91
+ startY: 0,
92
+ startPos: { x: 0, y: 0 }
93
+ });
94
+ const touchStartXRef = React.useRef(0);
95
+ const swipeBlockedRef = React.useRef(false);
96
+ const stateRef = React.useRef({ scale, position, enableZoom, isDragging, config });
97
+ React.useEffect(() => {
98
+ stateRef.current = { scale, position, enableZoom, isDragging, config };
99
+ }, [scale, position, enableZoom, isDragging, config]);
100
+ React.useEffect(() => {
101
+ const handleGlobalUp = () => {
102
+ if (stateRef.current.isDragging) {
103
+ setIsDragging(false);
104
+ }
105
+ };
106
+ const handleBlur = () => {
107
+ setIsDragging(false);
108
+ };
109
+ window.addEventListener("mouseup", handleGlobalUp);
110
+ window.addEventListener("touchend", handleGlobalUp);
111
+ window.addEventListener("touchcancel", handleGlobalUp);
112
+ window.addEventListener("blur", handleBlur);
113
+ return () => {
114
+ window.removeEventListener("mouseup", handleGlobalUp);
115
+ window.removeEventListener("touchend", handleGlobalUp);
116
+ window.removeEventListener("touchcancel", handleGlobalUp);
117
+ window.removeEventListener("blur", handleBlur);
118
+ setIsDragging(false);
119
+ dragStartRef.current.hasDragged = false;
120
+ setIsTransitioning(false);
121
+ };
122
+ }, []);
123
+ const updateBoundsAndClamp = React.useCallback(() => {
124
+ const container = containerRef.current;
125
+ const content = getContentElement();
126
+ if (!container || !content) return;
127
+ const currentPos = { x: stateRef.current.position.x, y: stateRef.current.position.y };
128
+ const clamped = clampPosition(currentPos, stateRef.current.scale, container, content, config.boundsBuffer);
129
+ if (clamped.x !== currentPos.x || clamped.y !== currentPos.y) {
130
+ setPosition(clamped);
131
+ }
132
+ }, [containerRef, config.boundsBuffer, getContentElement]);
133
+ React__default.default.useLayoutEffect(() => {
134
+ const container = containerRef.current;
135
+ if (!container) return;
136
+ const observer = new ResizeObserver(() => {
137
+ updateBoundsAndClamp();
138
+ });
139
+ observer.observe(container);
140
+ const content = getContentElement();
141
+ if (content instanceof HTMLImageElement && !content.complete) {
142
+ content.addEventListener("load", updateBoundsAndClamp);
143
+ }
144
+ return () => {
145
+ observer.disconnect();
146
+ if (content instanceof HTMLImageElement) {
147
+ content.removeEventListener("load", updateBoundsAndClamp);
148
+ }
149
+ };
150
+ }, [containerRef, updateBoundsAndClamp, getContentElement]);
151
+ const getClampedPosition = React.useCallback(
152
+ (pos, targetScale, element) => {
153
+ return clampPosition(
154
+ pos,
155
+ targetScale,
156
+ containerRef.current,
157
+ element,
158
+ config.boundsBuffer
159
+ );
160
+ },
161
+ [containerRef, config.boundsBuffer]
162
+ );
163
+ const handleWheelManual = React.useCallback(
164
+ (e) => {
165
+ if (!stateRef.current.enableZoom) return;
166
+ setIsTransitioning(false);
167
+ e.preventDefault();
168
+ const { scale: currentScale, position: currentPosition, config: config2 } = stateRef.current;
169
+ const delta = normalizeWheelDelta(e, config2.zoomSensitivity);
170
+ const newScale = Math.min(Math.max(config2.minScale, currentScale + delta), config2.maxScale);
171
+ if (newScale === config2.minScale) {
172
+ setScale(config2.minScale);
173
+ setPosition({ x: 0, y: 0 });
174
+ } else {
175
+ const container = containerRef.current;
176
+ const content = getContentElement();
177
+ if (container && content) {
178
+ const rect = container.getBoundingClientRect();
179
+ const containerWidth = rect.width;
180
+ const containerHeight = rect.height;
181
+ const centerX = containerWidth / 2;
182
+ const centerY = containerHeight / 2;
183
+ const mouseX = e.clientX - (rect.left + centerX);
184
+ const mouseY = e.clientY - (rect.top + centerY);
185
+ const contentX = (mouseX - currentPosition.x) / currentScale;
186
+ const contentY = (mouseY - currentPosition.y) / currentScale;
187
+ const newPosition = {
188
+ x: mouseX - contentX * newScale,
189
+ y: mouseY - contentY * newScale
190
+ };
191
+ const clampedPosition = getClampedPosition(newPosition, newScale, content);
192
+ setPosition(clampedPosition);
193
+ setScale(newScale);
194
+ }
195
+ }
196
+ },
197
+ [getClampedPosition, containerRef, getContentElement, config.zoomSensitivity, config.minScale, config.maxScale]
198
+ );
199
+ React.useEffect(() => {
200
+ const container = containerRef.current;
201
+ if (!container) return;
202
+ container.addEventListener("wheel", handleWheelManual, { passive: false });
203
+ return () => container.removeEventListener("wheel", handleWheelManual);
204
+ }, [containerRef, handleWheelManual]);
205
+ const reset = React.useCallback(() => {
206
+ setIsTransitioning(true);
207
+ setScale(config.minScale);
208
+ setPosition({ x: 0, y: 0 });
209
+ setIsDragging(false);
210
+ dragStartRef.current.hasDragged = false;
211
+ pinchRef.current = {
212
+ startDist: 0,
213
+ initialScale: config.minScale,
214
+ startX: 0,
215
+ startY: 0,
216
+ startPos: { x: 0, y: 0 }
217
+ };
218
+ }, [config.minScale]);
219
+ const handleFocalZoom = React.useCallback(
220
+ (e) => {
221
+ setIsTransitioning(true);
222
+ const container = containerRef.current;
223
+ const target = e.currentTarget;
224
+ if (!container || !target) return;
225
+ const rect = container.getBoundingClientRect();
226
+ const containerWidth = container.clientWidth;
227
+ const containerHeight = container.clientHeight;
228
+ const centerX = containerWidth / 2;
229
+ const centerY = containerHeight / 2;
230
+ const mouseX = e.clientX - (rect.left + centerX);
231
+ const mouseY = e.clientY - (rect.top + centerY);
232
+ const newPosition = {
233
+ x: mouseX * (1 - config.clickZoomScale),
234
+ y: mouseY * (1 - config.clickZoomScale)
235
+ };
236
+ const clampedPosition = getClampedPosition(newPosition, config.clickZoomScale, target);
237
+ setScale(config.clickZoomScale);
238
+ setPosition(clampedPosition);
239
+ },
240
+ [getClampedPosition, config.clickZoomScale, containerRef]
241
+ );
242
+ const onImageClick = React.useCallback(
243
+ (e) => {
244
+ if (dragStartRef.current.hasDragged) {
245
+ dragStartRef.current.hasDragged = false;
246
+ return;
247
+ }
248
+ if (scale > config.minScale) {
249
+ reset();
250
+ } else {
251
+ handleFocalZoom(e);
252
+ }
253
+ },
254
+ [scale, reset, handleFocalZoom, config.minScale]
255
+ );
256
+ const onImageDoubleClick = React.useCallback(
257
+ (e) => {
258
+ if (scale > config.minScale) {
259
+ reset();
260
+ } else {
261
+ handleFocalZoom(e);
262
+ }
263
+ },
264
+ [scale, reset, handleFocalZoom, config.minScale]
265
+ );
266
+ const getPinchPosition = React.useCallback((centerX, centerY, newScale) => {
267
+ const { containerRect, startX, startY, initialScale, startPos } = pinchRef.current;
268
+ if (!containerRect) return { x: 0, y: 0 };
269
+ const containerCenterX = containerRect.width / 2;
270
+ const containerCenterY = containerRect.height / 2;
271
+ const currentPinchX = centerX - (containerRect.left + containerCenterX);
272
+ const currentPinchY = centerY - (containerRect.top + containerCenterY);
273
+ const startPinchX = startX - (containerRect.left + containerCenterX);
274
+ const startPinchY = startY - (containerRect.top + containerCenterY);
275
+ const scaleRatio = newScale / initialScale;
276
+ const pinchImageX = startPinchX - startPos.x;
277
+ const pinchImageY = startPinchY - startPos.y;
278
+ return {
279
+ x: currentPinchX - pinchImageX * scaleRatio,
280
+ y: currentPinchY - pinchImageY * scaleRatio
281
+ };
282
+ }, []);
283
+ const onImageTouchStart = React.useCallback(
284
+ (e) => {
285
+ setIsTransitioning(false);
286
+ swipeBlockedRef.current = e.touches.length === 2;
287
+ if (e.touches.length === 2) {
288
+ const container = containerRef.current;
289
+ const dist = Math.hypot(
290
+ e.touches[0].clientX - e.touches[1].clientX,
291
+ e.touches[0].clientY - e.touches[1].clientY
292
+ );
293
+ const centerX = (e.touches[0].clientX + e.touches[1].clientX) / 2;
294
+ const centerY = (e.touches[0].clientY + e.touches[1].clientY) / 2;
295
+ pinchRef.current = {
296
+ startDist: dist,
297
+ initialScale: scale,
298
+ startX: centerX,
299
+ startY: centerY,
300
+ startPos: { x: position.x, y: position.y },
301
+ containerRect: container?.getBoundingClientRect()
302
+ };
303
+ } else if (e.touches.length === 1 && scale > config.minScale) {
304
+ setIsDragging(true);
305
+ dragStartRef.current = {
306
+ x: e.touches[0].clientX - position.x,
307
+ y: e.touches[0].clientY - position.y,
308
+ hasDragged: false,
309
+ startX: e.touches[0].clientX,
310
+ startY: e.touches[0].clientY
311
+ };
312
+ }
313
+ },
314
+ [scale, position, config.minScale, containerRef]
315
+ );
316
+ const onImageTouchMove = React.useCallback(
317
+ (e) => {
318
+ if (e.touches.length === 2) {
319
+ e.preventDefault();
320
+ const dist = Math.hypot(
321
+ e.touches[0].clientX - e.touches[1].clientX,
322
+ e.touches[0].clientY - e.touches[1].clientY
323
+ );
324
+ const centerX = (e.touches[0].clientX + e.touches[1].clientX) / 2;
325
+ const centerY = (e.touches[0].clientY + e.touches[1].clientY) / 2;
326
+ const ratio = dist / pinchRef.current.startDist;
327
+ const newScale = Math.min(Math.max(config.minScale, pinchRef.current.initialScale * ratio), config.maxScale);
328
+ if (pinchRef.current.containerRect && newScale > config.minScale) {
329
+ const newPosition = getPinchPosition(
330
+ centerX,
331
+ centerY,
332
+ newScale
333
+ );
334
+ const clampedPosition = getClampedPosition(
335
+ newPosition,
336
+ newScale,
337
+ getContentElement()
338
+ );
339
+ setPosition(clampedPosition);
340
+ } else {
341
+ setPosition({ x: 0, y: 0 });
342
+ }
343
+ setScale(newScale);
344
+ } else if (e.touches.length === 1 && isDragging && scale > config.minScale) {
345
+ e.preventDefault();
346
+ const touchX = e.touches[0].clientX;
347
+ const touchY = e.touches[0].clientY;
348
+ if (!dragStartRef.current.hasDragged) {
349
+ const moveDist = Math.hypot(
350
+ touchX - dragStartRef.current.startX,
351
+ touchY - dragStartRef.current.startY
352
+ );
353
+ if (moveDist > config.dragThresholdTouch) {
354
+ dragStartRef.current.hasDragged = true;
355
+ }
356
+ }
357
+ if (dragStartRef.current.hasDragged) {
358
+ const newPosition = {
359
+ x: touchX - dragStartRef.current.x,
360
+ y: touchY - dragStartRef.current.y
361
+ };
362
+ const clampedPosition = getClampedPosition(newPosition, scale, e.currentTarget);
363
+ setPosition(clampedPosition);
364
+ }
365
+ }
366
+ },
367
+ [isDragging, scale, getClampedPosition, getContentElement, getPinchPosition, config.minScale, config.maxScale, config.dragThresholdTouch]
368
+ );
369
+ const onImageTouchEnd = React.useCallback(() => {
370
+ setIsDragging(false);
371
+ pinchRef.current = {
372
+ startDist: 0,
373
+ initialScale: scale,
374
+ startX: 0,
375
+ startY: 0,
376
+ startPos: { x: position.x, y: position.y }
377
+ };
378
+ }, [scale, position]);
379
+ const onImageMouseDown = React.useCallback(
380
+ (e) => {
381
+ setIsTransitioning(false);
382
+ if (scale > config.minScale) {
383
+ e.preventDefault();
384
+ setIsDragging(true);
385
+ dragStartRef.current = {
386
+ x: e.clientX - position.x,
387
+ y: e.clientY - position.y,
388
+ hasDragged: false,
389
+ startX: e.clientX,
390
+ startY: e.clientY
391
+ };
392
+ }
393
+ },
394
+ [scale, position, config.minScale]
395
+ );
396
+ React.useCallback(
397
+ (targetX, targetY) => {
398
+ if (!config.enableSwipe) return;
399
+ const distanceX = Math.abs(targetX - dragStartRef.current.startX);
400
+ const distanceY = Math.abs(targetY - dragStartRef.current.startY);
401
+ if (distanceX > config.swipeThreshold && distanceX > distanceY) {
402
+ if (targetX < dragStartRef.current.startX) {
403
+ onNext?.();
404
+ } else {
405
+ onPrev?.();
406
+ }
407
+ }
408
+ },
409
+ [config.enableSwipe, config.swipeThreshold, onNext, onPrev]
410
+ );
411
+ const onImageMouseMove = React.useCallback(
412
+ (e) => {
413
+ if (isDragging && scale > config.minScale) {
414
+ e.preventDefault();
415
+ if (!dragStartRef.current.hasDragged) {
416
+ const moveDist = Math.hypot(
417
+ e.clientX - dragStartRef.current.startX,
418
+ e.clientY - dragStartRef.current.startY
419
+ );
420
+ if (moveDist > config.dragThresholdMouse) {
421
+ dragStartRef.current.hasDragged = true;
422
+ }
423
+ }
424
+ if (dragStartRef.current.hasDragged) {
425
+ const newPosition = {
426
+ x: e.clientX - dragStartRef.current.x,
427
+ y: e.clientY - dragStartRef.current.y
428
+ };
429
+ const clampedPosition = getClampedPosition(newPosition, scale, e.currentTarget);
430
+ setPosition(clampedPosition);
431
+ }
432
+ }
433
+ },
434
+ [isDragging, scale, getClampedPosition, config.minScale, config.dragThresholdMouse]
435
+ );
436
+ const onImageMouseUp = React.useCallback(() => {
437
+ setIsDragging(false);
438
+ }, []);
439
+ const onImageMouseLeave = React.useCallback(() => {
440
+ setIsDragging(false);
441
+ }, []);
442
+ const onContainerTouchStart = React.useCallback(
443
+ (e) => {
444
+ if (scale > config.minScale) return;
445
+ const touch = e.changedTouches[0];
446
+ touchStartXRef.current = touch.clientX;
447
+ },
448
+ [scale, config.minScale]
449
+ );
450
+ const onContainerTouchEnd = React.useCallback(
451
+ (e) => {
452
+ if (swipeBlockedRef.current) {
453
+ swipeBlockedRef.current = false;
454
+ return;
455
+ }
456
+ if (scale > config.minScale) return;
457
+ const touch = e.changedTouches[0];
458
+ const startX = touchStartXRef.current;
459
+ const endX = touch.clientX;
460
+ const diff = startX - endX;
461
+ if (Math.abs(diff) > config.swipeThreshold) {
462
+ if (diff > 0) {
463
+ onNext?.();
464
+ } else {
465
+ onPrev?.();
466
+ }
467
+ }
468
+ },
469
+ [scale, onNext, onPrev, config.minScale, config.swipeThreshold]
470
+ );
471
+ const onContainerMouseDown = React.useCallback(
472
+ (e) => {
473
+ if (scale > config.minScale) return;
474
+ touchStartXRef.current = e.clientX;
475
+ },
476
+ [scale, config.minScale]
477
+ );
478
+ const onContainerMouseUp = React.useCallback(
479
+ (e) => {
480
+ if (scale > config.minScale) return;
481
+ const startX = touchStartXRef.current;
482
+ const endX = e.clientX;
483
+ const diff = startX - endX;
484
+ if (Math.abs(diff) > config.swipeThreshold) {
485
+ if (diff > 0) {
486
+ onNext?.();
487
+ } else {
488
+ onPrev?.();
489
+ }
490
+ }
491
+ },
492
+ [scale, onNext, onPrev, config.minScale, config.swipeThreshold]
493
+ );
494
+ const zoomTo = React.useCallback(
495
+ (x, y, targetScale) => {
496
+ setIsTransitioning(true);
497
+ const container = containerRef.current;
498
+ const content = contentRef.current || container?.firstElementChild;
499
+ if (!container || !content) return;
500
+ const scaleToUse = targetScale ?? config.clickZoomScale;
501
+ const contentWidth = content.offsetWidth;
502
+ const contentHeight = content.offsetHeight;
503
+ const newPosition = {
504
+ x: (contentWidth / 2 - x) * scaleToUse,
505
+ y: (contentHeight / 2 - y) * scaleToUse
506
+ };
507
+ const clampedPosition = getClampedPosition(newPosition, scaleToUse, content);
508
+ setScale(scaleToUse);
509
+ setPosition(clampedPosition);
510
+ },
511
+ [getClampedPosition, config.clickZoomScale, containerRef]
512
+ );
513
+ React.useEffect(() => {
514
+ if (!isTransitioning) return;
515
+ const timer = setTimeout(() => setIsTransitioning(false), TRANSITION_DURATION);
516
+ return () => clearTimeout(timer);
517
+ }, [isTransitioning]);
518
+ const contentStyle = React__default.default.useMemo(() => {
519
+ const style = {
520
+ transformOrigin: "center",
521
+ transition: isTransitioning ? `transform ${TRANSITION_DURATION}ms ${TRANSITION_CURVE}` : "none"
522
+ };
523
+ if (config.manageCursor) {
524
+ if (isDragging) {
525
+ style.cursor = "grabbing";
526
+ } else if (scale > config.minScale) {
527
+ style.cursor = "grab";
528
+ } else if (enableZoom) {
529
+ style.cursor = "zoom-in";
530
+ } else {
531
+ style.cursor = "default";
532
+ }
533
+ }
534
+ return style;
535
+ }, [isTransitioning, config.manageCursor, isDragging, scale, config.minScale, enableZoom]);
536
+ const contentProps = React__default.default.useMemo(() => ({
537
+ ref: contentRef,
538
+ // Cast to compatible ref type
539
+ style: contentStyle,
540
+ onClick: onImageClick,
541
+ onDoubleClick: onImageDoubleClick,
542
+ onTouchStart: onImageTouchStart,
543
+ onTouchMove: onImageTouchMove,
544
+ onTouchEnd: onImageTouchEnd,
545
+ onMouseDown: onImageMouseDown,
546
+ onMouseMove: onImageMouseMove,
547
+ onMouseUp: onImageMouseUp,
548
+ onMouseLeave: onImageMouseLeave
549
+ }), [
550
+ contentStyle,
551
+ onImageClick,
552
+ onImageDoubleClick,
553
+ onImageTouchStart,
554
+ onImageTouchMove,
555
+ onImageTouchEnd,
556
+ onImageMouseDown,
557
+ onImageMouseMove,
558
+ onImageMouseUp,
559
+ onImageMouseLeave
560
+ ]);
561
+ const containerProps = React__default.default.useMemo(() => ({
562
+ onTouchStart: onContainerTouchStart,
563
+ onTouchEnd: onContainerTouchEnd,
564
+ onMouseDown: onContainerMouseDown,
565
+ onMouseUp: onContainerMouseUp
566
+ }), [
567
+ onContainerTouchStart,
568
+ onContainerTouchEnd,
569
+ onContainerMouseDown,
570
+ onContainerMouseUp
571
+ ]);
572
+ return {
573
+ scale,
574
+ position,
575
+ isDragging,
576
+ reset,
577
+ zoomTo,
578
+ contentProps,
579
+ containerProps
580
+ };
581
+ };
582
+ var ZoomPan = ({
583
+ children,
584
+ className = "",
585
+ style = {},
586
+ contentClassName = "",
587
+ contentStyle = {},
588
+ enableZoom = true,
589
+ onNext,
590
+ onPrev,
591
+ options
592
+ }) => {
593
+ const containerRef = React.useRef(null);
594
+ const { scale, position, contentProps, containerProps } = useZoomPan({
595
+ containerRef,
596
+ enableZoom,
597
+ onNext,
598
+ onPrev,
599
+ options
600
+ });
601
+ const defaultContainerStyle = {
602
+ width: "100%",
603
+ height: "100%",
604
+ overflow: "hidden",
605
+ display: "flex",
606
+ alignItems: "center",
607
+ justifyContent: "center",
608
+ cursor: scale > 1 ? "grab" : enableZoom ? "zoom-in" : "default",
609
+ position: "relative",
610
+ ...style
611
+ };
612
+ const defaultContentStyle = {
613
+ transform: `translate(${position.x}px, ${position.y}px) scale(${scale})`,
614
+ ...contentProps.style,
615
+ userSelect: "none",
616
+ WebkitUserSelect: "none",
617
+ touchAction: "none",
618
+ maxWidth: "100%",
619
+ maxHeight: "100%",
620
+ ...contentStyle
621
+ };
622
+ return /* @__PURE__ */ React__default.default.createElement(
623
+ "div",
624
+ {
625
+ ref: containerRef,
626
+ className,
627
+ style: defaultContainerStyle,
628
+ ...containerProps
629
+ },
630
+ /* @__PURE__ */ React__default.default.createElement(
631
+ "div",
632
+ {
633
+ className: contentClassName,
634
+ ...contentProps,
635
+ style: {
636
+ ...defaultContentStyle,
637
+ ...contentProps.style
638
+ }
639
+ },
640
+ children
641
+ )
642
+ );
643
+ };
644
+
645
+ exports.ZoomPan = ZoomPan;
646
+ exports.useZoomPan = useZoomPan;
647
+ //# sourceMappingURL=index.js.map
648
+ //# sourceMappingURL=index.js.map