swiper.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. import { template as _$template } from "solid-js/web";
  2. import { className as _$className } from "solid-js/web";
  3. import { effect as _$effect } from "solid-js/web";
  4. import { createComponent as _$createComponent } from "solid-js/web";
  5. import { insert as _$insert } from "solid-js/web";
  6. import { memo as _$memo } from "solid-js/web";
  7. import { spread as _$spread } from "solid-js/web";
  8. const _tmpl$ = /*#__PURE__*/_$template(`<div class="swiper-wrapper"></div>`, 2),
  9. _tmpl$2 = /*#__PURE__*/_$template(`<div class="swiper-button-prev"></div>`, 2),
  10. _tmpl$3 = /*#__PURE__*/_$template(`<div class="swiper-button-next"></div>`, 2),
  11. _tmpl$4 = /*#__PURE__*/_$template(`<div class="swiper-scrollbar"></div>`, 2),
  12. _tmpl$5 = /*#__PURE__*/_$template(`<div class="swiper-pagination"></div>`, 2),
  13. _tmpl$6 = /*#__PURE__*/_$template(`<div></div>`, 2);
  14. import { createEffect, createMemo, createSignal, onCleanup, onMount, Show, splitProps, children } from 'solid-js';
  15. import SwiperCore from 'swiper';
  16. import { SwiperContext } from './context.js';
  17. import { getChangedParams } from '../components-shared/get-changed-params.js';
  18. import { getChildren } from './get-children.js';
  19. import { getParams } from '../components-shared/get-params.js';
  20. import { calcLoopedSlides, renderLoop } from './loop.js';
  21. import { mountSwiper } from '../components-shared/mount-swiper.js';
  22. import { updateSwiper } from '../components-shared/update-swiper.js';
  23. import { extend, needsNavigation, needsPagination, needsScrollbar, uniqueClasses } from '../components-shared/utils.js';
  24. import { renderVirtual } from './virtual.js';
  25. import { updateOnVirtualData } from '../components-shared/update-on-virtual-data.js';
  26. const Swiper = props => {
  27. let eventsAssigned = false;
  28. const [containerClasses, setContainerClasses] = createSignal('swiper');
  29. const [virtualData, setVirtualData] = createSignal(null);
  30. const [, setBreakpointChanged] = createSignal(false); // The variables bellow are mofied by SolidJS and can't be const
  31. let initializedRef = false; // eslint-disable-line prefer-const
  32. let swiperElRef = null; // eslint-disable-line prefer-const
  33. let swiperRef = null; // eslint-disable-line prefer-const
  34. let oldPassedParamsRef = null; // eslint-disable-line prefer-const
  35. let oldSlides = null; // eslint-disable-line prefer-const
  36. let nextElRef = null; // eslint-disable-line prefer-const
  37. let prevElRef = null; // eslint-disable-line prefer-const
  38. let paginationElRef = null; // eslint-disable-line prefer-const
  39. let scrollbarElRef = null; // eslint-disable-line prefer-const
  40. const [local, rest] = splitProps(props, ['children', 'class', 'onSwiper', 'ref', 'tag', 'wrapperTag']);
  41. const params = createMemo(() => getParams(rest));
  42. const slidesSlots = children(() => getChildren(local.children));
  43. const onBeforeBreakpoint = () => {
  44. setBreakpointChanged(state => !state);
  45. };
  46. Object.assign(params().params.on, {
  47. _containerClasses(swiper, classes) {
  48. setContainerClasses(classes);
  49. }
  50. });
  51. const initSwiper = () => {
  52. // init swiper
  53. Object.assign(params().params.on, params().events);
  54. eventsAssigned = true;
  55. swiperRef = new SwiperCore(params().params);
  56. swiperRef.loopCreate = () => {};
  57. swiperRef.loopDestroy = () => {};
  58. if (params().params.loop) {
  59. swiperRef.loopedSlides = calcLoopedSlides(slidesSlots().slides, params().params);
  60. }
  61. if (swiperRef.virtual && swiperRef.params.virtual.enabled) {
  62. swiperRef.virtual.slides = slidesSlots().slides;
  63. const extendWith = {
  64. cache: false,
  65. slides: slidesSlots().slides,
  66. renderExternal: data => {
  67. setVirtualData(data);
  68. },
  69. renderExternalUpdate: true
  70. };
  71. extend(swiperRef.params.virtual, extendWith);
  72. extend(swiperRef.originalParams.virtual, extendWith);
  73. }
  74. };
  75. if (!swiperElRef) {
  76. initSwiper();
  77. } // Listen for breakpoints change
  78. if (swiperRef) {
  79. swiperRef.on('_beforeBreakpoint', onBeforeBreakpoint);
  80. }
  81. const attachEvents = () => {
  82. if (eventsAssigned || !params().events || !swiperRef) return;
  83. Object.keys(params().events).forEach(eventName => {
  84. swiperRef.on(eventName, params().events[eventName]);
  85. });
  86. };
  87. const detachEvents = () => {
  88. if (!params().events || !swiperRef) return;
  89. Object.keys(params().events).forEach(eventName => {
  90. swiperRef.off(eventName, params().events[eventName]);
  91. });
  92. };
  93. onCleanup(() => {
  94. if (swiperRef) swiperRef.off('_beforeBreakpoint', onBeforeBreakpoint);
  95. }); // set initialized flag
  96. createEffect(() => {
  97. if (!initializedRef && swiperRef) {
  98. swiperRef.emitSlidesClasses();
  99. initializedRef = true;
  100. }
  101. }); // mount swiper
  102. onMount(() => {
  103. if (local.ref) {
  104. if (typeof local.ref === 'function') {
  105. local.ref(swiperElRef);
  106. } else {
  107. local.ref = swiperElRef;
  108. }
  109. }
  110. if (!swiperElRef) return;
  111. if (swiperRef.destroyed) {
  112. initSwiper();
  113. }
  114. mountSwiper({
  115. el: swiperElRef,
  116. nextEl: nextElRef,
  117. prevEl: prevElRef,
  118. paginationEl: paginationElRef,
  119. scrollbarEl: scrollbarElRef,
  120. swiper: swiperRef
  121. }, params().params);
  122. if (local.onSwiper) local.onSwiper(swiperRef);
  123. });
  124. onCleanup(() => {
  125. if (swiperRef && !swiperRef.destroyed) {
  126. swiperRef.destroy(true, false);
  127. }
  128. }); // watch for params change
  129. createEffect(() => {
  130. attachEvents();
  131. const {
  132. passedParams
  133. } = params();
  134. const changedParams = getChangedParams(passedParams, oldPassedParamsRef, slidesSlots().slides, oldSlides, c => c.key);
  135. oldPassedParamsRef = passedParams;
  136. oldSlides = slidesSlots().slides;
  137. if (changedParams.length && swiperRef && !swiperRef.destroyed) {
  138. updateSwiper({
  139. swiper: swiperRef,
  140. slides: slidesSlots().slides,
  141. passedParams,
  142. changedParams,
  143. nextEl: nextElRef,
  144. prevEl: prevElRef,
  145. scrollbarEl: scrollbarElRef,
  146. paginationEl: paginationElRef
  147. });
  148. }
  149. onCleanup(detachEvents);
  150. }); // update on virtual update
  151. createEffect(() => {
  152. updateOnVirtualData(swiperRef);
  153. setTimeout(() => {
  154. updateOnVirtualData(swiperRef);
  155. });
  156. }); // bypass swiper instance to slides
  157. function renderSlides() {
  158. if (params().params.virtual) {
  159. return renderVirtual(swiperRef, slidesSlots().slides, virtualData());
  160. }
  161. if (!params().params.loop || swiperRef && swiperRef.destroyed) {
  162. return slidesSlots().slides;
  163. }
  164. return renderLoop(swiperRef, slidesSlots().slides, params().params);
  165. }
  166. /* eslint-disable react/react-in-jsx-scope */
  167. /* eslint-disable react/no-unknown-property */
  168. return (() => {
  169. const _el$ = _tmpl$6.cloneNode(true);
  170. const _ref$ = swiperElRef;
  171. typeof _ref$ === "function" ? _ref$(_el$) : swiperElRef = _el$;
  172. _$spread(_el$, () => params().rest, false, true);
  173. _$insert(_el$, _$createComponent(SwiperContext.Provider, {
  174. value: swiperRef,
  175. get children() {
  176. return [_$memo(() => slidesSlots().slots['container-start']), (() => {
  177. const _el$2 = _tmpl$.cloneNode(true);
  178. _$insert(_el$2, () => slidesSlots().slots['wrapper-start'], null);
  179. _$insert(_el$2, renderSlides, null);
  180. _$insert(_el$2, () => slidesSlots().slots['wrapper-end'], null);
  181. return _el$2;
  182. })(), _$createComponent(Show, {
  183. get when() {
  184. return needsNavigation(params().params);
  185. },
  186. get children() {
  187. return [(() => {
  188. const _el$3 = _tmpl$2.cloneNode(true);
  189. const _ref$2 = prevElRef;
  190. typeof _ref$2 === "function" ? _ref$2(_el$3) : prevElRef = _el$3;
  191. return _el$3;
  192. })(), (() => {
  193. const _el$4 = _tmpl$3.cloneNode(true);
  194. const _ref$3 = nextElRef;
  195. typeof _ref$3 === "function" ? _ref$3(_el$4) : nextElRef = _el$4;
  196. return _el$4;
  197. })()];
  198. }
  199. }), _$createComponent(Show, {
  200. get when() {
  201. return needsScrollbar(params().params);
  202. },
  203. get children() {
  204. const _el$5 = _tmpl$4.cloneNode(true);
  205. const _ref$4 = scrollbarElRef;
  206. typeof _ref$4 === "function" ? _ref$4(_el$5) : scrollbarElRef = _el$5;
  207. return _el$5;
  208. }
  209. }), _$createComponent(Show, {
  210. get when() {
  211. return needsPagination(params().params);
  212. },
  213. get children() {
  214. const _el$6 = _tmpl$5.cloneNode(true);
  215. const _ref$5 = paginationElRef;
  216. typeof _ref$5 === "function" ? _ref$5(_el$6) : paginationElRef = _el$6;
  217. return _el$6;
  218. }
  219. }), _$memo(() => slidesSlots().slots['container-end'])];
  220. }
  221. }));
  222. _$effect(() => _$className(_el$, uniqueClasses(`${containerClasses()}${local.class ? ` ${local.class}` : ''}`)));
  223. return _el$;
  224. })();
  225. };
  226. export { Swiper };