1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 | import React, { useEffect, useLayoutEffect, useContext, createContext, forwardRef, useState, useRef } from 'react';
|
14 | import { S as Swiper$1 } from './shared/swiper-core.mjs';
|
15 | import { g as getParams, m as mountSwiper, a as getChangedParams, u as updateOnVirtualData } from './shared/update-on-virtual-data.mjs';
|
16 | import { d as uniqueClasses, w as wrapperClass, n as needsNavigation, b as needsScrollbar, a as needsPagination, e as extend, u as updateSwiper } from './shared/update-swiper.mjs';
|
17 |
|
18 | function _extends() {
|
19 | _extends = Object.assign ? Object.assign.bind() : function (target) {
|
20 | for (var i = 1; i < arguments.length; i++) {
|
21 | var source = arguments[i];
|
22 | for (var key in source) {
|
23 | if (Object.prototype.hasOwnProperty.call(source, key)) {
|
24 | target[key] = source[key];
|
25 | }
|
26 | }
|
27 | }
|
28 | return target;
|
29 | };
|
30 | return _extends.apply(this, arguments);
|
31 | }
|
32 |
|
33 | function isChildSwiperSlide(child) {
|
34 | return child.type && child.type.displayName && child.type.displayName.includes('SwiperSlide');
|
35 | }
|
36 | function processChildren(c) {
|
37 | const slides = [];
|
38 | React.Children.toArray(c).forEach(child => {
|
39 | if (isChildSwiperSlide(child)) {
|
40 | slides.push(child);
|
41 | } else if (child.props && child.props.children) {
|
42 | processChildren(child.props.children).forEach(slide => slides.push(slide));
|
43 | }
|
44 | });
|
45 | return slides;
|
46 | }
|
47 | function getChildren(c) {
|
48 | const slides = [];
|
49 | const slots = {
|
50 | 'container-start': [],
|
51 | 'container-end': [],
|
52 | 'wrapper-start': [],
|
53 | 'wrapper-end': []
|
54 | };
|
55 | React.Children.toArray(c).forEach(child => {
|
56 | if (isChildSwiperSlide(child)) {
|
57 | slides.push(child);
|
58 | } else if (child.props && child.props.slot && slots[child.props.slot]) {
|
59 | slots[child.props.slot].push(child);
|
60 | } else if (child.props && child.props.children) {
|
61 | const foundSlides = processChildren(child.props.children);
|
62 | if (foundSlides.length > 0) {
|
63 | foundSlides.forEach(slide => slides.push(slide));
|
64 | } else {
|
65 | slots['container-end'].push(child);
|
66 | }
|
67 | } else {
|
68 | slots['container-end'].push(child);
|
69 | }
|
70 | });
|
71 | return {
|
72 | slides,
|
73 | slots
|
74 | };
|
75 | }
|
76 |
|
77 | function renderVirtual(swiper, slides, virtualData) {
|
78 | if (!virtualData) return null;
|
79 | const getSlideIndex = index => {
|
80 | let slideIndex = index;
|
81 | if (index < 0) {
|
82 | slideIndex = slides.length + index;
|
83 | } else if (slideIndex >= slides.length) {
|
84 |
|
85 | slideIndex = slideIndex - slides.length;
|
86 | }
|
87 | return slideIndex;
|
88 | };
|
89 | const style = swiper.isHorizontal() ? {
|
90 | [swiper.rtlTranslate ? 'right' : 'left']: `${virtualData.offset}px`
|
91 | } : {
|
92 | top: `${virtualData.offset}px`
|
93 | };
|
94 | const {
|
95 | from,
|
96 | to
|
97 | } = virtualData;
|
98 | const loopFrom = swiper.params.loop ? -slides.length : 0;
|
99 | const loopTo = swiper.params.loop ? slides.length * 2 : slides.length;
|
100 | const slidesToRender = [];
|
101 | for (let i = loopFrom; i < loopTo; i += 1) {
|
102 | if (i >= from && i <= to) {
|
103 | slidesToRender.push(slides[getSlideIndex(i)]);
|
104 | }
|
105 | }
|
106 | return slidesToRender.map((child, index) => {
|
107 | return React.cloneElement(child, {
|
108 | swiper,
|
109 | style,
|
110 | key: child.props.virtualIndex || child.key || `slide-${index}`
|
111 | });
|
112 | });
|
113 | }
|
114 |
|
115 | function useIsomorphicLayoutEffect(callback, deps) {
|
116 |
|
117 | if (typeof window === 'undefined') return useEffect(callback, deps);
|
118 | return useLayoutEffect(callback, deps);
|
119 | }
|
120 |
|
121 | const SwiperSlideContext = createContext(null);
|
122 | const useSwiperSlide = () => {
|
123 | return useContext(SwiperSlideContext);
|
124 | };
|
125 | const SwiperContext = createContext(null);
|
126 | const useSwiper = () => {
|
127 | return useContext(SwiperContext);
|
128 | };
|
129 |
|
130 | const Swiper = forwardRef(function (_temp, externalElRef) {
|
131 | let {
|
132 | className,
|
133 | tag: Tag = 'div',
|
134 | wrapperTag: WrapperTag = 'div',
|
135 | children,
|
136 | onSwiper,
|
137 | ...rest
|
138 | } = _temp === void 0 ? {} : _temp;
|
139 | let eventsAssigned = false;
|
140 | const [containerClasses, setContainerClasses] = useState('swiper');
|
141 | const [virtualData, setVirtualData] = useState(null);
|
142 | const [breakpointChanged, setBreakpointChanged] = useState(false);
|
143 | const initializedRef = useRef(false);
|
144 | const swiperElRef = useRef(null);
|
145 | const swiperRef = useRef(null);
|
146 | const oldPassedParamsRef = useRef(null);
|
147 | const oldSlides = useRef(null);
|
148 | const nextElRef = useRef(null);
|
149 | const prevElRef = useRef(null);
|
150 | const paginationElRef = useRef(null);
|
151 | const scrollbarElRef = useRef(null);
|
152 | const {
|
153 | params: swiperParams,
|
154 | passedParams,
|
155 | rest: restProps,
|
156 | events
|
157 | } = getParams(rest);
|
158 | const {
|
159 | slides,
|
160 | slots
|
161 | } = getChildren(children);
|
162 | const onBeforeBreakpoint = () => {
|
163 | setBreakpointChanged(!breakpointChanged);
|
164 | };
|
165 | Object.assign(swiperParams.on, {
|
166 | _containerClasses(swiper, classes) {
|
167 | setContainerClasses(classes);
|
168 | }
|
169 | });
|
170 | const initSwiper = () => {
|
171 |
|
172 | Object.assign(swiperParams.on, events);
|
173 | eventsAssigned = true;
|
174 | const passParams = {
|
175 | ...swiperParams
|
176 | };
|
177 | delete passParams.wrapperClass;
|
178 | swiperRef.current = new Swiper$1(passParams);
|
179 | if (swiperRef.current.virtual && swiperRef.current.params.virtual.enabled) {
|
180 | swiperRef.current.virtual.slides = slides;
|
181 | const extendWith = {
|
182 | cache: false,
|
183 | slides,
|
184 | renderExternal: setVirtualData,
|
185 | renderExternalUpdate: false
|
186 | };
|
187 | extend(swiperRef.current.params.virtual, extendWith);
|
188 | extend(swiperRef.current.originalParams.virtual, extendWith);
|
189 | }
|
190 | };
|
191 | if (!swiperElRef.current) {
|
192 | initSwiper();
|
193 | }
|
194 |
|
195 |
|
196 | if (swiperRef.current) {
|
197 | swiperRef.current.on('_beforeBreakpoint', onBeforeBreakpoint);
|
198 | }
|
199 | const attachEvents = () => {
|
200 | if (eventsAssigned || !events || !swiperRef.current) return;
|
201 | Object.keys(events).forEach(eventName => {
|
202 | swiperRef.current.on(eventName, events[eventName]);
|
203 | });
|
204 | };
|
205 | const detachEvents = () => {
|
206 | if (!events || !swiperRef.current) return;
|
207 | Object.keys(events).forEach(eventName => {
|
208 | swiperRef.current.off(eventName, events[eventName]);
|
209 | });
|
210 | };
|
211 | useEffect(() => {
|
212 | return () => {
|
213 | if (swiperRef.current) swiperRef.current.off('_beforeBreakpoint', onBeforeBreakpoint);
|
214 | };
|
215 | });
|
216 |
|
217 |
|
218 | useEffect(() => {
|
219 | if (!initializedRef.current && swiperRef.current) {
|
220 | swiperRef.current.emitSlidesClasses();
|
221 | initializedRef.current = true;
|
222 | }
|
223 | });
|
224 |
|
225 |
|
226 | useIsomorphicLayoutEffect(() => {
|
227 | if (externalElRef) {
|
228 | externalElRef.current = swiperElRef.current;
|
229 | }
|
230 | if (!swiperElRef.current) return;
|
231 | if (swiperRef.current.destroyed) {
|
232 | initSwiper();
|
233 | }
|
234 | mountSwiper({
|
235 | el: swiperElRef.current,
|
236 | nextEl: nextElRef.current,
|
237 | prevEl: prevElRef.current,
|
238 | paginationEl: paginationElRef.current,
|
239 | scrollbarEl: scrollbarElRef.current,
|
240 | swiper: swiperRef.current
|
241 | }, swiperParams);
|
242 | if (onSwiper && !swiperRef.current.destroyed) onSwiper(swiperRef.current);
|
243 |
|
244 | return () => {
|
245 | if (swiperRef.current && !swiperRef.current.destroyed) {
|
246 | swiperRef.current.destroy(true, false);
|
247 | }
|
248 | };
|
249 | }, []);
|
250 |
|
251 |
|
252 | useIsomorphicLayoutEffect(() => {
|
253 | attachEvents();
|
254 | const changedParams = getChangedParams(passedParams, oldPassedParamsRef.current, slides, oldSlides.current, c => c.key);
|
255 | oldPassedParamsRef.current = passedParams;
|
256 | oldSlides.current = slides;
|
257 | if (changedParams.length && swiperRef.current && !swiperRef.current.destroyed) {
|
258 | updateSwiper({
|
259 | swiper: swiperRef.current,
|
260 | slides,
|
261 | passedParams,
|
262 | changedParams,
|
263 | nextEl: nextElRef.current,
|
264 | prevEl: prevElRef.current,
|
265 | scrollbarEl: scrollbarElRef.current,
|
266 | paginationEl: paginationElRef.current
|
267 | });
|
268 | }
|
269 | return () => {
|
270 | detachEvents();
|
271 | };
|
272 | });
|
273 |
|
274 |
|
275 | useIsomorphicLayoutEffect(() => {
|
276 | updateOnVirtualData(swiperRef.current);
|
277 | }, [virtualData]);
|
278 |
|
279 |
|
280 | function renderSlides() {
|
281 | if (swiperParams.virtual) {
|
282 | return renderVirtual(swiperRef.current, slides, virtualData);
|
283 | }
|
284 | return slides.map((child, index) => {
|
285 | return React.cloneElement(child, {
|
286 | swiper: swiperRef.current,
|
287 | swiperSlideIndex: index
|
288 | });
|
289 | });
|
290 | }
|
291 | return React.createElement(Tag, _extends({
|
292 | ref: swiperElRef,
|
293 | className: uniqueClasses(`${containerClasses}${className ? ` ${className}` : ''}`)
|
294 | }, restProps), React.createElement(SwiperContext.Provider, {
|
295 | value: swiperRef.current
|
296 | }, slots['container-start'], React.createElement(WrapperTag, {
|
297 | className: wrapperClass(swiperParams.wrapperClass)
|
298 | }, slots['wrapper-start'], renderSlides(), slots['wrapper-end']), needsNavigation(swiperParams) && React.createElement(React.Fragment, null, React.createElement("div", {
|
299 | ref: prevElRef,
|
300 | className: "swiper-button-prev"
|
301 | }), React.createElement("div", {
|
302 | ref: nextElRef,
|
303 | className: "swiper-button-next"
|
304 | })), needsScrollbar(swiperParams) && React.createElement("div", {
|
305 | ref: scrollbarElRef,
|
306 | className: "swiper-scrollbar"
|
307 | }), needsPagination(swiperParams) && React.createElement("div", {
|
308 | ref: paginationElRef,
|
309 | className: "swiper-pagination"
|
310 | }), slots['container-end']));
|
311 | });
|
312 | Swiper.displayName = 'Swiper';
|
313 |
|
314 | const SwiperSlide = forwardRef(function (_temp, externalRef) {
|
315 | let {
|
316 | tag: Tag = 'div',
|
317 | children,
|
318 | className = '',
|
319 | swiper,
|
320 | zoom,
|
321 | lazy,
|
322 | virtualIndex,
|
323 | swiperSlideIndex,
|
324 | ...rest
|
325 | } = _temp === void 0 ? {} : _temp;
|
326 | const slideElRef = useRef(null);
|
327 | const [slideClasses, setSlideClasses] = useState('swiper-slide');
|
328 | const [lazyLoaded, setLazyLoaded] = useState(false);
|
329 | function updateClasses(_s, el, classNames) {
|
330 | if (el === slideElRef.current) {
|
331 | setSlideClasses(classNames);
|
332 | }
|
333 | }
|
334 | useIsomorphicLayoutEffect(() => {
|
335 | if (typeof swiperSlideIndex !== 'undefined') {
|
336 | slideElRef.current.swiperSlideIndex = swiperSlideIndex;
|
337 | }
|
338 | if (externalRef) {
|
339 | externalRef.current = slideElRef.current;
|
340 | }
|
341 | if (!slideElRef.current || !swiper) {
|
342 | return;
|
343 | }
|
344 | if (swiper.destroyed) {
|
345 | if (slideClasses !== 'swiper-slide') {
|
346 | setSlideClasses('swiper-slide');
|
347 | }
|
348 | return;
|
349 | }
|
350 | swiper.on('_slideClass', updateClasses);
|
351 |
|
352 | return () => {
|
353 | if (!swiper) return;
|
354 | swiper.off('_slideClass', updateClasses);
|
355 | };
|
356 | });
|
357 | useIsomorphicLayoutEffect(() => {
|
358 | if (swiper && slideElRef.current && !swiper.destroyed) {
|
359 | setSlideClasses(swiper.getSlideClasses(slideElRef.current));
|
360 | }
|
361 | }, [swiper]);
|
362 | const slideData = {
|
363 | isActive: slideClasses.indexOf('swiper-slide-active') >= 0,
|
364 | isVisible: slideClasses.indexOf('swiper-slide-visible') >= 0,
|
365 | isPrev: slideClasses.indexOf('swiper-slide-prev') >= 0,
|
366 | isNext: slideClasses.indexOf('swiper-slide-next') >= 0
|
367 | };
|
368 | const renderChildren = () => {
|
369 | return typeof children === 'function' ? children(slideData) : children;
|
370 | };
|
371 | const onLoad = () => {
|
372 | setLazyLoaded(true);
|
373 | };
|
374 | return React.createElement(Tag, _extends({
|
375 | ref: slideElRef,
|
376 | className: uniqueClasses(`${slideClasses}${className ? ` ${className}` : ''}`),
|
377 | "data-swiper-slide-index": virtualIndex,
|
378 | onLoad: onLoad
|
379 | }, rest), zoom && React.createElement(SwiperSlideContext.Provider, {
|
380 | value: slideData
|
381 | }, React.createElement("div", {
|
382 | className: "swiper-zoom-container",
|
383 | "data-swiper-zoom": typeof zoom === 'number' ? zoom : undefined
|
384 | }, renderChildren(), lazy && !lazyLoaded && React.createElement("div", {
|
385 | className: "swiper-lazy-preloader"
|
386 | }))), !zoom && React.createElement(SwiperSlideContext.Provider, {
|
387 | value: slideData
|
388 | }, renderChildren(), lazy && !lazyLoaded && React.createElement("div", {
|
389 | className: "swiper-lazy-preloader"
|
390 | })));
|
391 | });
|
392 | SwiperSlide.displayName = 'SwiperSlide';
|
393 |
|
394 | export { Swiper, SwiperSlide, useSwiper, useSwiperSlide };
|