@eureca/eureca-ui
Version:
UI component library of Eureca's user and admin apps
146 lines (133 loc) • 3.52 kB
JavaScript
import React, { useState, useCallback } from 'react';
import PropTypes from 'prop-types';
import Slider from 'react-slick';
import { Box } from '@material-ui/core';
import { useTheme } from '@material-ui/core/styles';
import { FiChevronLeft, FiChevronRight } from 'react-icons/fi';
import { colors } from '../../theme/colors';
import { useWindowSize } from '../../hooks/useWindowSizeSSR';
const settings = {
dots: {
dots: true,
arrows: false,
},
default: {
arrows: true,
dots: false,
nextArrow: <Arrow side="right" />,
prevArrow: <Arrow side="left" />,
},
};
const arrowStyle = {
cursor: 'pointer',
position: 'absolute',
top: '50%',
transform: 'translate(0,-50%)',
zIndex: 500,
};
function Arrow({ onClick, side }) {
const isClickable = typeof onClick !== 'object';
const boxProps = { style: arrowStyle, onClick, [side]: 16 };
return (
isClickable && (
<Box {...boxProps}>
{side === 'left' ? (
<FiChevronLeft color={colors.gray5} size={48} />
) : (
<FiChevronRight color={colors.gray5} size={48} />
)}
</Box>
)
);
}
const outerWidth = el => {
let width = el.offsetWidth;
const elementStyle = getComputedStyle(el);
width += parseInt(elementStyle.marginLeft, 10) + parseInt(elementStyle.marginRight, 10);
return width;
};
function Carousel({ children, variant = 'default', boxProps, ...props }) {
const [slides, setSlides] = useState(1);
const theme = useTheme();
const size = useWindowSize();
const sliderRef = useCallback(
ref => {
if (ref !== null && size?.width) {
const slider = ref.innerSlider.list;
const { clientWidth, firstChild } = slider;
const itemsPerPage = Math.floor(clientWidth / outerWidth(firstChild.firstChild));
setSlides(itemsPerPage);
}
},
[size]
);
const { xs, sm, md, lg, xl } = theme.breakpoints.values;
return (
<Box style={{ minWidth: '100%', width: 0 }} {...boxProps}>
<Slider
slidesToShow={slides}
slidesToScroll={slides}
speed={500}
{...settings[variant]}
ref={sliderRef}
responsive={[
// fixes the loading issue when using flex-box
{
breakpoint: xs,
settings: {
mobileFirst: false,
infinite: true,
slidesToShow: slides,
},
},
{
breakpoint: sm,
settings: {
mobileFirst: false,
infinite: true,
slidesToShow: slides,
},
},
{
breakpoint: md,
settings: {
mobileFirst: false,
infinite: true,
slidesToShow: slides,
},
},
{
breakpoint: lg,
settings: {
mobileFirst: false,
infinite: true,
slidesToShow: slides,
},
},
{
breakpoint: xl,
settings: {
mobileFirst: false,
infinite: true,
slidesToShow: slides,
},
},
]}
{...props}
>
{children}
</Slider>
</Box>
);
}
Carousel.propTypes = {
variant: PropTypes.string,
children: PropTypes.oneOfType([PropTypes.any]),
boxProps: PropTypes.object,
};
Carousel.defaulProps = {
variant: 'default',
children: null,
boxProps: {},
};
export { Carousel };