@wavv/ui 2.4.7 → 2.4.8-alpha.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/build/components/ImageViewer.js +122 -77
- package/package.json +1 -1
|
@@ -1,110 +1,152 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { keyframes } from "@emotion/react";
|
|
2
3
|
import styled from "@emotion/styled";
|
|
3
|
-
import { useEffect, useState } from "react";
|
|
4
|
-
import {
|
|
4
|
+
import { useCallback, useEffect, useState } from "react";
|
|
5
|
+
import { Dialog, Modal, ModalOverlay } from "react-aria-components";
|
|
6
|
+
import useEventListener from "../hooks/useEventListener.js";
|
|
5
7
|
import Icon from "./Icon/index.js";
|
|
6
8
|
const ImageViewer = ({ visible, close, images, startIndex, alt, maxWidth, maxHeight, opacity, ...rest })=>{
|
|
7
9
|
const [currentIndex, setCurrentIndex] = useState(startIndex);
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
'#viewer-prev *',
|
|
12
|
-
'#viewer-next *'
|
|
13
|
-
];
|
|
14
|
-
const imageRef = useOnClickOutside(close, visible, exclusions);
|
|
10
|
+
const handleOpenChange = (open)=>{
|
|
11
|
+
if (!open) close();
|
|
12
|
+
};
|
|
15
13
|
useEffect(()=>{
|
|
16
|
-
setCurrentIndex(startIndex);
|
|
14
|
+
if (visible) setCurrentIndex(startIndex);
|
|
17
15
|
}, [
|
|
16
|
+
visible,
|
|
18
17
|
startIndex
|
|
19
18
|
]);
|
|
20
|
-
const handlePrev = ()=>
|
|
21
|
-
const handleNext = ()=>
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
const handlePrev = ()=>setCurrentIndex((prev)=>prev > 0 ? prev - 1 : images.length - 1);
|
|
20
|
+
const handleNext = ()=>setCurrentIndex((prev)=>prev < images.length - 1 ? prev + 1 : 0);
|
|
21
|
+
const handleKeyDown = useCallback((e)=>{
|
|
22
|
+
switch(e.key){
|
|
23
|
+
case 'Escape':
|
|
24
|
+
e.preventDefault();
|
|
25
|
+
close();
|
|
26
|
+
break;
|
|
25
27
|
case 'ArrowLeft':
|
|
26
28
|
case 'ArrowDown':
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
e.preventDefault();
|
|
30
|
+
setCurrentIndex((prev)=>prev > 0 ? prev - 1 : images.length - 1);
|
|
29
31
|
break;
|
|
30
32
|
case 'ArrowRight':
|
|
31
33
|
case 'ArrowUp':
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
break;
|
|
35
|
-
case 'Escape':
|
|
36
|
-
event.preventDefault();
|
|
37
|
-
close();
|
|
34
|
+
e.preventDefault();
|
|
35
|
+
setCurrentIndex((prev)=>prev < images.length - 1 ? prev + 1 : 0);
|
|
38
36
|
break;
|
|
39
37
|
default:
|
|
40
38
|
break;
|
|
41
39
|
}
|
|
42
|
-
};
|
|
43
|
-
useEffect(()=>{
|
|
44
|
-
const ssr = "u" < typeof window;
|
|
45
|
-
const cleanup = ssr ? ()=>null : ()=>window.removeEventListener('keydown', handleKeyPress);
|
|
46
|
-
if (visible && !ssr) window.addEventListener('keydown', handleKeyPress);
|
|
47
|
-
return cleanup;
|
|
48
40
|
}, [
|
|
49
|
-
|
|
50
|
-
|
|
41
|
+
close,
|
|
42
|
+
images.length
|
|
43
|
+
]);
|
|
44
|
+
useEventListener("u" > typeof window ? window : {
|
|
45
|
+
current: null
|
|
46
|
+
}, 'keydown', handleKeyDown, visible, [
|
|
47
|
+
handleKeyDown
|
|
51
48
|
]);
|
|
52
|
-
|
|
49
|
+
if (0 === images.length) return null;
|
|
50
|
+
return /*#__PURE__*/ jsx(Overlay, {
|
|
51
|
+
isOpen: visible,
|
|
52
|
+
onOpenChange: handleOpenChange,
|
|
53
|
+
isDismissable: true,
|
|
53
54
|
opacity: opacity,
|
|
54
55
|
prevNext: images.length > 1,
|
|
55
56
|
...rest,
|
|
56
|
-
children:
|
|
57
|
-
/*#__PURE__*/ jsx(
|
|
58
|
-
|
|
59
|
-
children: /*#__PURE__*/
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
57
|
+
children: /*#__PURE__*/ jsx(StyledModal, {
|
|
58
|
+
children: /*#__PURE__*/ jsx(StyledDialog, {
|
|
59
|
+
"aria-label": alt || 'Image viewer',
|
|
60
|
+
children: /*#__PURE__*/ jsxs(ViewerContent, {
|
|
61
|
+
children: [
|
|
62
|
+
/*#__PURE__*/ jsx(Close, {
|
|
63
|
+
onClick: close,
|
|
64
|
+
children: /*#__PURE__*/ jsx(Icon, {
|
|
65
|
+
name: "close",
|
|
66
|
+
color: "white"
|
|
67
|
+
})
|
|
68
|
+
}),
|
|
69
|
+
images.length > 1 && /*#__PURE__*/ jsx(PrevNext, {
|
|
70
|
+
id: "viewer-prev",
|
|
71
|
+
onClick: handlePrev,
|
|
72
|
+
children: /*#__PURE__*/ jsx(Icon, {
|
|
73
|
+
name: "chevron-left",
|
|
74
|
+
size: 35,
|
|
75
|
+
color: "white"
|
|
76
|
+
})
|
|
77
|
+
}),
|
|
78
|
+
/*#__PURE__*/ jsx(Media, {
|
|
79
|
+
src: images[currentIndex],
|
|
80
|
+
alt: alt,
|
|
81
|
+
maxWidth: maxWidth,
|
|
82
|
+
maxHeight: maxHeight
|
|
83
|
+
}),
|
|
84
|
+
images.length > 1 && /*#__PURE__*/ jsx(PrevNext, {
|
|
85
|
+
$next: true,
|
|
86
|
+
id: "viewer-next",
|
|
87
|
+
onClick: handleNext,
|
|
88
|
+
children: /*#__PURE__*/ jsx(Icon, {
|
|
89
|
+
name: "chevron-right",
|
|
90
|
+
size: 35,
|
|
91
|
+
color: "white"
|
|
92
|
+
})
|
|
93
|
+
})
|
|
94
|
+
]
|
|
88
95
|
})
|
|
89
96
|
})
|
|
90
|
-
|
|
91
|
-
})
|
|
97
|
+
})
|
|
98
|
+
});
|
|
92
99
|
};
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
100
|
+
const fadeIn = keyframes({
|
|
101
|
+
from: {
|
|
102
|
+
opacity: 0
|
|
103
|
+
},
|
|
104
|
+
to: {
|
|
105
|
+
opacity: 1
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
const fadeOut = keyframes({
|
|
109
|
+
from: {
|
|
110
|
+
opacity: 1
|
|
111
|
+
},
|
|
112
|
+
to: {
|
|
113
|
+
opacity: 0
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
const Overlay = styled(ModalOverlay)(({ prevNext, opacity })=>({
|
|
97
117
|
position: 'fixed',
|
|
98
118
|
top: 0,
|
|
99
119
|
left: 0,
|
|
120
|
+
width: '100%',
|
|
121
|
+
height: '100%',
|
|
122
|
+
backgroundColor: `rgba(0, 0, 0, ${opacity ?? 0.3})`,
|
|
100
123
|
display: 'grid',
|
|
101
124
|
gridTemplateColumns: prevNext ? 'auto 1fr auto' : '1fr',
|
|
102
125
|
justifyContent: 'space-between',
|
|
103
126
|
alignItems: 'center',
|
|
104
127
|
zIndex: 10000,
|
|
105
128
|
userSelect: 'none',
|
|
106
|
-
borderRadius: 5
|
|
129
|
+
borderRadius: 5,
|
|
130
|
+
'&[data-entering]': {
|
|
131
|
+
animation: `${fadeIn} 200ms ease-out`
|
|
132
|
+
},
|
|
133
|
+
'&[data-exiting]': {
|
|
134
|
+
animation: `${fadeOut} 200ms ease-in forwards`
|
|
135
|
+
}
|
|
107
136
|
}));
|
|
137
|
+
const StyledModal = styled(Modal)({
|
|
138
|
+
outline: 'none',
|
|
139
|
+
pointerEvents: 'none',
|
|
140
|
+
display: 'contents'
|
|
141
|
+
});
|
|
142
|
+
const StyledDialog = styled(Dialog)({
|
|
143
|
+
outline: 'none',
|
|
144
|
+
pointerEvents: 'none',
|
|
145
|
+
display: 'contents'
|
|
146
|
+
});
|
|
147
|
+
const ViewerContent = styled.div({
|
|
148
|
+
display: 'contents'
|
|
149
|
+
});
|
|
108
150
|
const Close = styled.div({
|
|
109
151
|
position: 'absolute',
|
|
110
152
|
top: 0,
|
|
@@ -115,9 +157,10 @@ const Close = styled.div({
|
|
|
115
157
|
cursor: 'pointer',
|
|
116
158
|
width: 50,
|
|
117
159
|
height: 50,
|
|
118
|
-
zIndex: 1
|
|
160
|
+
zIndex: 1,
|
|
161
|
+
pointerEvents: 'auto'
|
|
119
162
|
});
|
|
120
|
-
const PrevNext = styled.div(({ next })=>({
|
|
163
|
+
const PrevNext = styled.div(({ $next })=>({
|
|
121
164
|
display: 'flex',
|
|
122
165
|
justifyContent: 'center',
|
|
123
166
|
alignItems: 'center',
|
|
@@ -125,18 +168,20 @@ const PrevNext = styled.div(({ next })=>({
|
|
|
125
168
|
width: 50,
|
|
126
169
|
height: '100%',
|
|
127
170
|
backgroundColor: 'transparent',
|
|
128
|
-
left: next ? void 0 : 0,
|
|
129
|
-
right: next ? 0 : void 0,
|
|
171
|
+
left: $next ? void 0 : 0,
|
|
172
|
+
right: $next ? 0 : void 0,
|
|
130
173
|
zIndex: 0,
|
|
174
|
+
pointerEvents: 'auto',
|
|
131
175
|
'&:hover': {
|
|
132
|
-
background: `linear-gradient(90deg, rgba(0,0,0,${next ? 0 : 0.4}) 0%, rgba(0,0,0,${next ? 0.4 : 0}) 100%)`
|
|
176
|
+
background: `linear-gradient(90deg, rgba(0,0,0,${$next ? 0 : 0.4}) 0%, rgba(0,0,0,${$next ? 0.4 : 0}) 100%)`
|
|
133
177
|
}
|
|
134
178
|
}));
|
|
135
179
|
const Media = styled.img(({ maxWidth, maxHeight })=>({
|
|
136
180
|
display: 'block',
|
|
137
181
|
justifySelf: 'center',
|
|
138
182
|
maxWidth: maxWidth || '100%',
|
|
139
|
-
maxHeight: maxHeight || '100%'
|
|
183
|
+
maxHeight: maxHeight || '100%',
|
|
184
|
+
pointerEvents: 'auto'
|
|
140
185
|
}));
|
|
141
186
|
const components_ImageViewer = ImageViewer;
|
|
142
187
|
export { components_ImageViewer as default };
|