"use strict"; "use client"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // packages/react/scroll-area/src/index.ts var src_exports = {}; __export(src_exports, { Corner: () => Corner, Root: () => Root, ScrollArea: () => ScrollArea, ScrollAreaCorner: () => ScrollAreaCorner, ScrollAreaScrollbar: () => ScrollAreaScrollbar, ScrollAreaThumb: () => ScrollAreaThumb, ScrollAreaViewport: () => ScrollAreaViewport, Scrollbar: () => Scrollbar, Thumb: () => Thumb, Viewport: () => Viewport, createScrollAreaScope: () => createScrollAreaScope }); module.exports = __toCommonJS(src_exports); // packages/react/scroll-area/src/ScrollArea.tsx var React2 = __toESM(require("react")); var import_react_primitive = require("@radix-ui/react-primitive"); var import_react_presence = require("@radix-ui/react-presence"); var import_react_context = require("@radix-ui/react-context"); var import_react_compose_refs = require("@radix-ui/react-compose-refs"); var import_react_use_callback_ref = require("@radix-ui/react-use-callback-ref"); var import_react_direction = require("@radix-ui/react-direction"); var import_react_use_layout_effect = require("@radix-ui/react-use-layout-effect"); var import_number = require("@radix-ui/number"); var import_primitive = require("@radix-ui/primitive"); // packages/react/scroll-area/src/useStateMachine.ts var React = __toESM(require("react")); function useStateMachine(initialState, machine) { return React.useReducer((state, event) => { const nextState = machine[state][event]; return nextState ?? state; }, initialState); } // packages/react/scroll-area/src/ScrollArea.tsx var import_jsx_runtime = require("react/jsx-runtime"); var SCROLL_AREA_NAME = "ScrollArea"; var [createScrollAreaContext, createScrollAreaScope] = (0, import_react_context.createContextScope)(SCROLL_AREA_NAME); var [ScrollAreaProvider, useScrollAreaContext] = createScrollAreaContext(SCROLL_AREA_NAME); var ScrollArea = React2.forwardRef( (props, forwardedRef) => { const { __scopeScrollArea, type = "hover", dir, scrollHideDelay = 600, ...scrollAreaProps } = props; const [scrollArea, setScrollArea] = React2.useState(null); const [viewport, setViewport] = React2.useState(null); const [content, setContent] = React2.useState(null); const [scrollbarX, setScrollbarX] = React2.useState(null); const [scrollbarY, setScrollbarY] = React2.useState(null); const [cornerWidth, setCornerWidth] = React2.useState(0); const [cornerHeight, setCornerHeight] = React2.useState(0); const [scrollbarXEnabled, setScrollbarXEnabled] = React2.useState(false); const [scrollbarYEnabled, setScrollbarYEnabled] = React2.useState(false); const composedRefs = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, (node) => setScrollArea(node)); const direction = (0, import_react_direction.useDirection)(dir); return /* @__PURE__ */ (0, import_jsx_runtime.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__ */ (0, import_jsx_runtime.jsx)( import_react_primitive.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.displayName = SCROLL_AREA_NAME; var VIEWPORT_NAME = "ScrollAreaViewport"; var ScrollAreaViewport = React2.forwardRef( (props, forwardedRef) => { const { __scopeScrollArea, children, asChild, nonce, ...viewportProps } = props; const context = useScrollAreaContext(VIEWPORT_NAME, __scopeScrollArea); const ref = React2.useRef(null); const composedRefs = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, ref, context.onViewportChange); return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [ /* @__PURE__ */ (0, import_jsx_runtime.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; } :where([data-radix-scroll-area-viewport]) { display: flex; flex-direction: column; align-items: stretch; } :where([data-radix-scroll-area-content]) { flex-grow: 1; } ` }, nonce } ), /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_react_primitive.Primitive.div, { "data-radix-scroll-area-viewport": "", ...viewportProps, asChild, 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: getSubtree({ asChild, children }, (children2) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)( "div", { "data-radix-scroll-area-content": "", ref: context.onContentChange, style: { minWidth: context.scrollbarXEnabled ? "fit-content" : void 0 }, children: children2 } )) } ) ] }); } ); ScrollAreaViewport.displayName = VIEWPORT_NAME; var SCROLLBAR_NAME = "ScrollAreaScrollbar"; var ScrollAreaScrollbar = React2.forwardRef( (props, forwardedRef) => { const { forceMount, ...scrollbarProps } = props; const context = useScrollAreaContext(SCROLLBAR_NAME, props.__scopeScrollArea); const { onScrollbarXEnabledChange, onScrollbarYEnabledChange } = context; const isHorizontal = props.orientation === "horizontal"; React2.useEffect(() => { isHorizontal ? onScrollbarXEnabledChange(true) : onScrollbarYEnabledChange(true); return () => { isHorizontal ? onScrollbarXEnabledChange(false) : onScrollbarYEnabledChange(false); }; }, [isHorizontal, onScrollbarXEnabledChange, onScrollbarYEnabledChange]); return context.type === "hover" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ScrollAreaScrollbarHover, { ...scrollbarProps, ref: forwardedRef, forceMount }) : context.type === "scroll" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ScrollAreaScrollbarScroll, { ...scrollbarProps, ref: forwardedRef, forceMount }) : context.type === "auto" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ScrollAreaScrollbarAuto, { ...scrollbarProps, ref: forwardedRef, forceMount }) : context.type === "always" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ScrollAreaScrollbarVisible, { ...scrollbarProps, ref: forwardedRef }) : null; } ); ScrollAreaScrollbar.displayName = SCROLLBAR_NAME; var ScrollAreaScrollbarHover = React2.forwardRef((props, forwardedRef) => { const { forceMount, ...scrollbarProps } = props; const context = useScrollAreaContext(SCROLLBAR_NAME, props.__scopeScrollArea); const [visible, setVisible] = React2.useState(false); React2.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__ */ (0, import_jsx_runtime.jsx)(import_react_presence.Presence, { present: forceMount || visible, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( ScrollAreaScrollbarAuto, { "data-state": visible ? "visible" : "hidden", ...scrollbarProps, ref: forwardedRef } ) }); }); var ScrollAreaScrollbarScroll = React2.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" } }); React2.useEffect(() => { if (state === "idle") { const hideTimer = window.setTimeout(() => send("HIDE"), context.scrollHideDelay); return () => window.clearTimeout(hideTimer); } }, [state, context.scrollHideDelay, send]); React2.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__ */ (0, import_jsx_runtime.jsx)(import_react_presence.Presence, { present: forceMount || state !== "hidden", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( ScrollAreaScrollbarVisible, { "data-state": state === "hidden" ? "hidden" : "visible", ...scrollbarProps, ref: forwardedRef, onPointerEnter: (0, import_primitive.composeEventHandlers)(props.onPointerEnter, () => send("POINTER_ENTER")), onPointerLeave: (0, import_primitive.composeEventHandlers)(props.onPointerLeave, () => send("POINTER_LEAVE")) } ) }); }); var ScrollAreaScrollbarAuto = React2.forwardRef((props, forwardedRef) => { const context = useScrollAreaContext(SCROLLBAR_NAME, props.__scopeScrollArea); const { forceMount, ...scrollbarProps } = props; const [visible, setVisible] = React2.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__ */ (0, import_jsx_runtime.jsx)(import_react_presence.Presence, { present: forceMount || visible, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( ScrollAreaScrollbarVisible, { "data-state": visible ? "visible" : "hidden", ...scrollbarProps, ref: forwardedRef } ) }); }); var ScrollAreaScrollbarVisible = React2.forwardRef((props, forwardedRef) => { const { orientation = "vertical", ...scrollbarProps } = props; const context = useScrollAreaContext(SCROLLBAR_NAME, props.__scopeScrollArea); const thumbRef = React2.useRef(null); const pointerOffsetRef = React2.useRef(0); const [sizes, setSizes] = React2.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__ */ (0, import_jsx_runtime.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__ */ (0, import_jsx_runtime.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 = React2.forwardRef((props, forwardedRef) => { const { sizes, onSizesChange, ...scrollbarProps } = props; const context = useScrollAreaContext(SCROLLBAR_NAME, props.__scopeScrollArea); const [computedStyle, setComputedStyle] = React2.useState(); const ref = React2.useRef(null); const composeRefs = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, ref, context.onScrollbarXChange); React2.useEffect(() => { if (ref.current) setComputedStyle(getComputedStyle(ref.current)); }, [ref]); return /* @__PURE__ */ (0, import_jsx_runtime.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 = React2.forwardRef((props, forwardedRef) => { const { sizes, onSizesChange, ...scrollbarProps } = props; const context = useScrollAreaContext(SCROLLBAR_NAME, props.__scopeScrollArea); const [computedStyle, setComputedStyle] = React2.useState(); const ref = React2.useRef(null); const composeRefs = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, ref, context.onScrollbarYChange); React2.useEffect(() => { if (ref.current) setComputedStyle(getComputedStyle(ref.current)); }, [ref]); return /* @__PURE__ */ (0, import_jsx_runtime.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 = React2.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] = React2.useState(null); const composeRefs = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, (node) => setScrollbar(node)); const rectRef = React2.useRef(null); const prevWebkitUserSelectRef = React2.useRef(""); const viewport = context.viewport; const maxScrollPos = sizes.content - sizes.viewport; const handleWheelScroll = (0, import_react_use_callback_ref.useCallbackRef)(onWheelScroll); const handleThumbPositionChange = (0, import_react_use_callback_ref.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 }); } } React2.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]); React2.useEffect(handleThumbPositionChange, [sizes, handleThumbPositionChange]); useResizeObserver(scrollbar, handleResize); useResizeObserver(context.content, handleResize); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( ScrollbarProvider, { scope: __scopeScrollArea, scrollbar, hasThumb, onThumbChange: (0, import_react_use_callback_ref.useCallbackRef)(onThumbChange), onThumbPointerUp: (0, import_react_use_callback_ref.useCallbackRef)(onThumbPointerUp), onThumbPositionChange: handleThumbPositionChange, onThumbPointerDown: (0, import_react_use_callback_ref.useCallbackRef)(onThumbPointerDown), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_react_primitive.Primitive.div, { ...scrollbarProps, ref: composeRefs, style: { position: "absolute", ...scrollbarProps.style }, onPointerDown: (0, import_primitive.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: (0, import_primitive.composeEventHandlers)(props.onPointerMove, handleDragScroll), onPointerUp: (0, import_primitive.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 = React2.forwardRef( (props, forwardedRef) => { const { forceMount, ...thumbProps } = props; const scrollbarContext = useScrollbarContext(THUMB_NAME, props.__scopeScrollArea); return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_presence.Presence, { present: forceMount || scrollbarContext.hasThumb, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ScrollAreaThumbImpl, { ref: forwardedRef, ...thumbProps }) }); } ); var ScrollAreaThumbImpl = React2.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 = (0, import_react_compose_refs.useComposedRefs)( forwardedRef, (node) => scrollbarContext.onThumbChange(node) ); const removeUnlinkedScrollListenerRef = React2.useRef(); const debounceScrollEnd = useDebounceCallback(() => { if (removeUnlinkedScrollListenerRef.current) { removeUnlinkedScrollListenerRef.current(); removeUnlinkedScrollListenerRef.current = void 0; } }, 100); React2.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__ */ (0, import_jsx_runtime.jsx)( import_react_primitive.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: (0, import_primitive.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: (0, import_primitive.composeEventHandlers)(props.onPointerUp, scrollbarContext.onThumbPointerUp) } ); } ); ScrollAreaThumb.displayName = THUMB_NAME; var CORNER_NAME = "ScrollAreaCorner"; var ScrollAreaCorner = React2.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__ */ (0, import_jsx_runtime.jsx)(ScrollAreaCornerImpl, { ...props, ref: forwardedRef }) : null; } ); ScrollAreaCorner.displayName = CORNER_NAME; var ScrollAreaCornerImpl = React2.forwardRef((props, forwardedRef) => { const { __scopeScrollArea, ...cornerProps } = props; const context = useScrollAreaContext(CORNER_NAME, __scopeScrollArea); const [width, setWidth] = React2.useState(0); const [height, setHeight] = React2.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__ */ (0, import_jsx_runtime.jsx)( import_react_primitive.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 = (0, import_number.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 = (0, import_react_use_callback_ref.useCallbackRef)(callback); const debounceTimerRef = React2.useRef(0); React2.useEffect(() => () => window.clearTimeout(debounceTimerRef.current), []); return React2.useCallback(() => { window.clearTimeout(debounceTimerRef.current); debounceTimerRef.current = window.setTimeout(handleCallback, delay); }, [handleCallback, delay]); } function useResizeObserver(element, onResize) { const handleResize = (0, import_react_use_callback_ref.useCallbackRef)(onResize); (0, import_react_use_layout_effect.useLayoutEffect)(() => { 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]); } function getSubtree(options, content) { const { asChild, children } = options; if (!asChild) return typeof content === "function" ? content(children) : content; const firstChild = React2.Children.only(children); return React2.cloneElement(firstChild, { children: typeof content === "function" ? content(firstChild.props.children) : content }); } var Root = ScrollArea; var Viewport = ScrollAreaViewport; var Scrollbar = ScrollAreaScrollbar; var Thumb = ScrollAreaThumb; var Corner = ScrollAreaCorner; //# sourceMappingURL=index.js.map