UNPKG

@mantine/hooks

Version:

A collection of 50+ hooks for state and UI management

132 lines (131 loc) 4.58 kB
"use client"; let react = require("react"); //#region packages/@mantine/hooks/src/use-scroller/use-scroller.ts function useScroller(options = {}) { const { scrollAmount = 200, draggable = true, onScrollStateChange } = options; const containerRef = (0, react.useRef)(null); const [canScrollStart, setCanScrollStart] = (0, react.useState)(false); const [canScrollEnd, setCanScrollEnd] = (0, react.useState)(false); const [isDragging, setIsDragging] = (0, react.useState)(false); const isDraggingRef = (0, react.useRef)(false); const hasDraggedRef = (0, react.useRef)(false); const startX = (0, react.useRef)(0); const scrollLeftStart = (0, react.useRef)(0); const onScrollStateChangeRef = (0, react.useRef)(onScrollStateChange); onScrollStateChangeRef.current = onScrollStateChange; const updateScrollState = (0, react.useCallback)(() => { const container = containerRef.current; if (container) { const { scrollLeft, scrollWidth, clientWidth } = container; const isRtl = getComputedStyle(container).direction === "rtl"; let newCanScrollStart; let newCanScrollEnd; if (isRtl) { newCanScrollStart = scrollLeft < 0; newCanScrollEnd = scrollLeft > -(scrollWidth - clientWidth); } else { newCanScrollStart = scrollLeft > 0; newCanScrollEnd = scrollLeft < scrollWidth - clientWidth - 1; } setCanScrollStart(newCanScrollStart); setCanScrollEnd(newCanScrollEnd); onScrollStateChangeRef.current?.({ canScrollStart: newCanScrollStart, canScrollEnd: newCanScrollEnd }); } }, []); (0, react.useEffect)(() => { updateScrollState(); const container = containerRef.current; if (container) { container.addEventListener("scroll", updateScrollState); const resizeObserver = new ResizeObserver(updateScrollState); resizeObserver.observe(container); return () => { container.removeEventListener("scroll", updateScrollState); resizeObserver.disconnect(); }; } }, [updateScrollState]); const scroll = (0, react.useCallback)((direction) => { const container = containerRef.current; if (container) { const isRtl = getComputedStyle(container).direction === "rtl"; const amount = scrollAmount; const scrollBy = direction === "end" ? amount : -amount; const adjustedScrollBy = isRtl ? -scrollBy : scrollBy; container.scrollBy({ left: adjustedScrollBy, behavior: "smooth" }); } }, [scrollAmount]); const scrollStart = (0, react.useCallback)(() => scroll("start"), [scroll]); const scrollEnd = (0, react.useCallback)(() => scroll("end"), [scroll]); const handleMouseDown = (0, react.useCallback)((event) => { if (!draggable) return; const container = containerRef.current; if (container) { isDraggingRef.current = true; hasDraggedRef.current = false; setIsDragging(true); startX.current = event.pageX - container.offsetLeft; scrollLeftStart.current = container.scrollLeft; container.style.cursor = "grabbing"; container.style.userSelect = "none"; } }, [draggable]); const handleMouseMove = (0, react.useCallback)((event) => { if (!isDraggingRef.current) return; event.preventDefault(); const container = containerRef.current; if (container) { const walk = event.pageX - container.offsetLeft - startX.current; if (Math.abs(walk) > 5) hasDraggedRef.current = true; container.scrollLeft = scrollLeftStart.current - walk; } }, []); const handleMouseUp = (0, react.useCallback)(() => { const wasDragged = hasDraggedRef.current; isDraggingRef.current = false; hasDraggedRef.current = false; setIsDragging(false); const container = containerRef.current; if (container) { container.style.cursor = ""; container.style.userSelect = ""; if (wasDragged) { const suppressClick = (event) => { event.stopPropagation(); event.preventDefault(); container.removeEventListener("click", suppressClick, true); }; container.addEventListener("click", suppressClick, true); } } }, []); const handleMouseLeave = (0, react.useCallback)(() => { if (isDraggingRef.current) handleMouseUp(); }, [handleMouseUp]); return { ref: (0, react.useCallback)((node) => { containerRef.current = node; if (node) updateScrollState(); }, [updateScrollState]), canScrollStart, canScrollEnd, scrollStart, scrollEnd, isDragging, dragHandlers: { onMouseDown: handleMouseDown, onMouseMove: handleMouseMove, onMouseUp: handleMouseUp, onMouseLeave: handleMouseLeave } }; } //#endregion exports.useScroller = useScroller; //# sourceMappingURL=use-scroller.cjs.map