@cimpress/react-components
Version:
React components to support the MCP styleguide
252 lines (249 loc) • 11.8 kB
JavaScript
;
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