UNPKG

react-card-carousel-materialui

Version:

A full-screen card carousel designed in Material UI, drawing inspiration from the Tesla website.

696 lines (682 loc) 21 kB
import React__default, { useRef, Fragment, useState, useEffect, createElement } from 'react'; import Box from '@mui/material/Box'; import Dialog from '@mui/material/Dialog'; import Stack from '@mui/material/Stack'; import PropTypes from 'prop-types'; import ChevronLeft from '@mui/icons-material/ChevronLeft'; import ChevronRight from '@mui/icons-material/ChevronRight'; import IconButton from '@mui/material/IconButton'; import Close from '@mui/icons-material/Close'; import Card from '@mui/material/Card'; import CardContent from '@mui/material/CardContent'; import Grid from '@mui/material/Grid'; import Typography from '@mui/material/Typography'; function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } /** * The base breakpoints for the Soft UI Dashboard PRO React. * You can add new breakpoints using this file. * You can customized the breakpoints for the entire Soft UI Dashboard PRO React using thie file. */ var breakpoints = { values: { xs: 0, sm: 576, md: 768, lg: 992, xl: 1200, xxl: 1400 } }; var SliderActions = function SliderActions(_ref) { var isNextItemAvailable = _ref.isNextItemAvailable, isPreviousItemAvailable = _ref.isPreviousItemAvailable, moveToNext = _ref.moveToNext, moveToPrevious = _ref.moveToPrevious; //create a ref for next and previous button var nextButtonRef = useRef(null); var previousButtonRef = useRef(null); return /*#__PURE__*/React__default.createElement(Fragment, null, isNextItemAvailable() && /*#__PURE__*/React__default.createElement(Box, { style: { position: 'absolute', top: '50%', right: 10, transform: 'translateY(-50%)', backgroundColor: 'transparent', height: '100%', width: window.innerWidth > breakpoints.values.md ? '10%' : '0px', zIndex: 10 }, onMouseEnter: function onMouseEnter(event) { if (nextButtonRef && window.innerWidth > breakpoints.values.md) { nextButtonRef.current.style.opacity = 1; } }, onMouseLeave: function onMouseLeave(event) { if (nextButtonRef && window.innerWidth > breakpoints.values.md) { nextButtonRef.current.style.opacity = window.innerWidth < breakpoints.values.md ? 0.5 : 0.1; } } }, /*#__PURE__*/React__default.createElement(Box // Add the ref to the button , _extends({ ref: nextButtonRef, style: _extends({ position: 'absolute', top: '50%', right: 10, transform: 'translateY(-50%)', zIndex: 10, display: 'flex', justifyContent: 'center', alignItems: 'center', height: '25%', width: '50px', cursor: 'pointer', backgroundColor: 'rgba(0, 0, 0, 0.6)' }, window.innerWidth < breakpoints.values.md ? { opacity: 0.5 } : { opacity: 0.1 }, { transition: 'opacity 0.5s', borderRadius: '15px' }) }, window.innerWidth > breakpoints.values.md && { onMouseEnter: function onMouseEnter(event) { event.target.style.opacity = 1; }, onMouseLeave: function onMouseLeave(event) { event.target.style.opacity = 0.1; } }, { onClick: moveToNext }), /*#__PURE__*/React__default.createElement(IconButton, { color: "white", style: { color: 'white', zIndex: 99 } }, /*#__PURE__*/React__default.createElement(ChevronRight, { fontSize: "large" })))), isPreviousItemAvailable() && /*#__PURE__*/React__default.createElement(Box, { style: { position: 'absolute', top: '50%', left: 10, transform: 'translateY(-50%)', backgroundColor: 'transparent', height: '100%', width: window.innerWidth > breakpoints.values.md ? '10%' : '0px', zIndex: 10 }, onMouseEnter: function onMouseEnter(event) { if (previousButtonRef && window.innerWidth > breakpoints.values.md) { previousButtonRef.current.style.opacity = 1; } }, onMouseLeave: function onMouseLeave(event) { if (previousButtonRef && window.innerWidth > breakpoints.values.md) { previousButtonRef.current.style.opacity = window.innerWidth < breakpoints.values.md ? 0.5 : 0.1; } } }, /*#__PURE__*/React__default.createElement(Box // Add the ref to the button , _extends({ ref: previousButtonRef, style: _extends({ position: 'absolute', top: '50%', left: 10, transform: 'translateY(-50%)', zIndex: 10, display: 'flex', justifyContent: 'center', alignItems: 'center', height: '25%', width: '50px', cursor: 'pointer', backgroundColor: 'rgba(0, 0, 0, 0.6)' }, window.innerWidth < breakpoints.values.md ? { opacity: 0.5 } : { opacity: 0.1 }, { transition: 'opacity 0.5s', borderRadius: '15px' }) }, window.innerWidth > breakpoints.values.md && { onMouseEnter: function onMouseEnter(event) { event.target.style.opacity = 1; }, onMouseLeave: function onMouseLeave(event) { event.target.style.opacity = 0.1; } }, { onClick: moveToPrevious }), /*#__PURE__*/React__default.createElement(IconButton, { color: "white" }, /*#__PURE__*/React__default.createElement(ChevronLeft, { fontSize: "large" }))))); }; SliderActions.propTypes = { isNextItemAvailable: PropTypes.func.isRequired, isPreviousItemAvailable: PropTypes.func.isRequired, moveToNext: PropTypes.func.isRequired, moveToPrevious: PropTypes.func.isRequired }; SliderActions.defaultProps = { isNextItemAvailable: function isNextItemAvailable() {}, isPreviousItemAvailable: function isPreviousItemAvailable() {}, moveToNext: function moveToNext() {}, moveToPrevious: function moveToPrevious() {} }; var SliderIndicator = function SliderIndicator(_ref) { var sliderItems = _ref.sliderItems, currentItem = _ref.currentItem, moveToASpecificItem = _ref.moveToASpecificItem; return /*#__PURE__*/React__default.createElement(Box, { style: { textAlign: 'center', position: 'absolute', bottom: window.innerWidth < breakpoints.values.md ? '4%' : window.innerWidth < breakpoints.values.lg ? '6%' : '10%', left: '50%', transform: 'translateX(-50%)' } }, /*#__PURE__*/React__default.createElement(Stack, { direction: "row", spacing: 1 }, sliderItems.map(function (item, index) { return /*#__PURE__*/React__default.createElement(Box, { key: index, style: { width: '10px', height: '10px', borderRadius: '50%', backgroundColor: currentItem === index ? 'white' : 'darkgray', cursor: 'pointer' }, onClick: function onClick() { return moveToASpecificItem(item.id); } }); }))); }; SliderIndicator.propTypes = { sliderItems: PropTypes.array, currentItem: PropTypes.number, moveToASpecificItem: PropTypes.func.isRequired }; SliderIndicator.defaultProps = { sliderItems: [], currentItem: 0, moveToASpecificItem: function moveToASpecificItem() {} }; // import "@fontsource/open-sans"; var SliderItem = function SliderItem(_ref) { var id = _ref.id, index = _ref.index, isHidden = _ref.isHidden, video = _ref.video, image = _ref.image, title = _ref.title, description = _ref.description, actions = _ref.actions, onlyItem = _ref.onlyItem, calculateMinWidth = _ref.calculateMinWidth, onClose = _ref.onClose, moveToASpecificItem = _ref.moveToASpecificItem; return /*#__PURE__*/React__default.createElement("div", { key: id, id: id }, isHidden ? /*#__PURE__*/React__default.createElement("div", { style: { width: calculateMinWidth(), minWidth: calculateMinWidth(), height: '550px', minHeight: '550px', marginRight: '30px', marginLeft: '30px' } }) : /*#__PURE__*/React__default.createElement(Card, { key: index, style: _extends({ width: calculateMinWidth(), minWidth: calculateMinWidth(), height: '550px', minHeight: '550px', marginRight: '30px', marginLeft: '30px' }, index === 1 || onlyItem ? { transform: 'scale(1.04)', transition: 'transform 1s 1s' } : { boxShadow: '0 0 10px 0 rgba(0, 0, 0, 0.1)', transition: 'box-shadow 0.5s', backgroundColor: 'white' }, { padding: 0, marginTop: 0, position: 'relative', borderRadius: '15px' }), onClick: function onClick() { return moveToASpecificItem(id); } }, index !== 1 && !onlyItem && /*#__PURE__*/React__default.createElement(Box, { style: { position: 'absolute', top: 0, left: 0, width: '100%', height: '100%', backgroundColor: 'rgba(0, 0, 0, 0.5)', backdropFilter: 'blur(1px)', zIndex: 9, cursor: 'pointer' } }), /*#__PURE__*/React__default.createElement(CardContent, { style: { display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%', width: '100%', marginTop: 0, padding: 0, overflow: 'auto' } }, /*#__PURE__*/React__default.createElement(Box, { style: { position: 'absolute', top: 0, right: 0, margin: '10px', zIndex: 8 } }, /*#__PURE__*/React__default.createElement(IconButton, { onClick: onClose, color: "info" }, /*#__PURE__*/React__default.createElement(Close, null))), /*#__PURE__*/React__default.createElement(Grid, { container: true, spacing: 2, style: { height: '100%', display: 'flex', justifyContent: 'center', alignItems: 'center', paddingTop: 0, marginTop: 0 }, direction: "row" }, (image || video) && /*#__PURE__*/React__default.createElement(Grid, { item: true, xs: window.innerWidth < breakpoints.values.md ? 12 : 7, style: { display: 'flex', justifyContent: 'center', alignItems: 'center', paddingTop: 0, marginTop: 0, height: window.innerWidth < breakpoints.values.md ? 'auto' : '100%' } }, video ? /*#__PURE__*/React__default.createElement("video", { src: video, autoPlay: true, loop: true, muted: true, style: _extends({ width: '100%', height: '100%', minWidth: '100%', minHeight: '100%' }, index !== 1 && { opacity: 0.1 }) }) : /*#__PURE__*/React__default.createElement("img", { src: image, alt: title, style: { width: '100%', height: '100%', objectFit: "fill" } })), /*#__PURE__*/React__default.createElement(Grid, { item: true, xs: window.innerWidth < breakpoints.values.md ? 12 : image || video ? 5 : 12, style: { justifyContent: 'center', alignItems: 'center', height: '100%', padding: image || video ? '20px 40px 20px 40px' : '40px 80px 40px 80px' // top right bottom left } }, /*#__PURE__*/React__default.createElement(Stack, { spacing: 2, direction: "column", justifyContent: "space-between", alignItems: "center", style: { height: '100%' } }, /*#__PURE__*/React__default.createElement(Stack, { spacing: 2, style: { marginTop: 50 } }, /*#__PURE__*/React__default.createElement(Typography, { variant: "h5", fontWeight: "bold", letterSpacing: "-0.6px", fontSize: "24px", fontFamily: "Open Sans" }, title), /*#__PURE__*/React__default.createElement(Typography, { variant: "body2", fontSize: "14px", fontFamily: "Open Sans", fontWeight: "medium", style: { whiteSpace: 'pre-line' } }, description)), actions && /*#__PURE__*/React__default.createElement(Box, { style: { width: '100%', marginBottom: 20 } }, actions))))))); }; SliderItem.propTypes = { id: PropTypes.string.isRequired, onlyItem: PropTypes.bool.isRequired, index: PropTypes.number.isRequired, isHidden: PropTypes.bool, video: PropTypes.string, image: PropTypes.string, title: PropTypes.string, description: PropTypes.string, actions: PropTypes.node, calculateMinWidth: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired, moveToASpecificItem: PropTypes.func.isRequired }; SliderItem.defaultProps = { isHidden: false, onlyItem: false, video: null, image: null, title: '', description: '', actions: null, calculateMinWidth: function calculateMinWidth() {}, onClose: function onClose() {}, moveToASpecificItem: function moveToASpecificItem() {} }; function ReactCardCarousel(_ref) { var open = _ref.open, onClose = _ref.onClose, items = _ref.items; var _useState = useState([]), sliderItems = _useState[0], setSliderItems = _useState[1]; var _useState2 = useState(0), currentItem = _useState2[0], setCurrentItem = _useState2[1]; var _useState3 = useState([]), viewedItems = _useState3[0], setViewedItems = _useState3[1]; useEffect(function () { setSliderItems(items || []); var itemsDeepCopy = [].concat(items); // Deep copy of items // Set viewed sliderItems to 3 var currentViewedItems = [].concat(items && items.length > 1 ? [{ id: 0, content: null, isHidden: true }] : [], itemsDeepCopy.slice(0, 2)); setViewedItems(currentViewedItems); setCurrentItem(0); }, []); var moveToNext = function moveToNext() { var itemsDeepCopy = [].concat(sliderItems); // Deep copy of items if (viewedItems && !viewedItems[0].isHidden) { var currentViewedItems = [].concat(itemsDeepCopy.slice(currentItem, currentItem + 3)); if (currentViewedItems.length < 3) { currentViewedItems.push({ id: 0, content: null, isHidden: true }); } setViewedItems(currentViewedItems); setCurrentItem(currentItem + 1); } else { var _currentViewedItems = [].concat(itemsDeepCopy.slice(0, 3)); if (_currentViewedItems.length < 3) { _currentViewedItems.push({ id: 0, content: null, isHidden: true }); } setViewedItems(_currentViewedItems); setCurrentItem(1); } }; var moveToPrevious = function moveToPrevious() { var _viewedItems$; var itemsDeepCopy = [].concat(sliderItems); // Deep copy of items if (viewedItems && (_viewedItems$ = viewedItems[0]) != null && _viewedItems$.isHidden) { var currentViewedItems = [].concat(itemsDeepCopy.slice(currentItem - 2, currentItem + 1)); if (currentViewedItems.length < 3) { currentViewedItems.unshift({ id: 0, content: null, isHidden: true }); } setViewedItems(currentViewedItems); setCurrentItem(currentItem - 1); } else { if (currentItem === 1) { var _currentViewedItems2 = [{ id: 0, content: null, isHidden: true }].concat(itemsDeepCopy.slice(0, 2)); if (_currentViewedItems2.length < 3) { _currentViewedItems2.push({ id: 0, content: null, isHidden: true }); } setViewedItems(_currentViewedItems2); setCurrentItem(currentItem - 1); } else { var _currentViewedItems3 = [].concat(itemsDeepCopy.slice(currentItem - 2, currentItem + 1)); if (_currentViewedItems3.length < 3) { _currentViewedItems3.unshift({ id: 0, content: null, isHidden: true }); } setViewedItems(_currentViewedItems3); setCurrentItem(currentItem - 1); } } }; var isNextItemAvailable = function isNextItemAvailable() { return currentItem < sliderItems.length - 1; }; var isPreviousItemAvailable = function isPreviousItemAvailable() { var _viewedItems$2; if (viewedItems && (_viewedItems$2 = viewedItems[0]) != null && _viewedItems$2.isHidden) { return currentItem > 1; } return currentItem > 0; }; var calculateMinWidth = function calculateMinWidth() { //currentWidth of screen var width = window.innerWidth; //calculate min width by 80% of current width var minWidth = width * 0.8; if (minWidth > 885) minWidth = 885; if (minWidth < 765) minWidth = width - 80; return minWidth + "px"; }; var moveToASpecificItem = function moveToASpecificItem(id) { //find the index of the item var index = sliderItems.findIndex(function (item) { return item.id === id; }); //if the item is not found, return if (index === -1) return; //if the item is already in the view, return if (index === currentItem) return; //if the item is in the next view if (index > currentItem && index < currentItem + 3) { //move to the next item moveToNext(); return; } //if the item is in the previous view else if (index < currentItem && index > currentItem - 3) { //move to the previous item moveToPrevious(); return; } else { var itemsDeepCopy = [].concat(sliderItems); // Deep copy of items //Get item after the current item var currentViewedItems = [itemsDeepCopy[index - 1] ? itemsDeepCopy[index - 1] : { id: 0, content: null, isHidden: true }, itemsDeepCopy[index], itemsDeepCopy[index + 1] ? itemsDeepCopy[index + 1] : { id: 0, content: null, isHidden: true }]; setViewedItems(currentViewedItems); setCurrentItem(index); } }; return /*#__PURE__*/React__default.createElement(Dialog, { fullScreen: true, open: open, onClose: onClose, style: { backgroundColor: "rgba(255, 255, 255, 0.5)", backdropFilter: "blur( 5px )", padding: 0, margin: 0 }, PaperProps: { style: { backgroundColor: 'transparent', boxShadow: 'none' } } }, /*#__PURE__*/React__default.createElement(Box, { id: "box1", style: { display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh', overflow: 'hidden', width: '100%', backgroundColor: "transparent" } }, /*#__PURE__*/React__default.createElement(Stack, { direction: "column", spacing: 2 }, /*#__PURE__*/React__default.createElement(Box, { id: "box2", style: { display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh', overflow: 'hidden', width: '100%', backgroundColor: "transparent" } }, viewedItems.map(function (item, index) { return /*#__PURE__*/React__default.createElement("div", { key: item.id, id: item.id }, item.isHidden ? /*#__PURE__*/React__default.createElement("div", { style: { width: calculateMinWidth(), minWidth: calculateMinWidth(), height: '550px', minHeight: '550px', marginRight: '30px', marginLeft: '30px' } }) : /*#__PURE__*/React__default.createElement(SliderItem, { onlyItem: viewedItems.length === 1, id: item.id, index: index, isHidden: item.isHidden, video: item.video, image: item.image, title: item.title, description: item.description, actions: item.actions || null, calculateMinWidth: calculateMinWidth, onClose: onClose, moveToASpecificItem: moveToASpecificItem })); })), /*#__PURE__*/React__default.createElement(SliderIndicator, { sliderItems: sliderItems, currentItem: currentItem, moveToASpecificItem: moveToASpecificItem })), /*#__PURE__*/React__default.createElement(SliderActions, { isNextItemAvailable: isNextItemAvailable, isPreviousItemAvailable: isPreviousItemAvailable, moveToNext: moveToNext, moveToPrevious: moveToPrevious }))); } ReactCardCarousel.defaultProps = { open: false, onClose: function onClose() {} }; ReactCardCarousel.propTypes = { open: PropTypes.bool, onClose: PropTypes.func }; var CardCarousel = function CardCarousel(_ref) { var _ref$open = _ref.open, open = _ref$open === void 0 ? false : _ref$open, _ref$onClose = _ref.onClose, onClose = _ref$onClose === void 0 ? function () {} : _ref$onClose, _ref$items = _ref.items, items = _ref$items === void 0 ? [] : _ref$items; return /*#__PURE__*/createElement(ReactCardCarousel, { open: open, onClose: onClose, items: items }); }; CardCarousel.propTypes = { open: PropTypes.bool, onClose: PropTypes.func, items: PropTypes.array }; export { CardCarousel }; //# sourceMappingURL=react-card-carousel-materialui.esm.js.map