@yamada-ui/react
Version:
React UI components of the Yamada, by the Yamada, for the Yamada built with React and Emotion
118 lines (114 loc) • 3.51 kB
JavaScript
"use client";
import { useSafeLayoutEffect } from "../../utils/effect.js";
import { mergeRefs } from "../../utils/ref.js";
import { utils_exports } from "../../utils/index.js";
import { useCallback, useEffect, useId, useMemo, useRef, useState } from "react";
//#region src/components/scroll-area/use-scroll-area.ts
const useScrollArea = ({ id, ref, type = "hover", scrollHideDelay = 1e3, onScrollPositionChange,...rest } = {}) => {
const [isHovered, setIsHovered] = useState(false);
const [isScrolling, setIsScrolling] = useState(false);
const isAlways = type === "always";
const isNever = type === "never";
const isHidden = !isAlways && !isHovered && !isScrolling;
const isSafari = (0, utils_exports.isMac)() && (0, utils_exports.vendor)(/apple/i);
const uuid = useId();
const key = `${id ?? uuid}-${isHovered}-${isScrolling}`;
const hoverTimeout = useRef(void 0);
const scrollTimeout = useRef(void 0);
const scrollAreaRef = useRef(null);
const scrollPosition = useRef({
x: 0,
y: 0
});
useSafeLayoutEffect(() => {
if (!scrollAreaRef.current || !isSafari) return;
scrollAreaRef.current.scrollLeft = scrollPosition.current.x;
scrollAreaRef.current.scrollTop = scrollPosition.current.y;
});
const onMouseEnter = useCallback(() => {
if (type !== "hover") return;
clearTimeout(hoverTimeout.current);
setIsHovered(true);
}, [type]);
const onMouseLeave = useCallback(() => {
if (type !== "hover") return;
hoverTimeout.current = setTimeout(() => setIsHovered(false), scrollHideDelay);
}, [scrollHideDelay, type]);
const onScroll = useCallback((ev) => {
const { scrollLeft: x, scrollTop: y } = ev.target;
const { x: prevX, y: prevY } = scrollPosition.current;
const isEqual = Math.abs(x - prevX) <= 5 && Math.abs(y - prevY) <= 5;
onScrollPositionChange?.({
x,
y
});
scrollPosition.current = {
x,
y
};
if (type !== "scroll" || isEqual) return;
if (!isScrolling) setIsScrolling(true);
clearTimeout(scrollTimeout.current);
scrollTimeout.current = setTimeout(() => setIsScrolling(false), scrollHideDelay);
}, [
isScrolling,
onScrollPositionChange,
scrollHideDelay,
type
]);
useEffect(() => {
return () => {
if (hoverTimeout.current) clearTimeout(hoverTimeout.current);
if (scrollTimeout.current) clearTimeout(scrollTimeout.current);
};
}, []);
const safariProps = useMemo(() => ({
key,
ref: mergeRefs(ref, scrollAreaRef),
"data-key": key
}), [
key,
ref,
scrollAreaRef
]);
return {
isAlways,
isHidden,
isHovered,
isNever,
isScrolling,
getRootProps: useCallback(({ style,...props } = {}) => ({
ref,
style: {
overflow: "auto",
...style
},
...rest,
...isSafari ? safariProps : {},
...props,
"data-hidden": (0, utils_exports.dataAttr)(isHidden),
"data-hover": (0, utils_exports.dataAttr)(isHovered),
"data-never": (0, utils_exports.dataAttr)(isNever),
"data-scroll": (0, utils_exports.dataAttr)(isScrolling),
tabIndex: 0,
onMouseEnter: (0, utils_exports.handlerAll)(props.onMouseEnter, rest.onMouseEnter, onMouseEnter),
onMouseLeave: (0, utils_exports.handlerAll)(props.onMouseLeave, rest.onMouseLeave, onMouseLeave),
onScroll: (0, utils_exports.handlerAll)(props.onScroll, rest.onScroll, onScroll)
}), [
isNever,
ref,
isHidden,
isHovered,
isScrolling,
isSafari,
safariProps,
rest,
onMouseEnter,
onMouseLeave,
onScroll
])
};
};
//#endregion
export { useScrollArea };
//# sourceMappingURL=use-scroll-area.js.map