@braineet/ui
Version:
Braineet design system
294 lines (292 loc) • 10.1 kB
JavaScript
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);