UNPKG

ivt

Version:

Ivt Components Library

788 lines (784 loc) 33.2 kB
import * as React from 'react'; import React__default from 'react'; import { P as Primitive } from './index-DgKlJYZP.mjs'; import { P as Presence } from './index-C6s8KI_8.mjs'; import { c as createContextScope } from './index-DT8WgpCS.mjs'; import { u as useComposedRefs } from './index-1tQVI0Jh.mjs'; import { u as useCallbackRef } from './index-Cbm3--wc.mjs'; import { u as useDirection } from './index-CGLjQEjG.mjs'; import { u as useLayoutEffect2 } from './index-DKOlG3mh.mjs'; import { c as clamp } from './index-GgS4otoq.mjs'; import { c as composeEventHandlers } from './index-Bl-WJHvp.mjs'; import { jsx, jsxs, Fragment } from 'react/jsx-runtime'; import { c as cn } from './utils-05LlW3Cl.mjs'; function useStateMachine(initialState, machine) { return React.useReducer((state, event)=>{ const nextState = machine[state][event]; return nextState ?? state; }, initialState); } var SCROLL_AREA_NAME = "ScrollArea"; var [createScrollAreaContext] = createContextScope(SCROLL_AREA_NAME); var [ScrollAreaProvider, useScrollAreaContext] = createScrollAreaContext(SCROLL_AREA_NAME); var ScrollArea$1 = React.forwardRef((props, forwardedRef)=>{ const { __scopeScrollArea, type = "hover", dir, scrollHideDelay = 600, ...scrollAreaProps } = props; const [scrollArea, setScrollArea] = React.useState(null); const [viewport, setViewport] = React.useState(null); const [content, setContent] = React.useState(null); const [scrollbarX, setScrollbarX] = React.useState(null); const [scrollbarY, setScrollbarY] = React.useState(null); const [cornerWidth, setCornerWidth] = React.useState(0); const [cornerHeight, setCornerHeight] = React.useState(0); const [scrollbarXEnabled, setScrollbarXEnabled] = React.useState(false); const [scrollbarYEnabled, setScrollbarYEnabled] = React.useState(false); const composedRefs = useComposedRefs(forwardedRef, (node)=>setScrollArea(node)); const direction = useDirection(dir); return /* @__PURE__ */ jsx(ScrollAreaProvider, { scope: __scopeScrollArea, type, dir: direction, scrollHideDelay, scrollArea, viewport, onViewportChange: setViewport, content, onContentChange: setContent, scrollbarX, onScrollbarXChange: setScrollbarX, scrollbarXEnabled, onScrollbarXEnabledChange: setScrollbarXEnabled, scrollbarY, onScrollbarYChange: setScrollbarY, scrollbarYEnabled, onScrollbarYEnabledChange: setScrollbarYEnabled, onCornerWidthChange: setCornerWidth, onCornerHeightChange: setCornerHeight, children: /* @__PURE__ */ jsx(Primitive.div, { dir: direction, ...scrollAreaProps, ref: composedRefs, style: { position: "relative", // Pass corner sizes as CSS vars to reduce re-renders of context consumers ["--radix-scroll-area-corner-width"]: cornerWidth + "px", ["--radix-scroll-area-corner-height"]: cornerHeight + "px", ...props.style } }) }); }); ScrollArea$1.displayName = SCROLL_AREA_NAME; var VIEWPORT_NAME = "ScrollAreaViewport"; var ScrollAreaViewport = React.forwardRef((props, forwardedRef)=>{ const { __scopeScrollArea, children, nonce, ...viewportProps } = props; const context = useScrollAreaContext(VIEWPORT_NAME, __scopeScrollArea); const ref = React.useRef(null); const composedRefs = useComposedRefs(forwardedRef, ref, context.onViewportChange); return /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: `[data-radix-scroll-area-viewport]{scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;}[data-radix-scroll-area-viewport]::-webkit-scrollbar{display:none}` }, nonce }), /* @__PURE__ */ jsx(Primitive.div, { "data-radix-scroll-area-viewport": "", ...viewportProps, ref: composedRefs, style: { /** * We don't support `visible` because the intention is to have at least one scrollbar * if this component is used and `visible` will behave like `auto` in that case * https://developer.mozilla.org/en-US/docs/Web/CSS/overflow#description * * We don't handle `auto` because the intention is for the native implementation * to be hidden if using this component. We just want to ensure the node is scrollable * so could have used either `scroll` or `auto` here. We picked `scroll` to prevent * the browser from having to work out whether to render native scrollbars or not, * we tell it to with the intention of hiding them in CSS. */ overflowX: context.scrollbarXEnabled ? "scroll" : "hidden", overflowY: context.scrollbarYEnabled ? "scroll" : "hidden", ...props.style }, children: /* @__PURE__ */ jsx("div", { ref: context.onContentChange, style: { minWidth: "100%", display: "table" }, children }) }) ] }); }); ScrollAreaViewport.displayName = VIEWPORT_NAME; var SCROLLBAR_NAME = "ScrollAreaScrollbar"; var ScrollAreaScrollbar = React.forwardRef((props, forwardedRef)=>{ const { forceMount, ...scrollbarProps } = props; const context = useScrollAreaContext(SCROLLBAR_NAME, props.__scopeScrollArea); const { onScrollbarXEnabledChange, onScrollbarYEnabledChange } = context; const isHorizontal = props.orientation === "horizontal"; React.useEffect(()=>{ isHorizontal ? onScrollbarXEnabledChange(true) : onScrollbarYEnabledChange(true); return ()=>{ isHorizontal ? onScrollbarXEnabledChange(false) : onScrollbarYEnabledChange(false); }; }, [ isHorizontal, onScrollbarXEnabledChange, onScrollbarYEnabledChange ]); return context.type === "hover" ? /* @__PURE__ */ jsx(ScrollAreaScrollbarHover, { ...scrollbarProps, ref: forwardedRef, forceMount }) : context.type === "scroll" ? /* @__PURE__ */ jsx(ScrollAreaScrollbarScroll, { ...scrollbarProps, ref: forwardedRef, forceMount }) : context.type === "auto" ? /* @__PURE__ */ jsx(ScrollAreaScrollbarAuto, { ...scrollbarProps, ref: forwardedRef, forceMount }) : context.type === "always" ? /* @__PURE__ */ jsx(ScrollAreaScrollbarVisible, { ...scrollbarProps, ref: forwardedRef }) : null; }); ScrollAreaScrollbar.displayName = SCROLLBAR_NAME; var ScrollAreaScrollbarHover = React.forwardRef((props, forwardedRef)=>{ const { forceMount, ...scrollbarProps } = props; const context = useScrollAreaContext(SCROLLBAR_NAME, props.__scopeScrollArea); const [visible, setVisible] = React.useState(false); React.useEffect(()=>{ const scrollArea = context.scrollArea; let hideTimer = 0; if (scrollArea) { const handlePointerEnter = ()=>{ window.clearTimeout(hideTimer); setVisible(true); }; const handlePointerLeave = ()=>{ hideTimer = window.setTimeout(()=>setVisible(false), context.scrollHideDelay); }; scrollArea.addEventListener("pointerenter", handlePointerEnter); scrollArea.addEventListener("pointerleave", handlePointerLeave); return ()=>{ window.clearTimeout(hideTimer); scrollArea.removeEventListener("pointerenter", handlePointerEnter); scrollArea.removeEventListener("pointerleave", handlePointerLeave); }; } }, [ context.scrollArea, context.scrollHideDelay ]); return /* @__PURE__ */ jsx(Presence, { present: forceMount || visible, children: /* @__PURE__ */ jsx(ScrollAreaScrollbarAuto, { "data-state": visible ? "visible" : "hidden", ...scrollbarProps, ref: forwardedRef }) }); }); var ScrollAreaScrollbarScroll = React.forwardRef((props, forwardedRef)=>{ const { forceMount, ...scrollbarProps } = props; const context = useScrollAreaContext(SCROLLBAR_NAME, props.__scopeScrollArea); const isHorizontal = props.orientation === "horizontal"; const debounceScrollEnd = useDebounceCallback(()=>send("SCROLL_END"), 100); const [state, send] = useStateMachine("hidden", { hidden: { SCROLL: "scrolling" }, scrolling: { SCROLL_END: "idle", POINTER_ENTER: "interacting" }, interacting: { SCROLL: "interacting", POINTER_LEAVE: "idle" }, idle: { HIDE: "hidden", SCROLL: "scrolling", POINTER_ENTER: "interacting" } }); React.useEffect(()=>{ if (state === "idle") { const hideTimer = window.setTimeout(()=>send("HIDE"), context.scrollHideDelay); return ()=>window.clearTimeout(hideTimer); } }, [ state, context.scrollHideDelay, send ]); React.useEffect(()=>{ const viewport = context.viewport; const scrollDirection = isHorizontal ? "scrollLeft" : "scrollTop"; if (viewport) { let prevScrollPos = viewport[scrollDirection]; const handleScroll = ()=>{ const scrollPos = viewport[scrollDirection]; const hasScrollInDirectionChanged = prevScrollPos !== scrollPos; if (hasScrollInDirectionChanged) { send("SCROLL"); debounceScrollEnd(); } prevScrollPos = scrollPos; }; viewport.addEventListener("scroll", handleScroll); return ()=>viewport.removeEventListener("scroll", handleScroll); } }, [ context.viewport, isHorizontal, send, debounceScrollEnd ]); return /* @__PURE__ */ jsx(Presence, { present: forceMount || state !== "hidden", children: /* @__PURE__ */ jsx(ScrollAreaScrollbarVisible, { "data-state": state === "hidden" ? "hidden" : "visible", ...scrollbarProps, ref: forwardedRef, onPointerEnter: composeEventHandlers(props.onPointerEnter, ()=>send("POINTER_ENTER")), onPointerLeave: composeEventHandlers(props.onPointerLeave, ()=>send("POINTER_LEAVE")) }) }); }); var ScrollAreaScrollbarAuto = React.forwardRef((props, forwardedRef)=>{ const context = useScrollAreaContext(SCROLLBAR_NAME, props.__scopeScrollArea); const { forceMount, ...scrollbarProps } = props; const [visible, setVisible] = React.useState(false); const isHorizontal = props.orientation === "horizontal"; const handleResize = useDebounceCallback(()=>{ if (context.viewport) { const isOverflowX = context.viewport.offsetWidth < context.viewport.scrollWidth; const isOverflowY = context.viewport.offsetHeight < context.viewport.scrollHeight; setVisible(isHorizontal ? isOverflowX : isOverflowY); } }, 10); useResizeObserver(context.viewport, handleResize); useResizeObserver(context.content, handleResize); return /* @__PURE__ */ jsx(Presence, { present: forceMount || visible, children: /* @__PURE__ */ jsx(ScrollAreaScrollbarVisible, { "data-state": visible ? "visible" : "hidden", ...scrollbarProps, ref: forwardedRef }) }); }); var ScrollAreaScrollbarVisible = React.forwardRef((props, forwardedRef)=>{ const { orientation = "vertical", ...scrollbarProps } = props; const context = useScrollAreaContext(SCROLLBAR_NAME, props.__scopeScrollArea); const thumbRef = React.useRef(null); const pointerOffsetRef = React.useRef(0); const [sizes, setSizes] = React.useState({ content: 0, viewport: 0, scrollbar: { size: 0, paddingStart: 0, paddingEnd: 0 } }); const thumbRatio = getThumbRatio(sizes.viewport, sizes.content); const commonProps = { ...scrollbarProps, sizes, onSizesChange: setSizes, hasThumb: Boolean(thumbRatio > 0 && thumbRatio < 1), onThumbChange: (thumb)=>thumbRef.current = thumb, onThumbPointerUp: ()=>pointerOffsetRef.current = 0, onThumbPointerDown: (pointerPos)=>pointerOffsetRef.current = pointerPos }; function getScrollPosition(pointerPos, dir) { return getScrollPositionFromPointer(pointerPos, pointerOffsetRef.current, sizes, dir); } if (orientation === "horizontal") { return /* @__PURE__ */ jsx(ScrollAreaScrollbarX, { ...commonProps, ref: forwardedRef, onThumbPositionChange: ()=>{ if (context.viewport && thumbRef.current) { const scrollPos = context.viewport.scrollLeft; const offset = getThumbOffsetFromScroll(scrollPos, sizes, context.dir); thumbRef.current.style.transform = `translate3d(${offset}px, 0, 0)`; } }, onWheelScroll: (scrollPos)=>{ if (context.viewport) context.viewport.scrollLeft = scrollPos; }, onDragScroll: (pointerPos)=>{ if (context.viewport) { context.viewport.scrollLeft = getScrollPosition(pointerPos, context.dir); } } }); } if (orientation === "vertical") { return /* @__PURE__ */ jsx(ScrollAreaScrollbarY, { ...commonProps, ref: forwardedRef, onThumbPositionChange: ()=>{ if (context.viewport && thumbRef.current) { const scrollPos = context.viewport.scrollTop; const offset = getThumbOffsetFromScroll(scrollPos, sizes); thumbRef.current.style.transform = `translate3d(0, ${offset}px, 0)`; } }, onWheelScroll: (scrollPos)=>{ if (context.viewport) context.viewport.scrollTop = scrollPos; }, onDragScroll: (pointerPos)=>{ if (context.viewport) context.viewport.scrollTop = getScrollPosition(pointerPos); } }); } return null; }); var ScrollAreaScrollbarX = React.forwardRef((props, forwardedRef)=>{ const { sizes, onSizesChange, ...scrollbarProps } = props; const context = useScrollAreaContext(SCROLLBAR_NAME, props.__scopeScrollArea); const [computedStyle, setComputedStyle] = React.useState(); const ref = React.useRef(null); const composeRefs = useComposedRefs(forwardedRef, ref, context.onScrollbarXChange); React.useEffect(()=>{ if (ref.current) setComputedStyle(getComputedStyle(ref.current)); }, [ ref ]); return /* @__PURE__ */ jsx(ScrollAreaScrollbarImpl, { "data-orientation": "horizontal", ...scrollbarProps, ref: composeRefs, sizes, style: { bottom: 0, left: context.dir === "rtl" ? "var(--radix-scroll-area-corner-width)" : 0, right: context.dir === "ltr" ? "var(--radix-scroll-area-corner-width)" : 0, ["--radix-scroll-area-thumb-width"]: getThumbSize(sizes) + "px", ...props.style }, onThumbPointerDown: (pointerPos)=>props.onThumbPointerDown(pointerPos.x), onDragScroll: (pointerPos)=>props.onDragScroll(pointerPos.x), onWheelScroll: (event, maxScrollPos)=>{ if (context.viewport) { const scrollPos = context.viewport.scrollLeft + event.deltaX; props.onWheelScroll(scrollPos); if (isScrollingWithinScrollbarBounds(scrollPos, maxScrollPos)) { event.preventDefault(); } } }, onResize: ()=>{ if (ref.current && context.viewport && computedStyle) { onSizesChange({ content: context.viewport.scrollWidth, viewport: context.viewport.offsetWidth, scrollbar: { size: ref.current.clientWidth, paddingStart: toInt(computedStyle.paddingLeft), paddingEnd: toInt(computedStyle.paddingRight) } }); } } }); }); var ScrollAreaScrollbarY = React.forwardRef((props, forwardedRef)=>{ const { sizes, onSizesChange, ...scrollbarProps } = props; const context = useScrollAreaContext(SCROLLBAR_NAME, props.__scopeScrollArea); const [computedStyle, setComputedStyle] = React.useState(); const ref = React.useRef(null); const composeRefs = useComposedRefs(forwardedRef, ref, context.onScrollbarYChange); React.useEffect(()=>{ if (ref.current) setComputedStyle(getComputedStyle(ref.current)); }, [ ref ]); return /* @__PURE__ */ jsx(ScrollAreaScrollbarImpl, { "data-orientation": "vertical", ...scrollbarProps, ref: composeRefs, sizes, style: { top: 0, right: context.dir === "ltr" ? 0 : void 0, left: context.dir === "rtl" ? 0 : void 0, bottom: "var(--radix-scroll-area-corner-height)", ["--radix-scroll-area-thumb-height"]: getThumbSize(sizes) + "px", ...props.style }, onThumbPointerDown: (pointerPos)=>props.onThumbPointerDown(pointerPos.y), onDragScroll: (pointerPos)=>props.onDragScroll(pointerPos.y), onWheelScroll: (event, maxScrollPos)=>{ if (context.viewport) { const scrollPos = context.viewport.scrollTop + event.deltaY; props.onWheelScroll(scrollPos); if (isScrollingWithinScrollbarBounds(scrollPos, maxScrollPos)) { event.preventDefault(); } } }, onResize: ()=>{ if (ref.current && context.viewport && computedStyle) { onSizesChange({ content: context.viewport.scrollHeight, viewport: context.viewport.offsetHeight, scrollbar: { size: ref.current.clientHeight, paddingStart: toInt(computedStyle.paddingTop), paddingEnd: toInt(computedStyle.paddingBottom) } }); } } }); }); var [ScrollbarProvider, useScrollbarContext] = createScrollAreaContext(SCROLLBAR_NAME); var ScrollAreaScrollbarImpl = React.forwardRef((props, forwardedRef)=>{ const { __scopeScrollArea, sizes, hasThumb, onThumbChange, onThumbPointerUp, onThumbPointerDown, onThumbPositionChange, onDragScroll, onWheelScroll, onResize, ...scrollbarProps } = props; const context = useScrollAreaContext(SCROLLBAR_NAME, __scopeScrollArea); const [scrollbar, setScrollbar] = React.useState(null); const composeRefs = useComposedRefs(forwardedRef, (node)=>setScrollbar(node)); const rectRef = React.useRef(null); const prevWebkitUserSelectRef = React.useRef(""); const viewport = context.viewport; const maxScrollPos = sizes.content - sizes.viewport; const handleWheelScroll = useCallbackRef(onWheelScroll); const handleThumbPositionChange = useCallbackRef(onThumbPositionChange); const handleResize = useDebounceCallback(onResize, 10); function handleDragScroll(event) { if (rectRef.current) { const x = event.clientX - rectRef.current.left; const y = event.clientY - rectRef.current.top; onDragScroll({ x, y }); } } React.useEffect(()=>{ const handleWheel = (event)=>{ const element = event.target; const isScrollbarWheel = scrollbar?.contains(element); if (isScrollbarWheel) handleWheelScroll(event, maxScrollPos); }; document.addEventListener("wheel", handleWheel, { passive: false }); return ()=>document.removeEventListener("wheel", handleWheel, { passive: false }); }, [ viewport, scrollbar, maxScrollPos, handleWheelScroll ]); React.useEffect(handleThumbPositionChange, [ sizes, handleThumbPositionChange ]); useResizeObserver(scrollbar, handleResize); useResizeObserver(context.content, handleResize); return /* @__PURE__ */ jsx(ScrollbarProvider, { scope: __scopeScrollArea, scrollbar, hasThumb, onThumbChange: useCallbackRef(onThumbChange), onThumbPointerUp: useCallbackRef(onThumbPointerUp), onThumbPositionChange: handleThumbPositionChange, onThumbPointerDown: useCallbackRef(onThumbPointerDown), children: /* @__PURE__ */ jsx(Primitive.div, { ...scrollbarProps, ref: composeRefs, style: { position: "absolute", ...scrollbarProps.style }, onPointerDown: composeEventHandlers(props.onPointerDown, (event)=>{ const mainPointer = 0; if (event.button === mainPointer) { const element = event.target; element.setPointerCapture(event.pointerId); rectRef.current = scrollbar.getBoundingClientRect(); prevWebkitUserSelectRef.current = document.body.style.webkitUserSelect; document.body.style.webkitUserSelect = "none"; if (context.viewport) context.viewport.style.scrollBehavior = "auto"; handleDragScroll(event); } }), onPointerMove: composeEventHandlers(props.onPointerMove, handleDragScroll), onPointerUp: composeEventHandlers(props.onPointerUp, (event)=>{ const element = event.target; if (element.hasPointerCapture(event.pointerId)) { element.releasePointerCapture(event.pointerId); } document.body.style.webkitUserSelect = prevWebkitUserSelectRef.current; if (context.viewport) context.viewport.style.scrollBehavior = ""; rectRef.current = null; }) }) }); }); var THUMB_NAME = "ScrollAreaThumb"; var ScrollAreaThumb = React.forwardRef((props, forwardedRef)=>{ const { forceMount, ...thumbProps } = props; const scrollbarContext = useScrollbarContext(THUMB_NAME, props.__scopeScrollArea); return /* @__PURE__ */ jsx(Presence, { present: forceMount || scrollbarContext.hasThumb, children: /* @__PURE__ */ jsx(ScrollAreaThumbImpl, { ref: forwardedRef, ...thumbProps }) }); }); var ScrollAreaThumbImpl = React.forwardRef((props, forwardedRef)=>{ const { __scopeScrollArea, style, ...thumbProps } = props; const scrollAreaContext = useScrollAreaContext(THUMB_NAME, __scopeScrollArea); const scrollbarContext = useScrollbarContext(THUMB_NAME, __scopeScrollArea); const { onThumbPositionChange } = scrollbarContext; const composedRef = useComposedRefs(forwardedRef, (node)=>scrollbarContext.onThumbChange(node)); const removeUnlinkedScrollListenerRef = React.useRef(void 0); const debounceScrollEnd = useDebounceCallback(()=>{ if (removeUnlinkedScrollListenerRef.current) { removeUnlinkedScrollListenerRef.current(); removeUnlinkedScrollListenerRef.current = void 0; } }, 100); React.useEffect(()=>{ const viewport = scrollAreaContext.viewport; if (viewport) { const handleScroll = ()=>{ debounceScrollEnd(); if (!removeUnlinkedScrollListenerRef.current) { const listener = addUnlinkedScrollListener(viewport, onThumbPositionChange); removeUnlinkedScrollListenerRef.current = listener; onThumbPositionChange(); } }; onThumbPositionChange(); viewport.addEventListener("scroll", handleScroll); return ()=>viewport.removeEventListener("scroll", handleScroll); } }, [ scrollAreaContext.viewport, debounceScrollEnd, onThumbPositionChange ]); return /* @__PURE__ */ jsx(Primitive.div, { "data-state": scrollbarContext.hasThumb ? "visible" : "hidden", ...thumbProps, ref: composedRef, style: { width: "var(--radix-scroll-area-thumb-width)", height: "var(--radix-scroll-area-thumb-height)", ...style }, onPointerDownCapture: composeEventHandlers(props.onPointerDownCapture, (event)=>{ const thumb = event.target; const thumbRect = thumb.getBoundingClientRect(); const x = event.clientX - thumbRect.left; const y = event.clientY - thumbRect.top; scrollbarContext.onThumbPointerDown({ x, y }); }), onPointerUp: composeEventHandlers(props.onPointerUp, scrollbarContext.onThumbPointerUp) }); }); ScrollAreaThumb.displayName = THUMB_NAME; var CORNER_NAME = "ScrollAreaCorner"; var ScrollAreaCorner = React.forwardRef((props, forwardedRef)=>{ const context = useScrollAreaContext(CORNER_NAME, props.__scopeScrollArea); const hasBothScrollbarsVisible = Boolean(context.scrollbarX && context.scrollbarY); const hasCorner = context.type !== "scroll" && hasBothScrollbarsVisible; return hasCorner ? /* @__PURE__ */ jsx(ScrollAreaCornerImpl, { ...props, ref: forwardedRef }) : null; }); ScrollAreaCorner.displayName = CORNER_NAME; var ScrollAreaCornerImpl = React.forwardRef((props, forwardedRef)=>{ const { __scopeScrollArea, ...cornerProps } = props; const context = useScrollAreaContext(CORNER_NAME, __scopeScrollArea); const [width, setWidth] = React.useState(0); const [height, setHeight] = React.useState(0); const hasSize = Boolean(width && height); useResizeObserver(context.scrollbarX, ()=>{ const height2 = context.scrollbarX?.offsetHeight || 0; context.onCornerHeightChange(height2); setHeight(height2); }); useResizeObserver(context.scrollbarY, ()=>{ const width2 = context.scrollbarY?.offsetWidth || 0; context.onCornerWidthChange(width2); setWidth(width2); }); return hasSize ? /* @__PURE__ */ jsx(Primitive.div, { ...cornerProps, ref: forwardedRef, style: { width, height, position: "absolute", right: context.dir === "ltr" ? 0 : void 0, left: context.dir === "rtl" ? 0 : void 0, bottom: 0, ...props.style } }) : null; }); function toInt(value) { return value ? parseInt(value, 10) : 0; } function getThumbRatio(viewportSize, contentSize) { const ratio = viewportSize / contentSize; return isNaN(ratio) ? 0 : ratio; } function getThumbSize(sizes) { const ratio = getThumbRatio(sizes.viewport, sizes.content); const scrollbarPadding = sizes.scrollbar.paddingStart + sizes.scrollbar.paddingEnd; const thumbSize = (sizes.scrollbar.size - scrollbarPadding) * ratio; return Math.max(thumbSize, 18); } function getScrollPositionFromPointer(pointerPos, pointerOffset, sizes, dir = "ltr") { const thumbSizePx = getThumbSize(sizes); const thumbCenter = thumbSizePx / 2; const offset = pointerOffset || thumbCenter; const thumbOffsetFromEnd = thumbSizePx - offset; const minPointerPos = sizes.scrollbar.paddingStart + offset; const maxPointerPos = sizes.scrollbar.size - sizes.scrollbar.paddingEnd - thumbOffsetFromEnd; const maxScrollPos = sizes.content - sizes.viewport; const scrollRange = dir === "ltr" ? [ 0, maxScrollPos ] : [ maxScrollPos * -1, 0 ]; const interpolate = linearScale([ minPointerPos, maxPointerPos ], scrollRange); return interpolate(pointerPos); } function getThumbOffsetFromScroll(scrollPos, sizes, dir = "ltr") { const thumbSizePx = getThumbSize(sizes); const scrollbarPadding = sizes.scrollbar.paddingStart + sizes.scrollbar.paddingEnd; const scrollbar = sizes.scrollbar.size - scrollbarPadding; const maxScrollPos = sizes.content - sizes.viewport; const maxThumbPos = scrollbar - thumbSizePx; const scrollClampRange = dir === "ltr" ? [ 0, maxScrollPos ] : [ maxScrollPos * -1, 0 ]; const scrollWithoutMomentum = clamp(scrollPos, scrollClampRange); const interpolate = linearScale([ 0, maxScrollPos ], [ 0, maxThumbPos ]); return interpolate(scrollWithoutMomentum); } function linearScale(input, output) { return (value)=>{ if (input[0] === input[1] || output[0] === output[1]) return output[0]; const ratio = (output[1] - output[0]) / (input[1] - input[0]); return output[0] + ratio * (value - input[0]); }; } function isScrollingWithinScrollbarBounds(scrollPos, maxScrollPos) { return scrollPos > 0 && scrollPos < maxScrollPos; } var addUnlinkedScrollListener = (node, handler = ()=>{})=>{ let prevPosition = { left: node.scrollLeft, top: node.scrollTop }; let rAF = 0; (function loop() { const position = { left: node.scrollLeft, top: node.scrollTop }; const isHorizontalScroll = prevPosition.left !== position.left; const isVerticalScroll = prevPosition.top !== position.top; if (isHorizontalScroll || isVerticalScroll) handler(); prevPosition = position; rAF = window.requestAnimationFrame(loop); })(); return ()=>window.cancelAnimationFrame(rAF); }; function useDebounceCallback(callback, delay) { const handleCallback = useCallbackRef(callback); const debounceTimerRef = React.useRef(0); React.useEffect(()=>()=>window.clearTimeout(debounceTimerRef.current), []); return React.useCallback(()=>{ window.clearTimeout(debounceTimerRef.current); debounceTimerRef.current = window.setTimeout(handleCallback, delay); }, [ handleCallback, delay ]); } function useResizeObserver(element, onResize) { const handleResize = useCallbackRef(onResize); useLayoutEffect2(()=>{ let rAF = 0; if (element) { const resizeObserver = new ResizeObserver(()=>{ cancelAnimationFrame(rAF); rAF = window.requestAnimationFrame(handleResize); }); resizeObserver.observe(element); return ()=>{ window.cancelAnimationFrame(rAF); resizeObserver.unobserve(element); }; } }, [ element, handleResize ]); } var Root = ScrollArea$1; var Viewport = ScrollAreaViewport; var Corner = ScrollAreaCorner; function ScrollArea({ className, children, ...props }) { return /*#__PURE__*/ React__default.createElement(Root, { "data-slot": "scroll-area", className: cn("relative", className), ...props }, /*#__PURE__*/ React__default.createElement(Viewport, { "data-slot": "scroll-area-viewport", className: "ring-ring/10 dark:ring-ring/20 dark:outline-ring/40 outline-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] focus-visible:ring-4 focus-visible:outline-1" }, children), /*#__PURE__*/ React__default.createElement(ScrollBar, null), /*#__PURE__*/ React__default.createElement(Corner, null)); } function ScrollBar({ className, orientation = "vertical", ...props }) { return /*#__PURE__*/ React__default.createElement(ScrollAreaScrollbar, { "data-slot": "scroll-area-scrollbar", orientation: orientation, className: cn("flex touch-none p-px transition-colors select-none", orientation === "vertical" && "h-full w-2.5 border-l border-l-transparent", orientation === "horizontal" && "h-2.5 flex-col border-t border-t-transparent", className), ...props }, /*#__PURE__*/ React__default.createElement(ScrollAreaThumb, { "data-slot": "scroll-area-thumb", className: "bg-border relative flex-1 rounded-full" })); } export { ScrollArea as S, ScrollBar as a }; //# sourceMappingURL=scroll-area-Cr1Iu-Ot.mjs.map