UNPKG

@braineet/ui

Version:

Braineet design system

294 lines (292 loc) 10.1 kB
function _readOnlyError(r) { throw new TypeError('"' + r + '" is read-only'); } function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } /* eslint-disable array-callback-return */ /* eslint-disable no-nested-ternary */ import React from 'react'; import { withTheme } from 'styled-components'; import Box from '../box'; // style import { StyledBoxTopSide, StyledTextTitle, StyledBoxArrows, StyledBoxNumbers, StyledNumber, StyledDivider, StyledButton, StyledSwiper, StyledWrapper, StyledChild } from './styles'; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; var Carousel = function Carousel(_ref) { var hasArrows = _ref.hasArrows, arrowTop = _ref.arrowTop, theme = _ref.theme, loader = _ref.loader, style = _ref.style, isFetching = _ref.isFetching, title = _ref.title, children = _ref.children; var _React$useState = React.useState({ index: 0, speed: 300, gutter: 20 }), config = _React$useState[0], setConfig = _React$useState[1]; var _React$useState2 = React.useState({}), carouselState = _React$useState2[0], setCarouselState = _React$useState2[1]; var containerRef = React.useRef(); var wrapperRef = React.useRef(); var childRefs = React.useRef([]); var init = function init(container, items) { var index = config.index, gutter = config.gutter; if (!(container != null && container.current) || !(wrapperRef != null && wrapperRef.current) || !(items != null && items.current) || items.current && items.current.length === 0) return; var browser = { addEventListener: !!window.addEventListener, touch: 'ontouchstart' in window || window.DocumentTouch && document instanceof window.DocumentTouch, smoth: function (temp) { if (temp.style.scrollBehavior !== undefined) return true; return false; }(document.createElement('swipe')), snap: function () { return false; }( // @TODO package https://github.com/malte-wessel/react-custom-scrollbars/issues/339 /* const props = [ 'scrollSnapType', 'WebkitScrollSnapType', 'ScrollSnapType', 'msScrollSnapType', ]; // eslint-disable-next-line no-restricted-syntax for (const i in props) { if (temp.style[props[i]] !== undefined) return true; } return false; */ document.createElement('swipe')) }; // eslint-disable-next-line prefer-destructuring var widthCards = items.current.map(function (item) { return item ? item.getBoundingClientRect ? Math.round(item.getBoundingClientRect().width + gutter) : Math.round(item.offsetWidth + gutter) : 0; }); var widthContainer = Math.round(container.current.getBoundingClientRect().width || container.current.offsetWidth); var width = widthCards.length ? widthCards.reduce(function (a, b) { return a + b; }) : widthContainer; var cards = wrapperRef.current.children; var cardsPos = new Array(cards.length); var pos = cards.length; var diffPos = 0; // eslint-disable-next-line no-plusplus while (pos--) { var card = cards[pos]; card.setAttribute('data-index', pos); if (!browser.snap) { card.style.width = widthCards[pos] + "px"; } diffPos += widthCards[pos]; cardsPos[pos] = width - diffPos; } if (browser.snap) { wrapperRef.current.style.overflow = 'auto hidden'; } else { wrapperRef.current.style.width = width + "px"; wrapperRef.current.style.overflow = 'hidden'; translate(index, -cardsPos[index], 0); } setCarouselState({ widthContainer: widthContainer, cards: cards, widthCards: widthCards, cardsPos: cardsPos, hasSnap: browser.snap }); }; var next = function next() { var index = config.index; var cards = carouselState.cards, widthContainer = carouselState.widthContainer, widthCards = carouselState.widthCards; if (cards[index] && cards[index].offsetLeft !== undefined && !(cards[index].offsetLeft + widthContainer >= widthCards.reduce(function (a, b) { return a + b; }))) { slide(index + 1); } }; var prev = function prev() { var index = config.index; if (index) slide(index - 1); }; var slide = function slide(to) { var index = config.index; var cardsPos = carouselState.cardsPos; if (index === to) return; var prevCardsPos = [].concat(cardsPos); setConfig(function (old) { return _extends({}, old, { index: to }); }); move(to, -prevCardsPos[to]); }; var move = function move(to, pos) { var hasSnap = carouselState.hasSnap; if (hasSnap) { scrollTo(to); } else { translate(to, pos); } }; var scrollTo = function scrollTo(to) { var cards = carouselState.cards; var card = cards[to]; if (!card) return; card.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'start' }); }; var translate = function translate(to, pos) { var _wrapperRef$current; var speed = config.speed; var styles = wrapperRef == null || (_wrapperRef$current = wrapperRef.current) == null ? void 0 : _wrapperRef$current.style; if (!styles) return; styles.webkitTransitionDuration = speed + "ms"; styles.MozTransitionDuration = speed + "ms"; styles.msTransitionDuration = speed + "ms"; styles.OTransitionDuration = speed + "ms"; styles.transitionDuration = speed + "ms"; styles.transform = "translateX(" + pos + "px)"; styles.msTransform = "translateX(" + pos + "px)"; styles.MozTransform = "translateX(" + pos + "px)"; styles.WebkitTransform = "translateX(" + pos + "px)"; styles.OTransform = "translateX(" + pos + "px)"; setConfig({ index: to }); }; React.useEffect(function () { init(containerRef, childRefs); }, []); React.useEffect(function () { init(containerRef, childRefs); }, [children == null ? void 0 : children.length]); var index = config.index; var cards = carouselState.cards, widthContainer = carouselState.widthContainer, widthCards = carouselState.widthCards, hasSnap = carouselState.hasSnap; var topSide = function topSide() { if (!hasArrows || !children.length || children.length === 0 || !cards) { return; } var nextDisable = index + 1 === cards.length; var handleNext = function handleNext(e) { if (!nextDisable && cards[index] && cards[index].offsetLeft !== undefined && cards[index].offsetLeft + widthContainer < widthCards.reduce(function (a, b) { return a + b; })) { e.preventDefault(); next(); } }; return /*#__PURE__*/_jsxs(StyledBoxTopSide, { margin: arrowTop ? "0 0 " + theme.spaces.md + " 0" : theme.spaces.md + " 0 0 0", children: [typeof title === 'string' ? /*#__PURE__*/_jsx(StyledTextTitle, { size: "xl", children: title }) : title, /*#__PURE__*/_jsxs(StyledBoxArrows, { elevation: 3, children: [/*#__PURE__*/_jsxs(StyledBoxNumbers, { children: [/*#__PURE__*/_jsx(StyledNumber, { size: "sm", isChanging: true, children: index + 1 }), /*#__PURE__*/_jsx(StyledDivider, {}), /*#__PURE__*/_jsx(StyledNumber, { size: "sm", children: children.length })] }), /*#__PURE__*/_jsx(StyledButton, { $position: "left", onClick: index !== 0 ? function (e) { e.preventDefault(); prev(); } : function () {}, styleType: "ghost", icon: "arrow_left", color: "black", disabled: index === 0 }), /*#__PURE__*/_jsx(StyledButton, { $position: "right", onClick: handleNext, styleType: "ghost", icon: "arrow_right", color: "black", disabled: nextDisable })] })] }); }; return /*#__PURE__*/_jsxs(Box, { display: "flex", flexDirection: arrowTop ? 'column' : 'column-reverse', position: "relative", children: [topSide(), /*#__PURE__*/_jsx(StyledSwiper, { ref: containerRef, style: style.container, clearFix: true, children: /*#__PURE__*/_jsx(StyledWrapper, { ref: wrapperRef, style: style.wrapper, children: children.length ? React.Children.map(children, function (child) { if (!child) { return null; } var childStyle = child.props.style ? _extends({}, style.child, child.props.style) : style.child; return /*#__PURE__*/_jsx(StyledChild, { children: /*#__PURE__*/React.cloneElement(child, { ref: function ref(arg) { if (!childRefs.current.includes(arg)) { childRefs.current.push(arg); } var ref = child.ref; if (typeof ref === 'function') { ref(arg); } }, style: _extends({}, childStyle, { marginRight: hasSnap ? theme.spaces.lg : 'auto' }) }) }); }) : isFetching ? loader() : null }) })] }); }; Carousel.defaultProps = { arrowTop: true, loader: /*#__PURE__*/_jsx("div", { children: "Loading..." }), options: { gutter: 20 }, theme: {}, hasArrows: true, isFetching: false, style: { container: { overflowX: 'hidden', overflowY: 'hidden', visibility: 'visible', position: 'relative' }, wrapper: { overflowY: 'hidden', position: 'relative' }, child: { float: 'left', position: 'relative', transitionProperty: 'transform' } }, title: '' }; export default withTheme(Carousel);