@jobber/components 8.14.0 → 8.15.0
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.
- package/FilterPicker.d.ts +1 -0
- package/{Combobox.js → FilterPicker.js} +3 -3
- package/dist/Autocomplete-es.js +1 -1
- package/dist/BottomSheet-cjs.js +109 -77
- package/dist/BottomSheet-es.js +103 -75
- package/dist/Card/index.cjs +1 -2
- package/dist/Card/index.mjs +1 -2
- package/dist/DataDump/index.cjs +1 -2
- package/dist/DataDump/index.mjs +1 -2
- package/dist/DataList/components/DataListFilters/components/DataListSort/index.cjs +11 -11
- package/dist/DataList/components/DataListFilters/components/DataListSort/index.mjs +11 -11
- package/dist/DataList/components/DataListFilters/index.cjs +11 -11
- package/dist/DataList/components/DataListFilters/index.mjs +11 -11
- package/dist/DataList/index.cjs +11 -11
- package/dist/DataList/index.mjs +11 -11
- package/dist/DataListSort-cjs.js +5 -5
- package/dist/DataListSort-es.js +5 -5
- package/dist/FilterPicker/FilterPicker.d.ts +11 -0
- package/dist/{Combobox/Combobox.types.d.ts → FilterPicker/FilterPicker.types.d.ts} +51 -51
- package/dist/FilterPicker/FilterPickerProvider.d.ts +18 -0
- package/dist/FilterPicker/components/FilterPickerAction/FilterPickerAction.d.ts +3 -0
- package/dist/FilterPicker/components/FilterPickerAction/index.cjs +12 -0
- package/dist/FilterPicker/components/FilterPickerAction/index.d.ts +1 -0
- package/dist/FilterPicker/components/FilterPickerAction/index.mjs +6 -0
- package/dist/FilterPicker/components/FilterPickerActivator/FilterPickerActivator.d.ts +3 -0
- package/dist/{Combobox/components/ComboboxActivator → FilterPicker/components/FilterPickerActivator}/index.cjs +3 -3
- package/dist/FilterPicker/components/FilterPickerActivator/index.d.ts +1 -0
- package/dist/{Combobox/components/ComboboxActivator → FilterPicker/components/FilterPickerActivator}/index.mjs +2 -2
- package/dist/FilterPicker/components/FilterPickerContent/FilterPickerContent.d.ts +3 -0
- package/dist/FilterPicker/components/FilterPickerContent/FilterPickerContentHeader/FilterPickerContentHeader.d.ts +3 -0
- package/dist/{Combobox/components/ComboboxContent/ComboboxContentHeader → FilterPicker/components/FilterPickerContent/FilterPickerContentHeader}/index.cjs +2 -2
- package/dist/FilterPicker/components/FilterPickerContent/FilterPickerContentHeader/index.d.ts +1 -0
- package/dist/{Combobox/components/ComboboxContent/ComboboxContentHeader → FilterPicker/components/FilterPickerContent/FilterPickerContentHeader}/index.mjs +1 -1
- package/dist/FilterPicker/components/FilterPickerContent/FilterPickerContentList/FilterPickerContentList.d.ts +3 -0
- package/dist/FilterPicker/components/FilterPickerContent/FilterPickerContentList/FilterPickerContentList.module.css.d.ts +13 -0
- package/dist/{Combobox/components/ComboboxContent/ComboboxContentList → FilterPicker/components/FilterPickerContent/FilterPickerContentList}/index.cjs +5 -5
- package/dist/FilterPicker/components/FilterPickerContent/FilterPickerContentList/index.d.ts +1 -0
- package/dist/{Combobox/components/ComboboxContent/ComboboxContentList → FilterPicker/components/FilterPickerContent/FilterPickerContentList}/index.mjs +4 -4
- package/dist/FilterPicker/components/FilterPickerContent/FilterPickerContentSearch/FilterPickerContentSearch.d.ts +3 -0
- package/dist/FilterPicker/components/FilterPickerContent/FilterPickerContentSearch/index.cjs +10 -0
- package/dist/FilterPicker/components/FilterPickerContent/FilterPickerContentSearch/index.d.ts +1 -0
- package/dist/FilterPicker/components/FilterPickerContent/FilterPickerContentSearch/index.mjs +4 -0
- package/dist/FilterPicker/components/FilterPickerContent/FilterPickerLoadMore/FilterPickerLoadMore.d.ts +6 -0
- package/dist/FilterPicker/components/FilterPickerContent/FilterPickerLoadMore/index.cjs +9 -0
- package/dist/FilterPicker/components/FilterPickerContent/FilterPickerLoadMore/index.d.ts +1 -0
- package/dist/FilterPicker/components/FilterPickerContent/FilterPickerLoadMore/index.mjs +3 -0
- package/dist/{Combobox/components/ComboboxContent → FilterPicker/components/FilterPickerContent}/index.cjs +8 -8
- package/dist/FilterPicker/components/FilterPickerContent/index.d.ts +1 -0
- package/dist/{Combobox/components/ComboboxContent → FilterPicker/components/FilterPickerContent}/index.mjs +7 -7
- package/dist/FilterPicker/components/FilterPickerOption/FilterPickerOption.d.ts +3 -0
- package/dist/{Combobox/components/ComboboxOption → FilterPicker/components/FilterPickerOption}/index.cjs +3 -3
- package/dist/FilterPicker/components/FilterPickerOption/index.d.ts +1 -0
- package/dist/{Combobox/components/ComboboxOption → FilterPicker/components/FilterPickerOption}/index.mjs +2 -2
- package/dist/FilterPicker/components/FilterPickerTrigger/FilterPickerTrigger.d.ts +3 -0
- package/dist/{Combobox/components/ComboboxTrigger → FilterPicker/components/FilterPickerTrigger}/index.cjs +3 -3
- package/dist/FilterPicker/components/FilterPickerTrigger/index.d.ts +1 -0
- package/dist/{Combobox/components/ComboboxTrigger → FilterPicker/components/FilterPickerTrigger}/index.mjs +2 -2
- package/dist/FilterPicker/constants.d.ts +1 -0
- package/dist/FilterPicker/hooks/useFilterPicker.d.ts +17 -0
- package/dist/FilterPicker/hooks/useFilterPickerAccessibility.d.ts +9 -0
- package/dist/FilterPicker/hooks/useFilterPickerActivatorAccessibility.d.ts +2 -0
- package/dist/FilterPicker/hooks/useFilterPickerContent.d.ts +9 -0
- package/dist/FilterPicker/hooks/useFilterPickerValidation.d.ts +12 -0
- package/dist/FilterPicker/hooks/useMakeFilterPickerHandlers.d.ts +8 -0
- package/dist/{Combobox → FilterPicker}/index.cjs +13 -13
- package/dist/FilterPicker/index.d.ts +3 -0
- package/dist/{Combobox → FilterPicker}/index.mjs +11 -11
- package/dist/{Combobox-cjs.js → FilterPicker-cjs.js} +25 -25
- package/dist/{Combobox-es.js → FilterPicker-es.js} +25 -25
- package/dist/{ComboboxAction-cjs.js → FilterPickerAction-cjs.js} +5 -5
- package/dist/{ComboboxAction-es.js → FilterPickerAction-es.js} +5 -5
- package/dist/{ComboboxActivator-cjs.js → FilterPickerActivator-cjs.js} +8 -8
- package/dist/{ComboboxActivator-es.js → FilterPickerActivator-es.js} +9 -9
- package/dist/{ComboboxContent-cjs.js → FilterPickerContent-cjs.js} +19 -19
- package/dist/{ComboboxContent-es.js → FilterPickerContent-es.js} +20 -20
- package/dist/{ComboboxContentHeader-cjs.js → FilterPickerContentHeader-cjs.js} +4 -4
- package/dist/{ComboboxContentHeader-es.js → FilterPickerContentHeader-es.js} +4 -4
- package/dist/{ComboboxContentList-cjs.js → FilterPickerContentList-cjs.js} +7 -7
- package/dist/{ComboboxContentList-es.js → FilterPickerContentList-es.js} +7 -7
- package/dist/{ComboboxContentSearch-cjs.js → FilterPickerContentSearch-cjs.js} +4 -4
- package/dist/{ComboboxContentSearch-es.js → FilterPickerContentSearch-es.js} +4 -4
- package/dist/FilterPickerLoadMore-cjs.js +16 -0
- package/dist/{ComboboxLoadMore-es.js → FilterPickerLoadMore-es.js} +4 -4
- package/dist/{ComboboxOption-cjs.js → FilterPickerOption-cjs.js} +5 -5
- package/dist/{ComboboxOption-es.js → FilterPickerOption-es.js} +5 -5
- package/dist/FilterPickerProvider-cjs.js +13 -0
- package/dist/FilterPickerProvider-es.js +10 -0
- package/dist/{ComboboxTrigger-cjs.js → FilterPickerTrigger-cjs.js} +4 -4
- package/dist/{ComboboxTrigger-es.js → FilterPickerTrigger-es.js} +4 -4
- package/dist/InputNumberExperimental-cjs.js +3 -4
- package/dist/InputNumberExperimental-es.js +2 -3
- package/dist/Menu/index.cjs +1 -2
- package/dist/Menu/index.mjs +1 -2
- package/dist/Menu-cjs.js +11 -56
- package/dist/Menu-es.js +4 -49
- package/dist/MenuSubmenuTrigger-cjs.js +160 -345
- package/dist/MenuSubmenuTrigger-es.js +4 -186
- package/dist/Modal/index.mjs +1 -1
- package/dist/NumberFieldInput-cjs.js +3 -4
- package/dist/NumberFieldInput-es.js +2 -3
- package/dist/Page/index.cjs +1 -2
- package/dist/Page/index.mjs +1 -2
- package/dist/{DrawerRoot-cjs.js → ScrollAreaViewport-cjs.js} +1042 -3
- package/dist/{DrawerRoot-es.js → ScrollAreaViewport-es.js} +1035 -5
- package/dist/constants-cjs.js +2 -2
- package/dist/constants-es.js +2 -2
- package/dist/docs/Autocomplete/Autocomplete.md +1 -1
- package/dist/docs/Chip/Chip.md +4 -4
- package/dist/docs/DataList/DataList.md +16 -15
- package/dist/docs/{Combobox/Combobox.md → FilterPicker/FilterPicker.md} +91 -85
- package/dist/docs/Menu/Menu.md +1 -1
- package/dist/docs/MultiSelect/MultiSelect.md +1 -1
- package/dist/docs/Tabs/Tabs.md +2 -2
- package/dist/docs/index.md +1 -1
- package/dist/docs/usage-guidelines/usage-guidelines.md +5 -5
- package/dist/floating-ui.react-es.js +1 -1
- package/dist/index.cjs +14 -15
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +12 -13
- package/dist/primitives/BottomSheet/BottomSheet.d.ts +15 -16
- package/dist/primitives/BottomSheet/BottomSheet.types.d.ts +27 -0
- package/dist/primitives/BottomSheet/BottomSheet.utils.d.ts +6 -0
- package/dist/primitives/BottomSheet/index.cjs +7 -2
- package/dist/primitives/BottomSheet/index.d.ts +1 -0
- package/dist/primitives/BottomSheet/index.mjs +7 -2
- package/dist/primitives/InputNumberExperimental/index.cjs +1 -2
- package/dist/primitives/InputNumberExperimental/index.mjs +1 -2
- package/dist/primitives/index.cjs +7 -8
- package/dist/primitives/index.mjs +7 -8
- package/dist/styles.css +115 -54
- package/dist/unstyledPrimitives/index.cjs +665 -297
- package/dist/unstyledPrimitives/index.d.ts +1 -0
- package/dist/unstyledPrimitives/index.mjs +375 -8
- package/dist/useRenderElement-es.js +1 -1
- package/dist/useValueChanged-cjs.js +251 -1
- package/dist/useValueChanged-es.js +248 -2
- package/dist/utils/meta/meta.json +5 -5
- package/package.json +6 -6
- package/rollup.config.mjs +2 -2
- package/Combobox.d.ts +0 -1
- package/dist/Combobox/Combobox.d.ts +0 -11
- package/dist/Combobox/ComboboxProvider.d.ts +0 -18
- package/dist/Combobox/components/ComboboxAction/ComboboxAction.d.ts +0 -3
- package/dist/Combobox/components/ComboboxAction/index.cjs +0 -12
- package/dist/Combobox/components/ComboboxAction/index.d.ts +0 -1
- package/dist/Combobox/components/ComboboxAction/index.mjs +0 -6
- package/dist/Combobox/components/ComboboxActivator/ComboboxActivator.d.ts +0 -3
- package/dist/Combobox/components/ComboboxActivator/index.d.ts +0 -1
- package/dist/Combobox/components/ComboboxContent/ComboboxContent.d.ts +0 -3
- package/dist/Combobox/components/ComboboxContent/ComboboxContentHeader/ComboboxContentHeader.d.ts +0 -3
- package/dist/Combobox/components/ComboboxContent/ComboboxContentHeader/index.d.ts +0 -1
- package/dist/Combobox/components/ComboboxContent/ComboboxContentList/ComboboxContentList.d.ts +0 -3
- package/dist/Combobox/components/ComboboxContent/ComboboxContentList/index.d.ts +0 -1
- package/dist/Combobox/components/ComboboxContent/ComboboxContentSearch/ComboboxContentSearch.d.ts +0 -3
- package/dist/Combobox/components/ComboboxContent/ComboboxContentSearch/index.cjs +0 -10
- package/dist/Combobox/components/ComboboxContent/ComboboxContentSearch/index.d.ts +0 -1
- package/dist/Combobox/components/ComboboxContent/ComboboxContentSearch/index.mjs +0 -4
- package/dist/Combobox/components/ComboboxContent/ComboboxLoadMore/ComboboxLoadMore.d.ts +0 -6
- package/dist/Combobox/components/ComboboxContent/ComboboxLoadMore/index.cjs +0 -9
- package/dist/Combobox/components/ComboboxContent/ComboboxLoadMore/index.d.ts +0 -1
- package/dist/Combobox/components/ComboboxContent/ComboboxLoadMore/index.mjs +0 -3
- package/dist/Combobox/components/ComboboxContent/index.d.ts +0 -1
- package/dist/Combobox/components/ComboboxOption/ComboboxOption.d.ts +0 -3
- package/dist/Combobox/components/ComboboxOption/index.d.ts +0 -1
- package/dist/Combobox/components/ComboboxTrigger/ComboboxTrigger.d.ts +0 -3
- package/dist/Combobox/components/ComboboxTrigger/index.d.ts +0 -1
- package/dist/Combobox/constants.d.ts +0 -1
- package/dist/Combobox/hooks/useCombobox.d.ts +0 -17
- package/dist/Combobox/hooks/useComboboxAccessibility.d.ts +0 -9
- package/dist/Combobox/hooks/useComboboxActivatorAccessibility.d.ts +0 -2
- package/dist/Combobox/hooks/useComboboxContent.d.ts +0 -9
- package/dist/Combobox/hooks/useComboboxValidation.d.ts +0 -12
- package/dist/Combobox/hooks/useMakeComboboxHandlers.d.ts +0 -8
- package/dist/Combobox/index.d.ts +0 -3
- package/dist/ComboboxLoadMore-cjs.js +0 -16
- package/dist/ComboboxProvider-cjs.js +0 -13
- package/dist/ComboboxProvider-es.js +0 -10
- package/dist/useBaseUiId-cjs.js +0 -275
- package/dist/useBaseUiId-es.js +0 -251
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import React__default from 'react';
|
|
3
|
-
import { f as formatErrorMessage, u as useRenderElement, E as EMPTY_OBJECT,
|
|
4
|
-
import { X as TransitionStatusDataAttributes, t as transitionStatusMapping, Y as isJSDOM,
|
|
3
|
+
import { f as formatErrorMessage, u as useRenderElement, E as EMPTY_OBJECT, a as useRefWithInit, b as useMergedRefs, i as isReactVersionAtLeast, N as NOOP } from './useRenderElement-es.js';
|
|
4
|
+
import { X as TransitionStatusDataAttributes, t as transitionStatusMapping, Y as isJSDOM, A as stopEvent, s as ownerDocument, d as useIsoLayoutEffect, H as isSafari, l as visuallyHidden, k as createChangeEventDetails, M as focusOut, E as useId, a as useStableCallback, i as useValueAsRef, b as useTimeout, Z as useAnimationFrame, _ as resolveRef, K as triggerHover, Q as outsidePress, N as isVirtualClick, O as isVirtualPointerEvent, $ as isWebKit, D as isMouseLikePointerType, a0 as isClickLikeEvent, I as triggerPress, a1 as isReactEvent, J as escapeKey, T as Timeout, c as useTransitionStatus, e as useOpenChangeComplete, g as clamp, j as isIOS, a2 as AnimationFrame, z as useValueChanged, U as imperativeAction, u as useBaseUiId, y as useButton, h as useControlled, n as none, a3 as isAndroid, a4 as closeWatcher } from './useValueChanged-es.js';
|
|
5
5
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
6
6
|
import { f as floor, t as tabbable, i as isTabbable, a as focusable } from './index.esm-es.js';
|
|
7
7
|
import { i as isShadowRoot, b as isElement, a as isHTMLElement, f as getComputedStyle$1, g as getNodeName, c as isNode, k as getWindow, j as isWebKit$1, d as isLastTraversableNode, e as getParentNode, o as isOverflowElement } from './floating-ui.utils.dom-es.js';
|
|
@@ -1897,6 +1897,109 @@ function FloatingFocusManager(props) {
|
|
|
1897
1897
|
});
|
|
1898
1898
|
}
|
|
1899
1899
|
|
|
1900
|
+
/**
|
|
1901
|
+
* Opens or closes the floating element when clicking the reference element.
|
|
1902
|
+
* @see https://floating-ui.com/docs/useClick
|
|
1903
|
+
*/
|
|
1904
|
+
function useClick(context, props = {}) {
|
|
1905
|
+
const store = 'rootStore' in context ? context.rootStore : context;
|
|
1906
|
+
const dataRef = store.context.dataRef;
|
|
1907
|
+
const {
|
|
1908
|
+
enabled = true,
|
|
1909
|
+
event: eventOption = 'click',
|
|
1910
|
+
toggle = true,
|
|
1911
|
+
ignoreMouse = false,
|
|
1912
|
+
stickIfOpen = true,
|
|
1913
|
+
touchOpenDelay = 0,
|
|
1914
|
+
reason = triggerPress
|
|
1915
|
+
} = props;
|
|
1916
|
+
const pointerTypeRef = React.useRef(undefined);
|
|
1917
|
+
const frame = useAnimationFrame();
|
|
1918
|
+
const touchOpenTimeout = useTimeout();
|
|
1919
|
+
const reference = React.useMemo(() => ({
|
|
1920
|
+
onPointerDown(event) {
|
|
1921
|
+
pointerTypeRef.current = event.pointerType;
|
|
1922
|
+
},
|
|
1923
|
+
onMouseDown(event) {
|
|
1924
|
+
const pointerType = pointerTypeRef.current;
|
|
1925
|
+
const nativeEvent = event.nativeEvent;
|
|
1926
|
+
const open = store.select('open');
|
|
1927
|
+
|
|
1928
|
+
// Ignore all buttons except for the "main" button.
|
|
1929
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button
|
|
1930
|
+
if (event.button !== 0 || eventOption === 'click' || isMouseLikePointerType(pointerType, true) && ignoreMouse) {
|
|
1931
|
+
return;
|
|
1932
|
+
}
|
|
1933
|
+
const openEvent = dataRef.current.openEvent;
|
|
1934
|
+
const openEventType = openEvent?.type;
|
|
1935
|
+
const hasClickedOnInactiveTrigger = store.select('domReferenceElement') !== event.currentTarget;
|
|
1936
|
+
const nextOpen = open && hasClickedOnInactiveTrigger || !(open && toggle && (openEvent && stickIfOpen ? openEventType === 'click' || openEventType === 'mousedown' : true));
|
|
1937
|
+
|
|
1938
|
+
// Animations sometimes won't run on a typeable element if using a rAF.
|
|
1939
|
+
// Focus is always set on these elements. For touch, we may delay opening.
|
|
1940
|
+
if (isTypeableElement(nativeEvent.target)) {
|
|
1941
|
+
const details = createChangeEventDetails(reason, nativeEvent, nativeEvent.target);
|
|
1942
|
+
if (nextOpen && pointerType === 'touch' && touchOpenDelay > 0) {
|
|
1943
|
+
touchOpenTimeout.start(touchOpenDelay, () => {
|
|
1944
|
+
store.setOpen(true, details);
|
|
1945
|
+
});
|
|
1946
|
+
} else {
|
|
1947
|
+
store.setOpen(nextOpen, details);
|
|
1948
|
+
}
|
|
1949
|
+
return;
|
|
1950
|
+
}
|
|
1951
|
+
|
|
1952
|
+
// Capture the currentTarget before the rAF.
|
|
1953
|
+
// as React sets it to null after the event handler completes.
|
|
1954
|
+
const eventCurrentTarget = event.currentTarget;
|
|
1955
|
+
|
|
1956
|
+
// Wait until focus is set on the element. This is an alternative to
|
|
1957
|
+
// `event.preventDefault()` to avoid :focus-visible from appearing when using a pointer.
|
|
1958
|
+
frame.request(() => {
|
|
1959
|
+
const details = createChangeEventDetails(reason, nativeEvent, eventCurrentTarget);
|
|
1960
|
+
if (nextOpen && pointerType === 'touch' && touchOpenDelay > 0) {
|
|
1961
|
+
touchOpenTimeout.start(touchOpenDelay, () => {
|
|
1962
|
+
store.setOpen(true, details);
|
|
1963
|
+
});
|
|
1964
|
+
} else {
|
|
1965
|
+
store.setOpen(nextOpen, details);
|
|
1966
|
+
}
|
|
1967
|
+
});
|
|
1968
|
+
},
|
|
1969
|
+
onClick(event) {
|
|
1970
|
+
if (eventOption === 'mousedown-only') {
|
|
1971
|
+
return;
|
|
1972
|
+
}
|
|
1973
|
+
const pointerType = pointerTypeRef.current;
|
|
1974
|
+
if (eventOption === 'mousedown' && pointerType) {
|
|
1975
|
+
pointerTypeRef.current = undefined;
|
|
1976
|
+
return;
|
|
1977
|
+
}
|
|
1978
|
+
if (isMouseLikePointerType(pointerType, true) && ignoreMouse) {
|
|
1979
|
+
return;
|
|
1980
|
+
}
|
|
1981
|
+
const open = store.select('open');
|
|
1982
|
+
const openEvent = dataRef.current.openEvent;
|
|
1983
|
+
const hasClickedOnInactiveTrigger = store.select('domReferenceElement') !== event.currentTarget;
|
|
1984
|
+
const nextOpen = open && hasClickedOnInactiveTrigger || !(open && toggle && (openEvent && stickIfOpen ? isClickLikeEvent(openEvent) : true));
|
|
1985
|
+
const details = createChangeEventDetails(reason, event.nativeEvent, event.currentTarget);
|
|
1986
|
+
if (nextOpen && pointerType === 'touch' && touchOpenDelay > 0) {
|
|
1987
|
+
touchOpenTimeout.start(touchOpenDelay, () => {
|
|
1988
|
+
store.setOpen(true, details);
|
|
1989
|
+
});
|
|
1990
|
+
} else {
|
|
1991
|
+
store.setOpen(nextOpen, details);
|
|
1992
|
+
}
|
|
1993
|
+
},
|
|
1994
|
+
onKeyDown() {
|
|
1995
|
+
pointerTypeRef.current = undefined;
|
|
1996
|
+
}
|
|
1997
|
+
}), [dataRef, eventOption, ignoreMouse, store, stickIfOpen, toggle, frame, touchOpenTimeout, touchOpenDelay, reason]);
|
|
1998
|
+
return React.useMemo(() => enabled ? {
|
|
1999
|
+
reference
|
|
2000
|
+
} : EMPTY_OBJECT, [enabled, reference]);
|
|
2001
|
+
}
|
|
2002
|
+
|
|
1900
2003
|
const bubbleHandlerKeys = {
|
|
1901
2004
|
intentional: 'onClick',
|
|
1902
2005
|
sloppy: 'onPointerDown'
|
|
@@ -4587,7 +4690,7 @@ let drawerSwipeVarsRegistered = false;
|
|
|
4587
4690
|
* See https://motion.dev/blog/web-animation-performance-tier-list
|
|
4588
4691
|
* under the "Improving CSS variable performance" section.
|
|
4589
4692
|
*/
|
|
4590
|
-
function removeCSSVariableInheritance() {
|
|
4693
|
+
function removeCSSVariableInheritance$1() {
|
|
4591
4694
|
if (drawerSwipeVarsRegistered) {
|
|
4592
4695
|
return;
|
|
4593
4696
|
}
|
|
@@ -4752,7 +4855,7 @@ const DrawerPopup = /*#__PURE__*/React.forwardRef(function DrawerPopup(component
|
|
|
4752
4855
|
if (!popupElement) {
|
|
4753
4856
|
return undefined;
|
|
4754
4857
|
}
|
|
4755
|
-
removeCSSVariableInheritance();
|
|
4858
|
+
removeCSSVariableInheritance$1();
|
|
4756
4859
|
measureHeight();
|
|
4757
4860
|
if (typeof ResizeObserver !== 'function') {
|
|
4758
4861
|
return undefined;
|
|
@@ -5569,6 +5672,66 @@ function DialogRoot(props) {
|
|
|
5569
5672
|
});
|
|
5570
5673
|
}
|
|
5571
5674
|
|
|
5675
|
+
/**
|
|
5676
|
+
* A button that opens the dialog.
|
|
5677
|
+
* Renders a `<button>` element.
|
|
5678
|
+
*
|
|
5679
|
+
* Documentation: [Base UI Dialog](https://base-ui.com/react/components/dialog)
|
|
5680
|
+
*/
|
|
5681
|
+
const DialogTrigger = /*#__PURE__*/React.forwardRef(function DialogTrigger(componentProps, forwardedRef) {
|
|
5682
|
+
const {
|
|
5683
|
+
render,
|
|
5684
|
+
className,
|
|
5685
|
+
disabled = false,
|
|
5686
|
+
nativeButton = true,
|
|
5687
|
+
id: idProp,
|
|
5688
|
+
payload,
|
|
5689
|
+
handle,
|
|
5690
|
+
...elementProps
|
|
5691
|
+
} = componentProps;
|
|
5692
|
+
const dialogRootContext = useDialogRootContext(true);
|
|
5693
|
+
const store = handle?.store ?? dialogRootContext?.store;
|
|
5694
|
+
if (!store) {
|
|
5695
|
+
throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: <Dialog.Trigger> must be used within <Dialog.Root> or provided with a handle.' : formatErrorMessage(79));
|
|
5696
|
+
}
|
|
5697
|
+
const thisTriggerId = useBaseUiId(idProp);
|
|
5698
|
+
const floatingContext = store.useState('floatingRootContext');
|
|
5699
|
+
const isOpenedByThisTrigger = store.useState('isOpenedByTrigger', thisTriggerId);
|
|
5700
|
+
const triggerElementRef = React.useRef(null);
|
|
5701
|
+
const {
|
|
5702
|
+
registerTrigger,
|
|
5703
|
+
isMountedByThisTrigger
|
|
5704
|
+
} = useTriggerDataForwarding(thisTriggerId, triggerElementRef, store, {
|
|
5705
|
+
payload
|
|
5706
|
+
});
|
|
5707
|
+
const {
|
|
5708
|
+
getButtonProps,
|
|
5709
|
+
buttonRef
|
|
5710
|
+
} = useButton({
|
|
5711
|
+
disabled,
|
|
5712
|
+
native: nativeButton
|
|
5713
|
+
});
|
|
5714
|
+
const click = useClick(floatingContext, {
|
|
5715
|
+
enabled: floatingContext != null
|
|
5716
|
+
});
|
|
5717
|
+
const localInteractionProps = useInteractions([click]);
|
|
5718
|
+
const state = {
|
|
5719
|
+
disabled,
|
|
5720
|
+
open: isOpenedByThisTrigger
|
|
5721
|
+
};
|
|
5722
|
+
const rootTriggerProps = store.useState('triggerProps', isMountedByThisTrigger);
|
|
5723
|
+
return useRenderElement('button', componentProps, {
|
|
5724
|
+
state,
|
|
5725
|
+
ref: [buttonRef, forwardedRef, registerTrigger, triggerElementRef],
|
|
5726
|
+
props: [localInteractionProps.getReferenceProps(), rootTriggerProps, {
|
|
5727
|
+
[CLICK_TRIGGER_IDENTIFIER]: '',
|
|
5728
|
+
id: thisTriggerId
|
|
5729
|
+
}, elementProps, getButtonProps],
|
|
5730
|
+
stateAttributesMapping: triggerOpenStateMapping
|
|
5731
|
+
});
|
|
5732
|
+
});
|
|
5733
|
+
if (process.env.NODE_ENV !== "production") DialogTrigger.displayName = "DialogTrigger";
|
|
5734
|
+
|
|
5572
5735
|
var _DrawerProviderReport, _DrawerProviderReport2;
|
|
5573
5736
|
/**
|
|
5574
5737
|
* Groups all parts of the drawer.
|
|
@@ -5788,4 +5951,871 @@ function DrawerProviderReporter() {
|
|
|
5788
5951
|
return null;
|
|
5789
5952
|
}
|
|
5790
5953
|
|
|
5791
|
-
|
|
5954
|
+
/**
|
|
5955
|
+
* A button that opens the drawer.
|
|
5956
|
+
* Renders a `<button>` element.
|
|
5957
|
+
*
|
|
5958
|
+
* Documentation: [Base UI Drawer](https://base-ui.com/react/components/drawer)
|
|
5959
|
+
*/
|
|
5960
|
+
const DrawerTrigger = DialogTrigger;
|
|
5961
|
+
|
|
5962
|
+
/**
|
|
5963
|
+
* @internal
|
|
5964
|
+
*/
|
|
5965
|
+
const DirectionContext = /*#__PURE__*/React.createContext(undefined);
|
|
5966
|
+
if (process.env.NODE_ENV !== "production") DirectionContext.displayName = "DirectionContext";
|
|
5967
|
+
function useDirection() {
|
|
5968
|
+
const context = React.useContext(DirectionContext);
|
|
5969
|
+
return context?.direction ?? 'ltr';
|
|
5970
|
+
}
|
|
5971
|
+
|
|
5972
|
+
const ScrollAreaRootContext = /*#__PURE__*/React.createContext(undefined);
|
|
5973
|
+
if (process.env.NODE_ENV !== "production") ScrollAreaRootContext.displayName = "ScrollAreaRootContext";
|
|
5974
|
+
function useScrollAreaRootContext() {
|
|
5975
|
+
const context = React.useContext(ScrollAreaRootContext);
|
|
5976
|
+
if (context === undefined) {
|
|
5977
|
+
throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: ScrollAreaRootContext is missing. ScrollArea parts must be placed within <ScrollArea.Root>.' : formatErrorMessage(53));
|
|
5978
|
+
}
|
|
5979
|
+
return context;
|
|
5980
|
+
}
|
|
5981
|
+
|
|
5982
|
+
let ScrollAreaRootCssVars = /*#__PURE__*/function (ScrollAreaRootCssVars) {
|
|
5983
|
+
/**
|
|
5984
|
+
* The scroll area's corner height.
|
|
5985
|
+
* @type {number}
|
|
5986
|
+
*/
|
|
5987
|
+
ScrollAreaRootCssVars["scrollAreaCornerHeight"] = "--scroll-area-corner-height";
|
|
5988
|
+
/**
|
|
5989
|
+
* The scroll area's corner width.
|
|
5990
|
+
* @type {number}
|
|
5991
|
+
*/
|
|
5992
|
+
ScrollAreaRootCssVars["scrollAreaCornerWidth"] = "--scroll-area-corner-width";
|
|
5993
|
+
return ScrollAreaRootCssVars;
|
|
5994
|
+
}({});
|
|
5995
|
+
|
|
5996
|
+
const SCROLL_TIMEOUT = 500;
|
|
5997
|
+
const MIN_THUMB_SIZE = 16;
|
|
5998
|
+
|
|
5999
|
+
function getOffset(element, prop, axis) {
|
|
6000
|
+
if (!element) {
|
|
6001
|
+
return 0;
|
|
6002
|
+
}
|
|
6003
|
+
const styles = getComputedStyle(element);
|
|
6004
|
+
const propAxis = axis === 'x' ? 'Inline' : 'Block';
|
|
6005
|
+
|
|
6006
|
+
// Safari misreports `marginInlineEnd` in RTL.
|
|
6007
|
+
// We have to assume the start/end values are symmetrical, which is likely.
|
|
6008
|
+
if (axis === 'x' && prop === 'margin') {
|
|
6009
|
+
return parseFloat(styles[`${prop}InlineStart`]) * 2;
|
|
6010
|
+
}
|
|
6011
|
+
return parseFloat(styles[`${prop}${propAxis}Start`]) + parseFloat(styles[`${prop}${propAxis}End`]);
|
|
6012
|
+
}
|
|
6013
|
+
|
|
6014
|
+
let ScrollAreaScrollbarDataAttributes = /*#__PURE__*/function (ScrollAreaScrollbarDataAttributes) {
|
|
6015
|
+
/**
|
|
6016
|
+
* Indicates the orientation of the scrollbar.
|
|
6017
|
+
* @type {'horizontal' | 'vertical'}
|
|
6018
|
+
*/
|
|
6019
|
+
ScrollAreaScrollbarDataAttributes["orientation"] = "data-orientation";
|
|
6020
|
+
/**
|
|
6021
|
+
* Present when the pointer is over the scroll area.
|
|
6022
|
+
*/
|
|
6023
|
+
ScrollAreaScrollbarDataAttributes["hovering"] = "data-hovering";
|
|
6024
|
+
/**
|
|
6025
|
+
* Present when the user scrolls inside the scroll area.
|
|
6026
|
+
*/
|
|
6027
|
+
ScrollAreaScrollbarDataAttributes["scrolling"] = "data-scrolling";
|
|
6028
|
+
/**
|
|
6029
|
+
* Present when the scroll area content is wider than the viewport.
|
|
6030
|
+
*/
|
|
6031
|
+
ScrollAreaScrollbarDataAttributes["hasOverflowX"] = "data-has-overflow-x";
|
|
6032
|
+
/**
|
|
6033
|
+
* Present when the scroll area content is taller than the viewport.
|
|
6034
|
+
*/
|
|
6035
|
+
ScrollAreaScrollbarDataAttributes["hasOverflowY"] = "data-has-overflow-y";
|
|
6036
|
+
/**
|
|
6037
|
+
* Present when there is overflow on the horizontal start side.
|
|
6038
|
+
*/
|
|
6039
|
+
ScrollAreaScrollbarDataAttributes["overflowXStart"] = "data-overflow-x-start";
|
|
6040
|
+
/**
|
|
6041
|
+
* Present when there is overflow on the horizontal end side.
|
|
6042
|
+
*/
|
|
6043
|
+
ScrollAreaScrollbarDataAttributes["overflowXEnd"] = "data-overflow-x-end";
|
|
6044
|
+
/**
|
|
6045
|
+
* Present when there is overflow on the vertical start side.
|
|
6046
|
+
*/
|
|
6047
|
+
ScrollAreaScrollbarDataAttributes["overflowYStart"] = "data-overflow-y-start";
|
|
6048
|
+
/**
|
|
6049
|
+
* Present when there is overflow on the vertical end side.
|
|
6050
|
+
*/
|
|
6051
|
+
ScrollAreaScrollbarDataAttributes["overflowYEnd"] = "data-overflow-y-end";
|
|
6052
|
+
return ScrollAreaScrollbarDataAttributes;
|
|
6053
|
+
}({});
|
|
6054
|
+
|
|
6055
|
+
const DISABLE_SCROLLBAR_CLASS_NAME = 'base-ui-disable-scrollbar';
|
|
6056
|
+
const styleDisableScrollbar = {
|
|
6057
|
+
className: DISABLE_SCROLLBAR_CLASS_NAME,
|
|
6058
|
+
getElement(nonce) {
|
|
6059
|
+
return /*#__PURE__*/jsx("style", {
|
|
6060
|
+
nonce: nonce,
|
|
6061
|
+
href: DISABLE_SCROLLBAR_CLASS_NAME,
|
|
6062
|
+
precedence: "base-ui:low",
|
|
6063
|
+
children: `.${DISABLE_SCROLLBAR_CLASS_NAME}{scrollbar-width:none}.${DISABLE_SCROLLBAR_CLASS_NAME}::-webkit-scrollbar{display:none}`
|
|
6064
|
+
});
|
|
6065
|
+
}
|
|
6066
|
+
};
|
|
6067
|
+
if (process.env.NODE_ENV !== "production") styleDisableScrollbar.getElement.displayName = "styleDisableScrollbar.getElement";
|
|
6068
|
+
|
|
6069
|
+
let ScrollAreaRootDataAttributes = /*#__PURE__*/function (ScrollAreaRootDataAttributes) {
|
|
6070
|
+
/**
|
|
6071
|
+
* Present when the user scrolls inside the scroll area.
|
|
6072
|
+
*/
|
|
6073
|
+
ScrollAreaRootDataAttributes["scrolling"] = "data-scrolling";
|
|
6074
|
+
/**
|
|
6075
|
+
* Present when the scroll area content is wider than the viewport.
|
|
6076
|
+
*/
|
|
6077
|
+
ScrollAreaRootDataAttributes["hasOverflowX"] = "data-has-overflow-x";
|
|
6078
|
+
/**
|
|
6079
|
+
* Present when the scroll area content is taller than the viewport.
|
|
6080
|
+
*/
|
|
6081
|
+
ScrollAreaRootDataAttributes["hasOverflowY"] = "data-has-overflow-y";
|
|
6082
|
+
/**
|
|
6083
|
+
* Present when there is overflow on the horizontal start side.
|
|
6084
|
+
*/
|
|
6085
|
+
ScrollAreaRootDataAttributes["overflowXStart"] = "data-overflow-x-start";
|
|
6086
|
+
/**
|
|
6087
|
+
* Present when there is overflow on the horizontal end side.
|
|
6088
|
+
*/
|
|
6089
|
+
ScrollAreaRootDataAttributes["overflowXEnd"] = "data-overflow-x-end";
|
|
6090
|
+
/**
|
|
6091
|
+
* Present when there is overflow on the vertical start side.
|
|
6092
|
+
*/
|
|
6093
|
+
ScrollAreaRootDataAttributes["overflowYStart"] = "data-overflow-y-start";
|
|
6094
|
+
/**
|
|
6095
|
+
* Present when there is overflow on the vertical end side.
|
|
6096
|
+
*/
|
|
6097
|
+
ScrollAreaRootDataAttributes["overflowYEnd"] = "data-overflow-y-end";
|
|
6098
|
+
return ScrollAreaRootDataAttributes;
|
|
6099
|
+
}({});
|
|
6100
|
+
|
|
6101
|
+
const scrollAreaStateAttributesMapping = {
|
|
6102
|
+
hasOverflowX: value => value ? {
|
|
6103
|
+
[ScrollAreaRootDataAttributes.hasOverflowX]: ''
|
|
6104
|
+
} : null,
|
|
6105
|
+
hasOverflowY: value => value ? {
|
|
6106
|
+
[ScrollAreaRootDataAttributes.hasOverflowY]: ''
|
|
6107
|
+
} : null,
|
|
6108
|
+
overflowXStart: value => value ? {
|
|
6109
|
+
[ScrollAreaRootDataAttributes.overflowXStart]: ''
|
|
6110
|
+
} : null,
|
|
6111
|
+
overflowXEnd: value => value ? {
|
|
6112
|
+
[ScrollAreaRootDataAttributes.overflowXEnd]: ''
|
|
6113
|
+
} : null,
|
|
6114
|
+
overflowYStart: value => value ? {
|
|
6115
|
+
[ScrollAreaRootDataAttributes.overflowYStart]: ''
|
|
6116
|
+
} : null,
|
|
6117
|
+
overflowYEnd: value => value ? {
|
|
6118
|
+
[ScrollAreaRootDataAttributes.overflowYEnd]: ''
|
|
6119
|
+
} : null,
|
|
6120
|
+
cornerHidden: () => null
|
|
6121
|
+
};
|
|
6122
|
+
|
|
6123
|
+
/**
|
|
6124
|
+
* @internal
|
|
6125
|
+
*/
|
|
6126
|
+
const CSPContext = /*#__PURE__*/React.createContext(undefined);
|
|
6127
|
+
if (process.env.NODE_ENV !== "production") CSPContext.displayName = "CSPContext";
|
|
6128
|
+
const DEFAULT_CSP_CONTEXT_VALUE = {
|
|
6129
|
+
disableStyleElements: false
|
|
6130
|
+
};
|
|
6131
|
+
|
|
6132
|
+
/**
|
|
6133
|
+
* @internal
|
|
6134
|
+
*/
|
|
6135
|
+
function useCSPContext() {
|
|
6136
|
+
return React.useContext(CSPContext) ?? DEFAULT_CSP_CONTEXT_VALUE;
|
|
6137
|
+
}
|
|
6138
|
+
|
|
6139
|
+
const DEFAULT_COORDS = {
|
|
6140
|
+
x: 0,
|
|
6141
|
+
y: 0
|
|
6142
|
+
};
|
|
6143
|
+
const DEFAULT_SIZE = {
|
|
6144
|
+
width: 0,
|
|
6145
|
+
height: 0
|
|
6146
|
+
};
|
|
6147
|
+
const DEFAULT_OVERFLOW_EDGES = {
|
|
6148
|
+
xStart: false,
|
|
6149
|
+
xEnd: false,
|
|
6150
|
+
yStart: false,
|
|
6151
|
+
yEnd: false
|
|
6152
|
+
};
|
|
6153
|
+
const DEFAULT_HIDDEN_STATE = {
|
|
6154
|
+
x: true,
|
|
6155
|
+
y: true,
|
|
6156
|
+
corner: true
|
|
6157
|
+
};
|
|
6158
|
+
/**
|
|
6159
|
+
* Groups all parts of the scroll area.
|
|
6160
|
+
* Renders a `<div>` element.
|
|
6161
|
+
*
|
|
6162
|
+
* Documentation: [Base UI Scroll Area](https://base-ui.com/react/components/scroll-area)
|
|
6163
|
+
*/
|
|
6164
|
+
const ScrollAreaRoot = /*#__PURE__*/React.forwardRef(function ScrollAreaRoot(componentProps, forwardedRef) {
|
|
6165
|
+
const {
|
|
6166
|
+
render,
|
|
6167
|
+
className,
|
|
6168
|
+
overflowEdgeThreshold: overflowEdgeThresholdProp,
|
|
6169
|
+
...elementProps
|
|
6170
|
+
} = componentProps;
|
|
6171
|
+
const overflowEdgeThreshold = normalizeOverflowEdgeThreshold(overflowEdgeThresholdProp);
|
|
6172
|
+
const rootId = useBaseUiId();
|
|
6173
|
+
const scrollYTimeout = useTimeout();
|
|
6174
|
+
const scrollXTimeout = useTimeout();
|
|
6175
|
+
const {
|
|
6176
|
+
nonce,
|
|
6177
|
+
disableStyleElements
|
|
6178
|
+
} = useCSPContext();
|
|
6179
|
+
const [hovering, setHovering] = React.useState(false);
|
|
6180
|
+
const [scrollingX, setScrollingX] = React.useState(false);
|
|
6181
|
+
const [scrollingY, setScrollingY] = React.useState(false);
|
|
6182
|
+
const [touchModality, setTouchModality] = React.useState(false);
|
|
6183
|
+
const [hasMeasuredScrollbar, setHasMeasuredScrollbar] = React.useState(false);
|
|
6184
|
+
const [cornerSize, setCornerSize] = React.useState(DEFAULT_SIZE);
|
|
6185
|
+
const [thumbSize, setThumbSize] = React.useState(DEFAULT_SIZE);
|
|
6186
|
+
const [overflowEdges, setOverflowEdges] = React.useState(DEFAULT_OVERFLOW_EDGES);
|
|
6187
|
+
const [hiddenState, setHiddenState] = React.useState(DEFAULT_HIDDEN_STATE);
|
|
6188
|
+
const rootRef = React.useRef(null);
|
|
6189
|
+
const viewportRef = React.useRef(null);
|
|
6190
|
+
const scrollbarYRef = React.useRef(null);
|
|
6191
|
+
const scrollbarXRef = React.useRef(null);
|
|
6192
|
+
const thumbYRef = React.useRef(null);
|
|
6193
|
+
const thumbXRef = React.useRef(null);
|
|
6194
|
+
const cornerRef = React.useRef(null);
|
|
6195
|
+
const thumbDraggingRef = React.useRef(false);
|
|
6196
|
+
const startYRef = React.useRef(0);
|
|
6197
|
+
const startXRef = React.useRef(0);
|
|
6198
|
+
const startScrollTopRef = React.useRef(0);
|
|
6199
|
+
const startScrollLeftRef = React.useRef(0);
|
|
6200
|
+
const currentOrientationRef = React.useRef('vertical');
|
|
6201
|
+
const scrollPositionRef = React.useRef(DEFAULT_COORDS);
|
|
6202
|
+
const handleScroll = useStableCallback(scrollPosition => {
|
|
6203
|
+
const offsetX = scrollPosition.x - scrollPositionRef.current.x;
|
|
6204
|
+
const offsetY = scrollPosition.y - scrollPositionRef.current.y;
|
|
6205
|
+
scrollPositionRef.current = scrollPosition;
|
|
6206
|
+
if (offsetY !== 0) {
|
|
6207
|
+
setScrollingY(true);
|
|
6208
|
+
scrollYTimeout.start(SCROLL_TIMEOUT, () => {
|
|
6209
|
+
setScrollingY(false);
|
|
6210
|
+
});
|
|
6211
|
+
}
|
|
6212
|
+
if (offsetX !== 0) {
|
|
6213
|
+
setScrollingX(true);
|
|
6214
|
+
scrollXTimeout.start(SCROLL_TIMEOUT, () => {
|
|
6215
|
+
setScrollingX(false);
|
|
6216
|
+
});
|
|
6217
|
+
}
|
|
6218
|
+
});
|
|
6219
|
+
const handlePointerDown = useStableCallback(event => {
|
|
6220
|
+
if (event.button !== 0) {
|
|
6221
|
+
return;
|
|
6222
|
+
}
|
|
6223
|
+
thumbDraggingRef.current = true;
|
|
6224
|
+
startYRef.current = event.clientY;
|
|
6225
|
+
startXRef.current = event.clientX;
|
|
6226
|
+
currentOrientationRef.current = event.currentTarget.getAttribute(ScrollAreaScrollbarDataAttributes.orientation);
|
|
6227
|
+
if (viewportRef.current) {
|
|
6228
|
+
startScrollTopRef.current = viewportRef.current.scrollTop;
|
|
6229
|
+
startScrollLeftRef.current = viewportRef.current.scrollLeft;
|
|
6230
|
+
}
|
|
6231
|
+
if (thumbYRef.current && currentOrientationRef.current === 'vertical') {
|
|
6232
|
+
thumbYRef.current.setPointerCapture(event.pointerId);
|
|
6233
|
+
}
|
|
6234
|
+
if (thumbXRef.current && currentOrientationRef.current === 'horizontal') {
|
|
6235
|
+
thumbXRef.current.setPointerCapture(event.pointerId);
|
|
6236
|
+
}
|
|
6237
|
+
});
|
|
6238
|
+
const handlePointerMove = useStableCallback(event => {
|
|
6239
|
+
if (!thumbDraggingRef.current) {
|
|
6240
|
+
return;
|
|
6241
|
+
}
|
|
6242
|
+
const deltaY = event.clientY - startYRef.current;
|
|
6243
|
+
const deltaX = event.clientX - startXRef.current;
|
|
6244
|
+
if (viewportRef.current) {
|
|
6245
|
+
const scrollableContentHeight = viewportRef.current.scrollHeight;
|
|
6246
|
+
const viewportHeight = viewportRef.current.clientHeight;
|
|
6247
|
+
const scrollableContentWidth = viewportRef.current.scrollWidth;
|
|
6248
|
+
const viewportWidth = viewportRef.current.clientWidth;
|
|
6249
|
+
if (thumbYRef.current && scrollbarYRef.current && currentOrientationRef.current === 'vertical') {
|
|
6250
|
+
const scrollbarYOffset = getOffset(scrollbarYRef.current, 'padding', 'y');
|
|
6251
|
+
const thumbYOffset = getOffset(thumbYRef.current, 'margin', 'y');
|
|
6252
|
+
const thumbHeight = thumbYRef.current.offsetHeight;
|
|
6253
|
+
const maxThumbOffsetY = scrollbarYRef.current.offsetHeight - thumbHeight - scrollbarYOffset - thumbYOffset;
|
|
6254
|
+
const scrollRatioY = deltaY / maxThumbOffsetY;
|
|
6255
|
+
viewportRef.current.scrollTop = startScrollTopRef.current + scrollRatioY * (scrollableContentHeight - viewportHeight);
|
|
6256
|
+
event.preventDefault();
|
|
6257
|
+
setScrollingY(true);
|
|
6258
|
+
scrollYTimeout.start(SCROLL_TIMEOUT, () => {
|
|
6259
|
+
setScrollingY(false);
|
|
6260
|
+
});
|
|
6261
|
+
}
|
|
6262
|
+
if (thumbXRef.current && scrollbarXRef.current && currentOrientationRef.current === 'horizontal') {
|
|
6263
|
+
const scrollbarXOffset = getOffset(scrollbarXRef.current, 'padding', 'x');
|
|
6264
|
+
const thumbXOffset = getOffset(thumbXRef.current, 'margin', 'x');
|
|
6265
|
+
const thumbWidth = thumbXRef.current.offsetWidth;
|
|
6266
|
+
const maxThumbOffsetX = scrollbarXRef.current.offsetWidth - thumbWidth - scrollbarXOffset - thumbXOffset;
|
|
6267
|
+
const scrollRatioX = deltaX / maxThumbOffsetX;
|
|
6268
|
+
viewportRef.current.scrollLeft = startScrollLeftRef.current + scrollRatioX * (scrollableContentWidth - viewportWidth);
|
|
6269
|
+
event.preventDefault();
|
|
6270
|
+
setScrollingX(true);
|
|
6271
|
+
scrollXTimeout.start(SCROLL_TIMEOUT, () => {
|
|
6272
|
+
setScrollingX(false);
|
|
6273
|
+
});
|
|
6274
|
+
}
|
|
6275
|
+
}
|
|
6276
|
+
});
|
|
6277
|
+
const handlePointerUp = useStableCallback(event => {
|
|
6278
|
+
thumbDraggingRef.current = false;
|
|
6279
|
+
if (thumbYRef.current && currentOrientationRef.current === 'vertical') {
|
|
6280
|
+
thumbYRef.current.releasePointerCapture(event.pointerId);
|
|
6281
|
+
}
|
|
6282
|
+
if (thumbXRef.current && currentOrientationRef.current === 'horizontal') {
|
|
6283
|
+
thumbXRef.current.releasePointerCapture(event.pointerId);
|
|
6284
|
+
}
|
|
6285
|
+
});
|
|
6286
|
+
function handleTouchModalityChange(event) {
|
|
6287
|
+
setTouchModality(event.pointerType === 'touch');
|
|
6288
|
+
}
|
|
6289
|
+
function handlePointerEnterOrMove(event) {
|
|
6290
|
+
handleTouchModalityChange(event);
|
|
6291
|
+
if (event.pointerType !== 'touch') {
|
|
6292
|
+
const isTargetRootChild = contains(rootRef.current, event.target);
|
|
6293
|
+
setHovering(isTargetRootChild);
|
|
6294
|
+
}
|
|
6295
|
+
}
|
|
6296
|
+
const state = React.useMemo(() => ({
|
|
6297
|
+
scrolling: scrollingX || scrollingY,
|
|
6298
|
+
hasOverflowX: !hiddenState.x,
|
|
6299
|
+
hasOverflowY: !hiddenState.y,
|
|
6300
|
+
overflowXStart: overflowEdges.xStart,
|
|
6301
|
+
overflowXEnd: overflowEdges.xEnd,
|
|
6302
|
+
overflowYStart: overflowEdges.yStart,
|
|
6303
|
+
overflowYEnd: overflowEdges.yEnd,
|
|
6304
|
+
cornerHidden: hiddenState.corner
|
|
6305
|
+
}), [scrollingX, scrollingY, hiddenState.x, hiddenState.y, hiddenState.corner, overflowEdges]);
|
|
6306
|
+
const props = {
|
|
6307
|
+
role: 'presentation',
|
|
6308
|
+
onPointerEnter: handlePointerEnterOrMove,
|
|
6309
|
+
onPointerMove: handlePointerEnterOrMove,
|
|
6310
|
+
onPointerDown: handleTouchModalityChange,
|
|
6311
|
+
onPointerLeave() {
|
|
6312
|
+
setHovering(false);
|
|
6313
|
+
},
|
|
6314
|
+
style: {
|
|
6315
|
+
position: 'relative',
|
|
6316
|
+
[ScrollAreaRootCssVars.scrollAreaCornerHeight]: `${cornerSize.height}px`,
|
|
6317
|
+
[ScrollAreaRootCssVars.scrollAreaCornerWidth]: `${cornerSize.width}px`
|
|
6318
|
+
}
|
|
6319
|
+
};
|
|
6320
|
+
const element = useRenderElement('div', componentProps, {
|
|
6321
|
+
state,
|
|
6322
|
+
ref: [forwardedRef, rootRef],
|
|
6323
|
+
props: [props, elementProps],
|
|
6324
|
+
stateAttributesMapping: scrollAreaStateAttributesMapping
|
|
6325
|
+
});
|
|
6326
|
+
const contextValue = React.useMemo(() => ({
|
|
6327
|
+
handlePointerDown,
|
|
6328
|
+
handlePointerMove,
|
|
6329
|
+
handlePointerUp,
|
|
6330
|
+
handleScroll,
|
|
6331
|
+
cornerSize,
|
|
6332
|
+
setCornerSize,
|
|
6333
|
+
thumbSize,
|
|
6334
|
+
setThumbSize,
|
|
6335
|
+
hasMeasuredScrollbar,
|
|
6336
|
+
setHasMeasuredScrollbar,
|
|
6337
|
+
touchModality,
|
|
6338
|
+
cornerRef,
|
|
6339
|
+
scrollingX,
|
|
6340
|
+
setScrollingX,
|
|
6341
|
+
scrollingY,
|
|
6342
|
+
setScrollingY,
|
|
6343
|
+
hovering,
|
|
6344
|
+
setHovering,
|
|
6345
|
+
viewportRef,
|
|
6346
|
+
rootRef,
|
|
6347
|
+
scrollbarYRef,
|
|
6348
|
+
scrollbarXRef,
|
|
6349
|
+
thumbYRef,
|
|
6350
|
+
thumbXRef,
|
|
6351
|
+
rootId,
|
|
6352
|
+
hiddenState,
|
|
6353
|
+
setHiddenState,
|
|
6354
|
+
overflowEdges,
|
|
6355
|
+
setOverflowEdges,
|
|
6356
|
+
viewportState: state,
|
|
6357
|
+
overflowEdgeThreshold
|
|
6358
|
+
}), [handlePointerDown, handlePointerMove, handlePointerUp, handleScroll, cornerSize, thumbSize, hasMeasuredScrollbar, touchModality, scrollingX, setScrollingX, scrollingY, setScrollingY, hovering, setHovering, rootId, hiddenState, overflowEdges, state, overflowEdgeThreshold]);
|
|
6359
|
+
return /*#__PURE__*/jsxs(ScrollAreaRootContext.Provider, {
|
|
6360
|
+
value: contextValue,
|
|
6361
|
+
children: [!disableStyleElements && styleDisableScrollbar.getElement(nonce), element]
|
|
6362
|
+
});
|
|
6363
|
+
});
|
|
6364
|
+
if (process.env.NODE_ENV !== "production") ScrollAreaRoot.displayName = "ScrollAreaRoot";
|
|
6365
|
+
function normalizeOverflowEdgeThreshold(threshold) {
|
|
6366
|
+
if (typeof threshold === 'number') {
|
|
6367
|
+
const value = Math.max(0, threshold);
|
|
6368
|
+
return {
|
|
6369
|
+
xStart: value,
|
|
6370
|
+
xEnd: value,
|
|
6371
|
+
yStart: value,
|
|
6372
|
+
yEnd: value
|
|
6373
|
+
};
|
|
6374
|
+
}
|
|
6375
|
+
return {
|
|
6376
|
+
xStart: Math.max(0, threshold?.xStart || 0),
|
|
6377
|
+
xEnd: Math.max(0, threshold?.xEnd || 0),
|
|
6378
|
+
yStart: Math.max(0, threshold?.yStart || 0),
|
|
6379
|
+
yEnd: Math.max(0, threshold?.yEnd || 0)
|
|
6380
|
+
};
|
|
6381
|
+
}
|
|
6382
|
+
|
|
6383
|
+
const ScrollAreaViewportContext = /*#__PURE__*/React.createContext(undefined);
|
|
6384
|
+
if (process.env.NODE_ENV !== "production") ScrollAreaViewportContext.displayName = "ScrollAreaViewportContext";
|
|
6385
|
+
function useScrollAreaViewportContext() {
|
|
6386
|
+
const context = React.useContext(ScrollAreaViewportContext);
|
|
6387
|
+
if (context === undefined) {
|
|
6388
|
+
throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: ScrollAreaViewportContext missing. ScrollAreaViewport parts must be placed within <ScrollArea.Viewport>.' : formatErrorMessage(55));
|
|
6389
|
+
}
|
|
6390
|
+
return context;
|
|
6391
|
+
}
|
|
6392
|
+
|
|
6393
|
+
/**
|
|
6394
|
+
* Executes a callback when an element becomes visible.
|
|
6395
|
+
*/
|
|
6396
|
+
function onVisible(element, callback) {
|
|
6397
|
+
if (typeof IntersectionObserver === 'undefined') {
|
|
6398
|
+
return () => {};
|
|
6399
|
+
}
|
|
6400
|
+
const observer = new IntersectionObserver(entries => {
|
|
6401
|
+
entries.forEach(entry => {
|
|
6402
|
+
if (entry.intersectionRatio > 0) {
|
|
6403
|
+
callback();
|
|
6404
|
+
observer.disconnect();
|
|
6405
|
+
}
|
|
6406
|
+
});
|
|
6407
|
+
});
|
|
6408
|
+
observer.observe(element);
|
|
6409
|
+
return () => {
|
|
6410
|
+
observer.disconnect();
|
|
6411
|
+
};
|
|
6412
|
+
}
|
|
6413
|
+
|
|
6414
|
+
let ScrollAreaViewportCssVars = /*#__PURE__*/function (ScrollAreaViewportCssVars) {
|
|
6415
|
+
/**
|
|
6416
|
+
* The distance from the horizontal start edge in pixels.
|
|
6417
|
+
* @type {number}
|
|
6418
|
+
*/
|
|
6419
|
+
ScrollAreaViewportCssVars["scrollAreaOverflowXStart"] = "--scroll-area-overflow-x-start";
|
|
6420
|
+
/**
|
|
6421
|
+
* The distance from the horizontal end edge in pixels.
|
|
6422
|
+
* @type {number}
|
|
6423
|
+
*/
|
|
6424
|
+
ScrollAreaViewportCssVars["scrollAreaOverflowXEnd"] = "--scroll-area-overflow-x-end";
|
|
6425
|
+
/**
|
|
6426
|
+
* The distance from the vertical start edge in pixels.
|
|
6427
|
+
* @type {number}
|
|
6428
|
+
*/
|
|
6429
|
+
ScrollAreaViewportCssVars["scrollAreaOverflowYStart"] = "--scroll-area-overflow-y-start";
|
|
6430
|
+
/**
|
|
6431
|
+
* The distance from the vertical end edge in pixels.
|
|
6432
|
+
* @type {number}
|
|
6433
|
+
*/
|
|
6434
|
+
ScrollAreaViewportCssVars["scrollAreaOverflowYEnd"] = "--scroll-area-overflow-y-end";
|
|
6435
|
+
return ScrollAreaViewportCssVars;
|
|
6436
|
+
}({});
|
|
6437
|
+
|
|
6438
|
+
const SCROLL_EDGE_TOLERANCE_PX = 1;
|
|
6439
|
+
function normalizeScrollOffset(value, max) {
|
|
6440
|
+
if (max <= 0) {
|
|
6441
|
+
return 0;
|
|
6442
|
+
}
|
|
6443
|
+
const clamped = clamp(value, 0, max);
|
|
6444
|
+
const startDistance = clamped;
|
|
6445
|
+
const endDistance = max - clamped;
|
|
6446
|
+
const withinStartTolerance = startDistance <= SCROLL_EDGE_TOLERANCE_PX;
|
|
6447
|
+
const withinEndTolerance = endDistance <= SCROLL_EDGE_TOLERANCE_PX;
|
|
6448
|
+
if (withinStartTolerance && withinEndTolerance) {
|
|
6449
|
+
return startDistance <= endDistance ? 0 : max;
|
|
6450
|
+
}
|
|
6451
|
+
if (withinStartTolerance) {
|
|
6452
|
+
return 0;
|
|
6453
|
+
}
|
|
6454
|
+
if (withinEndTolerance) {
|
|
6455
|
+
return max;
|
|
6456
|
+
}
|
|
6457
|
+
return clamped;
|
|
6458
|
+
}
|
|
6459
|
+
|
|
6460
|
+
let scrollAreaOverflowVarsRegistered = false;
|
|
6461
|
+
const HAS_RESIZE_OBSERVER = typeof ResizeObserver !== 'undefined';
|
|
6462
|
+
|
|
6463
|
+
/**
|
|
6464
|
+
* Removes inheritance of the scroll area overflow CSS variables, which
|
|
6465
|
+
* improves rendering performance in complex scroll areas with deep subtrees.
|
|
6466
|
+
* Instead, each child must manually opt-in to using these properties by
|
|
6467
|
+
* specifying `inherit`.
|
|
6468
|
+
* See https://motion.dev/blog/web-animation-performance-tier-list
|
|
6469
|
+
* under the "Improving CSS variable performance" section.
|
|
6470
|
+
*/
|
|
6471
|
+
function removeCSSVariableInheritance() {
|
|
6472
|
+
if (scrollAreaOverflowVarsRegistered ||
|
|
6473
|
+
// When `inherits: false`, specifying `inherit` on child elements doesn't work
|
|
6474
|
+
// in Safari. To let CSS features work correctly, this optimization must be skipped.
|
|
6475
|
+
isWebKit) {
|
|
6476
|
+
return;
|
|
6477
|
+
}
|
|
6478
|
+
if (typeof CSS !== 'undefined' && 'registerProperty' in CSS) {
|
|
6479
|
+
[ScrollAreaViewportCssVars.scrollAreaOverflowXStart, ScrollAreaViewportCssVars.scrollAreaOverflowXEnd, ScrollAreaViewportCssVars.scrollAreaOverflowYStart, ScrollAreaViewportCssVars.scrollAreaOverflowYEnd].forEach(name => {
|
|
6480
|
+
try {
|
|
6481
|
+
CSS.registerProperty({
|
|
6482
|
+
name,
|
|
6483
|
+
syntax: '<length>',
|
|
6484
|
+
inherits: false,
|
|
6485
|
+
initialValue: '0px'
|
|
6486
|
+
});
|
|
6487
|
+
} catch {
|
|
6488
|
+
/* ignore already-registered */
|
|
6489
|
+
}
|
|
6490
|
+
});
|
|
6491
|
+
}
|
|
6492
|
+
scrollAreaOverflowVarsRegistered = true;
|
|
6493
|
+
}
|
|
6494
|
+
|
|
6495
|
+
/**
|
|
6496
|
+
* The actual scrollable container of the scroll area.
|
|
6497
|
+
* Renders a `<div>` element.
|
|
6498
|
+
*
|
|
6499
|
+
* Documentation: [Base UI Scroll Area](https://base-ui.com/react/components/scroll-area)
|
|
6500
|
+
*/
|
|
6501
|
+
const ScrollAreaViewport = /*#__PURE__*/React.forwardRef(function ScrollAreaViewport(componentProps, forwardedRef) {
|
|
6502
|
+
const {
|
|
6503
|
+
render,
|
|
6504
|
+
className,
|
|
6505
|
+
...elementProps
|
|
6506
|
+
} = componentProps;
|
|
6507
|
+
const {
|
|
6508
|
+
viewportRef,
|
|
6509
|
+
scrollbarYRef,
|
|
6510
|
+
scrollbarXRef,
|
|
6511
|
+
thumbYRef,
|
|
6512
|
+
thumbXRef,
|
|
6513
|
+
cornerRef,
|
|
6514
|
+
cornerSize,
|
|
6515
|
+
setCornerSize,
|
|
6516
|
+
setThumbSize,
|
|
6517
|
+
rootId,
|
|
6518
|
+
setHiddenState,
|
|
6519
|
+
hiddenState,
|
|
6520
|
+
setHasMeasuredScrollbar,
|
|
6521
|
+
handleScroll,
|
|
6522
|
+
setHovering,
|
|
6523
|
+
setOverflowEdges,
|
|
6524
|
+
overflowEdges,
|
|
6525
|
+
overflowEdgeThreshold,
|
|
6526
|
+
scrollingX,
|
|
6527
|
+
scrollingY
|
|
6528
|
+
} = useScrollAreaRootContext();
|
|
6529
|
+
const direction = useDirection();
|
|
6530
|
+
const programmaticScrollRef = React.useRef(true);
|
|
6531
|
+
const lastMeasuredViewportMetricsRef = React.useRef([NaN, NaN, NaN, NaN]);
|
|
6532
|
+
const scrollEndTimeout = useTimeout();
|
|
6533
|
+
const waitForAnimationsTimeout = useTimeout();
|
|
6534
|
+
const computeThumbPosition = useStableCallback(() => {
|
|
6535
|
+
const viewportEl = viewportRef.current;
|
|
6536
|
+
const scrollbarYEl = scrollbarYRef.current;
|
|
6537
|
+
const scrollbarXEl = scrollbarXRef.current;
|
|
6538
|
+
const thumbYEl = thumbYRef.current;
|
|
6539
|
+
const thumbXEl = thumbXRef.current;
|
|
6540
|
+
const cornerEl = cornerRef.current;
|
|
6541
|
+
if (!viewportEl) {
|
|
6542
|
+
return;
|
|
6543
|
+
}
|
|
6544
|
+
const scrollableContentHeight = viewportEl.scrollHeight;
|
|
6545
|
+
const scrollableContentWidth = viewportEl.scrollWidth;
|
|
6546
|
+
const viewportHeight = viewportEl.clientHeight;
|
|
6547
|
+
const viewportWidth = viewportEl.clientWidth;
|
|
6548
|
+
const scrollTop = viewportEl.scrollTop;
|
|
6549
|
+
const scrollLeft = viewportEl.scrollLeft;
|
|
6550
|
+
const lastMeasuredViewportMetrics = lastMeasuredViewportMetricsRef.current;
|
|
6551
|
+
const isFirstMeasurement = Number.isNaN(lastMeasuredViewportMetrics[0]);
|
|
6552
|
+
lastMeasuredViewportMetrics[0] = viewportHeight;
|
|
6553
|
+
lastMeasuredViewportMetrics[1] = scrollableContentHeight;
|
|
6554
|
+
lastMeasuredViewportMetrics[2] = viewportWidth;
|
|
6555
|
+
lastMeasuredViewportMetrics[3] = scrollableContentWidth;
|
|
6556
|
+
if (isFirstMeasurement) {
|
|
6557
|
+
setHasMeasuredScrollbar(true);
|
|
6558
|
+
}
|
|
6559
|
+
if (scrollableContentHeight === 0 || scrollableContentWidth === 0) {
|
|
6560
|
+
return;
|
|
6561
|
+
}
|
|
6562
|
+
const nextHiddenState = getHiddenState(viewportEl);
|
|
6563
|
+
const scrollbarYHidden = nextHiddenState.y;
|
|
6564
|
+
const scrollbarXHidden = nextHiddenState.x;
|
|
6565
|
+
const ratioX = viewportWidth / scrollableContentWidth;
|
|
6566
|
+
const ratioY = viewportHeight / scrollableContentHeight;
|
|
6567
|
+
const maxScrollLeft = Math.max(0, scrollableContentWidth - viewportWidth);
|
|
6568
|
+
const maxScrollTop = Math.max(0, scrollableContentHeight - viewportHeight);
|
|
6569
|
+
let scrollLeftFromStart = 0;
|
|
6570
|
+
let scrollLeftFromEnd = 0;
|
|
6571
|
+
if (!scrollbarXHidden) {
|
|
6572
|
+
let rawScrollLeftFromStart = 0;
|
|
6573
|
+
if (direction === 'rtl') {
|
|
6574
|
+
rawScrollLeftFromStart = clamp(-scrollLeft, 0, maxScrollLeft);
|
|
6575
|
+
} else {
|
|
6576
|
+
rawScrollLeftFromStart = clamp(scrollLeft, 0, maxScrollLeft);
|
|
6577
|
+
}
|
|
6578
|
+
scrollLeftFromStart = normalizeScrollOffset(rawScrollLeftFromStart, maxScrollLeft);
|
|
6579
|
+
scrollLeftFromEnd = maxScrollLeft - scrollLeftFromStart;
|
|
6580
|
+
}
|
|
6581
|
+
const rawScrollTopFromStart = !scrollbarYHidden ? clamp(scrollTop, 0, maxScrollTop) : 0;
|
|
6582
|
+
const scrollTopFromStart = !scrollbarYHidden ? normalizeScrollOffset(rawScrollTopFromStart, maxScrollTop) : 0;
|
|
6583
|
+
const scrollTopFromEnd = !scrollbarYHidden ? maxScrollTop - scrollTopFromStart : 0;
|
|
6584
|
+
const nextWidth = scrollbarXHidden ? 0 : viewportWidth;
|
|
6585
|
+
const nextHeight = scrollbarYHidden ? 0 : viewportHeight;
|
|
6586
|
+
let nextCornerWidth = 0;
|
|
6587
|
+
let nextCornerHeight = 0;
|
|
6588
|
+
if (!scrollbarXHidden && !scrollbarYHidden) {
|
|
6589
|
+
nextCornerWidth = scrollbarYEl?.offsetWidth || 0;
|
|
6590
|
+
nextCornerHeight = scrollbarXEl?.offsetHeight || 0;
|
|
6591
|
+
}
|
|
6592
|
+
|
|
6593
|
+
// Only subtract corner size from scrollbar dimensions if the corner hasn't been sized yet.
|
|
6594
|
+
// Once sized, the layout will already account for it.
|
|
6595
|
+
const cornerNotYetSized = cornerSize.width === 0 && cornerSize.height === 0;
|
|
6596
|
+
const cornerWidthOffset = cornerNotYetSized ? nextCornerWidth : 0;
|
|
6597
|
+
const cornerHeightOffset = cornerNotYetSized ? nextCornerHeight : 0;
|
|
6598
|
+
const scrollbarXOffset = getOffset(scrollbarXEl, 'padding', 'x');
|
|
6599
|
+
const scrollbarYOffset = getOffset(scrollbarYEl, 'padding', 'y');
|
|
6600
|
+
const thumbXOffset = getOffset(thumbXEl, 'margin', 'x');
|
|
6601
|
+
const thumbYOffset = getOffset(thumbYEl, 'margin', 'y');
|
|
6602
|
+
const idealNextWidth = nextWidth - scrollbarXOffset - thumbXOffset;
|
|
6603
|
+
const idealNextHeight = nextHeight - scrollbarYOffset - thumbYOffset;
|
|
6604
|
+
const maxNextWidth = scrollbarXEl ? Math.min(scrollbarXEl.offsetWidth - cornerWidthOffset, idealNextWidth) : idealNextWidth;
|
|
6605
|
+
const maxNextHeight = scrollbarYEl ? Math.min(scrollbarYEl.offsetHeight - cornerHeightOffset, idealNextHeight) : idealNextHeight;
|
|
6606
|
+
const clampedNextWidth = Math.max(MIN_THUMB_SIZE, maxNextWidth * ratioX);
|
|
6607
|
+
const clampedNextHeight = Math.max(MIN_THUMB_SIZE, maxNextHeight * ratioY);
|
|
6608
|
+
setThumbSize(prevSize => {
|
|
6609
|
+
if (prevSize.height === clampedNextHeight && prevSize.width === clampedNextWidth) {
|
|
6610
|
+
return prevSize;
|
|
6611
|
+
}
|
|
6612
|
+
return {
|
|
6613
|
+
width: clampedNextWidth,
|
|
6614
|
+
height: clampedNextHeight
|
|
6615
|
+
};
|
|
6616
|
+
});
|
|
6617
|
+
|
|
6618
|
+
// Handle Y (vertical) scroll
|
|
6619
|
+
if (scrollbarYEl && thumbYEl) {
|
|
6620
|
+
const maxThumbOffsetY = scrollbarYEl.offsetHeight - clampedNextHeight - scrollbarYOffset - thumbYOffset;
|
|
6621
|
+
const scrollRangeY = scrollableContentHeight - viewportHeight;
|
|
6622
|
+
const scrollRatioY = scrollRangeY === 0 ? 0 : scrollTop / scrollRangeY;
|
|
6623
|
+
|
|
6624
|
+
// In Safari, don't allow it to go negative or too far as `scrollTop` considers the rubber
|
|
6625
|
+
// band effect.
|
|
6626
|
+
const thumbOffsetY = Math.min(maxThumbOffsetY, Math.max(0, scrollRatioY * maxThumbOffsetY));
|
|
6627
|
+
thumbYEl.style.transform = `translate3d(0,${thumbOffsetY}px,0)`;
|
|
6628
|
+
}
|
|
6629
|
+
|
|
6630
|
+
// Handle X (horizontal) scroll
|
|
6631
|
+
if (scrollbarXEl && thumbXEl) {
|
|
6632
|
+
const maxThumbOffsetX = scrollbarXEl.offsetWidth - clampedNextWidth - scrollbarXOffset - thumbXOffset;
|
|
6633
|
+
const scrollRangeX = scrollableContentWidth - viewportWidth;
|
|
6634
|
+
const scrollRatioX = scrollRangeX === 0 ? 0 : scrollLeft / scrollRangeX;
|
|
6635
|
+
|
|
6636
|
+
// In Safari, don't allow it to go negative or too far as `scrollLeft` considers the rubber
|
|
6637
|
+
// band effect.
|
|
6638
|
+
const thumbOffsetX = direction === 'rtl' ? clamp(scrollRatioX * maxThumbOffsetX, -maxThumbOffsetX, 0) : clamp(scrollRatioX * maxThumbOffsetX, 0, maxThumbOffsetX);
|
|
6639
|
+
thumbXEl.style.transform = `translate3d(${thumbOffsetX}px,0,0)`;
|
|
6640
|
+
}
|
|
6641
|
+
const overflowMetricsPx = [[ScrollAreaViewportCssVars.scrollAreaOverflowXStart, scrollLeftFromStart], [ScrollAreaViewportCssVars.scrollAreaOverflowXEnd, scrollLeftFromEnd], [ScrollAreaViewportCssVars.scrollAreaOverflowYStart, scrollTopFromStart], [ScrollAreaViewportCssVars.scrollAreaOverflowYEnd, scrollTopFromEnd]];
|
|
6642
|
+
for (const [cssVar, value] of overflowMetricsPx) {
|
|
6643
|
+
viewportEl.style.setProperty(cssVar, `${value}px`);
|
|
6644
|
+
}
|
|
6645
|
+
if (cornerEl) {
|
|
6646
|
+
if (scrollbarXHidden || scrollbarYHidden) {
|
|
6647
|
+
setCornerSize({
|
|
6648
|
+
width: 0,
|
|
6649
|
+
height: 0
|
|
6650
|
+
});
|
|
6651
|
+
} else if (!scrollbarXHidden && !scrollbarYHidden) {
|
|
6652
|
+
setCornerSize({
|
|
6653
|
+
width: nextCornerWidth,
|
|
6654
|
+
height: nextCornerHeight
|
|
6655
|
+
});
|
|
6656
|
+
}
|
|
6657
|
+
}
|
|
6658
|
+
setHiddenState(prevState => mergeHiddenState(prevState, nextHiddenState));
|
|
6659
|
+
const nextOverflowEdges = {
|
|
6660
|
+
xStart: !scrollbarXHidden && scrollLeftFromStart > overflowEdgeThreshold.xStart,
|
|
6661
|
+
xEnd: !scrollbarXHidden && scrollLeftFromEnd > overflowEdgeThreshold.xEnd,
|
|
6662
|
+
yStart: !scrollbarYHidden && scrollTopFromStart > overflowEdgeThreshold.yStart,
|
|
6663
|
+
yEnd: !scrollbarYHidden && scrollTopFromEnd > overflowEdgeThreshold.yEnd
|
|
6664
|
+
};
|
|
6665
|
+
setOverflowEdges(prev => {
|
|
6666
|
+
if (prev.xStart === nextOverflowEdges.xStart && prev.xEnd === nextOverflowEdges.xEnd && prev.yStart === nextOverflowEdges.yStart && prev.yEnd === nextOverflowEdges.yEnd) {
|
|
6667
|
+
return prev;
|
|
6668
|
+
}
|
|
6669
|
+
return nextOverflowEdges;
|
|
6670
|
+
});
|
|
6671
|
+
});
|
|
6672
|
+
useIsoLayoutEffect(() => {
|
|
6673
|
+
if (!viewportRef.current) {
|
|
6674
|
+
return undefined;
|
|
6675
|
+
}
|
|
6676
|
+
removeCSSVariableInheritance();
|
|
6677
|
+
if (HAS_RESIZE_OBSERVER) {
|
|
6678
|
+
return undefined;
|
|
6679
|
+
}
|
|
6680
|
+
return onVisible(viewportRef.current, () => {
|
|
6681
|
+
computeThumbPosition();
|
|
6682
|
+
});
|
|
6683
|
+
}, [computeThumbPosition, viewportRef]);
|
|
6684
|
+
useIsoLayoutEffect(() => {
|
|
6685
|
+
// Wait for scrollbar and thumb refs after hidden-state toggles, and refresh math on direction flips.
|
|
6686
|
+
queueMicrotask(computeThumbPosition);
|
|
6687
|
+
}, [computeThumbPosition, hiddenState, direction]);
|
|
6688
|
+
useIsoLayoutEffect(() => {
|
|
6689
|
+
// `onMouseEnter` doesn't fire upon load, so we need to check if the viewport is already
|
|
6690
|
+
// being hovered.
|
|
6691
|
+
if (viewportRef.current?.matches(':hover')) {
|
|
6692
|
+
setHovering(true);
|
|
6693
|
+
}
|
|
6694
|
+
}, [viewportRef, setHovering]);
|
|
6695
|
+
React.useEffect(() => {
|
|
6696
|
+
const viewport = viewportRef.current;
|
|
6697
|
+
if (!HAS_RESIZE_OBSERVER || !viewport) {
|
|
6698
|
+
return undefined;
|
|
6699
|
+
}
|
|
6700
|
+
let hasInitialized = false;
|
|
6701
|
+
const ro = new ResizeObserver(() => {
|
|
6702
|
+
// Avoid duplicate mount-time recompute when observer data matches what the mount
|
|
6703
|
+
// scheduling pass already measured. If dimensions changed before the first observer
|
|
6704
|
+
// delivery, keep the recompute so overflow transitions stay in sync.
|
|
6705
|
+
if (!hasInitialized) {
|
|
6706
|
+
hasInitialized = true;
|
|
6707
|
+
const lastMeasuredViewportMetrics = lastMeasuredViewportMetricsRef.current;
|
|
6708
|
+
if (lastMeasuredViewportMetrics[0] === viewport.clientHeight && lastMeasuredViewportMetrics[1] === viewport.scrollHeight && lastMeasuredViewportMetrics[2] === viewport.clientWidth && lastMeasuredViewportMetrics[3] === viewport.scrollWidth) {
|
|
6709
|
+
return;
|
|
6710
|
+
}
|
|
6711
|
+
}
|
|
6712
|
+
computeThumbPosition();
|
|
6713
|
+
});
|
|
6714
|
+
ro.observe(viewport);
|
|
6715
|
+
|
|
6716
|
+
// If there are animations in the viewport, wait for them to finish and then recompute the thumb position.
|
|
6717
|
+
// This is necessary when the viewport contains a Dialog that is animating its popup on open
|
|
6718
|
+
// and the popup is using a transform for the animation, which affects the size of the viewport.
|
|
6719
|
+
// Without this, the thumb position will be incorrect until scrolling (i.e. if the scrollbar shows
|
|
6720
|
+
// on hover, the thumb has an incorrect size).
|
|
6721
|
+
// We assume the user is using `onOpenChangeComplete` to hide the scrollbar
|
|
6722
|
+
// until animations complete because otherwise the scrollbar would show the thumb resizing mid-animation.
|
|
6723
|
+
waitForAnimationsTimeout.start(0, () => {
|
|
6724
|
+
const animations = viewport.getAnimations({
|
|
6725
|
+
subtree: true
|
|
6726
|
+
});
|
|
6727
|
+
if (animations.length === 0) {
|
|
6728
|
+
return;
|
|
6729
|
+
}
|
|
6730
|
+
Promise.allSettled(animations.map(animation => animation.finished)).then(computeThumbPosition).catch(() => {});
|
|
6731
|
+
});
|
|
6732
|
+
return () => {
|
|
6733
|
+
ro.disconnect();
|
|
6734
|
+
waitForAnimationsTimeout.clear();
|
|
6735
|
+
};
|
|
6736
|
+
}, [computeThumbPosition, viewportRef, waitForAnimationsTimeout]);
|
|
6737
|
+
function handleUserInteraction() {
|
|
6738
|
+
programmaticScrollRef.current = false;
|
|
6739
|
+
}
|
|
6740
|
+
const props = {
|
|
6741
|
+
role: 'presentation',
|
|
6742
|
+
...(rootId && {
|
|
6743
|
+
'data-id': `${rootId}-viewport`
|
|
6744
|
+
}),
|
|
6745
|
+
// https://accessibilityinsights.io/info-examples/web/scrollable-region-focusable/
|
|
6746
|
+
// Keep non-scrollable viewports out of tab order.
|
|
6747
|
+
tabIndex: hiddenState.x && hiddenState.y ? -1 : 0,
|
|
6748
|
+
className: styleDisableScrollbar.className,
|
|
6749
|
+
style: {
|
|
6750
|
+
overflow: 'scroll'
|
|
6751
|
+
},
|
|
6752
|
+
onScroll() {
|
|
6753
|
+
if (!viewportRef.current) {
|
|
6754
|
+
return;
|
|
6755
|
+
}
|
|
6756
|
+
computeThumbPosition();
|
|
6757
|
+
if (!programmaticScrollRef.current) {
|
|
6758
|
+
handleScroll({
|
|
6759
|
+
x: viewportRef.current.scrollLeft,
|
|
6760
|
+
y: viewportRef.current.scrollTop
|
|
6761
|
+
});
|
|
6762
|
+
}
|
|
6763
|
+
|
|
6764
|
+
// Debounce the restoration of the programmatic flag so that it only
|
|
6765
|
+
// flips back to `true` once scrolling has come to a rest. This ensures
|
|
6766
|
+
// that momentum scrolling (where no further user-interaction events fire)
|
|
6767
|
+
// is still treated as user-driven.
|
|
6768
|
+
// 100 ms without scroll events ≈ scroll end
|
|
6769
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollend_event
|
|
6770
|
+
scrollEndTimeout.start(100, () => {
|
|
6771
|
+
programmaticScrollRef.current = true;
|
|
6772
|
+
});
|
|
6773
|
+
},
|
|
6774
|
+
onWheel: handleUserInteraction,
|
|
6775
|
+
onTouchMove: handleUserInteraction,
|
|
6776
|
+
onPointerMove: handleUserInteraction,
|
|
6777
|
+
onPointerEnter: handleUserInteraction,
|
|
6778
|
+
onKeyDown: handleUserInteraction
|
|
6779
|
+
};
|
|
6780
|
+
const viewportState = React.useMemo(() => ({
|
|
6781
|
+
scrolling: scrollingX || scrollingY,
|
|
6782
|
+
hasOverflowX: !hiddenState.x,
|
|
6783
|
+
hasOverflowY: !hiddenState.y,
|
|
6784
|
+
overflowXStart: overflowEdges.xStart,
|
|
6785
|
+
overflowXEnd: overflowEdges.xEnd,
|
|
6786
|
+
overflowYStart: overflowEdges.yStart,
|
|
6787
|
+
overflowYEnd: overflowEdges.yEnd,
|
|
6788
|
+
cornerHidden: hiddenState.corner
|
|
6789
|
+
}), [scrollingX, scrollingY, hiddenState.x, hiddenState.y, hiddenState.corner, overflowEdges]);
|
|
6790
|
+
const element = useRenderElement('div', componentProps, {
|
|
6791
|
+
ref: [forwardedRef, viewportRef],
|
|
6792
|
+
state: viewportState,
|
|
6793
|
+
props: [props, elementProps],
|
|
6794
|
+
stateAttributesMapping: scrollAreaStateAttributesMapping
|
|
6795
|
+
});
|
|
6796
|
+
const contextValue = React.useMemo(() => ({
|
|
6797
|
+
computeThumbPosition
|
|
6798
|
+
}), [computeThumbPosition]);
|
|
6799
|
+
return /*#__PURE__*/jsx(ScrollAreaViewportContext.Provider, {
|
|
6800
|
+
value: contextValue,
|
|
6801
|
+
children: element
|
|
6802
|
+
});
|
|
6803
|
+
});
|
|
6804
|
+
if (process.env.NODE_ENV !== "production") ScrollAreaViewport.displayName = "ScrollAreaViewport";
|
|
6805
|
+
function getHiddenState(viewport) {
|
|
6806
|
+
const y = viewport.clientHeight >= viewport.scrollHeight;
|
|
6807
|
+
const x = viewport.clientWidth >= viewport.scrollWidth;
|
|
6808
|
+
return {
|
|
6809
|
+
y,
|
|
6810
|
+
x,
|
|
6811
|
+
corner: y || x
|
|
6812
|
+
};
|
|
6813
|
+
}
|
|
6814
|
+
function mergeHiddenState(prevState, nextState) {
|
|
6815
|
+
if (prevState.y === nextState.y && prevState.x === nextState.x && prevState.corner === nextState.corner) {
|
|
6816
|
+
return prevState;
|
|
6817
|
+
}
|
|
6818
|
+
return nextState;
|
|
6819
|
+
}
|
|
6820
|
+
|
|
6821
|
+
export { createInitialPopupStoreState as $, getGridCellIndexOfCorner as A, ARROW_DOWN$1 as B, ARROW_LEFT$1 as C, DrawerTrigger as D, ARROW_RIGHT$1 as E, FloatingRootStore as F, findNonDisabledListIndex as G, enqueueFocus as H, ARROW_UP$1 as I, isElementVisible as J, DISABLED_TRANSITIONS_STYLE as K, popupStateMapping as L, COMPOSITE_KEYS as M, FloatingFocusManager as N, FloatingPortal as O, PopupTriggerMap as P, useDirection as Q, POPUP_COLLISION_AVOIDANCE as R, ScrollAreaRoot as S, TYPEABLE_SELECTOR as T, InternalBackdrop as U, inertValue as V, FloatingNode as W, DROPDOWN_COLLISION_AVOIDANCE as X, popupStoreSelectors as Y, createSelector as Z, ReactStore as _, DrawerRoot as a, FloatingTreeStore as a0, fastComponent as a1, useOnFirstRender as a2, useFloatingNodeId as a3, useOpenInteractionType as a4, useImplicitActiveTrigger as a5, useOpenStateTransitions as a6, useScrollLock as a7, useSyncedFloatingRootContext as a8, useDismiss as a9, DrawerViewportContext as aA, BASE_UI_SWIPE_IGNORE_SELECTOR as aB, DRAWER_CONTENT_ATTRIBUTE as aC, useScrollAreaRootContext as aD, getOffset as aE, ScrollAreaRootCssVars as aF, scrollAreaStateAttributesMapping as aG, useScrollAreaViewportContext as aH, useStore as aI, Store as aJ, useRole as aa, TYPEAHEAD_RESET_MS as ab, useInteractions as ac, FloatingTree as ad, fastComponentRef as ae, useTriggerDataForwarding as af, useClick as ag, getTabbableBeforeElement as ah, isOutsideEvent as ai, getTabbableAfterElement as aj, getNextTabbable as ak, pressableTriggerOpenStateMapping as al, FocusGuard as am, PATIENT_CLICK_THRESHOLD as an, useTriggerRegistration as ao, triggerOpenStateMapping as ap, useDrawerProviderContext as aq, DrawerBackdropCssVars as ar, DrawerPopupCssVars as as, DrawerProviderContext as at, CommonPopupDataAttributes as au, useDialogPortalContext as av, DialogStore as aw, useDrawerRootContext as ax, DrawerPopupDataAttributes as ay, useDrawerSnapPoints as az, DrawerPortal as b, DrawerBackdrop as c, DrawerPopup as d, ScrollAreaViewport as e, DrawerContent as f, useFloatingParentNodeId as g, useFloatingTree as h, getTarget as i, isTypeableElement as j, isTargetInsideEnabledTrigger as k, createAttribute as l, matchesFocusVisible as m, activeElement as n, contains as o, getNodeChildren as p, getFloatingFocusElement as q, isTypeableCombobox as r, isIndexOutOfListBounds as s, getMinListIndex as t, useDialogRootContext as u, getMaxListIndex as v, createGridCellMap as w, isListIndexDisabled as x, getGridNavigatedIndex as y, getGridCellIndices as z };
|