@octanejs/radix 0.1.32 → 0.1.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/dist/cjs/AccessibleIcon.cjs +56 -0
  2. package/dist/cjs/Accordion.cjs +272 -0
  3. package/dist/cjs/AlertDialog.cjs +144 -0
  4. package/dist/cjs/Arrow.cjs +43 -0
  5. package/dist/cjs/AspectRatio.cjs +56 -0
  6. package/dist/cjs/Avatar.cjs +150 -0
  7. package/dist/cjs/Checkbox.cjs +281 -0
  8. package/dist/cjs/Collapsible.cjs +176 -0
  9. package/dist/cjs/ContextMenu.cjs +315 -0
  10. package/dist/cjs/Dialog.cjs +291 -0
  11. package/dist/cjs/DismissableLayer.cjs +382 -0
  12. package/dist/cjs/DropdownMenu.cjs +296 -0
  13. package/dist/cjs/FocusScope.cjs +257 -0
  14. package/dist/cjs/Form.cjs +537 -0
  15. package/dist/cjs/HoverCard.cjs +309 -0
  16. package/dist/cjs/Label.cjs +42 -0
  17. package/dist/cjs/Menu.cjs +925 -0
  18. package/dist/cjs/Menubar.cjs +475 -0
  19. package/dist/cjs/NavigationMenu.cjs +942 -0
  20. package/dist/cjs/OneTimePasswordField.cjs +729 -0
  21. package/dist/cjs/PasswordToggleField.cjs +377 -0
  22. package/dist/cjs/Popover.cjs +340 -0
  23. package/dist/cjs/Popper.cjs +368 -0
  24. package/dist/cjs/Portal.cjs +40 -0
  25. package/dist/cjs/Presence.cjs +183 -0
  26. package/dist/cjs/Primitive.cjs +63 -0
  27. package/dist/cjs/Progress.cjs +111 -0
  28. package/dist/cjs/Radio.cjs +240 -0
  29. package/dist/cjs/RadioGroup.cjs +216 -0
  30. package/dist/cjs/RovingFocusGroup.cjs +253 -0
  31. package/dist/cjs/ScrollArea.cjs +828 -0
  32. package/dist/cjs/Select.cjs +1429 -0
  33. package/dist/cjs/Separator.cjs +51 -0
  34. package/dist/cjs/Slider.cjs +634 -0
  35. package/dist/cjs/Slot.cjs +97 -0
  36. package/dist/cjs/Switch.cjs +253 -0
  37. package/dist/cjs/Tabs.cjs +195 -0
  38. package/dist/cjs/Toast.cjs +733 -0
  39. package/dist/cjs/Toggle.cjs +54 -0
  40. package/dist/cjs/ToggleGroup.cjs +174 -0
  41. package/dist/cjs/Toolbar.cjs +165 -0
  42. package/dist/cjs/Tooltip.cjs +628 -0
  43. package/dist/cjs/VisuallyHidden.cjs +52 -0
  44. package/dist/cjs/collection.cjs +95 -0
  45. package/dist/cjs/compose-event-handlers.cjs +35 -0
  46. package/dist/cjs/compose-refs.cjs +68 -0
  47. package/dist/cjs/context.cjs +96 -0
  48. package/dist/cjs/direction.cjs +41 -0
  49. package/dist/cjs/focus-guards.cjs +76 -0
  50. package/dist/cjs/index.cjs +174 -0
  51. package/dist/cjs/internal.cjs +51 -0
  52. package/dist/cjs/scroll-lock.cjs +67 -0
  53. package/dist/cjs/use-callback-ref.cjs +47 -0
  54. package/dist/cjs/use-effect-event.cjs +52 -0
  55. package/dist/cjs/use-is-hydrated.cjs +43 -0
  56. package/dist/cjs/use-previous.cjs +47 -0
  57. package/dist/cjs/use-size.cjs +69 -0
  58. package/dist/cjs/useControllableState.cjs +80 -0
  59. package/dist/cjs/useId.cjs +36 -0
  60. package/package.json +14 -7
@@ -0,0 +1,828 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var ScrollArea_exports = {};
20
+ __export(ScrollArea_exports, {
21
+ Corner: () => Corner,
22
+ Root: () => Root,
23
+ ScrollArea: () => Root,
24
+ ScrollAreaCorner: () => Corner,
25
+ ScrollAreaScrollbar: () => Scrollbar,
26
+ ScrollAreaThumb: () => Thumb,
27
+ ScrollAreaViewport: () => Viewport,
28
+ Scrollbar: () => Scrollbar,
29
+ Thumb: () => Thumb,
30
+ Viewport: () => Viewport,
31
+ createScrollAreaScope: () => createScrollAreaScope
32
+ });
33
+ module.exports = __toCommonJS(ScrollArea_exports);
34
+ var import_octane = require("octane");
35
+ var import_compose_event_handlers = require("./compose-event-handlers.cjs");
36
+ var import_compose_refs = require("./compose-refs.cjs");
37
+ var import_context = require("./context.cjs");
38
+ var import_direction = require("./direction.cjs");
39
+ var import_internal = require("./internal.cjs");
40
+ var import_Presence = require("./Presence.cjs");
41
+ var import_Primitive = require("./Primitive.cjs");
42
+ var import_use_callback_ref = require("./use-callback-ref.cjs");
43
+ const SCROLL_AREA_NAME = "ScrollArea";
44
+ const [createScrollAreaContext, createScrollAreaScope] = (0, import_context.createContextScope)(SCROLL_AREA_NAME);
45
+ const [ScrollAreaProvider, useScrollAreaContext] = createScrollAreaContext(SCROLL_AREA_NAME);
46
+ function Root(props) {
47
+ const slot = (0, import_internal.S)("ScrollArea.Root");
48
+ const {
49
+ __scopeScrollArea,
50
+ type = "hover",
51
+ dir,
52
+ scrollHideDelay = 600,
53
+ ref: forwardedRef,
54
+ ...scrollAreaProps
55
+ } = props ?? {};
56
+ const [scrollArea, setScrollArea] = (0, import_octane.useState)(null, (0, import_internal.subSlot)(slot, "area"));
57
+ const [viewport, setViewport] = (0, import_octane.useState)(null, (0, import_internal.subSlot)(slot, "viewport"));
58
+ const [content, setContent] = (0, import_octane.useState)(null, (0, import_internal.subSlot)(slot, "content"));
59
+ const [scrollbarX, setScrollbarX] = (0, import_octane.useState)(null, (0, import_internal.subSlot)(slot, "sbx"));
60
+ const [scrollbarY, setScrollbarY] = (0, import_octane.useState)(null, (0, import_internal.subSlot)(slot, "sby"));
61
+ const [cornerWidth, setCornerWidth] = (0, import_octane.useState)(0, (0, import_internal.subSlot)(slot, "cw"));
62
+ const [cornerHeight, setCornerHeight] = (0, import_octane.useState)(0, (0, import_internal.subSlot)(slot, "ch"));
63
+ const [scrollbarXEnabled, setScrollbarXEnabled] = (0, import_octane.useState)(false, (0, import_internal.subSlot)(slot, "sbxOn"));
64
+ const [scrollbarYEnabled, setScrollbarYEnabled] = (0, import_octane.useState)(false, (0, import_internal.subSlot)(slot, "sbyOn"));
65
+ const composedRefs = (0, import_compose_refs.useComposedRefs)(forwardedRef, setScrollArea, (0, import_internal.subSlot)(slot, "refs"));
66
+ const direction = (0, import_direction.useDirection)(dir);
67
+ return (0, import_octane.createElement)(ScrollAreaProvider, {
68
+ scope: __scopeScrollArea,
69
+ type,
70
+ dir: direction,
71
+ scrollHideDelay,
72
+ scrollArea,
73
+ viewport,
74
+ onViewportChange: setViewport,
75
+ content,
76
+ onContentChange: setContent,
77
+ scrollbarX,
78
+ onScrollbarXChange: setScrollbarX,
79
+ scrollbarXEnabled,
80
+ onScrollbarXEnabledChange: setScrollbarXEnabled,
81
+ scrollbarY,
82
+ onScrollbarYChange: setScrollbarY,
83
+ scrollbarYEnabled,
84
+ onScrollbarYEnabledChange: setScrollbarYEnabled,
85
+ onCornerWidthChange: setCornerWidth,
86
+ onCornerHeightChange: setCornerHeight,
87
+ children: (0, import_octane.createElement)(import_Primitive.Primitive.div, {
88
+ dir: direction,
89
+ ...scrollAreaProps,
90
+ ref: composedRefs,
91
+ style: {
92
+ position: "relative",
93
+ // Pass corner sizes as CSS vars to reduce re-renders of context consumers
94
+ "--radix-scroll-area-corner-width": cornerWidth + "px",
95
+ "--radix-scroll-area-corner-height": cornerHeight + "px",
96
+ ...props?.style
97
+ }
98
+ })
99
+ });
100
+ }
101
+ function ViewportStyle(props) {
102
+ return (0, import_octane.createElement)("style", {
103
+ dangerouslySetInnerHTML: {
104
+ __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}`
105
+ },
106
+ nonce: props.nonce
107
+ });
108
+ }
109
+ function Viewport(props) {
110
+ const slot = (0, import_internal.S)("ScrollArea.Viewport");
111
+ const { __scopeScrollArea, children, nonce, ref: forwardedRef, ...viewportProps } = props ?? {};
112
+ const context = useScrollAreaContext("ScrollAreaViewport", __scopeScrollArea);
113
+ const ref = (0, import_octane.useRef)(null, (0, import_internal.subSlot)(slot, "ref"));
114
+ const composedRefs = (0, import_compose_refs.useComposedRefs)(
115
+ forwardedRef,
116
+ ref,
117
+ context.onViewportChange,
118
+ (0, import_internal.subSlot)(slot, "refs")
119
+ );
120
+ return [
121
+ (0, import_octane.createElement)(ViewportStyle, { key: "style", nonce }),
122
+ (0, import_octane.createElement)(import_Primitive.Primitive.div, {
123
+ key: "viewport",
124
+ "data-radix-scroll-area-viewport": "",
125
+ ...viewportProps,
126
+ ref: composedRefs,
127
+ style: {
128
+ // `visible` is unsupported and `auto` would show native bars — force `scroll`
129
+ // and hide the native scrollbars with the injected style (see the source's
130
+ // rationale comment).
131
+ overflowX: context.scrollbarXEnabled ? "scroll" : "hidden",
132
+ overflowY: context.scrollbarYEnabled ? "scroll" : "hidden",
133
+ ...props?.style
134
+ },
135
+ // `display: table` ensures the content div matches the size of its children in
136
+ // both axes so scroll width/height changes are measurable for thumb sizing.
137
+ children: (0, import_octane.createElement)("div", {
138
+ ref: context.onContentChange,
139
+ style: { minWidth: "100%", display: "table" },
140
+ children
141
+ })
142
+ })
143
+ ];
144
+ }
145
+ const SCROLLBAR_NAME = "ScrollAreaScrollbar";
146
+ function Scrollbar(props) {
147
+ const slot = (0, import_internal.S)("ScrollArea.Scrollbar");
148
+ const { forceMount, ...scrollbarProps } = props ?? {};
149
+ const context = useScrollAreaContext(SCROLLBAR_NAME, props?.__scopeScrollArea);
150
+ const { onScrollbarXEnabledChange, onScrollbarYEnabledChange } = context;
151
+ const isHorizontal = props?.orientation === "horizontal";
152
+ (0, import_octane.useEffect)(
153
+ () => {
154
+ isHorizontal ? onScrollbarXEnabledChange(true) : onScrollbarYEnabledChange(true);
155
+ return () => {
156
+ isHorizontal ? onScrollbarXEnabledChange(false) : onScrollbarYEnabledChange(false);
157
+ };
158
+ },
159
+ [isHorizontal, onScrollbarXEnabledChange, onScrollbarYEnabledChange],
160
+ (0, import_internal.subSlot)(slot, "e:enabled")
161
+ );
162
+ return context.type === "hover" ? (0, import_octane.createElement)(ScrollbarHover, { ...scrollbarProps, forceMount }) : context.type === "scroll" ? (0, import_octane.createElement)(ScrollbarScroll, { ...scrollbarProps, forceMount }) : context.type === "auto" ? (0, import_octane.createElement)(ScrollbarAuto, { ...scrollbarProps, forceMount }) : context.type === "always" ? (0, import_octane.createElement)(ScrollbarVisible, { ...scrollbarProps, "data-state": "visible" }) : null;
163
+ }
164
+ function ScrollbarHover(props) {
165
+ const slot = (0, import_internal.S)("ScrollArea.ScrollbarHover");
166
+ const { forceMount, ...scrollbarProps } = props;
167
+ const context = useScrollAreaContext(SCROLLBAR_NAME, props.__scopeScrollArea);
168
+ const [visible, setVisible] = (0, import_octane.useState)(false, (0, import_internal.subSlot)(slot, "visible"));
169
+ (0, import_octane.useEffect)(
170
+ () => {
171
+ const scrollArea = context.scrollArea;
172
+ let hideTimer = 0;
173
+ if (scrollArea) {
174
+ const handlePointerEnter = () => {
175
+ window.clearTimeout(hideTimer);
176
+ setVisible(true);
177
+ };
178
+ const handlePointerLeave = () => {
179
+ hideTimer = window.setTimeout(() => setVisible(false), context.scrollHideDelay);
180
+ };
181
+ scrollArea.addEventListener("pointerenter", handlePointerEnter);
182
+ scrollArea.addEventListener("pointerleave", handlePointerLeave);
183
+ return () => {
184
+ window.clearTimeout(hideTimer);
185
+ scrollArea.removeEventListener("pointerenter", handlePointerEnter);
186
+ scrollArea.removeEventListener("pointerleave", handlePointerLeave);
187
+ };
188
+ }
189
+ },
190
+ [context.scrollArea, context.scrollHideDelay],
191
+ (0, import_internal.subSlot)(slot, "e:hover")
192
+ );
193
+ return (0, import_octane.createElement)(import_Presence.Presence, {
194
+ present: forceMount || visible,
195
+ children: (0, import_octane.createElement)(ScrollbarAuto, {
196
+ "data-state": visible ? "visible" : "hidden",
197
+ ...scrollbarProps
198
+ })
199
+ });
200
+ }
201
+ function useStateMachine(initialState, machine, slot) {
202
+ const [state, dispatch] = (0, import_octane.useReducer)(
203
+ (state2, event) => {
204
+ const nextState = machine[state2][event];
205
+ return nextState ?? state2;
206
+ },
207
+ initialState,
208
+ slot
209
+ );
210
+ return [state, dispatch];
211
+ }
212
+ function ScrollbarScroll(props) {
213
+ const slot = (0, import_internal.S)("ScrollArea.ScrollbarScroll");
214
+ const { forceMount, ...scrollbarProps } = props;
215
+ const context = useScrollAreaContext(SCROLLBAR_NAME, props.__scopeScrollArea);
216
+ const isHorizontal = props.orientation === "horizontal";
217
+ const debounceScrollEnd = useDebounceCallback(
218
+ () => send("SCROLL_END"),
219
+ 100,
220
+ (0, import_internal.subSlot)(slot, "debounce")
221
+ );
222
+ const [state, send] = useStateMachine(
223
+ "hidden",
224
+ {
225
+ hidden: {
226
+ SCROLL: "scrolling"
227
+ },
228
+ scrolling: {
229
+ SCROLL_END: "idle",
230
+ POINTER_ENTER: "interacting"
231
+ },
232
+ interacting: {
233
+ SCROLL: "interacting",
234
+ POINTER_LEAVE: "idle"
235
+ },
236
+ idle: {
237
+ HIDE: "hidden",
238
+ SCROLL: "scrolling",
239
+ POINTER_ENTER: "interacting"
240
+ }
241
+ },
242
+ (0, import_internal.subSlot)(slot, "machine")
243
+ );
244
+ (0, import_octane.useEffect)(
245
+ () => {
246
+ if (state === "idle") {
247
+ const hideTimer = window.setTimeout(() => send("HIDE"), context.scrollHideDelay);
248
+ return () => window.clearTimeout(hideTimer);
249
+ }
250
+ },
251
+ [state, context.scrollHideDelay, send],
252
+ (0, import_internal.subSlot)(slot, "e:hide")
253
+ );
254
+ (0, import_octane.useEffect)(
255
+ () => {
256
+ const viewport = context.viewport;
257
+ const scrollDirection = isHorizontal ? "scrollLeft" : "scrollTop";
258
+ if (viewport) {
259
+ let prevScrollPos = viewport[scrollDirection];
260
+ const handleScroll = () => {
261
+ const scrollPos = viewport[scrollDirection];
262
+ const hasScrollInDirectionChanged = prevScrollPos !== scrollPos;
263
+ if (hasScrollInDirectionChanged) {
264
+ send("SCROLL");
265
+ debounceScrollEnd();
266
+ }
267
+ prevScrollPos = scrollPos;
268
+ };
269
+ viewport.addEventListener("scroll", handleScroll);
270
+ return () => viewport.removeEventListener("scroll", handleScroll);
271
+ }
272
+ },
273
+ [context.viewport, isHorizontal, send, debounceScrollEnd],
274
+ (0, import_internal.subSlot)(slot, "e:scroll")
275
+ );
276
+ return (0, import_octane.createElement)(import_Presence.Presence, {
277
+ present: forceMount || state !== "hidden",
278
+ children: (0, import_octane.createElement)(ScrollbarVisible, {
279
+ "data-state": state === "hidden" ? "hidden" : "visible",
280
+ ...scrollbarProps,
281
+ onPointerEnter: (0, import_compose_event_handlers.composeEventHandlers)(props.onPointerEnter, () => send("POINTER_ENTER")),
282
+ onPointerLeave: (0, import_compose_event_handlers.composeEventHandlers)(props.onPointerLeave, () => send("POINTER_LEAVE"))
283
+ })
284
+ });
285
+ }
286
+ function ScrollbarAuto(props) {
287
+ const slot = (0, import_internal.S)("ScrollArea.ScrollbarAuto");
288
+ const context = useScrollAreaContext(SCROLLBAR_NAME, props.__scopeScrollArea);
289
+ const { forceMount, ...scrollbarProps } = props;
290
+ const [visible, setVisible] = (0, import_octane.useState)(false, (0, import_internal.subSlot)(slot, "visible"));
291
+ const isHorizontal = props.orientation === "horizontal";
292
+ const handleResize = useDebounceCallback(
293
+ () => {
294
+ if (context.viewport) {
295
+ const isOverflowX = context.viewport.offsetWidth < context.viewport.scrollWidth;
296
+ const isOverflowY = context.viewport.offsetHeight < context.viewport.scrollHeight;
297
+ setVisible(isHorizontal ? isOverflowX : isOverflowY);
298
+ }
299
+ },
300
+ 10,
301
+ (0, import_internal.subSlot)(slot, "debounce")
302
+ );
303
+ useResizeObserver(context.viewport, handleResize, (0, import_internal.subSlot)(slot, "ro:viewport"));
304
+ useResizeObserver(context.content, handleResize, (0, import_internal.subSlot)(slot, "ro:content"));
305
+ return (0, import_octane.createElement)(import_Presence.Presence, {
306
+ present: forceMount || visible,
307
+ children: (0, import_octane.createElement)(ScrollbarVisible, {
308
+ "data-state": visible ? "visible" : "hidden",
309
+ ...scrollbarProps
310
+ })
311
+ });
312
+ }
313
+ function ScrollbarVisible(props) {
314
+ const slot = (0, import_internal.S)("ScrollArea.ScrollbarVisible");
315
+ const { orientation = "vertical", ref: forwardedRef, ...scrollbarProps } = props;
316
+ const context = useScrollAreaContext(SCROLLBAR_NAME, props.__scopeScrollArea);
317
+ const thumbRef = (0, import_octane.useRef)(null, (0, import_internal.subSlot)(slot, "thumb"));
318
+ const pointerOffsetRef = (0, import_octane.useRef)(0, (0, import_internal.subSlot)(slot, "offset"));
319
+ const [sizes, setSizes] = (0, import_octane.useState)(
320
+ {
321
+ content: 0,
322
+ viewport: 0,
323
+ scrollbar: { size: 0, paddingStart: 0, paddingEnd: 0 }
324
+ },
325
+ (0, import_internal.subSlot)(slot, "sizes")
326
+ );
327
+ const thumbRatio = getThumbRatio(sizes.viewport, sizes.content);
328
+ const commonProps = {
329
+ ...scrollbarProps,
330
+ sizes,
331
+ onSizesChange: setSizes,
332
+ hasThumb: Boolean(thumbRatio > 0 && thumbRatio < 1),
333
+ onThumbChange: (thumb) => thumbRef.current = thumb,
334
+ onThumbPointerUp: () => pointerOffsetRef.current = 0,
335
+ onThumbPointerDown: (pointerPos) => pointerOffsetRef.current = pointerPos
336
+ };
337
+ function getScrollPosition(pointerPos, dir) {
338
+ return getScrollPositionFromPointer(pointerPos, pointerOffsetRef.current, sizes, dir);
339
+ }
340
+ if (orientation === "horizontal") {
341
+ return (0, import_octane.createElement)(ScrollbarX, {
342
+ ...commonProps,
343
+ ref: forwardedRef,
344
+ onThumbPositionChange: () => {
345
+ if (context.viewport && thumbRef.current) {
346
+ const scrollPos = context.viewport.scrollLeft;
347
+ const offset = getThumbOffsetFromScroll(scrollPos, sizes, context.dir);
348
+ thumbRef.current.style.transform = `translate3d(${offset}px, 0, 0)`;
349
+ }
350
+ },
351
+ onWheelScroll: (scrollPos) => {
352
+ if (context.viewport) context.viewport.scrollLeft = scrollPos;
353
+ },
354
+ onDragScroll: (pointerPos) => {
355
+ if (context.viewport) {
356
+ context.viewport.scrollLeft = getScrollPosition(pointerPos, context.dir);
357
+ }
358
+ }
359
+ });
360
+ }
361
+ if (orientation === "vertical") {
362
+ return (0, import_octane.createElement)(ScrollbarY, {
363
+ ...commonProps,
364
+ ref: forwardedRef,
365
+ onThumbPositionChange: () => {
366
+ if (context.viewport && thumbRef.current) {
367
+ const scrollPos = context.viewport.scrollTop;
368
+ const offset = getThumbOffsetFromScroll(scrollPos, sizes);
369
+ thumbRef.current.style.transform = `translate3d(0, ${offset}px, 0)`;
370
+ }
371
+ },
372
+ onWheelScroll: (scrollPos) => {
373
+ if (context.viewport) context.viewport.scrollTop = scrollPos;
374
+ },
375
+ onDragScroll: (pointerPos) => {
376
+ if (context.viewport) context.viewport.scrollTop = getScrollPosition(pointerPos);
377
+ }
378
+ });
379
+ }
380
+ return null;
381
+ }
382
+ function ScrollbarX(props) {
383
+ const slot = (0, import_internal.S)("ScrollArea.ScrollbarX");
384
+ const { sizes, onSizesChange, ref: forwardedRef, ...scrollbarProps } = props;
385
+ const context = useScrollAreaContext(SCROLLBAR_NAME, props.__scopeScrollArea);
386
+ const [computedStyle, setComputedStyle] = (0, import_octane.useState)(
387
+ void 0,
388
+ (0, import_internal.subSlot)(slot, "style")
389
+ );
390
+ const ref = (0, import_octane.useRef)(null, (0, import_internal.subSlot)(slot, "ref"));
391
+ const composeRefs = (0, import_compose_refs.useComposedRefs)(
392
+ forwardedRef,
393
+ ref,
394
+ context.onScrollbarXChange,
395
+ (0, import_internal.subSlot)(slot, "refs")
396
+ );
397
+ (0, import_octane.useEffect)(
398
+ () => {
399
+ if (ref.current) setComputedStyle(getComputedStyle(ref.current));
400
+ },
401
+ [ref],
402
+ (0, import_internal.subSlot)(slot, "e:style")
403
+ );
404
+ return (0, import_octane.createElement)(ScrollbarImpl, {
405
+ "data-orientation": "horizontal",
406
+ ...scrollbarProps,
407
+ __scopeScrollArea: props.__scopeScrollArea,
408
+ ref: composeRefs,
409
+ sizes,
410
+ style: {
411
+ bottom: 0,
412
+ left: context.dir === "rtl" ? "var(--radix-scroll-area-corner-width)" : 0,
413
+ right: context.dir === "ltr" ? "var(--radix-scroll-area-corner-width)" : 0,
414
+ "--radix-scroll-area-thumb-width": getThumbSize(sizes) + "px",
415
+ ...props.style
416
+ },
417
+ onThumbPointerDown: (pointerPos) => props.onThumbPointerDown(pointerPos.x),
418
+ onDragScroll: (pointerPos) => props.onDragScroll(pointerPos.x),
419
+ onWheelScroll: (event, maxScrollPos) => {
420
+ if (context.viewport) {
421
+ const scrollPos = context.viewport.scrollLeft + event.deltaX;
422
+ props.onWheelScroll(scrollPos);
423
+ if (isScrollingWithinScrollbarBounds(scrollPos, maxScrollPos)) {
424
+ event.preventDefault();
425
+ }
426
+ }
427
+ },
428
+ onResize: () => {
429
+ if (ref.current && context.viewport && computedStyle) {
430
+ onSizesChange({
431
+ content: context.viewport.scrollWidth,
432
+ viewport: context.viewport.offsetWidth,
433
+ scrollbar: {
434
+ size: ref.current.clientWidth,
435
+ paddingStart: toInt(computedStyle.paddingLeft),
436
+ paddingEnd: toInt(computedStyle.paddingRight)
437
+ }
438
+ });
439
+ }
440
+ }
441
+ });
442
+ }
443
+ function ScrollbarY(props) {
444
+ const slot = (0, import_internal.S)("ScrollArea.ScrollbarY");
445
+ const { sizes, onSizesChange, ref: forwardedRef, ...scrollbarProps } = props;
446
+ const context = useScrollAreaContext(SCROLLBAR_NAME, props.__scopeScrollArea);
447
+ const [computedStyle, setComputedStyle] = (0, import_octane.useState)(
448
+ void 0,
449
+ (0, import_internal.subSlot)(slot, "style")
450
+ );
451
+ const ref = (0, import_octane.useRef)(null, (0, import_internal.subSlot)(slot, "ref"));
452
+ const composeRefs = (0, import_compose_refs.useComposedRefs)(
453
+ forwardedRef,
454
+ ref,
455
+ context.onScrollbarYChange,
456
+ (0, import_internal.subSlot)(slot, "refs")
457
+ );
458
+ (0, import_octane.useEffect)(
459
+ () => {
460
+ if (ref.current) setComputedStyle(getComputedStyle(ref.current));
461
+ },
462
+ [ref],
463
+ (0, import_internal.subSlot)(slot, "e:style")
464
+ );
465
+ return (0, import_octane.createElement)(ScrollbarImpl, {
466
+ "data-orientation": "vertical",
467
+ ...scrollbarProps,
468
+ __scopeScrollArea: props.__scopeScrollArea,
469
+ ref: composeRefs,
470
+ sizes,
471
+ style: {
472
+ top: 0,
473
+ right: context.dir === "ltr" ? 0 : void 0,
474
+ left: context.dir === "rtl" ? 0 : void 0,
475
+ bottom: "var(--radix-scroll-area-corner-height)",
476
+ "--radix-scroll-area-thumb-height": getThumbSize(sizes) + "px",
477
+ ...props.style
478
+ },
479
+ onThumbPointerDown: (pointerPos) => props.onThumbPointerDown(pointerPos.y),
480
+ onDragScroll: (pointerPos) => props.onDragScroll(pointerPos.y),
481
+ onWheelScroll: (event, maxScrollPos) => {
482
+ if (context.viewport) {
483
+ const scrollPos = context.viewport.scrollTop + event.deltaY;
484
+ props.onWheelScroll(scrollPos);
485
+ if (isScrollingWithinScrollbarBounds(scrollPos, maxScrollPos)) {
486
+ event.preventDefault();
487
+ }
488
+ }
489
+ },
490
+ onResize: () => {
491
+ if (ref.current && context.viewport && computedStyle) {
492
+ onSizesChange({
493
+ content: context.viewport.scrollHeight,
494
+ viewport: context.viewport.offsetHeight,
495
+ scrollbar: {
496
+ size: ref.current.clientHeight,
497
+ paddingStart: toInt(computedStyle.paddingTop),
498
+ paddingEnd: toInt(computedStyle.paddingBottom)
499
+ }
500
+ });
501
+ }
502
+ }
503
+ });
504
+ }
505
+ const [ScrollbarProvider, useScrollbarContext] = createScrollAreaContext(SCROLLBAR_NAME);
506
+ function ScrollbarImpl(props) {
507
+ const slot = (0, import_internal.S)("ScrollArea.ScrollbarImpl");
508
+ const {
509
+ __scopeScrollArea,
510
+ sizes,
511
+ hasThumb,
512
+ onThumbChange,
513
+ onThumbPointerUp,
514
+ onThumbPointerDown,
515
+ onThumbPositionChange,
516
+ onDragScroll,
517
+ onWheelScroll,
518
+ onResize,
519
+ ref: forwardedRef,
520
+ ...scrollbarProps
521
+ } = props;
522
+ const context = useScrollAreaContext(SCROLLBAR_NAME, __scopeScrollArea);
523
+ const [scrollbar, setScrollbar] = (0, import_octane.useState)(null, (0, import_internal.subSlot)(slot, "node"));
524
+ const composeRefs = (0, import_compose_refs.useComposedRefs)(forwardedRef, setScrollbar, (0, import_internal.subSlot)(slot, "refs"));
525
+ const rectRef = (0, import_octane.useRef)(null, (0, import_internal.subSlot)(slot, "rect"));
526
+ const prevWebkitUserSelectRef = (0, import_octane.useRef)("", (0, import_internal.subSlot)(slot, "select"));
527
+ const viewport = context.viewport;
528
+ const maxScrollPos = sizes.content - sizes.viewport;
529
+ const handleWheelScroll = (0, import_use_callback_ref.useCallbackRef)(onWheelScroll, (0, import_internal.subSlot)(slot, "wheel"));
530
+ const handleThumbPositionChange = (0, import_use_callback_ref.useCallbackRef)(onThumbPositionChange, (0, import_internal.subSlot)(slot, "thumb"));
531
+ const handleResize = useDebounceCallback(onResize, 10, (0, import_internal.subSlot)(slot, "resize"));
532
+ function handleDragScroll(event) {
533
+ if (rectRef.current) {
534
+ const x = event.clientX - rectRef.current.left;
535
+ const y = event.clientY - rectRef.current.top;
536
+ onDragScroll({ x, y });
537
+ }
538
+ }
539
+ (0, import_octane.useEffect)(
540
+ () => {
541
+ const handleWheel = (event) => {
542
+ const element = event.target;
543
+ const isScrollbarWheel = scrollbar?.contains(element);
544
+ if (isScrollbarWheel) handleWheelScroll(event, maxScrollPos);
545
+ };
546
+ document.addEventListener("wheel", handleWheel, { passive: false });
547
+ return () => document.removeEventListener("wheel", handleWheel, { passive: false });
548
+ },
549
+ [viewport, scrollbar, maxScrollPos, handleWheelScroll],
550
+ (0, import_internal.subSlot)(slot, "e:wheel")
551
+ );
552
+ (0, import_octane.useEffect)(handleThumbPositionChange, [sizes, handleThumbPositionChange], (0, import_internal.subSlot)(slot, "e:pos"));
553
+ useResizeObserver(scrollbar, handleResize, (0, import_internal.subSlot)(slot, "ro:scrollbar"));
554
+ useResizeObserver(context.content, handleResize, (0, import_internal.subSlot)(slot, "ro:content"));
555
+ return (0, import_octane.createElement)(ScrollbarProvider, {
556
+ scope: __scopeScrollArea,
557
+ scrollbar,
558
+ hasThumb,
559
+ onThumbChange: (0, import_use_callback_ref.useCallbackRef)(onThumbChange, (0, import_internal.subSlot)(slot, "cb:thumb")),
560
+ onThumbPointerUp: (0, import_use_callback_ref.useCallbackRef)(onThumbPointerUp, (0, import_internal.subSlot)(slot, "cb:up")),
561
+ onThumbPositionChange: handleThumbPositionChange,
562
+ onThumbPointerDown: (0, import_use_callback_ref.useCallbackRef)(onThumbPointerDown, (0, import_internal.subSlot)(slot, "cb:down")),
563
+ children: (0, import_octane.createElement)(import_Primitive.Primitive.div, {
564
+ ...scrollbarProps,
565
+ ref: composeRefs,
566
+ style: { position: "absolute", ...scrollbarProps.style },
567
+ onPointerDown: (0, import_compose_event_handlers.composeEventHandlers)(props.onPointerDown, (event) => {
568
+ const mainPointer = 0;
569
+ if (event.button === mainPointer) {
570
+ const element = event.target;
571
+ element.setPointerCapture(event.pointerId);
572
+ rectRef.current = scrollbar.getBoundingClientRect();
573
+ prevWebkitUserSelectRef.current = document.body.style.webkitUserSelect;
574
+ document.body.style.webkitUserSelect = "none";
575
+ if (context.viewport) context.viewport.style.scrollBehavior = "auto";
576
+ handleDragScroll(event);
577
+ }
578
+ }),
579
+ onPointerMove: (0, import_compose_event_handlers.composeEventHandlers)(props.onPointerMove, handleDragScroll),
580
+ onPointerUp: (0, import_compose_event_handlers.composeEventHandlers)(props.onPointerUp, (event) => {
581
+ const element = event.target;
582
+ if (element.hasPointerCapture(event.pointerId)) {
583
+ element.releasePointerCapture(event.pointerId);
584
+ }
585
+ document.body.style.webkitUserSelect = prevWebkitUserSelectRef.current;
586
+ if (context.viewport) context.viewport.style.scrollBehavior = "";
587
+ rectRef.current = null;
588
+ })
589
+ })
590
+ });
591
+ }
592
+ const THUMB_NAME = "ScrollAreaThumb";
593
+ function Thumb(props) {
594
+ const { forceMount, ...thumbProps } = props ?? {};
595
+ const scrollbarContext = useScrollbarContext(THUMB_NAME, props?.__scopeScrollArea);
596
+ return (0, import_octane.createElement)(import_Presence.Presence, {
597
+ present: forceMount || scrollbarContext.hasThumb,
598
+ children: (0, import_octane.createElement)(ThumbImpl, thumbProps)
599
+ });
600
+ }
601
+ function ThumbImpl(props) {
602
+ const slot = (0, import_internal.S)("ScrollArea.ThumbImpl");
603
+ const { __scopeScrollArea, style, ref: forwardedRef, ...thumbProps } = props;
604
+ const scrollAreaContext = useScrollAreaContext(THUMB_NAME, __scopeScrollArea);
605
+ const scrollbarContext = useScrollbarContext(THUMB_NAME, __scopeScrollArea);
606
+ const { onThumbPositionChange } = scrollbarContext;
607
+ const composedRef = (0, import_compose_refs.useComposedRefs)(
608
+ forwardedRef,
609
+ scrollbarContext.onThumbChange,
610
+ (0, import_internal.subSlot)(slot, "refs")
611
+ );
612
+ const removeUnlinkedScrollListenerRef = (0, import_octane.useRef)(
613
+ void 0,
614
+ (0, import_internal.subSlot)(slot, "unlinked")
615
+ );
616
+ const debounceScrollEnd = useDebounceCallback(
617
+ () => {
618
+ if (removeUnlinkedScrollListenerRef.current) {
619
+ removeUnlinkedScrollListenerRef.current();
620
+ removeUnlinkedScrollListenerRef.current = void 0;
621
+ }
622
+ },
623
+ 100,
624
+ (0, import_internal.subSlot)(slot, "debounce")
625
+ );
626
+ (0, import_octane.useEffect)(
627
+ () => {
628
+ const viewport = scrollAreaContext.viewport;
629
+ if (viewport) {
630
+ const handleScroll = () => {
631
+ debounceScrollEnd();
632
+ if (!removeUnlinkedScrollListenerRef.current) {
633
+ const listener = addUnlinkedScrollListener(viewport, onThumbPositionChange);
634
+ removeUnlinkedScrollListenerRef.current = listener;
635
+ onThumbPositionChange();
636
+ }
637
+ };
638
+ onThumbPositionChange();
639
+ viewport.addEventListener("scroll", handleScroll);
640
+ return () => viewport.removeEventListener("scroll", handleScroll);
641
+ }
642
+ },
643
+ [scrollAreaContext.viewport, debounceScrollEnd, onThumbPositionChange],
644
+ (0, import_internal.subSlot)(slot, "e:scroll")
645
+ );
646
+ return (0, import_octane.createElement)(import_Primitive.Primitive.div, {
647
+ "data-state": scrollbarContext.hasThumb ? "visible" : "hidden",
648
+ ...thumbProps,
649
+ ref: composedRef,
650
+ style: {
651
+ width: "var(--radix-scroll-area-thumb-width)",
652
+ height: "var(--radix-scroll-area-thumb-height)",
653
+ ...style
654
+ },
655
+ onPointerDownCapture: (0, import_compose_event_handlers.composeEventHandlers)(
656
+ props.onPointerDownCapture,
657
+ (event) => {
658
+ const thumb = event.target;
659
+ const thumbRect = thumb.getBoundingClientRect();
660
+ const x = event.clientX - thumbRect.left;
661
+ const y = event.clientY - thumbRect.top;
662
+ scrollbarContext.onThumbPointerDown({ x, y });
663
+ }
664
+ ),
665
+ onPointerUp: (0, import_compose_event_handlers.composeEventHandlers)(props.onPointerUp, scrollbarContext.onThumbPointerUp)
666
+ });
667
+ }
668
+ const CORNER_NAME = "ScrollAreaCorner";
669
+ function Corner(props) {
670
+ const context = useScrollAreaContext(CORNER_NAME, props?.__scopeScrollArea);
671
+ const hasBothScrollbarsVisible = Boolean(context.scrollbarX && context.scrollbarY);
672
+ const hasCorner = context.type !== "scroll" && hasBothScrollbarsVisible;
673
+ return hasCorner ? (0, import_octane.createElement)(CornerImpl, props) : null;
674
+ }
675
+ function CornerImpl(props) {
676
+ const slot = (0, import_internal.S)("ScrollArea.CornerImpl");
677
+ const { __scopeScrollArea, ...cornerProps } = props;
678
+ const context = useScrollAreaContext(CORNER_NAME, __scopeScrollArea);
679
+ const [width, setWidth] = (0, import_octane.useState)(0, (0, import_internal.subSlot)(slot, "w"));
680
+ const [height, setHeight] = (0, import_octane.useState)(0, (0, import_internal.subSlot)(slot, "h"));
681
+ const hasSize = Boolean(width && height);
682
+ useResizeObserver(
683
+ context.scrollbarX,
684
+ () => {
685
+ const height2 = context.scrollbarX?.offsetHeight || 0;
686
+ context.onCornerHeightChange(height2);
687
+ setHeight(height2);
688
+ },
689
+ (0, import_internal.subSlot)(slot, "ro:x")
690
+ );
691
+ useResizeObserver(
692
+ context.scrollbarY,
693
+ () => {
694
+ const width2 = context.scrollbarY?.offsetWidth || 0;
695
+ context.onCornerWidthChange(width2);
696
+ setWidth(width2);
697
+ },
698
+ (0, import_internal.subSlot)(slot, "ro:y")
699
+ );
700
+ return hasSize ? (0, import_octane.createElement)(import_Primitive.Primitive.div, {
701
+ ...cornerProps,
702
+ style: {
703
+ width,
704
+ height,
705
+ position: "absolute",
706
+ right: context.dir === "ltr" ? 0 : void 0,
707
+ left: context.dir === "rtl" ? 0 : void 0,
708
+ bottom: 0,
709
+ ...props.style
710
+ }
711
+ }) : null;
712
+ }
713
+ function toInt(value) {
714
+ return value ? parseInt(value, 10) : 0;
715
+ }
716
+ function getThumbRatio(viewportSize, contentSize) {
717
+ const ratio = viewportSize / contentSize;
718
+ return isNaN(ratio) ? 0 : ratio;
719
+ }
720
+ function getThumbSize(sizes) {
721
+ const ratio = getThumbRatio(sizes.viewport, sizes.content);
722
+ const scrollbarPadding = sizes.scrollbar.paddingStart + sizes.scrollbar.paddingEnd;
723
+ const thumbSize = (sizes.scrollbar.size - scrollbarPadding) * ratio;
724
+ return Math.max(thumbSize, 18);
725
+ }
726
+ function getScrollPositionFromPointer(pointerPos, pointerOffset, sizes, dir = "ltr") {
727
+ const thumbSizePx = getThumbSize(sizes);
728
+ const thumbCenter = thumbSizePx / 2;
729
+ const offset = pointerOffset || thumbCenter;
730
+ const thumbOffsetFromEnd = thumbSizePx - offset;
731
+ const minPointerPos = sizes.scrollbar.paddingStart + offset;
732
+ const maxPointerPos = sizes.scrollbar.size - sizes.scrollbar.paddingEnd - thumbOffsetFromEnd;
733
+ const maxScrollPos = sizes.content - sizes.viewport;
734
+ const scrollRange = dir === "ltr" ? [0, maxScrollPos] : [maxScrollPos * -1, 0];
735
+ const interpolate = linearScale([minPointerPos, maxPointerPos], scrollRange);
736
+ return interpolate(pointerPos);
737
+ }
738
+ function getThumbOffsetFromScroll(scrollPos, sizes, dir = "ltr") {
739
+ const thumbSizePx = getThumbSize(sizes);
740
+ const scrollbarPadding = sizes.scrollbar.paddingStart + sizes.scrollbar.paddingEnd;
741
+ const scrollbar = sizes.scrollbar.size - scrollbarPadding;
742
+ const maxScrollPos = sizes.content - sizes.viewport;
743
+ const maxThumbPos = scrollbar - thumbSizePx;
744
+ const scrollClampRange = dir === "ltr" ? [0, maxScrollPos] : [maxScrollPos * -1, 0];
745
+ const scrollWithoutMomentum = clamp(scrollPos, scrollClampRange);
746
+ const interpolate = linearScale([0, maxScrollPos], [0, maxThumbPos]);
747
+ return interpolate(scrollWithoutMomentum);
748
+ }
749
+ function linearScale(input, output) {
750
+ return (value) => {
751
+ if (input[0] === input[1] || output[0] === output[1]) return output[0];
752
+ const ratio = (output[1] - output[0]) / (input[1] - input[0]);
753
+ return output[0] + ratio * (value - input[0]);
754
+ };
755
+ }
756
+ function clamp(value, [min, max]) {
757
+ return Math.min(max, Math.max(min, value));
758
+ }
759
+ function isScrollingWithinScrollbarBounds(scrollPos, maxScrollPos) {
760
+ return scrollPos > 0 && scrollPos < maxScrollPos;
761
+ }
762
+ const addUnlinkedScrollListener = (node, handler = () => {
763
+ }) => {
764
+ let prevPosition = { left: node.scrollLeft, top: node.scrollTop };
765
+ let rAF = 0;
766
+ (function loop() {
767
+ const position = { left: node.scrollLeft, top: node.scrollTop };
768
+ const isHorizontalScroll = prevPosition.left !== position.left;
769
+ const isVerticalScroll = prevPosition.top !== position.top;
770
+ if (isHorizontalScroll || isVerticalScroll) handler();
771
+ prevPosition = position;
772
+ rAF = window.requestAnimationFrame(loop);
773
+ })();
774
+ return () => window.cancelAnimationFrame(rAF);
775
+ };
776
+ function useDebounceCallback(callback, delay, slot) {
777
+ const handleCallback = (0, import_use_callback_ref.useCallbackRef)(callback, (0, import_internal.subSlot)(slot, "cb"));
778
+ const debounceTimerRef = (0, import_octane.useRef)(0, (0, import_internal.subSlot)(slot, "timer"));
779
+ (0, import_octane.useEffect)(
780
+ () => () => window.clearTimeout(debounceTimerRef.current),
781
+ [],
782
+ (0, import_internal.subSlot)(slot, "e:clear")
783
+ );
784
+ return (0, import_octane.useCallback)(
785
+ () => {
786
+ window.clearTimeout(debounceTimerRef.current);
787
+ debounceTimerRef.current = window.setTimeout(handleCallback, delay);
788
+ },
789
+ [handleCallback, delay],
790
+ (0, import_internal.subSlot)(slot, "memo")
791
+ );
792
+ }
793
+ function useResizeObserver(element, onResize, slot) {
794
+ const handleResize = (0, import_use_callback_ref.useCallbackRef)(onResize, (0, import_internal.subSlot)(slot, "cb"));
795
+ (0, import_octane.useLayoutEffect)(
796
+ () => {
797
+ let rAF = 0;
798
+ if (element) {
799
+ if (typeof ResizeObserver === "undefined") return;
800
+ const resizeObserver = new ResizeObserver(() => {
801
+ cancelAnimationFrame(rAF);
802
+ rAF = window.requestAnimationFrame(handleResize);
803
+ });
804
+ resizeObserver.observe(element);
805
+ return () => {
806
+ window.cancelAnimationFrame(rAF);
807
+ resizeObserver.unobserve(element);
808
+ };
809
+ }
810
+ },
811
+ [element, handleResize],
812
+ (0, import_internal.subSlot)(slot, "e")
813
+ );
814
+ }
815
+ // Annotate the CommonJS export names for ESM import in node:
816
+ 0 && (module.exports = {
817
+ Corner,
818
+ Root,
819
+ ScrollArea,
820
+ ScrollAreaCorner,
821
+ ScrollAreaScrollbar,
822
+ ScrollAreaThumb,
823
+ ScrollAreaViewport,
824
+ Scrollbar,
825
+ Thumb,
826
+ Viewport,
827
+ createScrollAreaScope
828
+ });