@radix-ui/react-scroll-area
Advanced tools
Comparing version 1.1.0-rc.2 to 1.1.0-rc.3
1408
dist/index.js
"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 __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { | ||
get: (a, b) => (typeof require !== "undefined" ? require : a)[b] | ||
}) : x)(function(x) { | ||
if (typeof require !== "undefined") return require.apply(this, arguments); | ||
throw Error('Dynamic require of "' + x + '" is not supported'); | ||
}); | ||
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 __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/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/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/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 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/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, 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}` | ||
}, | ||
nonce | ||
} | ||
), | ||
/* @__PURE__ */ (0, import_jsx_runtime.jsx)( | ||
// 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, | ||
{ | ||
"data-radix-scroll-area-viewport": "", | ||
...viewportProps, | ||
dir: direction, | ||
...scrollAreaProps, | ||
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/overflowed#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", | ||
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 | ||
}, | ||
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: context.onContentChange, style: { minWidth: "100%", display: "table" }, children }) | ||
} | ||
} | ||
) | ||
] }); | ||
} | ||
); | ||
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) => { | ||
); | ||
} | ||
); | ||
ScrollArea.displayName = SCROLL_AREA_NAME; | ||
var VIEWPORT_NAME = "ScrollAreaViewport"; | ||
var ScrollAreaViewport = React2.forwardRef( | ||
(props, forwardedRef) => { | ||
const { __scopeScrollArea, children, 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}` | ||
}, | ||
nonce | ||
} | ||
), | ||
/* @__PURE__ */ (0, import_jsx_runtime.jsx)( | ||
import_react_primitive.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/overflowed#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__ */ (0, import_jsx_runtime.jsx)("div", { ref: context.onContentChange, style: { minWidth: "100%", display: "table" }, children }) | ||
} | ||
) | ||
] }); | ||
} | ||
); | ||
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"; | ||
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 = { | ||
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, | ||
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); | ||
ref: forwardedRef | ||
} | ||
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); | ||
} | ||
} | ||
} | ||
); | ||
) }); | ||
}); | ||
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" | ||
} | ||
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); | ||
} | ||
}); | ||
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); | ||
} | ||
return null; | ||
}, [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 } | ||
}); | ||
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]); | ||
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)( | ||
ScrollAreaScrollbarImpl, | ||
ScrollAreaScrollbarX, | ||
{ | ||
"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 | ||
...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)`; | ||
} | ||
}, | ||
onThumbPointerDown: (pointerPos) => props.onThumbPointerDown(pointerPos.x), | ||
onDragScroll: (pointerPos) => props.onDragScroll(pointerPos.x), | ||
onWheelScroll: (event, maxScrollPos) => { | ||
onWheelScroll: (scrollPos) => { | ||
if (context.viewport) context.viewport.scrollLeft = scrollPos; | ||
}, | ||
onDragScroll: (pointerPos) => { | ||
if (context.viewport) { | ||
const scrollPos = context.viewport.scrollLeft + event.deltaX; | ||
props.onWheelScroll(scrollPos); | ||
if (isScrollingWithinScrollbarBounds(scrollPos, maxScrollPos)) { | ||
event.preventDefault(); | ||
} | ||
context.viewport.scrollLeft = getScrollPosition(pointerPos, context.dir); | ||
} | ||
}, | ||
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]); | ||
} | ||
if (orientation === "vertical") { | ||
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( | ||
ScrollAreaScrollbarImpl, | ||
ScrollAreaScrollbarY, | ||
{ | ||
"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(); | ||
} | ||
...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)`; | ||
} | ||
}, | ||
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) | ||
} | ||
}); | ||
} | ||
onWheelScroll: (scrollPos) => { | ||
if (context.viewport) context.viewport.scrollTop = scrollPos; | ||
}, | ||
onDragScroll: (pointerPos) => { | ||
if (context.viewport) context.viewport.scrollTop = getScrollPosition(pointerPos); | ||
} | ||
} | ||
); | ||
}); | ||
var [ScrollbarProvider, useScrollbarContext] = createScrollAreaContext(SCROLLBAR_NAME); | ||
var ScrollAreaScrollbarImpl = React2.forwardRef((props, forwardedRef) => { | ||
const { | ||
__scopeScrollArea, | ||
} | ||
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, | ||
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; | ||
}) | ||
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 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; | ||
}); | ||
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(); | ||
} | ||
} | ||
}, 100); | ||
React2.useEffect(() => { | ||
const viewport = scrollAreaContext.viewport; | ||
if (viewport) { | ||
const handleScroll = () => { | ||
debounceScrollEnd(); | ||
if (!removeUnlinkedScrollListenerRef.current) { | ||
const listener = addUnlinkedScrollListener(viewport, onThumbPositionChange); | ||
removeUnlinkedScrollListenerRef.current = listener; | ||
onThumbPositionChange(); | ||
}, | ||
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) | ||
} | ||
}; | ||
onThumbPositionChange(); | ||
viewport.addEventListener("scroll", handleScroll); | ||
return () => viewport.removeEventListener("scroll", handleScroll); | ||
}); | ||
} | ||
}, [scrollAreaContext.viewport, debounceScrollEnd, onThumbPositionChange]); | ||
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( | ||
} | ||
} | ||
); | ||
}); | ||
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, | ||
{ | ||
"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 }); | ||
...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); | ||
} | ||
}), | ||
onPointerUp: (0, import_primitive.composeEventHandlers)(props.onPointerUp, scrollbarContext.onThumbPointerUp) | ||
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; | ||
}) | ||
} | ||
); | ||
) | ||
} | ||
); | ||
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)( | ||
}); | ||
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, | ||
{ | ||
...cornerProps, | ||
ref: forwardedRef, | ||
"data-state": scrollbarContext.hasThumb ? "visible" : "hidden", | ||
...thumbProps, | ||
ref: composedRef, | ||
style: { | ||
width, | ||
height, | ||
position: "absolute", | ||
right: context.dir === "ltr" ? 0 : void 0, | ||
left: context.dir === "rtl" ? 0 : void 0, | ||
bottom: 0, | ||
...props.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) | ||
} | ||
) : null; | ||
}); | ||
function toInt(value) { | ||
return value ? parseInt(value, 10) : 0; | ||
); | ||
} | ||
function getThumbRatio(viewportSize, contentSize) { | ||
const ratio = viewportSize / contentSize; | ||
return isNaN(ratio) ? 0 : ratio; | ||
); | ||
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; | ||
} | ||
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 }; | ||
); | ||
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; | ||
(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]); | ||
} | ||
var Root = ScrollArea; | ||
var Viewport = ScrollAreaViewport; | ||
var Scrollbar = ScrollAreaScrollbar; | ||
var Thumb = ScrollAreaThumb; | ||
var Corner = ScrollAreaCorner; | ||
})(); | ||
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; | ||
var Viewport = ScrollAreaViewport; | ||
var Scrollbar = ScrollAreaScrollbar; | ||
var Thumb = ScrollAreaThumb; | ||
var Corner = ScrollAreaCorner; | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "@radix-ui/react-scroll-area", | ||
"version": "1.1.0-rc.2", | ||
"version": "1.1.0-rc.3", | ||
"license": "MIT", | ||
@@ -31,11 +31,11 @@ "exports": { | ||
"dependencies": { | ||
"@radix-ui/number": "1.1.0-rc.2", | ||
"@radix-ui/primitive": "1.1.0-rc.2", | ||
"@radix-ui/react-compose-refs": "1.1.0-rc.2", | ||
"@radix-ui/react-context": "1.1.0-rc.2", | ||
"@radix-ui/react-direction": "1.1.0-rc.2", | ||
"@radix-ui/react-presence": "1.1.0-rc.2", | ||
"@radix-ui/react-primitive": "1.1.0-rc.2", | ||
"@radix-ui/react-use-callback-ref": "1.1.0-rc.2", | ||
"@radix-ui/react-use-layout-effect": "1.1.0-rc.2" | ||
"@radix-ui/number": "1.1.0-rc.3", | ||
"@radix-ui/primitive": "1.1.0-rc.3", | ||
"@radix-ui/react-compose-refs": "1.1.0-rc.3", | ||
"@radix-ui/react-context": "1.1.0-rc.3", | ||
"@radix-ui/react-direction": "1.1.0-rc.3", | ||
"@radix-ui/react-presence": "1.1.0-rc.3", | ||
"@radix-ui/react-primitive": "1.1.0-rc.3", | ||
"@radix-ui/react-use-callback-ref": "1.1.0-rc.3", | ||
"@radix-ui/react-use-layout-effect": "1.1.0-rc.3" | ||
}, | ||
@@ -42,0 +42,0 @@ "devDependencies": { |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
1638
0
196905
+ Added@radix-ui/number@1.1.0-rc.3(transitive)
+ Added@radix-ui/primitive@1.1.0-rc.3(transitive)
+ Added@radix-ui/react-compose-refs@1.1.0-rc.3(transitive)
+ Added@radix-ui/react-context@1.1.0-rc.3(transitive)
+ Added@radix-ui/react-direction@1.1.0-rc.3(transitive)
+ Added@radix-ui/react-presence@1.1.0-rc.3(transitive)
+ Added@radix-ui/react-primitive@1.1.0-rc.3(transitive)
+ Added@radix-ui/react-slot@1.1.0-rc.3(transitive)
+ Added@radix-ui/react-use-callback-ref@1.1.0-rc.3(transitive)
+ Added@radix-ui/react-use-layout-effect@1.1.0-rc.3(transitive)
- Removed@radix-ui/number@1.1.0-rc.2(transitive)
- Removed@radix-ui/primitive@1.1.0-rc.2(transitive)
- Removed@radix-ui/react-compose-refs@1.1.0-rc.2(transitive)
- Removed@radix-ui/react-context@1.1.0-rc.2(transitive)
- Removed@radix-ui/react-direction@1.1.0-rc.2(transitive)
- Removed@radix-ui/react-presence@1.1.0-rc.2(transitive)
- Removed@radix-ui/react-primitive@1.1.0-rc.2(transitive)
- Removed@radix-ui/react-slot@1.1.0-rc.2(transitive)
- Removed@radix-ui/react-use-callback-ref@1.1.0-rc.2(transitive)
- Removed@radix-ui/react-use-layout-effect@1.1.0-rc.2(transitive)
Updated@radix-ui/number@1.1.0-rc.3