UNPKG

2.55 kBJavaScriptView Raw
1import React, { forwardRef, useImperativeHandle, useRef } from 'react';
2import { useDrag } from '@use-gesture/react';
3import { useSpring, animated } from '@react-spring/web';
4import { Slide } from './slide';
5import { convertPx } from '../../utils/convert-px';
6import { bound } from '../../utils/bound';
7const classPrefix = `adm-image-viewer`;
8export const Slides = forwardRef((props, ref) => {
9 const slideWidth = window.innerWidth + convertPx(16);
10 const [{
11 x
12 }, api] = useSpring(() => ({
13 x: props.defaultIndex * slideWidth,
14 config: {
15 tension: 250,
16 clamp: true
17 }
18 }));
19 const count = props.images.length;
20 function swipeTo(index, immediate = false) {
21 var _a;
22 const i = bound(index, 0, count - 1);
23 (_a = props.onIndexChange) === null || _a === void 0 ? void 0 : _a.call(props, i);
24 api.start({
25 x: i * slideWidth,
26 immediate
27 });
28 }
29 useImperativeHandle(ref, () => ({
30 swipeTo
31 }));
32 const dragLockRef = useRef(false);
33 const bind = useDrag(state => {
34 if (dragLockRef.current) return;
35 const [offsetX] = state.offset;
36 if (state.last) {
37 const minIndex = Math.floor(offsetX / slideWidth);
38 const maxIndex = minIndex + 1;
39 const velocityOffset = Math.min(state.velocity[0] * 2000, slideWidth) * state.direction[0];
40 swipeTo(bound(Math.round((offsetX + velocityOffset) / slideWidth), minIndex, maxIndex));
41 } else {
42 api.start({
43 x: offsetX,
44 immediate: true
45 });
46 }
47 }, {
48 transform: ([x, y]) => [-x, y],
49 from: () => [x.get(), 0],
50 bounds: () => ({
51 left: 0,
52 right: (count - 1) * slideWidth
53 }),
54 rubberband: true,
55 axis: 'x',
56 pointer: {
57 touch: true
58 }
59 });
60 return React.createElement("div", Object.assign({
61 className: `${classPrefix}-slides`
62 }, bind()), React.createElement(animated.div, {
63 className: `${classPrefix}-indicator`
64 }, x.to(v => {
65 const index = bound(Math.round(v / slideWidth), 0, count - 1);
66 return `${index + 1} / ${count}`;
67 })), React.createElement(animated.div, {
68 className: `${classPrefix}-slides-inner`,
69 style: {
70 x: x.to(x => -x)
71 }
72 }, props.images.map((image, index) => React.createElement(Slide, {
73 key: index,
74 image: image,
75 onTap: props.onTap,
76 maxZoom: props.maxZoom,
77 onZoomChange: zoom => {
78 if (zoom !== 1) {
79 const index = Math.round(x.get() / slideWidth);
80 api.start({
81 x: index * slideWidth
82 });
83 }
84 },
85 dragLockRef: dragLockRef
86 }))));
87});
\No newline at end of file