@swissup/pwa-easy-slide
Version:
Easy slide(r) integration into venia-ui
230 lines (198 loc) • 7.15 kB
JavaScript
import React, { useEffect, useState } from 'react';
import SwiperCore, {
Navigation,
Pagination,
Scrollbar,
Virtual,
Keyboard,
Parallax,
Lazy,
Autoplay,
EffectFade,
EffectCube,
EffectFlip
} from 'swiper';
// Import Swiper styles
import 'swiper/swiper-bundle.min.css';
import { useStyle } from '@magento/venia-ui/lib/classify';
import defaultClasses from './easyslider.module.css';
// Import Swiper React components
import { Swiper, SwiperSlide } from 'swiper/react';
import SlideImage from './slide/image';
import SlideDescription from './slide/description';
import { UNCONSTRAINED_SIZE_KEY } from '@magento/peregrine/lib/talons/Image/useImage';
import { useWindowSize } from '@magento/peregrine';
import easysliderOperations from '@swissup/pwa-easy-slide/lib/queries/getEasySlider.gql';
import { useEasySlider, useEasySlideImg } from '@swissup/pwa-easy-slide/lib/talons/EasySlide';
import PlaceholderImage from '@magento/venia-ui/lib/components/Image/placeholderImage';
// install Swiper components
SwiperCore.use([
Navigation,
Pagination,
Scrollbar,
Virtual,
Keyboard,
Parallax,
Lazy,
Autoplay,
EffectFade,
EffectCube,
EffectFlip
]);
const unescapeHtml = (html) => {
const tempElement = document.createElement('div');
tempElement.innerHTML = html;
return tempElement.textContent || tempElement.innerText || "";
};
const toHTML = str => ({ __html: unescapeHtml(str) });
const EasySlider = props => {
const {
identifier,
sliderConfig: defaultSliderConfig,
placeholder: placeholderProps
} = props;
const classes = useStyle(defaultClasses, props.classes);
const talonProps = useEasySlider({
...easysliderOperations,
identifier
});
const {
data: {
slider_config: loadedSliderConfig,
slides
}
} = talonProps;
const [isLoaded, setIsLoaded] = useState(false);
const [swiper, setSwiper] = useState(null);
const [isConfigLoaded, setIsConfigLoaded] = useState(false);
const [swiperConfig, setSwiperConfig] = useState({
spaceBetween: 50,
slidesPerView: 1,//'auto',
loop: true,
roundLengths: true,
...defaultSliderConfig,
// autoHeight: true,
// loadprevnext: true,
// startrandomslide: true,
});
useEffect(() => {
if (!isConfigLoaded && loadedSliderConfig) {
setIsConfigLoaded(true);
setSwiperConfig({
...swiperConfig,
...loadedSliderConfig
});
}
}, [
isConfigLoaded,
setIsConfigLoaded,
swiperConfig,
setSwiperConfig,
loadedSliderConfig,
defaultSliderConfig
]);
useEffect(() => {
if (isConfigLoaded && slides && slides.length > 0) {
setIsLoaded(true);
}
}, [slides, setIsLoaded, isConfigLoaded]);
const placeholder = (<PlaceholderImage
classes={classes}
{...placeholderProps}
/>);
const windowSize = useWindowSize();
const isDesktop = windowSize.innerWidth >= 768;//1024;
// const getSlideDescription = (description) => {
// if (!description) {
// return '';
// }
// const node = new DOMParser().parseFromString(
// description,
// 'text/html'
// );
// const title = node.querySelector('div.h1').innerText;
// const text = node.querySelector('div.text').innerText;
// const actionNode = node.querySelector('a.action.primary');
// const href = actionNode.getAttribute('href')
// .replace(process.env.MAGENTO_BACKEND_URL, '/')
// .replace('/index.php', '');
// return (<div className={classes.slideDescription}>
// <div className={classes.slideDescriptionTitle}>{title}</div>
// <div className={classes.slideDescriptionText}>{text}</div>
// <div>
// <a className={classes.slideDescriptionAction} title={actionNode.getAttribute('title')} href={href}>
// <div dangerouslySetInnerHTML={toHTML(actionNode.innerHTML)} />
// </a>
// </div>
// </div>);
// // return description ? <div className={classes.slideDescription} dangerouslySetInnerHTML={toHTML(description)} /> : '';
// }
const getSwiper = (config) => {
const loop = !!config.loop;
const scrollbar = config.scrollbar ? { draggable: true } : false;
const freeMode = !!config.freeMode;
const pagination = config.pagination ? { clickable: true } : false;
const navigation = !!config.navigation;
const lazy = !!config.lazy;
const slidesPerView = config.slidesPerView && isDesktop ?
config.slidesPerView : 'auto';
const spaceBetween = config.spaceBetween ? config.spaceBetween : 50;
const widths = new Map();
if (config.sizes) {
config.sizes.forEach(
({image_width}) => {widths.set(image_width, image_width)}
);
}
return (<Swiper
scrollbar={scrollbar}
freeMode={freeMode}
pagination={pagination}
navigation={navigation}
loop={loop}
lazy={lazy}
slidesPerView={slidesPerView}
spaceBetween={spaceBetween}
onSwiper={setSwiper}
onInit={(swiper) => {/*console.log('Swiper initialized!', swiper)*/}}
onSlideChange={() => {/*console.log('slide change')*/}}
onReachEnd={() => {/*console.log('Swiper end reached')*/}}
>
{ slides && slides.length > 0 ? slides.map(({
slide_id,
image,
width,
height,
description
}, index ) => {
const { path, alt /*, src*/ } = useEasySlideImg({
slide_id,
image,
width,
height
});
widths.set(UNCONSTRAINED_SIZE_KEY, width);
// const slideDescription = getSlideDescription(description);
const isImageLazy = index === 0 ? false : lazy;
return <SwiperSlide className={classes.slide} key={`slide-${slide_id}`}>
<SlideImage
className={classes.image}
resource={path}
type={'image-easyslide'}
alt={alt}
width={width}
height={height}
widths={widths}
lazy={isImageLazy}
/>
<SlideDescription description={description} />
</SwiperSlide>
}) : placeholder }
</Swiper>)
};
return (
<div className={classes.root}>
{isLoaded ? getSwiper(swiperConfig) : placeholder}
</div>
)
};
export default EasySlider;