UNPKG

@cimpress/react-components

Version:
252 lines (249 loc) 11.8 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Carousel = void 0; const react_1 = __importStar(require("react")); const css_1 = require("@emotion/css"); const colors_1 = require("../colors"); const CarouselSlide_1 = __importDefault(require("./CarouselSlide")); const CarouselControl_1 = __importDefault(require("./CarouselControl")); const CarouselIndicator_1 = __importDefault(require("./CarouselIndicator")); const CarouselLoading_1 = __importDefault(require("./CarouselLoading")); const CarouselFallback_1 = __importDefault(require("./CarouselFallback")); const cvar_1 = __importDefault(require("../theme/cvar")); const THUMBNAIL_WIDTH = 70; const getCarouselWidthForThumbs = (numberOfThumbs) => 40 + THUMBNAIL_WIDTH * numberOfThumbs; const sizeMap = { xs: { maxThumbs: 3, pxWidth: getCarouselWidthForThumbs(3) }, s: { maxThumbs: 4, pxWidth: getCarouselWidthForThumbs(4) }, m: { maxThumbs: 5, pxWidth: getCarouselWidthForThumbs(5) }, l: { maxThumbs: 6, pxWidth: getCarouselWidthForThumbs(6) }, xl: { maxThumbs: 7, pxWidth: getCarouselWidthForThumbs(7) }, }; const carouselCss = (0, css_1.css) ` position: relative; div { height: 100%; } `; const slideCss = (0, css_1.css) ` border: 1px solid ${(0, cvar_1.default)('color-border-light')}; background-color: ${(0, cvar_1.default)('color-background')}; height: 100%; `; const carouselInnerCss = (0, css_1.css) ` position: relative; width: 100%; overflow: hidden; img { margin: auto; max-height: 100%; width: auto; height: auto; position: absolute; top: 0; bottom: 0; left: 0; right: 0; display: block; max-width: 100%; line-height: 1; } `; const carouselNavigationCss = (0, css_1.css) ` margin-top: 25px; display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; -ms-flex-pack: justify; justify-content: space-between; `; const carouselNavigationSmallCss = (0, css_1.css) ` margin-top: 16px; `; const carouselNavigationVerticalCss = (0, css_1.css) ` margin-top: 0; margin-right: 25px; -ms-flex-direction: column; flex-direction: column; -ms-flex-pack: start; justify-content: flex-start; `; const carouselIndicatorsCss = (0, css_1.css) ` position: relative; bottom: 0; left: 0; margin: 0; width: auto; line-height: 0; overflow: hidden; height: 70px; display: -ms-flexbox; display: flex; -ms-flex-wrap: nowrap; flex-wrap: nowrap; z-index: 15; padding-left: 0; text-align: center; list-style: none; flex: 1; li { transition: 0.6s ease-in-out all; -ms-flex-negative: 0; flex-shrink: 0; margin: 5px; width: 60px; height: 60px; background-color: ${(0, cvar_1.default)('color-background')}; border-radius: 0; overflow: hidden; text-indent: 0; position: relative; display: inline-block; cursor: pointer; img { margin: auto; max-height: 100%; max-width: 100%; width: auto; height: auto; position: absolute; top: 0; bottom: 0; left: 0; right: 0; } } `; const smallCss = (0, css_1.css) ` font-size: 85%; width: 100%; `; const Carousel = (_a) => { var { loading, size = 'm', pxSize = 200, minimal = false, children, onCarouselClick, fallbackPreview = react_1.default.createElement(CarouselFallback_1.default, null), hideIndicators = false, showZoomOverlay = false, zoomOverlayContent, className, style, landscape = false, currentSlide = 0, onSlideChanged } = _a, rest = __rest(_a, ["loading", "size", "pxSize", "minimal", "children", "onCarouselClick", "fallbackPreview", "hideIndicators", "showZoomOverlay", "zoomOverlayContent", "className", "style", "landscape", "currentSlide", "onSlideChanged"]); const total = react_1.default.Children.count(children); const pixels = size && !minimal ? sizeMap[size].pxWidth : pxSize; const allowNavigation = (minimal && total > 1) || (!minimal && total > sizeMap[size].maxThumbs); const isLandscape = minimal ? false : landscape; /** * State and control for slides */ const [slideState, setSlideState] = (0, react_1.useState)({ currentSlide: currentSlide > total - 1 ? 0 : currentSlide, previousSlide: null, transitioning: false, timer: null, direction: '', }); (0, react_1.useEffect)(() => { setSlideState(previousState => { if (currentSlide !== undefined && previousState.currentSlide !== currentSlide) { const slideNumber = currentSlide < 0 || currentSlide >= total ? previousState.currentSlide : currentSlide; return Object.assign(Object.assign({}, previousState), { currentSlide: slideNumber }); } return previousState; }); }, [currentSlide, total]); const clearPendingAnimation = () => { if (slideState.timer) { clearTimeout(slideState.timer); } }; const endAnimation = () => window.setTimeout(() => setSlideState(prevState => (Object.assign(Object.assign({}, prevState), { previousSlide: null, transitioning: false }))), 600); const goToSlide = (nextSlide, direction) => { if (nextSlide === slideState.currentSlide) { return; } clearPendingAnimation(); setSlideState(prevState => (Object.assign(Object.assign({}, prevState), { direction: direction || (nextSlide > slideState.currentSlide ? 'next' : 'prev'), previousSlide: prevState.currentSlide, currentSlide: nextSlide, transitioning: true, timer: endAnimation() }))); onSlideChanged && onSlideChanged(nextSlide); }; const goToNextSlide = () => { let nextSlide = slideState.currentSlide + 1; if (nextSlide >= react_1.default.Children.count(children)) { nextSlide = 0; } goToSlide(nextSlide, 'next'); }; const goToPreviousSlide = () => { const nextSlide = slideState.currentSlide > 0 ? slideState.currentSlide - 1 : react_1.default.Children.count(children) - 1; goToSlide(nextSlide, 'prev'); }; /** * State and controls for thumbnails */ const [thumbsPosition, setThumbsPosition] = (0, react_1.useState)(0); const goToThumbs = (direction) => { let newThumbsPosition = thumbsPosition; const totalLength = react_1.default.Children.count(children) * THUMBNAIL_WIDTH; const thumbsWidth = sizeMap[size].maxThumbs * THUMBNAIL_WIDTH; const loopPosition = direction === 'next' ? 0 : (Math.floor(totalLength / thumbsWidth) - 1) * thumbsWidth * -1; direction === 'next' ? (newThumbsPosition -= thumbsWidth) : (newThumbsPosition += thumbsWidth); newThumbsPosition = Math.abs(newThumbsPosition) >= totalLength || newThumbsPosition > 0 ? loopPosition : newThumbsPosition; setThumbsPosition(newThumbsPosition); }; const goToNextThumbs = () => goToThumbs('next'); const goToPreviousThumbs = () => goToThumbs('prev'); const slides = react_1.default.Children.map(children, (child, i) => (react_1.default.createElement(CarouselSlide_1.default, { active: i === slideState.currentSlide, index: i, animateOut: i === slideState.previousSlide && slideState.transitioning, animateIn: i === slideState.currentSlide && slideState.previousSlide !== null && slideState.transitioning, direction: slideState.direction, onCarouselClick: onCarouselClick, showZoomOverlay: showZoomOverlay, zoomOverlayContent: zoomOverlayContent }, child))); const componentStyle = isLandscape ? { height: `${pixels}px`, display: 'flex', flexDirection: 'row-reverse', width: 'fit-content' } : { width: `${pixels}px` }; return (react_1.default.createElement("div", Object.assign({ className: (0, css_1.cx)('crc-carousel', className), style: Object.assign(Object.assign({}, componentStyle), style) }, rest), react_1.default.createElement("div", { style: isLandscape ? { width: `${pixels}px` } : { height: `${pixels}px` } }, react_1.default.createElement("div", { className: (0, css_1.cx)(carouselCss, slideCss) }, react_1.default.createElement("div", { className: carouselInnerCss, role: "listbox" }, loading ? react_1.default.createElement(CarouselLoading_1.default, { size: pixels }) : slides && slides.length ? slides : fallbackPreview))), !hideIndicators && (react_1.default.createElement("div", { className: (0, css_1.cx)(carouselNavigationCss, { [carouselNavigationSmallCss]: minimal, [carouselNavigationVerticalCss]: isLandscape, }) }, react_1.default.createElement(CarouselControl_1.default, { disabled: !allowNavigation, onClick: minimal ? goToPreviousSlide : goToPreviousThumbs, large: !minimal, direction: isLandscape ? 'up' : 'left', hintText: "Previous" }), react_1.default.createElement("ol", { className: (0, css_1.cx)(carouselIndicatorsCss, { [(0, css_1.css) ` flex-direction: column; `]: isLandscape, [(0, css_1.css) ` justify-content: center; `]: !total, }), style: minimal ? { height: 'auto', overflow: 'visible' } : {} }, total && !minimal ? (react_1.default.Children.map(children, (child, i) => (react_1.default.createElement(CarouselIndicator_1.default, { slideNumber: i, active: slideState.currentSlide === i, goToSlide: goToSlide, offset: isLandscape ? { top: thumbsPosition } : { left: thumbsPosition } }, loading ? null : child)))) : minimal ? (react_1.default.createElement("div", { className: smallCss }, total > 0 ? `${slideState.currentSlide + 1} / ${total}` : '– / –')) : (react_1.default.createElement("li", { style: { backgroundColor: colors_1.horizon } }))), react_1.default.createElement(CarouselControl_1.default, { disabled: !allowNavigation, onClick: minimal ? goToNextSlide : goToNextThumbs, large: !minimal, direction: isLandscape ? 'down' : 'right', hintText: "Next" }))))); }; exports.Carousel = Carousel; //# sourceMappingURL=Carousel.js.map