UNPKG

6.76 kBJavaScriptView Raw
1function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
3import React, { useRef, useState, useEffect, forwardRef } from 'react';
4import { getParams } from './get-params.js';
5import { initSwiper, mountSwiper } from './init-swiper.js';
6import { needsScrollbar, needsNavigation, needsPagination, uniqueClasses, extend } from './utils.js';
7import { renderLoop, calcLoopedSlides } from './loop.js';
8import { getChangedParams } from './get-changed-params.js';
9import { getChildren } from './get-children.js';
10import { updateSwiper } from './update-swiper.js';
11import { renderVirtual, updateOnVirtualData } from './virtual.js';
12import { useIsomorphicLayoutEffect } from './use-isomorphic-layout-effect.js';
13const Swiper = /*#__PURE__*/forwardRef(({
14 className,
15 tag: Tag = 'div',
16 wrapperTag: WrapperTag = 'div',
17 children,
18 onSwiper,
19 ...rest
20} = {}, externalElRef) => {
21 let eventsAssigned = false;
22 const [containerClasses, setContainerClasses] = useState('swiper');
23 const [virtualData, setVirtualData] = useState(null);
24 const [breakpointChanged, setBreakpointChanged] = useState(false);
25 const initializedRef = useRef(false);
26 const swiperElRef = useRef(null);
27 const swiperRef = useRef(null);
28 const oldPassedParamsRef = useRef(null);
29 const oldSlides = useRef(null);
30 const nextElRef = useRef(null);
31 const prevElRef = useRef(null);
32 const paginationElRef = useRef(null);
33 const scrollbarElRef = useRef(null);
34 const {
35 params: swiperParams,
36 passedParams,
37 rest: restProps,
38 events
39 } = getParams(rest);
40 const {
41 slides,
42 slots
43 } = getChildren(children);
44
45 const onBeforeBreakpoint = () => {
46 setBreakpointChanged(!breakpointChanged);
47 };
48
49 Object.assign(swiperParams.on, {
50 _containerClasses(swiper, classes) {
51 setContainerClasses(classes);
52 }
53
54 });
55
56 if (!swiperElRef.current) {
57 // init swiper
58 Object.assign(swiperParams.on, events);
59 eventsAssigned = true;
60 swiperRef.current = initSwiper(swiperParams);
61
62 swiperRef.current.loopCreate = () => {};
63
64 swiperRef.current.loopDestroy = () => {};
65
66 if (swiperParams.loop) {
67 swiperRef.current.loopedSlides = calcLoopedSlides(slides, swiperParams);
68 }
69
70 if (swiperRef.current.virtual && swiperRef.current.params.virtual.enabled) {
71 swiperRef.current.virtual.slides = slides;
72 const extendWith = {
73 cache: false,
74 slides,
75 renderExternal: setVirtualData,
76 renderExternalUpdate: false
77 };
78 extend(swiperRef.current.params.virtual, extendWith);
79 extend(swiperRef.current.originalParams.virtual, extendWith);
80 }
81 } // Listen for breakpoints change
82
83
84 if (swiperRef.current) {
85 swiperRef.current.on('_beforeBreakpoint', onBeforeBreakpoint);
86 }
87
88 const attachEvents = () => {
89 if (eventsAssigned || !events || !swiperRef.current) return;
90 Object.keys(events).forEach(eventName => {
91 swiperRef.current.on(eventName, events[eventName]);
92 });
93 };
94
95 const detachEvents = () => {
96 if (!events || !swiperRef.current) return;
97 Object.keys(events).forEach(eventName => {
98 swiperRef.current.off(eventName, events[eventName]);
99 });
100 };
101
102 useEffect(() => {
103 return () => {
104 if (swiperRef.current) swiperRef.current.off('_beforeBreakpoint', onBeforeBreakpoint);
105 };
106 }); // set initialized flag
107
108 useEffect(() => {
109 if (!initializedRef.current && swiperRef.current) {
110 swiperRef.current.emitSlidesClasses();
111 initializedRef.current = true;
112 }
113 }); // mount swiper
114
115 useIsomorphicLayoutEffect(() => {
116 if (externalElRef) {
117 externalElRef.current = swiperElRef.current;
118 }
119
120 if (!swiperElRef.current) return;
121 mountSwiper({
122 el: swiperElRef.current,
123 nextEl: nextElRef.current,
124 prevEl: prevElRef.current,
125 paginationEl: paginationElRef.current,
126 scrollbarEl: scrollbarElRef.current,
127 swiper: swiperRef.current
128 }, swiperParams);
129 if (onSwiper) onSwiper(swiperRef.current); // eslint-disable-next-line
130
131 return () => {
132 if (swiperRef.current && !swiperRef.current.destroyed) {
133 swiperRef.current.destroy(true, false);
134 }
135 };
136 }, []); // watch for params change
137
138 useIsomorphicLayoutEffect(() => {
139 attachEvents();
140 const changedParams = getChangedParams(passedParams, oldPassedParamsRef.current, slides, oldSlides.current);
141 oldPassedParamsRef.current = passedParams;
142 oldSlides.current = slides;
143
144 if (changedParams.length && swiperRef.current && !swiperRef.current.destroyed) {
145 updateSwiper({
146 swiper: swiperRef.current,
147 slides,
148 passedParams,
149 changedParams,
150 nextEl: nextElRef.current,
151 prevEl: prevElRef.current,
152 scrollbarEl: scrollbarElRef.current,
153 paginationEl: paginationElRef.current
154 });
155 }
156
157 return () => {
158 detachEvents();
159 };
160 }); // update on virtual update
161
162 useIsomorphicLayoutEffect(() => {
163 updateOnVirtualData(swiperRef.current);
164 }, [virtualData]); // bypass swiper instance to slides
165
166 function renderSlides() {
167 if (swiperParams.virtual) {
168 return renderVirtual(swiperRef.current, slides, virtualData);
169 }
170
171 if (!swiperParams.loop || swiperRef.current && swiperRef.current.destroyed) {
172 return slides.map(child => {
173 return /*#__PURE__*/React.cloneElement(child, {
174 swiper: swiperRef.current
175 });
176 });
177 }
178
179 return renderLoop(swiperRef.current, slides, swiperParams);
180 }
181
182 return /*#__PURE__*/React.createElement(Tag, _extends({
183 ref: swiperElRef,
184 className: uniqueClasses(`${containerClasses}${className ? ` ${className}` : ''}`)
185 }, restProps), slots['container-start'], needsNavigation(swiperParams) && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
186 ref: prevElRef,
187 className: "swiper-button-prev"
188 }), /*#__PURE__*/React.createElement("div", {
189 ref: nextElRef,
190 className: "swiper-button-next"
191 })), needsScrollbar(swiperParams) && /*#__PURE__*/React.createElement("div", {
192 ref: scrollbarElRef,
193 className: "swiper-scrollbar"
194 }), needsPagination(swiperParams) && /*#__PURE__*/React.createElement("div", {
195 ref: paginationElRef,
196 className: "swiper-pagination"
197 }), /*#__PURE__*/React.createElement(WrapperTag, {
198 className: "swiper-wrapper"
199 }, slots['wrapper-start'], renderSlides(), slots['wrapper-end']), slots['container-end']);
200});
201Swiper.displayName = 'Swiper';
202export { Swiper };
\No newline at end of file