@yamada-ui/react
Version:
React UI components of the Yamada, by the Yamada, for the Yamada built with React and Emotion
305 lines (301 loc) • 9.52 kB
JavaScript
"use client";
const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
const require_context = require('../../utils/context.cjs');
const require_dom = require('../../utils/dom.cjs');
const require_effect = require('../../utils/effect.cjs');
const require_ref = require('../../utils/ref.cjs');
const require_utils_index = require('../../utils/index.cjs');
const require_hooks_use_controllable_state_index = require('../../hooks/use-controllable-state/index.cjs');
const require_i18n_provider = require('../../providers/i18n-provider/i18n-provider.cjs');
const require_hooks_use_boolean_index = require('../../hooks/use-boolean/index.cjs');
let react = require("react");
react = require_rolldown_runtime.__toESM(react);
let embla_carousel_react = require("embla-carousel-react");
embla_carousel_react = require_rolldown_runtime.__toESM(embla_carousel_react);
//#region src/components/carousel/use-carousel.ts
const [CarouselContext, useCarouselContext] = require_context.createContext({ name: "CarouselContext" });
const useCarousel = ({ id, align = "center", autoplay = false, containScroll = false, controlRef, defaultIndex = 0, delay = 4e3, dragFree = false, draggable = true, duration = 25, index: indexProp, inViewThreshold = 0, loop = true, orientation = "horizontal", plugins = [], skipSnaps = false, slidesToScroll = 1, stopMouseEnterAutoplay = true, watchDrag = draggable, watchResize: watchResizeProp = true, watchSlides = true, onChange, onScrollProgress,...rest } = {}) => {
const { t } = require_i18n_provider.useI18n("carousel");
const [index, setIndex] = require_hooks_use_controllable_state_index.useControllableState({
defaultValue: defaultIndex,
value: indexProp,
onChange
});
const [rootId, listId] = require_dom.useIds();
const [hover, { off: onMouseLeave, on: onMouseEnter }] = require_hooks_use_boolean_index.useBoolean();
const timeoutId = (0, react.useRef)(null);
const indicatorMapRef = (0, react.useRef)(/* @__PURE__ */ new Map());
const listRef = (0, react.useRef)(null);
const horizontal = orientation === "horizontal";
const axis = horizontal ? "x" : "y";
const [snapCount, setSnapCount] = (0, react.useState)(0);
const [total, setTotal] = (0, react.useState)(0);
const watchResize = (0, react.useCallback)((methods, entries) => {
const result = (0, require_utils_index.utils_exports.isFunction)(watchResizeProp) ? watchResizeProp(methods, entries) : true;
const snapCount$1 = methods.scrollSnapList().length;
const total$1 = methods.slideNodes().length;
setSnapCount(snapCount$1);
setTotal(total$1);
return result;
}, [watchResizeProp]);
const [carouselRef, carousel] = (0, embla_carousel_react.default)({
align,
axis,
container: listRef.current,
containScroll,
dragFree,
duration,
inViewThreshold,
loop,
skipSnaps,
slidesToScroll,
startIndex: defaultIndex,
watchDrag,
watchResize,
watchSlides
}, plugins);
id ??= rootId;
const onInit = (0, react.useCallback)((methods) => {
const snapCount$1 = methods.scrollSnapList().length;
const total$1 = methods.slideNodes().length;
setSnapCount(snapCount$1);
setTotal(total$1);
}, []);
const onScroll = (0, react.useCallback)(() => {
if (!carousel) return;
const progress = Math.round(Math.max(0, Math.min(1, carousel.scrollProgress())) * 100);
onScrollProgress?.(progress);
}, [carousel, onScrollProgress]);
const onSelect = (0, react.useCallback)(() => {
if (!carousel) return;
setIndex(carousel.selectedScrollSnap());
}, [carousel, setIndex]);
const onFocusIndicator = (0, react.useCallback)((index$1) => {
indicatorMapRef.current.get(index$1)?.focus();
carousel?.scrollTo(index$1);
}, [carousel]);
const onKeyDown = (0, react.useCallback)((index$1) => (ev) => {
const lastIndex = snapCount - 1;
require_dom.runKeyAction(ev, {
ArrowDown: () => {
if (horizontal) return;
index$1 = index$1 === lastIndex ? 0 : index$1 + 1;
onFocusIndicator(index$1);
},
ArrowLeft: () => {
if (!horizontal) return;
index$1 = index$1 === 0 ? lastIndex : index$1 - 1;
onFocusIndicator(index$1);
},
ArrowRight: () => {
if (!horizontal) return;
index$1 = index$1 === lastIndex ? 0 : index$1 + 1;
onFocusIndicator(index$1);
},
ArrowUp: () => {
if (horizontal) return;
index$1 = index$1 === 0 ? lastIndex : index$1 - 1;
onFocusIndicator(index$1);
},
End: () => {
onFocusIndicator(lastIndex);
},
Home: () => {
onFocusIndicator(0);
}
});
}, [
snapCount,
horizontal,
onFocusIndicator
]);
require_ref.assignRef(controlRef, carousel);
(0, react.useEffect)(() => {
if (carousel) {
carousel.on("reInit", onInit);
carousel.on("select", onSelect);
carousel.on("scroll", onScroll);
onScroll();
return () => {
carousel.off("reInit", onInit);
carousel.off("select", onSelect);
carousel.off("scroll", onScroll);
};
}
}, [
carousel,
onInit,
onScroll,
onSelect
]);
(0, react.useEffect)(() => {
const stop = hover && stopMouseEnterAutoplay;
const last = !carousel?.canScrollNext();
if (carousel && autoplay && !stop && !last) timeoutId.current = setInterval(() => {
carousel.scrollNext();
}, delay);
else {
if (timeoutId.current) clearInterval(timeoutId.current);
timeoutId.current = null;
}
return () => {
if (timeoutId.current) clearInterval(timeoutId.current);
};
}, [
autoplay,
carousel,
delay,
hover,
stopMouseEnterAutoplay
]);
require_effect.useUpdateEffect(() => {
if (!carousel) return;
if (indexProp === void 0) return;
carousel.scrollTo(indexProp);
}, [indexProp]);
require_effect.useUpdateEffect(() => {
if (!carousel) return;
carousel.reInit();
}, [
carousel,
total,
align,
axis,
containScroll,
dragFree,
duration,
inViewThreshold,
loop,
skipSnaps,
slidesToScroll
]);
const getRootProps = (0, react.useCallback)(({ ref,...props } = {}) => ({
id,
"aria-roledescription": "carousel",
"data-orientation": orientation,
...rest,
...props,
ref: require_ref.mergeRefs(ref, rest.ref, carouselRef),
onMouseEnter: (0, require_utils_index.utils_exports.handlerAll)(props.onMouseEnter, onMouseEnter),
onMouseLeave: (0, require_utils_index.utils_exports.handlerAll)(props.onMouseLeave, onMouseLeave)
}), [
id,
onMouseEnter,
onMouseLeave,
rest,
carouselRef,
orientation
]);
const getListProps = (0, react.useCallback)(({ ref,...props } = {}) => ({
id: listId,
"aria-live": autoplay ? "off" : "polite",
"data-orientation": orientation,
...props,
ref: require_ref.mergeRefs(ref, listRef)
}), [
autoplay,
listId,
orientation
]);
const getItemProps = (0, react.useCallback)(({ index: indexProp$1,...props }) => {
const page = indexProp$1 + 1;
const selected = index === indexProp$1;
return {
id: `${listId}-${indexProp$1}`,
"aria-label": t("{page} of {total}", {
page,
total
}),
"aria-roledescription": "slide",
"data-index": indexProp$1.toString(),
"data-orientation": orientation,
"data-selected": (0, require_utils_index.utils_exports.dataAttr)(selected),
role: "tabpanel",
...props
};
}, [
index,
listId,
total,
orientation,
t
]);
const getPrevTriggerProps = (0, react.useCallback)((props = {}) => ({
"aria-controls": listId,
"aria-label": t("Go to previous slide"),
"data-orientation": orientation,
disabled: !carousel?.canScrollPrev(),
...props,
onClick: (0, require_utils_index.utils_exports.handlerAll)(props.onClick, () => carousel?.scrollPrev())
}), [
carousel,
listId,
orientation,
t
]);
const getNextTriggerProps = (0, react.useCallback)((props = {}) => ({
"aria-controls": listId,
"aria-label": t("Go to next slide"),
"data-orientation": orientation,
disabled: !carousel?.canScrollNext(),
...props,
onClick: (0, require_utils_index.utils_exports.handlerAll)(props.onClick, () => carousel?.scrollNext())
}), [
carousel,
listId,
orientation,
t
]);
const getIndicatorsProps = (0, react.useCallback)((props = {}) => ({
"aria-label": t("Slides"),
"aria-orientation": orientation,
role: "tablist",
...props
}), [orientation, t]);
return {
carousel,
index,
setIndex,
snapCount,
total,
getIndicatorProps: (0, react.useCallback)(({ ref, index: indexProp$1,...props }) => {
const page = indexProp$1 + 1;
const selected = index === indexProp$1;
return {
type: "button",
"aria-controls": `${listId}-${indexProp$1}`,
"aria-label": t("Go to {page} slide", { page }),
"aria-selected": selected,
"data-index": indexProp$1.toString(),
"data-orientation": orientation,
"data-selected": (0, require_utils_index.utils_exports.dataAttr)(selected),
role: "tab",
tabIndex: selected ? 0 : -1,
...props,
ref: require_ref.mergeRefs(ref, (node) => {
indicatorMapRef.current.set(indexProp$1, node);
}),
onClick: (0, require_utils_index.utils_exports.handlerAll)(props.onClick, () => carousel?.scrollTo(indexProp$1)),
onKeyDown: (0, require_utils_index.utils_exports.handlerAll)(props.onKeyDown, onKeyDown(indexProp$1))
};
}, [
index,
listId,
t,
orientation,
onKeyDown,
carousel
]),
getIndicatorsProps,
getItemProps,
getListProps,
getNextTriggerProps,
getPrevTriggerProps,
getRootProps
};
};
//#endregion
exports.CarouselContext = CarouselContext;
exports.useCarousel = useCarousel;
exports.useCarouselContext = useCarouselContext;
//# sourceMappingURL=use-carousel.cjs.map