@hitachivantara/uikit-react-core
Version:
Core React components for the NEXT Design System.
228 lines (227 loc) • 8.42 kB
JavaScript
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const jsxRuntime = require("react/jsx-runtime");
const React = require("react");
const useCarousel = require("embla-carousel-react");
const uikitReactUtils = require("@hitachivantara/uikit-react-utils");
const useLabels = require("../hooks/useLabels.cjs");
const icons = require("../icons.cjs");
const Carousel_styles = require("./Carousel.styles.cjs");
const CarouselControls = require("./CarouselControls.cjs");
const CarouselThumbnails = require("./CarouselThumbnails.cjs");
const Container = require("../Container/Container.cjs");
const Button = require("../Button/Button.cjs");
const IconButton = require("../IconButton/IconButton.cjs");
const Typography = require("../Typography/Typography.cjs");
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
const useCarousel__default = /* @__PURE__ */ _interopDefault(useCarousel);
const DEFAULT_LABELS = {
close: "Close",
fullscreen: "Fullscreen",
backwards: "Backwards",
forwards: "Forwards"
};
const HvCarousel = React.forwardRef(function HvCarousel2(props, ref) {
const {
className,
classes: classesProp,
height: heightProp = "auto",
thumbnailWidth = 90,
title,
children,
actions: actionsProp,
xs,
showDots: showDotsProp,
showCounter: showCounterProp,
showSlideControls,
showFullscreen: showFullscreenProp,
hideThumbnails: hideThumbnailsProp,
controlsPosition: controlsPositionProp,
thumbnailsPosition: thumbnailsPositionProp,
labels: labelsProps,
carouselOptions,
renderThumbnail,
onChange,
onFullscreen,
...others
} = uikitReactUtils.useDefaultProps("HvCarousel", props);
const { activeTheme } = uikitReactUtils.useTheme();
const { classes, css, cx } = Carousel_styles.useClasses(classesProp);
const labels = useLabels.useLabels(DEFAULT_LABELS, labelsProps);
const thumbnailsRef = React.useRef(null);
const [isFullscreen, setIsFullscreen] = React.useState(false);
const isDs3 = activeTheme?.base === "ds3";
const actionsPosition = isDs3 ? "header" : "controls";
const controlsPosition = controlsPositionProp ?? (isDs3 ? "bottom" : "top");
const thumbnailsPosition = thumbnailsPositionProp ?? "bottom";
const [containerRef, controller] = useCarousel__default.default({
align: "start",
loop: true,
...carouselOptions
});
const [selectedIndex, setSelectedIndex] = React.useState(
carouselOptions?.startIndex ?? 0
);
const numSlides = React.Children.count(children);
const handlePrevious = React.useCallback(() => {
controller?.scrollPrev();
}, [controller]);
const handleNext = React.useCallback(() => {
controller?.scrollNext();
}, [controller]);
const handleScroll = (index) => {
controller?.scrollTo(index);
};
const handleSelect = React.useCallback(() => {
if (!controller) return;
const slideIndex = controller.selectedScrollSnap();
setSelectedIndex(slideIndex);
thumbnailsRef.current?.querySelectorAll("button")?.[slideIndex]?.scrollIntoView({
behavior: "smooth",
block: "nearest"
});
onChange?.(slideIndex);
}, [controller, onChange]);
React.useEffect(() => {
if (!controller) return;
controller.on("select", handleSelect);
return () => {
controller.off("select", handleSelect);
};
}, [controller, handleSelect]);
React.useEffect(() => {
if (!controller) return;
controller.reInit();
setSelectedIndex((currentIndex) => uikitReactUtils.clamp(currentIndex, numSlides));
}, [numSlides, controller]);
const handleFullscreen = (event) => {
onFullscreen?.(event, !isFullscreen);
setIsFullscreen((curr) => !curr);
};
const canPrev = controller?.canScrollPrev() ?? false;
const canNext = controller?.canScrollNext() ?? false;
const showTitle = !!title && (!xs || isFullscreen);
const showFullscreen = showFullscreenProp ?? xs;
const height = isFullscreen ? "100%" : heightProp ?? "auto";
const showCounter = xs;
const hideThumbnails = hideThumbnailsProp ?? (xs && !isFullscreen);
const showThumbnails = !hideThumbnails && !!renderThumbnail;
const showDots = showDotsProp ?? numSlides <= 5;
const actions = /* @__PURE__ */ jsxRuntime.jsxs(
"div",
{
className: cx(
classes.actions,
actionsPosition === "header" ? css({ position: "relative", top: -40, height: 0 }) : css({ position: "absolute" })
),
children: [
actionsProp,
showFullscreen && /* @__PURE__ */ jsxRuntime.jsx(
IconButton.HvIconButton,
{
title: isFullscreen ? labels.close : labels.fullscreen,
onClick: handleFullscreen,
className: classes.closeButton,
children: /* @__PURE__ */ jsxRuntime.jsx(icons.HvIcon, { name: isFullscreen ? "Close" : "Fullscreen" })
}
)
]
}
);
const controls = /* @__PURE__ */ jsxRuntime.jsx(
CarouselControls.HvCarouselControls,
{
classes,
showDots,
page: selectedIndex,
pages: numSlides,
canPrevious: canPrev,
canNext,
onPreviousClick: handlePrevious,
onNextClick: handleNext,
actions: actionsPosition === "controls" && actions,
labels: {
backwards: labels.backwards,
forwards: labels.forwards
}
}
);
const thumbnails = showThumbnails && /* @__PURE__ */ jsxRuntime.jsx(
CarouselThumbnails.HvCarouselThumbnails,
{
classes,
ref: thumbnailsRef,
page: selectedIndex,
pages: numSlides,
width: thumbnailWidth,
onThumbnailClick: (evt, i) => handleScroll(i),
renderThumbnail
}
);
return /* @__PURE__ */ jsxRuntime.jsxs(
Container.HvContainer,
{
ref,
className: cx(classes.root, className, {
[classes.xs]: xs,
[classes.fullscreen]: isFullscreen
}),
...others,
children: [
showTitle && /* @__PURE__ */ jsxRuntime.jsx(Typography.HvTypography, { variant: "title2", className: classes.title, children: title }),
actionsPosition === "header" && actions,
thumbnailsPosition === "top" && thumbnails,
controlsPosition === "top" && controls,
/* @__PURE__ */ jsxRuntime.jsxs(
"div",
{
className: cx(classes.main, {
[classes.mainXs]: xs,
[classes.mainFullscreen]: isFullscreen
}),
children: [
showCounter && /* @__PURE__ */ jsxRuntime.jsx("div", { className: classes.counterContainer, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: classes.counter, children: `${selectedIndex + 1}/${numSlides}` }) }),
showSlideControls && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: classes.slideControls, children: [
/* @__PURE__ */ jsxRuntime.jsx(
Button.HvButton,
{
icon: true,
disabled: !canPrev,
variant: "secondarySubtle",
"aria-label": labels.backwards,
onClick: handlePrevious,
children: /* @__PURE__ */ jsxRuntime.jsx(icons.HvIcon, { name: "Backwards", size: "xs" })
}
),
/* @__PURE__ */ jsxRuntime.jsx(
Button.HvButton,
{
icon: true,
disabled: !canNext,
variant: "secondarySubtle",
"aria-label": labels.forwards,
onClick: handleNext,
children: /* @__PURE__ */ jsxRuntime.jsx(icons.HvIcon, { name: "Forwards", size: "xs" })
}
)
] }),
/* @__PURE__ */ jsxRuntime.jsx(
"div",
{
ref: containerRef,
style: { height },
className: classes.slidesViewport,
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: classes.slidesContainer, children })
}
)
]
}
),
controlsPosition === "bottom" && controls,
thumbnailsPosition === "bottom" && thumbnails
]
}
);
});
exports.carouselClasses = Carousel_styles.staticClasses;
exports.HvCarousel = HvCarousel;