@jobber/components 8.15.0 → 8.16.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/dist/Card/index.cjs +1 -1
- package/dist/Card/index.mjs +1 -1
- package/dist/DataDump/index.cjs +1 -1
- package/dist/DataDump/index.mjs +1 -1
- package/dist/InputNumberExperimental-cjs.js +16 -16
- package/dist/InputNumberExperimental-es.js +1 -1
- package/dist/Menu/index.cjs +1 -1
- package/dist/Menu/index.mjs +1 -1
- package/dist/MenuSubmenuTrigger-cjs.js +1060 -1060
- package/dist/MenuSubmenuTrigger-es.js +928 -928
- package/dist/NumberFieldInput-cjs.js +53 -53
- package/dist/NumberFieldInput-es.js +1 -1
- package/dist/Page/index.cjs +1 -1
- package/dist/Page/index.mjs +1 -1
- package/dist/ScrollAreaViewport-cjs.js +4436 -4436
- package/dist/ScrollAreaViewport-es.js +4372 -4372
- package/dist/{useValueChanged-cjs.js → clamp-cjs.js} +594 -592
- package/dist/{useValueChanged-es.js → clamp-es.js} +595 -594
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/primitives/BottomSheet/index.cjs +2 -2
- package/dist/primitives/BottomSheet/index.mjs +2 -2
- package/dist/primitives/InputNumberExperimental/index.cjs +2 -2
- package/dist/primitives/InputNumberExperimental/index.mjs +2 -2
- package/dist/primitives/index.cjs +2 -2
- package/dist/primitives/index.mjs +2 -2
- package/dist/unstyledPrimitives/index.cjs +6271 -6134
- package/dist/unstyledPrimitives/index.d.ts +1 -0
- package/dist/unstyledPrimitives/index.mjs +6318 -6182
- package/dist/useRenderElement-cjs.js +30 -30
- package/dist/useRenderElement-es.js +30 -30
- package/package.json +2 -2
|
@@ -1,64 +1,13 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { u as
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { u as useFloatingParentNodeId, F as FloatingRootStore, P as PopupTriggerMap, g as useFloatingTree, h as getTarget, i as isTypeableElement, m as matchesFocusVisible, j as isTargetInsideEnabledTrigger, k as createAttribute, l as activeElement, n as contains, T as TYPEABLE_SELECTOR, o as getNodeChildren, p as getFloatingFocusElement, q as isTypeableCombobox, r as isIndexOutOfListBounds, s as getMinListIndex, t as getMaxListIndex, v as createGridCellMap, w as isListIndexDisabled, x as getGridNavigatedIndex, y as getGridCellIndices, z as getGridCellIndexOfCorner, A as ARROW_DOWN, B as ARROW_LEFT, C as ARROW_RIGHT, E as findNonDisabledListIndex, G as enqueueFocus, H as ARROW_UP, I as isElementVisible, J as useDirection, K as DISABLED_TRANSITIONS_STYLE, L as useDialogRootContext, M as popupStateMapping, N as COMPOSITE_KEYS, O as FloatingFocusManager, Q as FloatingPortal, R as POPUP_COLLISION_AVOIDANCE, U as InternalBackdrop, V as inertValue, W as FloatingNode, X as DROPDOWN_COLLISION_AVOIDANCE, Y as popupStoreSelectors, Z as createSelector, _ as ReactStore, $ as createInitialPopupStoreState, a0 as FloatingTreeStore, a1 as fastComponent, a2 as useOnFirstRender, a3 as useFloatingNodeId, a4 as useOpenInteractionType, a5 as useImplicitActiveTrigger, a6 as useOpenStateTransitions, a7 as useScrollLock, a8 as useSyncedFloatingRootContext, a9 as useDismiss, aa as useRole, ab as TYPEAHEAD_RESET_MS, ac as useInteractions, ad as FloatingTree, ae as fastComponentRef, af as useTriggerDataForwarding, ag as useClick, ah as getTabbableBeforeElement, ai as isOutsideEvent, aj as getTabbableAfterElement, ak as getNextTabbable, al as pressableTriggerOpenStateMapping, am as FocusGuard, an as PATIENT_CLICK_THRESHOLD, ao as useTriggerRegistration, ap as triggerOpenStateMapping } from './ScrollAreaViewport-es.js';
|
|
3
|
+
import { a as useRefWithInit, E as EMPTY_OBJECT, u as useRenderElement, f as formatErrorMessage, m as mergeProps, b as useMergedRefs, d as EMPTY_ARRAY } from './useRenderElement-es.js';
|
|
4
|
+
import { C as isMouseLikePointerType, D as useId, d as useIsoLayoutEffect, b as useTimeout, k as createChangeEventDetails, E as triggerFocus, F as isMac, G as isSafari, s as ownerDocument, H as triggerPress, I as escapeKey, f as useOnMount, T as Timeout, a as useStableCallback, J as triggerHover, i as useValueAsRef, A as stopEvent, K as listNavigation, L as focusOut, M as isVirtualClick, N as isVirtualPointerEvent, y as useButton, O as closePress, u as useBaseUiId, P as itemPress, t as transitionStatusMapping, e as useOpenChangeComplete, Q as outsidePress, R as useAnimationsFinished, S as siblingOpen, h as useControlled, c as useTransitionStatus, U as imperativeAction, V as useCompositeRootContext, W as cancelOpen } from './clamp-es.js';
|
|
5
5
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
6
6
|
import { b as isElement, k as getWindow, a as isHTMLElement, d as isLastTraversableNode, e as getParentNode } from './floating-ui.utils.dom-es.js';
|
|
7
7
|
import { e as evaluate, h as getPaddingObject, b as getAlignmentAxis, d as getAlignment, q as getAxisLength, n as clamp, c as getSide, g as getSideAxis } from './index.esm-es.js';
|
|
8
8
|
import { u as useFloating$1, h as hide$1, f as flip, d as size, b as autoUpdate, o as offset, s as shift, l as limitShift } from './floating-ui.react-dom-es.js';
|
|
9
9
|
import * as ReactDOM from 'react-dom';
|
|
10
10
|
|
|
11
|
-
/**
|
|
12
|
-
* A button that closes the dialog.
|
|
13
|
-
* Renders a `<button>` element.
|
|
14
|
-
*
|
|
15
|
-
* Documentation: [Base UI Dialog](https://base-ui.com/react/components/dialog)
|
|
16
|
-
*/
|
|
17
|
-
const DialogClose = /*#__PURE__*/React.forwardRef(function DialogClose(componentProps, forwardedRef) {
|
|
18
|
-
const {
|
|
19
|
-
render,
|
|
20
|
-
className,
|
|
21
|
-
disabled = false,
|
|
22
|
-
nativeButton = true,
|
|
23
|
-
...elementProps
|
|
24
|
-
} = componentProps;
|
|
25
|
-
const {
|
|
26
|
-
store
|
|
27
|
-
} = useDialogRootContext();
|
|
28
|
-
const open = store.useState('open');
|
|
29
|
-
function handleClick(event) {
|
|
30
|
-
if (open) {
|
|
31
|
-
store.setOpen(false, createChangeEventDetails(closePress, event.nativeEvent));
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
const {
|
|
35
|
-
getButtonProps,
|
|
36
|
-
buttonRef
|
|
37
|
-
} = useButton({
|
|
38
|
-
disabled,
|
|
39
|
-
native: nativeButton
|
|
40
|
-
});
|
|
41
|
-
const state = {
|
|
42
|
-
disabled
|
|
43
|
-
};
|
|
44
|
-
return useRenderElement('button', componentProps, {
|
|
45
|
-
state,
|
|
46
|
-
ref: [forwardedRef, buttonRef],
|
|
47
|
-
props: [{
|
|
48
|
-
onClick: handleClick
|
|
49
|
-
}, elementProps, getButtonProps]
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
if (process.env.NODE_ENV !== "production") DialogClose.displayName = "DialogClose";
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* A button that closes the drawer.
|
|
56
|
-
* Renders a `<button>` element.
|
|
57
|
-
*
|
|
58
|
-
* Documentation: [Base UI Drawer](https://base-ui.com/react/components/drawer)
|
|
59
|
-
*/
|
|
60
|
-
const DrawerClose = DialogClose;
|
|
61
|
-
|
|
62
11
|
function resolveValue(value, pointerType) {
|
|
63
12
|
if (pointerType != null && !isMouseLikePointerType(pointerType)) {
|
|
64
13
|
return 0;
|
|
@@ -1869,752 +1818,294 @@ function safePolygon(options = {}) {
|
|
|
1869
1818
|
return fn;
|
|
1870
1819
|
}
|
|
1871
1820
|
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
* Renders an `<h2>` element.
|
|
1875
|
-
*
|
|
1876
|
-
* Documentation: [Base UI Dialog](https://base-ui.com/react/components/dialog)
|
|
1877
|
-
*/
|
|
1878
|
-
const DialogTitle = /*#__PURE__*/React.forwardRef(function DialogTitle(componentProps, forwardedRef) {
|
|
1879
|
-
const {
|
|
1880
|
-
render,
|
|
1881
|
-
className,
|
|
1882
|
-
id: idProp,
|
|
1883
|
-
...elementProps
|
|
1884
|
-
} = componentProps;
|
|
1885
|
-
const {
|
|
1886
|
-
store
|
|
1887
|
-
} = useDialogRootContext();
|
|
1888
|
-
const id = useBaseUiId(idProp);
|
|
1889
|
-
store.useSyncedValueWithCleanup('titleElementId', id);
|
|
1890
|
-
return useRenderElement('h2', componentProps, {
|
|
1891
|
-
ref: forwardedRef,
|
|
1892
|
-
props: [{
|
|
1893
|
-
id
|
|
1894
|
-
}, elementProps]
|
|
1895
|
-
});
|
|
1896
|
-
});
|
|
1897
|
-
if (process.env.NODE_ENV !== "production") DialogTitle.displayName = "DialogTitle";
|
|
1898
|
-
|
|
1899
|
-
/**
|
|
1900
|
-
* A heading that labels the drawer.
|
|
1901
|
-
* Renders an `<h2>` element.
|
|
1902
|
-
*
|
|
1903
|
-
* Documentation: [Base UI Drawer](https://base-ui.com/react/components/drawer)
|
|
1904
|
-
*/
|
|
1905
|
-
const DrawerTitle = DialogTitle;
|
|
1821
|
+
function getPseudoElementBounds(element) {
|
|
1822
|
+
const elementRect = element.getBoundingClientRect();
|
|
1906
1823
|
|
|
1907
|
-
|
|
1908
|
-
if (process.env.NODE_ENV !==
|
|
1909
|
-
|
|
1910
|
-
const context = React.useContext(MenuPositionerContext);
|
|
1911
|
-
if (context === undefined && !optional) {
|
|
1912
|
-
throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: MenuPositionerContext is missing. MenuPositioner parts must be placed within <Menu.Positioner>.' : formatErrorMessage(33));
|
|
1824
|
+
// Avoid "Not implemented: window.getComputedStyle(elt, pseudoElt)"
|
|
1825
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
1826
|
+
return elementRect;
|
|
1913
1827
|
}
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
function useMenuRootContext(optional) {
|
|
1920
|
-
const context = React.useContext(MenuRootContext);
|
|
1921
|
-
if (context === undefined && !optional) {
|
|
1922
|
-
throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: MenuRootContext is missing. Menu parts must be placed within <Menu.Root>.' : formatErrorMessage(36));
|
|
1828
|
+
const beforeStyles = window.getComputedStyle(element, '::before');
|
|
1829
|
+
const afterStyles = window.getComputedStyle(element, '::after');
|
|
1830
|
+
const hasPseudoElements = beforeStyles.content !== 'none' || afterStyles.content !== 'none';
|
|
1831
|
+
if (!hasPseudoElements) {
|
|
1832
|
+
return elementRect;
|
|
1923
1833
|
}
|
|
1924
|
-
|
|
1834
|
+
|
|
1835
|
+
// Get dimensions of pseudo-elements
|
|
1836
|
+
const beforeWidth = parseFloat(beforeStyles.width) || 0;
|
|
1837
|
+
const beforeHeight = parseFloat(beforeStyles.height) || 0;
|
|
1838
|
+
const afterWidth = parseFloat(afterStyles.width) || 0;
|
|
1839
|
+
const afterHeight = parseFloat(afterStyles.height) || 0;
|
|
1840
|
+
|
|
1841
|
+
// Calculate max dimensions including pseudo-elements
|
|
1842
|
+
const totalWidth = Math.max(elementRect.width, beforeWidth, afterWidth);
|
|
1843
|
+
const totalHeight = Math.max(elementRect.height, beforeHeight, afterHeight);
|
|
1844
|
+
|
|
1845
|
+
// Calculate the differences to extend the bounds
|
|
1846
|
+
const widthDiff = totalWidth - elementRect.width;
|
|
1847
|
+
const heightDiff = totalHeight - elementRect.height;
|
|
1848
|
+
return {
|
|
1849
|
+
left: elementRect.left - widthDiff / 2,
|
|
1850
|
+
right: elementRect.right + widthDiff / 2,
|
|
1851
|
+
top: elementRect.top - heightDiff / 2,
|
|
1852
|
+
bottom: elementRect.bottom + heightDiff / 2
|
|
1853
|
+
};
|
|
1925
1854
|
}
|
|
1926
1855
|
|
|
1927
|
-
const
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1856
|
+
const CompositeListContext = /*#__PURE__*/React.createContext({
|
|
1857
|
+
register: () => {},
|
|
1858
|
+
unregister: () => {},
|
|
1859
|
+
subscribeMapChange: () => {
|
|
1860
|
+
return () => {};
|
|
1861
|
+
},
|
|
1862
|
+
elementsRef: {
|
|
1863
|
+
current: []
|
|
1864
|
+
},
|
|
1865
|
+
nextIndexRef: {
|
|
1866
|
+
current: 0
|
|
1933
1867
|
}
|
|
1934
|
-
|
|
1868
|
+
});
|
|
1869
|
+
if (process.env.NODE_ENV !== "production") CompositeListContext.displayName = "CompositeListContext";
|
|
1870
|
+
function useCompositeListContext() {
|
|
1871
|
+
return React.useContext(CompositeListContext);
|
|
1935
1872
|
}
|
|
1936
1873
|
|
|
1874
|
+
/* eslint-disable no-bitwise */
|
|
1937
1875
|
/**
|
|
1938
|
-
*
|
|
1939
|
-
*
|
|
1940
|
-
* onMouseMove, onClick, and onMouseUp handlers.
|
|
1876
|
+
* Provides context for a list of items in a composite component.
|
|
1877
|
+
* @internal
|
|
1941
1878
|
*/
|
|
1942
|
-
function
|
|
1943
|
-
const {
|
|
1944
|
-
closeOnClick,
|
|
1945
|
-
highlighted,
|
|
1946
|
-
id,
|
|
1947
|
-
nodeId,
|
|
1948
|
-
store,
|
|
1949
|
-
typingRef,
|
|
1950
|
-
itemRef,
|
|
1951
|
-
itemMetadata
|
|
1952
|
-
} = params;
|
|
1879
|
+
function CompositeList(props) {
|
|
1953
1880
|
const {
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
onKeyDown(event) {
|
|
1963
|
-
if (event.key === ' ' && typingRef?.current) {
|
|
1964
|
-
event.preventDefault();
|
|
1965
|
-
}
|
|
1966
|
-
},
|
|
1967
|
-
onMouseMove(event) {
|
|
1968
|
-
if (!nodeId) {
|
|
1969
|
-
return;
|
|
1970
|
-
}
|
|
1971
|
-
|
|
1972
|
-
// Inform the floating tree that a menu item within this menu was hovered/moved over
|
|
1973
|
-
// so unrelated descendant submenus can be closed.
|
|
1974
|
-
menuEvents.emit('itemhover', {
|
|
1975
|
-
nodeId,
|
|
1976
|
-
target: event.currentTarget
|
|
1977
|
-
});
|
|
1978
|
-
},
|
|
1979
|
-
onClick(event) {
|
|
1980
|
-
if (closeOnClick) {
|
|
1981
|
-
menuEvents.emit('close', {
|
|
1982
|
-
domEvent: event,
|
|
1983
|
-
reason: itemPress
|
|
1984
|
-
});
|
|
1985
|
-
}
|
|
1986
|
-
},
|
|
1987
|
-
onMouseUp(event) {
|
|
1988
|
-
if (contextMenuContext) {
|
|
1989
|
-
const initialCursorPoint = contextMenuContext.initialCursorPointRef.current;
|
|
1990
|
-
contextMenuContext.initialCursorPointRef.current = null;
|
|
1991
|
-
if (isContextMenu && initialCursorPoint && Math.abs(event.clientX - initialCursorPoint.x) <= 1 && Math.abs(event.clientY - initialCursorPoint.y) <= 1) {
|
|
1992
|
-
return;
|
|
1993
|
-
}
|
|
1881
|
+
children,
|
|
1882
|
+
elementsRef,
|
|
1883
|
+
labelsRef,
|
|
1884
|
+
onMapChange: onMapChangeProp
|
|
1885
|
+
} = props;
|
|
1886
|
+
const onMapChange = useStableCallback(onMapChangeProp);
|
|
1887
|
+
const nextIndexRef = React.useRef(0);
|
|
1888
|
+
const listeners = useRefWithInit(createListeners).current;
|
|
1994
1889
|
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
// This fires whenever the user clicks on the trigger, moves the cursor, and releases it over the item.
|
|
2003
|
-
// We trigger the click and override the `closeOnClick` preference to always close the menu.
|
|
2004
|
-
if (!itemMetadata || itemMetadata.type === 'regular-item') {
|
|
2005
|
-
itemRef.current.click();
|
|
2006
|
-
}
|
|
2007
|
-
}
|
|
2008
|
-
}
|
|
2009
|
-
}), [closeOnClick, highlighted, id, menuEvents, nodeId, store, typingRef, itemRef, contextMenuContext, isContextMenu, itemMetadata]);
|
|
2010
|
-
}
|
|
1890
|
+
// We use a stable `map` to avoid O(n^2) re-allocation costs for large lists.
|
|
1891
|
+
// `mapTick` is our re-render trigger mechanism. We also need to update the
|
|
1892
|
+
// elements and label refs, but there's a lot of async work going on and sometimes
|
|
1893
|
+
// the effect that handles `onMapChange` gets called after those refs have been
|
|
1894
|
+
// filled, and we don't want to lose those values by setting their lengths to `0`.
|
|
1895
|
+
// We also need to have them at the proper length because floating-ui uses that
|
|
1896
|
+
// information for list navigation.
|
|
2011
1897
|
|
|
2012
|
-
const
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
const {
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
id,
|
|
2021
|
-
store,
|
|
2022
|
-
typingRef = store.context.typingRef,
|
|
2023
|
-
nativeButton,
|
|
2024
|
-
itemMetadata,
|
|
2025
|
-
nodeId
|
|
2026
|
-
} = params;
|
|
2027
|
-
const itemRef = React.useRef(null);
|
|
2028
|
-
const {
|
|
2029
|
-
getButtonProps,
|
|
2030
|
-
buttonRef
|
|
2031
|
-
} = useButton({
|
|
2032
|
-
disabled,
|
|
2033
|
-
focusableWhenDisabled: true,
|
|
2034
|
-
native: nativeButton,
|
|
2035
|
-
composite: true
|
|
1898
|
+
const map = useRefWithInit(createMap).current;
|
|
1899
|
+
// `mapTick` uses a counter rather than objects for low precision-loss risk and better memory efficiency
|
|
1900
|
+
const [mapTick, setMapTick] = React.useState(0);
|
|
1901
|
+
const lastTickRef = React.useRef(mapTick);
|
|
1902
|
+
const register = useStableCallback((node, metadata) => {
|
|
1903
|
+
map.set(node, metadata ?? null);
|
|
1904
|
+
lastTickRef.current += 1;
|
|
1905
|
+
setMapTick(lastTickRef.current);
|
|
2036
1906
|
});
|
|
2037
|
-
const
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
nodeId,
|
|
2042
|
-
store,
|
|
2043
|
-
typingRef,
|
|
2044
|
-
itemRef,
|
|
2045
|
-
itemMetadata
|
|
1907
|
+
const unregister = useStableCallback(node => {
|
|
1908
|
+
map.delete(node);
|
|
1909
|
+
lastTickRef.current += 1;
|
|
1910
|
+
setMapTick(lastTickRef.current);
|
|
2046
1911
|
});
|
|
2047
|
-
const
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
1912
|
+
const sortedMap = React.useMemo(() => {
|
|
1913
|
+
const newMap = new Map();
|
|
1914
|
+
// Filter out disconnected elements before sorting to avoid inconsistent
|
|
1915
|
+
// compareDocumentPosition results when elements are detached from the DOM.
|
|
1916
|
+
const sortedNodes = Array.from(map.keys()).filter(node => node.isConnected).sort(sortByDocumentPosition);
|
|
1917
|
+
sortedNodes.forEach((node, index) => {
|
|
1918
|
+
const metadata = map.get(node) ?? {};
|
|
1919
|
+
newMap.set(node, {
|
|
1920
|
+
...metadata,
|
|
1921
|
+
index
|
|
1922
|
+
});
|
|
1923
|
+
});
|
|
1924
|
+
return newMap;
|
|
1925
|
+
}, [map, mapTick]);
|
|
1926
|
+
useIsoLayoutEffect(() => {
|
|
1927
|
+
if (typeof MutationObserver !== 'function' || sortedMap.size === 0) {
|
|
1928
|
+
return undefined;
|
|
1929
|
+
}
|
|
1930
|
+
const mutationObserver = new MutationObserver(entries => {
|
|
1931
|
+
const diff = new Set();
|
|
1932
|
+
const updateDiff = node => diff.has(node) ? diff.delete(node) : diff.add(node);
|
|
1933
|
+
entries.forEach(entry => {
|
|
1934
|
+
entry.removedNodes.forEach(updateDiff);
|
|
1935
|
+
entry.addedNodes.forEach(updateDiff);
|
|
1936
|
+
});
|
|
1937
|
+
if (diff.size === 0) {
|
|
1938
|
+
lastTickRef.current += 1;
|
|
1939
|
+
setMapTick(lastTickRef.current);
|
|
2054
1940
|
}
|
|
2055
|
-
}
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
}
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
const {
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
1941
|
+
});
|
|
1942
|
+
sortedMap.forEach((_, node) => {
|
|
1943
|
+
if (node.parentElement) {
|
|
1944
|
+
mutationObserver.observe(node.parentElement, {
|
|
1945
|
+
childList: true
|
|
1946
|
+
});
|
|
1947
|
+
}
|
|
1948
|
+
});
|
|
1949
|
+
return () => {
|
|
1950
|
+
mutationObserver.disconnect();
|
|
1951
|
+
};
|
|
1952
|
+
}, [sortedMap]);
|
|
1953
|
+
useIsoLayoutEffect(() => {
|
|
1954
|
+
const shouldUpdateLengths = lastTickRef.current === mapTick;
|
|
1955
|
+
if (shouldUpdateLengths) {
|
|
1956
|
+
if (elementsRef.current.length !== sortedMap.size) {
|
|
1957
|
+
elementsRef.current.length = sortedMap.size;
|
|
1958
|
+
}
|
|
1959
|
+
if (labelsRef && labelsRef.current.length !== sortedMap.size) {
|
|
1960
|
+
labelsRef.current.length = sortedMap.size;
|
|
1961
|
+
}
|
|
1962
|
+
nextIndexRef.current = sortedMap.size;
|
|
1963
|
+
}
|
|
1964
|
+
onMapChange(sortedMap);
|
|
1965
|
+
}, [onMapChange, sortedMap, elementsRef, labelsRef, mapTick]);
|
|
1966
|
+
useIsoLayoutEffect(() => {
|
|
1967
|
+
return () => {
|
|
1968
|
+
elementsRef.current = [];
|
|
1969
|
+
};
|
|
1970
|
+
}, [elementsRef]);
|
|
1971
|
+
useIsoLayoutEffect(() => {
|
|
1972
|
+
return () => {
|
|
1973
|
+
if (labelsRef) {
|
|
1974
|
+
labelsRef.current = [];
|
|
1975
|
+
}
|
|
1976
|
+
};
|
|
1977
|
+
}, [labelsRef]);
|
|
1978
|
+
const subscribeMapChange = useStableCallback(fn => {
|
|
1979
|
+
listeners.add(fn);
|
|
1980
|
+
return () => {
|
|
1981
|
+
listeners.delete(fn);
|
|
1982
|
+
};
|
|
1983
|
+
});
|
|
1984
|
+
useIsoLayoutEffect(() => {
|
|
1985
|
+
listeners.forEach(l => l(sortedMap));
|
|
1986
|
+
}, [listeners, sortedMap]);
|
|
1987
|
+
const contextValue = React.useMemo(() => ({
|
|
2100
1988
|
register,
|
|
2101
1989
|
unregister,
|
|
2102
1990
|
subscribeMapChange,
|
|
2103
1991
|
elementsRef,
|
|
2104
1992
|
labelsRef,
|
|
2105
1993
|
nextIndexRef
|
|
2106
|
-
}
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
useIsoLayoutEffect(() => {
|
|
2128
|
-
if (externalIndex != null) {
|
|
2129
|
-
return undefined;
|
|
2130
|
-
}
|
|
2131
|
-
const node = componentRef.current;
|
|
2132
|
-
if (node) {
|
|
2133
|
-
register(node, metadata);
|
|
2134
|
-
return () => {
|
|
2135
|
-
unregister(node);
|
|
2136
|
-
};
|
|
2137
|
-
}
|
|
2138
|
-
return undefined;
|
|
2139
|
-
}, [externalIndex, register, unregister, metadata]);
|
|
2140
|
-
useIsoLayoutEffect(() => {
|
|
2141
|
-
if (externalIndex != null) {
|
|
2142
|
-
return undefined;
|
|
2143
|
-
}
|
|
2144
|
-
return subscribeMapChange(map => {
|
|
2145
|
-
const i = componentRef.current ? map.get(componentRef.current)?.index : null;
|
|
2146
|
-
if (i != null) {
|
|
2147
|
-
setIndex(i);
|
|
2148
|
-
}
|
|
2149
|
-
});
|
|
2150
|
-
}, [externalIndex, subscribeMapChange, setIndex]);
|
|
2151
|
-
return React.useMemo(() => ({
|
|
2152
|
-
ref,
|
|
2153
|
-
index
|
|
2154
|
-
}), [index, ref]);
|
|
1994
|
+
}), [register, unregister, subscribeMapChange, elementsRef, labelsRef, nextIndexRef]);
|
|
1995
|
+
return /*#__PURE__*/jsx(CompositeListContext.Provider, {
|
|
1996
|
+
value: contextValue,
|
|
1997
|
+
children: children
|
|
1998
|
+
});
|
|
1999
|
+
}
|
|
2000
|
+
function createMap() {
|
|
2001
|
+
return new Map();
|
|
2002
|
+
}
|
|
2003
|
+
function createListeners() {
|
|
2004
|
+
return new Set();
|
|
2005
|
+
}
|
|
2006
|
+
function sortByDocumentPosition(a, b) {
|
|
2007
|
+
const position = a.compareDocumentPosition(b);
|
|
2008
|
+
if (position & Node.DOCUMENT_POSITION_FOLLOWING || position & Node.DOCUMENT_POSITION_CONTAINED_BY) {
|
|
2009
|
+
return -1;
|
|
2010
|
+
}
|
|
2011
|
+
if (position & Node.DOCUMENT_POSITION_PRECEDING || position & Node.DOCUMENT_POSITION_CONTAINS) {
|
|
2012
|
+
return 1;
|
|
2013
|
+
}
|
|
2014
|
+
return 0;
|
|
2155
2015
|
}
|
|
2156
2016
|
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2017
|
+
/**
|
|
2018
|
+
* Fork of the original `arrow` middleware from Floating UI that allows
|
|
2019
|
+
* configuring the offset parent.
|
|
2020
|
+
*/
|
|
2021
|
+
const baseArrow = options => ({
|
|
2022
|
+
name: 'arrow',
|
|
2023
|
+
options,
|
|
2024
|
+
async fn(state) {
|
|
2025
|
+
const {
|
|
2026
|
+
x,
|
|
2027
|
+
y,
|
|
2028
|
+
placement,
|
|
2029
|
+
rects,
|
|
2030
|
+
platform,
|
|
2031
|
+
elements,
|
|
2032
|
+
middlewareData
|
|
2033
|
+
} = state;
|
|
2034
|
+
// Since `element` is required, we don't Partial<> the type.
|
|
2035
|
+
const {
|
|
2036
|
+
element,
|
|
2037
|
+
padding = 0,
|
|
2038
|
+
offsetParent = 'real'
|
|
2039
|
+
} = evaluate(options, state) || {};
|
|
2040
|
+
if (element == null) {
|
|
2041
|
+
return {};
|
|
2042
|
+
}
|
|
2043
|
+
const paddingObject = getPaddingObject(padding);
|
|
2044
|
+
const coords = {
|
|
2045
|
+
x,
|
|
2046
|
+
y
|
|
2186
2047
|
};
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
const
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
return context;
|
|
2199
|
-
}
|
|
2048
|
+
const axis = getAlignmentAxis(placement);
|
|
2049
|
+
const length = getAxisLength(axis);
|
|
2050
|
+
const arrowDimensions = await platform.getDimensions(element);
|
|
2051
|
+
const isYAxis = axis === 'y';
|
|
2052
|
+
const minProp = isYAxis ? 'top' : 'left';
|
|
2053
|
+
const maxProp = isYAxis ? 'bottom' : 'right';
|
|
2054
|
+
const clientProp = isYAxis ? 'clientHeight' : 'clientWidth';
|
|
2055
|
+
const endDiff = rects.reference[length] + rects.reference[axis] - coords[axis] - rects.floating[length];
|
|
2056
|
+
const startDiff = coords[axis] - rects.reference[axis];
|
|
2057
|
+
const arrowOffsetParent = offsetParent === 'real' ? await platform.getOffsetParent?.(element) : elements.floating;
|
|
2058
|
+
let clientSize = elements.floating[clientProp] || rects.floating[length];
|
|
2200
2059
|
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
className,
|
|
2205
|
-
...elementProps
|
|
2206
|
-
} = componentProps;
|
|
2207
|
-
const [labelId, setLabelId] = React.useState(undefined);
|
|
2208
|
-
const context = React.useMemo(() => ({
|
|
2209
|
-
setLabelId
|
|
2210
|
-
}), [setLabelId]);
|
|
2211
|
-
const element = useRenderElement('div', componentProps, {
|
|
2212
|
-
ref: forwardedRef,
|
|
2213
|
-
props: {
|
|
2214
|
-
role: 'group',
|
|
2215
|
-
'aria-labelledby': labelId,
|
|
2216
|
-
...elementProps
|
|
2060
|
+
// DOM platform can return `window` as the `offsetParent`.
|
|
2061
|
+
if (!clientSize || !(await platform.isElement?.(arrowOffsetParent))) {
|
|
2062
|
+
clientSize = elements.floating[clientProp] || rects.floating[length];
|
|
2217
2063
|
}
|
|
2218
|
-
|
|
2219
|
-
return /*#__PURE__*/jsx(MenuGroupContext.Provider, {
|
|
2220
|
-
value: context,
|
|
2221
|
-
children: element
|
|
2222
|
-
});
|
|
2223
|
-
});
|
|
2224
|
-
if (process.env.NODE_ENV !== "production") MenuGroup.displayName = "MenuGroup";
|
|
2064
|
+
const centerToReference = endDiff / 2 - startDiff / 2;
|
|
2225
2065
|
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2066
|
+
// If the padding is large enough that it causes the arrow to no longer be
|
|
2067
|
+
// centered, modify the padding so that it is centered.
|
|
2068
|
+
const largestPossiblePadding = clientSize / 2 - arrowDimensions[length] / 2 - 1;
|
|
2069
|
+
const minPadding = Math.min(paddingObject[minProp], largestPossiblePadding);
|
|
2070
|
+
const maxPadding = Math.min(paddingObject[maxProp], largestPossiblePadding);
|
|
2071
|
+
|
|
2072
|
+
// Make sure the arrow doesn't overflow the floating element if the center
|
|
2073
|
+
// point is outside the floating element's bounds.
|
|
2074
|
+
const min = minPadding;
|
|
2075
|
+
const max = clientSize - arrowDimensions[length] - maxPadding;
|
|
2076
|
+
const center = clientSize / 2 - arrowDimensions[length] / 2 + centerToReference;
|
|
2077
|
+
const offset = clamp(min, center, max);
|
|
2078
|
+
|
|
2079
|
+
// If the reference is small enough that the arrow's padding causes it to
|
|
2080
|
+
// to point to nothing for an aligned placement, adjust the offset of the
|
|
2081
|
+
// floating element itself. To ensure `shift()` continues to take action,
|
|
2082
|
+
// a single reset is performed when this is true.
|
|
2083
|
+
const shouldAddOffset = !middlewareData.arrow && getAlignment(placement) != null && center !== offset && rects.reference[length] / 2 - (center < min ? minPadding : maxPadding) - arrowDimensions[length] / 2 < 0;
|
|
2084
|
+
// eslint-disable-next-line no-nested-ternary
|
|
2085
|
+
const alignmentOffset = shouldAddOffset ? center < min ? center - min : center - max : 0;
|
|
2086
|
+
return {
|
|
2087
|
+
[axis]: coords[axis] + alignmentOffset,
|
|
2088
|
+
data: {
|
|
2089
|
+
[axis]: offset,
|
|
2090
|
+
centerOffset: center - offset - alignmentOffset,
|
|
2091
|
+
...(shouldAddOffset && {
|
|
2092
|
+
alignmentOffset
|
|
2093
|
+
})
|
|
2094
|
+
},
|
|
2095
|
+
reset: shouldAddOffset
|
|
2247
2096
|
};
|
|
2248
|
-
}
|
|
2249
|
-
return useRenderElement('div', componentProps, {
|
|
2250
|
-
ref: forwardedRef,
|
|
2251
|
-
props: {
|
|
2252
|
-
id,
|
|
2253
|
-
role: 'presentation',
|
|
2254
|
-
...elementProps
|
|
2255
|
-
}
|
|
2256
|
-
});
|
|
2097
|
+
}
|
|
2257
2098
|
});
|
|
2258
|
-
if (process.env.NODE_ENV !== "production") MenuGroupLabel.displayName = "MenuGroupLabel";
|
|
2259
2099
|
|
|
2260
2100
|
/**
|
|
2261
|
-
*
|
|
2262
|
-
*
|
|
2263
|
-
*
|
|
2264
|
-
*
|
|
2101
|
+
* Provides data to position an inner element of the floating element so that it
|
|
2102
|
+
* appears centered to the reference element.
|
|
2103
|
+
* This wraps the core `arrow` middleware to allow React refs as the element.
|
|
2104
|
+
* @see https://floating-ui.com/docs/arrow
|
|
2265
2105
|
*/
|
|
2266
|
-
const
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
className,
|
|
2270
|
-
id: idProp,
|
|
2271
|
-
label,
|
|
2272
|
-
nativeButton = false,
|
|
2273
|
-
disabled = false,
|
|
2274
|
-
closeOnClick = true,
|
|
2275
|
-
...elementProps
|
|
2276
|
-
} = componentProps;
|
|
2277
|
-
const listItem = useCompositeListItem({
|
|
2278
|
-
label
|
|
2279
|
-
});
|
|
2280
|
-
const menuPositionerContext = useMenuPositionerContext(true);
|
|
2281
|
-
const id = useBaseUiId(idProp);
|
|
2282
|
-
const {
|
|
2283
|
-
store
|
|
2284
|
-
} = useMenuRootContext();
|
|
2285
|
-
const highlighted = store.useState('isActive', listItem.index);
|
|
2286
|
-
const itemProps = store.useState('itemProps');
|
|
2287
|
-
const {
|
|
2288
|
-
getItemProps,
|
|
2289
|
-
itemRef
|
|
2290
|
-
} = useMenuItem({
|
|
2291
|
-
closeOnClick,
|
|
2292
|
-
disabled,
|
|
2293
|
-
highlighted,
|
|
2294
|
-
id,
|
|
2295
|
-
store,
|
|
2296
|
-
nativeButton,
|
|
2297
|
-
nodeId: menuPositionerContext?.nodeId,
|
|
2298
|
-
itemMetadata: REGULAR_ITEM
|
|
2299
|
-
});
|
|
2300
|
-
const state = {
|
|
2301
|
-
disabled,
|
|
2302
|
-
highlighted
|
|
2303
|
-
};
|
|
2304
|
-
return useRenderElement('div', componentProps, {
|
|
2305
|
-
state,
|
|
2306
|
-
props: [itemProps, elementProps, getItemProps],
|
|
2307
|
-
ref: [itemRef, forwardedRef, listItem.ref]
|
|
2308
|
-
});
|
|
2309
|
-
});
|
|
2310
|
-
if (process.env.NODE_ENV !== "production") MenuItem.displayName = "MenuItem";
|
|
2311
|
-
|
|
2312
|
-
/**
|
|
2313
|
-
* A link in the menu that can be used to navigate to a different page or section.
|
|
2314
|
-
* Renders an `<a>` element.
|
|
2315
|
-
*
|
|
2316
|
-
* Documentation: [Base UI Menu](https://base-ui.com/react/components/menu)
|
|
2317
|
-
*/
|
|
2318
|
-
const MenuLinkItem = /*#__PURE__*/React.forwardRef(function MenuLinkItem(componentProps, forwardedRef) {
|
|
2319
|
-
const {
|
|
2320
|
-
render,
|
|
2321
|
-
className,
|
|
2322
|
-
id: idProp,
|
|
2323
|
-
label,
|
|
2324
|
-
closeOnClick = false,
|
|
2325
|
-
...elementProps
|
|
2326
|
-
} = componentProps;
|
|
2327
|
-
const linkRef = React.useRef(null);
|
|
2328
|
-
const listItem = useCompositeListItem({
|
|
2329
|
-
label
|
|
2330
|
-
});
|
|
2331
|
-
const menuPositionerContext = useMenuPositionerContext(true);
|
|
2332
|
-
const nodeId = menuPositionerContext?.nodeId;
|
|
2333
|
-
const id = useBaseUiId(idProp);
|
|
2334
|
-
const {
|
|
2335
|
-
store
|
|
2336
|
-
} = useMenuRootContext();
|
|
2337
|
-
const highlighted = store.useState('isActive', listItem.index);
|
|
2338
|
-
const itemProps = store.useState('itemProps');
|
|
2339
|
-
const typingRef = store.context.typingRef;
|
|
2340
|
-
const {
|
|
2341
|
-
getButtonProps,
|
|
2342
|
-
buttonRef
|
|
2343
|
-
} = useButton({
|
|
2344
|
-
native: false,
|
|
2345
|
-
composite: true
|
|
2346
|
-
});
|
|
2347
|
-
const commonProps = useMenuItemCommonProps({
|
|
2348
|
-
closeOnClick,
|
|
2349
|
-
highlighted,
|
|
2350
|
-
id,
|
|
2351
|
-
nodeId,
|
|
2352
|
-
store,
|
|
2353
|
-
typingRef,
|
|
2354
|
-
itemRef: linkRef
|
|
2355
|
-
});
|
|
2356
|
-
function getItemProps(externalProps) {
|
|
2357
|
-
return mergeProps(commonProps, externalProps, getButtonProps);
|
|
2358
|
-
}
|
|
2359
|
-
const state = React.useMemo(() => ({
|
|
2360
|
-
highlighted
|
|
2361
|
-
}), [highlighted]);
|
|
2362
|
-
return useRenderElement('a', componentProps, {
|
|
2363
|
-
state,
|
|
2364
|
-
props: [itemProps, elementProps, getItemProps],
|
|
2365
|
-
ref: [linkRef, buttonRef, forwardedRef, listItem.ref]
|
|
2366
|
-
});
|
|
2367
|
-
});
|
|
2368
|
-
if (process.env.NODE_ENV !== "production") MenuLinkItem.displayName = "MenuLinkItem";
|
|
2369
|
-
|
|
2370
|
-
const ToolbarRootContext = /*#__PURE__*/React.createContext(undefined);
|
|
2371
|
-
if (process.env.NODE_ENV !== "production") ToolbarRootContext.displayName = "ToolbarRootContext";
|
|
2372
|
-
function useToolbarRootContext(optional) {
|
|
2373
|
-
const context = React.useContext(ToolbarRootContext);
|
|
2374
|
-
if (context === undefined && !optional) {
|
|
2375
|
-
throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: ToolbarRootContext is missing. Toolbar parts must be placed within <Toolbar.Root>.' : formatErrorMessage(69));
|
|
2376
|
-
}
|
|
2377
|
-
return context;
|
|
2378
|
-
}
|
|
2379
|
-
|
|
2380
|
-
function getDisabledMountTransitionStyles(transitionStatus) {
|
|
2381
|
-
return transitionStatus === 'starting' ? DISABLED_TRANSITIONS_STYLE : EMPTY_OBJECT;
|
|
2382
|
-
}
|
|
2383
|
-
|
|
2384
|
-
const stateAttributesMapping = {
|
|
2385
|
-
...popupStateMapping,
|
|
2386
|
-
...transitionStatusMapping
|
|
2387
|
-
};
|
|
2388
|
-
|
|
2389
|
-
/**
|
|
2390
|
-
* A container for the menu items.
|
|
2391
|
-
* Renders a `<div>` element.
|
|
2392
|
-
*
|
|
2393
|
-
* Documentation: [Base UI Menu](https://base-ui.com/react/components/menu)
|
|
2394
|
-
*/
|
|
2395
|
-
const MenuPopup = /*#__PURE__*/React.forwardRef(function MenuPopup(componentProps, forwardedRef) {
|
|
2396
|
-
const {
|
|
2397
|
-
render,
|
|
2398
|
-
className,
|
|
2399
|
-
finalFocus,
|
|
2400
|
-
...elementProps
|
|
2401
|
-
} = componentProps;
|
|
2402
|
-
const {
|
|
2403
|
-
store
|
|
2404
|
-
} = useMenuRootContext();
|
|
2405
|
-
const {
|
|
2406
|
-
side,
|
|
2407
|
-
align
|
|
2408
|
-
} = useMenuPositionerContext();
|
|
2409
|
-
const insideToolbar = useToolbarRootContext(true) != null;
|
|
2410
|
-
const open = store.useState('open');
|
|
2411
|
-
const transitionStatus = store.useState('transitionStatus');
|
|
2412
|
-
const popupProps = store.useState('popupProps');
|
|
2413
|
-
const mounted = store.useState('mounted');
|
|
2414
|
-
const instantType = store.useState('instantType');
|
|
2415
|
-
const triggerElement = store.useState('activeTriggerElement');
|
|
2416
|
-
const parent = store.useState('parent');
|
|
2417
|
-
const lastOpenChangeReason = store.useState('lastOpenChangeReason');
|
|
2418
|
-
const rootId = store.useState('rootId');
|
|
2419
|
-
const floatingContext = store.useState('floatingRootContext');
|
|
2420
|
-
const floatingTreeRoot = store.useState('floatingTreeRoot');
|
|
2421
|
-
const closeDelay = store.useState('closeDelay');
|
|
2422
|
-
const activeTriggerElement = store.useState('activeTriggerElement');
|
|
2423
|
-
const isContextMenu = parent.type === 'context-menu';
|
|
2424
|
-
useOpenChangeComplete({
|
|
2425
|
-
open,
|
|
2426
|
-
ref: store.context.popupRef,
|
|
2427
|
-
onComplete() {
|
|
2428
|
-
if (open) {
|
|
2429
|
-
store.context.onOpenChangeComplete?.(true);
|
|
2430
|
-
}
|
|
2431
|
-
}
|
|
2432
|
-
});
|
|
2433
|
-
React.useEffect(() => {
|
|
2434
|
-
function handleClose(event) {
|
|
2435
|
-
store.setOpen(false, createChangeEventDetails(event.reason, event.domEvent));
|
|
2436
|
-
}
|
|
2437
|
-
floatingTreeRoot.events.on('close', handleClose);
|
|
2438
|
-
return () => {
|
|
2439
|
-
floatingTreeRoot.events.off('close', handleClose);
|
|
2440
|
-
};
|
|
2441
|
-
}, [floatingTreeRoot.events, store]);
|
|
2442
|
-
const hoverEnabled = store.useState('hoverEnabled');
|
|
2443
|
-
const disabled = store.useState('disabled');
|
|
2444
|
-
useHoverFloatingInteraction(floatingContext, {
|
|
2445
|
-
enabled: hoverEnabled && !disabled && !isContextMenu && parent.type !== 'menubar',
|
|
2446
|
-
closeDelay
|
|
2447
|
-
});
|
|
2448
|
-
const state = {
|
|
2449
|
-
transitionStatus,
|
|
2450
|
-
side,
|
|
2451
|
-
align,
|
|
2452
|
-
open,
|
|
2453
|
-
nested: parent.type === 'menu',
|
|
2454
|
-
instant: instantType
|
|
2455
|
-
};
|
|
2456
|
-
const setPopupElement = React.useCallback(element => {
|
|
2457
|
-
store.set('popupElement', element);
|
|
2458
|
-
}, [store]);
|
|
2459
|
-
const element = useRenderElement('div', componentProps, {
|
|
2460
|
-
state,
|
|
2461
|
-
ref: [forwardedRef, store.context.popupRef, setPopupElement],
|
|
2462
|
-
stateAttributesMapping,
|
|
2463
|
-
props: [popupProps, {
|
|
2464
|
-
onKeyDown(event) {
|
|
2465
|
-
if (insideToolbar && COMPOSITE_KEYS.has(event.key)) {
|
|
2466
|
-
event.stopPropagation();
|
|
2467
|
-
}
|
|
2468
|
-
}
|
|
2469
|
-
}, getDisabledMountTransitionStyles(transitionStatus), elementProps, {
|
|
2470
|
-
'data-rootownerid': rootId
|
|
2471
|
-
}]
|
|
2472
|
-
});
|
|
2473
|
-
let returnFocus = parent.type === undefined || isContextMenu;
|
|
2474
|
-
if (triggerElement || parent.type === 'menubar' && lastOpenChangeReason !== outsidePress) {
|
|
2475
|
-
returnFocus = true;
|
|
2476
|
-
}
|
|
2477
|
-
return /*#__PURE__*/jsx(FloatingFocusManager, {
|
|
2478
|
-
context: floatingContext,
|
|
2479
|
-
modal: isContextMenu,
|
|
2480
|
-
disabled: !mounted,
|
|
2481
|
-
returnFocus: finalFocus === undefined ? returnFocus : finalFocus,
|
|
2482
|
-
initialFocus: parent.type !== 'menu',
|
|
2483
|
-
restoreFocus: true,
|
|
2484
|
-
externalTree: parent.type !== 'menubar' ? floatingTreeRoot : undefined,
|
|
2485
|
-
previousFocusableElement: activeTriggerElement,
|
|
2486
|
-
nextFocusableElement: parent.type === undefined ? store.context.triggerFocusTargetRef : undefined,
|
|
2487
|
-
beforeContentFocusGuardRef: parent.type === undefined ? store.context.beforeContentFocusGuardRef : undefined,
|
|
2488
|
-
children: element
|
|
2489
|
-
});
|
|
2490
|
-
});
|
|
2491
|
-
if (process.env.NODE_ENV !== "production") MenuPopup.displayName = "MenuPopup";
|
|
2492
|
-
|
|
2493
|
-
const MenuPortalContext = /*#__PURE__*/React.createContext(undefined);
|
|
2494
|
-
if (process.env.NODE_ENV !== "production") MenuPortalContext.displayName = "MenuPortalContext";
|
|
2495
|
-
function useMenuPortalContext() {
|
|
2496
|
-
const value = React.useContext(MenuPortalContext);
|
|
2497
|
-
if (value === undefined) {
|
|
2498
|
-
throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: <Menu.Portal> is missing.' : formatErrorMessage(32));
|
|
2499
|
-
}
|
|
2500
|
-
return value;
|
|
2501
|
-
}
|
|
2502
|
-
|
|
2503
|
-
const MenuPortal = /*#__PURE__*/React.forwardRef(function MenuPortal(props, forwardedRef) {
|
|
2504
|
-
const {
|
|
2505
|
-
keepMounted = false,
|
|
2506
|
-
...portalProps
|
|
2507
|
-
} = props;
|
|
2508
|
-
const {
|
|
2509
|
-
store
|
|
2510
|
-
} = useMenuRootContext();
|
|
2511
|
-
const mounted = store.useState('mounted');
|
|
2512
|
-
const shouldRender = mounted || keepMounted;
|
|
2513
|
-
if (!shouldRender) {
|
|
2514
|
-
return null;
|
|
2515
|
-
}
|
|
2516
|
-
return /*#__PURE__*/jsx(MenuPortalContext.Provider, {
|
|
2517
|
-
value: keepMounted,
|
|
2518
|
-
children: /*#__PURE__*/jsx(FloatingPortal, {
|
|
2519
|
-
ref: forwardedRef,
|
|
2520
|
-
...portalProps
|
|
2521
|
-
})
|
|
2522
|
-
});
|
|
2523
|
-
});
|
|
2524
|
-
if (process.env.NODE_ENV !== "production") MenuPortal.displayName = "MenuPortal";
|
|
2525
|
-
|
|
2526
|
-
/**
|
|
2527
|
-
* Fork of the original `arrow` middleware from Floating UI that allows
|
|
2528
|
-
* configuring the offset parent.
|
|
2529
|
-
*/
|
|
2530
|
-
const baseArrow = options => ({
|
|
2531
|
-
name: 'arrow',
|
|
2532
|
-
options,
|
|
2533
|
-
async fn(state) {
|
|
2534
|
-
const {
|
|
2535
|
-
x,
|
|
2536
|
-
y,
|
|
2537
|
-
placement,
|
|
2538
|
-
rects,
|
|
2539
|
-
platform,
|
|
2540
|
-
elements,
|
|
2541
|
-
middlewareData
|
|
2542
|
-
} = state;
|
|
2543
|
-
// Since `element` is required, we don't Partial<> the type.
|
|
2544
|
-
const {
|
|
2545
|
-
element,
|
|
2546
|
-
padding = 0,
|
|
2547
|
-
offsetParent = 'real'
|
|
2548
|
-
} = evaluate(options, state) || {};
|
|
2549
|
-
if (element == null) {
|
|
2550
|
-
return {};
|
|
2551
|
-
}
|
|
2552
|
-
const paddingObject = getPaddingObject(padding);
|
|
2553
|
-
const coords = {
|
|
2554
|
-
x,
|
|
2555
|
-
y
|
|
2556
|
-
};
|
|
2557
|
-
const axis = getAlignmentAxis(placement);
|
|
2558
|
-
const length = getAxisLength(axis);
|
|
2559
|
-
const arrowDimensions = await platform.getDimensions(element);
|
|
2560
|
-
const isYAxis = axis === 'y';
|
|
2561
|
-
const minProp = isYAxis ? 'top' : 'left';
|
|
2562
|
-
const maxProp = isYAxis ? 'bottom' : 'right';
|
|
2563
|
-
const clientProp = isYAxis ? 'clientHeight' : 'clientWidth';
|
|
2564
|
-
const endDiff = rects.reference[length] + rects.reference[axis] - coords[axis] - rects.floating[length];
|
|
2565
|
-
const startDiff = coords[axis] - rects.reference[axis];
|
|
2566
|
-
const arrowOffsetParent = offsetParent === 'real' ? await platform.getOffsetParent?.(element) : elements.floating;
|
|
2567
|
-
let clientSize = elements.floating[clientProp] || rects.floating[length];
|
|
2568
|
-
|
|
2569
|
-
// DOM platform can return `window` as the `offsetParent`.
|
|
2570
|
-
if (!clientSize || !(await platform.isElement?.(arrowOffsetParent))) {
|
|
2571
|
-
clientSize = elements.floating[clientProp] || rects.floating[length];
|
|
2572
|
-
}
|
|
2573
|
-
const centerToReference = endDiff / 2 - startDiff / 2;
|
|
2574
|
-
|
|
2575
|
-
// If the padding is large enough that it causes the arrow to no longer be
|
|
2576
|
-
// centered, modify the padding so that it is centered.
|
|
2577
|
-
const largestPossiblePadding = clientSize / 2 - arrowDimensions[length] / 2 - 1;
|
|
2578
|
-
const minPadding = Math.min(paddingObject[minProp], largestPossiblePadding);
|
|
2579
|
-
const maxPadding = Math.min(paddingObject[maxProp], largestPossiblePadding);
|
|
2580
|
-
|
|
2581
|
-
// Make sure the arrow doesn't overflow the floating element if the center
|
|
2582
|
-
// point is outside the floating element's bounds.
|
|
2583
|
-
const min = minPadding;
|
|
2584
|
-
const max = clientSize - arrowDimensions[length] - maxPadding;
|
|
2585
|
-
const center = clientSize / 2 - arrowDimensions[length] / 2 + centerToReference;
|
|
2586
|
-
const offset = clamp(min, center, max);
|
|
2587
|
-
|
|
2588
|
-
// If the reference is small enough that the arrow's padding causes it to
|
|
2589
|
-
// to point to nothing for an aligned placement, adjust the offset of the
|
|
2590
|
-
// floating element itself. To ensure `shift()` continues to take action,
|
|
2591
|
-
// a single reset is performed when this is true.
|
|
2592
|
-
const shouldAddOffset = !middlewareData.arrow && getAlignment(placement) != null && center !== offset && rects.reference[length] / 2 - (center < min ? minPadding : maxPadding) - arrowDimensions[length] / 2 < 0;
|
|
2593
|
-
// eslint-disable-next-line no-nested-ternary
|
|
2594
|
-
const alignmentOffset = shouldAddOffset ? center < min ? center - min : center - max : 0;
|
|
2595
|
-
return {
|
|
2596
|
-
[axis]: coords[axis] + alignmentOffset,
|
|
2597
|
-
data: {
|
|
2598
|
-
[axis]: offset,
|
|
2599
|
-
centerOffset: center - offset - alignmentOffset,
|
|
2600
|
-
...(shouldAddOffset && {
|
|
2601
|
-
alignmentOffset
|
|
2602
|
-
})
|
|
2603
|
-
},
|
|
2604
|
-
reset: shouldAddOffset
|
|
2605
|
-
};
|
|
2606
|
-
}
|
|
2607
|
-
});
|
|
2608
|
-
|
|
2609
|
-
/**
|
|
2610
|
-
* Provides data to position an inner element of the floating element so that it
|
|
2611
|
-
* appears centered to the reference element.
|
|
2612
|
-
* This wraps the core `arrow` middleware to allow React refs as the element.
|
|
2613
|
-
* @see https://floating-ui.com/docs/arrow
|
|
2614
|
-
*/
|
|
2615
|
-
const arrow = (options, deps) => ({
|
|
2616
|
-
...baseArrow(options),
|
|
2617
|
-
options: [options, deps]
|
|
2106
|
+
const arrow = (options, deps) => ({
|
|
2107
|
+
...baseArrow(options),
|
|
2108
|
+
options: [options, deps]
|
|
2618
2109
|
});
|
|
2619
2110
|
|
|
2620
2111
|
const hide = {
|
|
@@ -3094,149 +2585,693 @@ function isRef(param) {
|
|
|
3094
2585
|
return param != null && 'current' in param;
|
|
3095
2586
|
}
|
|
3096
2587
|
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
*/
|
|
3102
|
-
|
|
2588
|
+
function getDisabledMountTransitionStyles(transitionStatus) {
|
|
2589
|
+
return transitionStatus === 'starting' ? DISABLED_TRANSITIONS_STYLE : EMPTY_OBJECT;
|
|
2590
|
+
}
|
|
2591
|
+
|
|
2592
|
+
let IndexGuessBehavior = /*#__PURE__*/function (IndexGuessBehavior) {
|
|
2593
|
+
IndexGuessBehavior[IndexGuessBehavior["None"] = 0] = "None";
|
|
2594
|
+
IndexGuessBehavior[IndexGuessBehavior["GuessFromOrder"] = 1] = "GuessFromOrder";
|
|
2595
|
+
return IndexGuessBehavior;
|
|
2596
|
+
}({});
|
|
2597
|
+
|
|
2598
|
+
/**
|
|
2599
|
+
* Used to register a list item and its index (DOM position) in the `CompositeList`.
|
|
2600
|
+
*/
|
|
2601
|
+
function useCompositeListItem(params = {}) {
|
|
3103
2602
|
const {
|
|
3104
|
-
|
|
2603
|
+
label,
|
|
2604
|
+
metadata,
|
|
2605
|
+
textRef,
|
|
2606
|
+
indexGuessBehavior,
|
|
2607
|
+
index: externalIndex
|
|
2608
|
+
} = params;
|
|
2609
|
+
const {
|
|
2610
|
+
register,
|
|
2611
|
+
unregister,
|
|
2612
|
+
subscribeMapChange,
|
|
3105
2613
|
elementsRef,
|
|
3106
2614
|
labelsRef,
|
|
3107
|
-
|
|
3108
|
-
} =
|
|
3109
|
-
const
|
|
3110
|
-
const
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
});
|
|
3130
|
-
const unregister = useStableCallback(node => {
|
|
3131
|
-
map.delete(node);
|
|
3132
|
-
lastTickRef.current += 1;
|
|
3133
|
-
setMapTick(lastTickRef.current);
|
|
3134
|
-
});
|
|
3135
|
-
const sortedMap = React.useMemo(() => {
|
|
3136
|
-
const newMap = new Map();
|
|
3137
|
-
// Filter out disconnected elements before sorting to avoid inconsistent
|
|
3138
|
-
// compareDocumentPosition results when elements are detached from the DOM.
|
|
3139
|
-
const sortedNodes = Array.from(map.keys()).filter(node => node.isConnected).sort(sortByDocumentPosition);
|
|
3140
|
-
sortedNodes.forEach((node, index) => {
|
|
3141
|
-
const metadata = map.get(node) ?? {};
|
|
3142
|
-
newMap.set(node, {
|
|
3143
|
-
...metadata,
|
|
3144
|
-
index
|
|
3145
|
-
});
|
|
3146
|
-
});
|
|
3147
|
-
return newMap;
|
|
3148
|
-
}, [map, mapTick]);
|
|
2615
|
+
nextIndexRef
|
|
2616
|
+
} = useCompositeListContext();
|
|
2617
|
+
const indexRef = React.useRef(-1);
|
|
2618
|
+
const [index, setIndex] = React.useState(externalIndex ?? (indexGuessBehavior === IndexGuessBehavior.GuessFromOrder ? () => {
|
|
2619
|
+
if (indexRef.current === -1) {
|
|
2620
|
+
const newIndex = nextIndexRef.current;
|
|
2621
|
+
nextIndexRef.current += 1;
|
|
2622
|
+
indexRef.current = newIndex;
|
|
2623
|
+
}
|
|
2624
|
+
return indexRef.current;
|
|
2625
|
+
} : -1));
|
|
2626
|
+
const componentRef = React.useRef(null);
|
|
2627
|
+
const ref = React.useCallback(node => {
|
|
2628
|
+
componentRef.current = node;
|
|
2629
|
+
if (index !== -1 && node !== null) {
|
|
2630
|
+
elementsRef.current[index] = node;
|
|
2631
|
+
if (labelsRef) {
|
|
2632
|
+
const isLabelDefined = label !== undefined;
|
|
2633
|
+
labelsRef.current[index] = isLabelDefined ? label : textRef?.current?.textContent ?? node.textContent;
|
|
2634
|
+
}
|
|
2635
|
+
}
|
|
2636
|
+
}, [index, elementsRef, labelsRef, label, textRef]);
|
|
3149
2637
|
useIsoLayoutEffect(() => {
|
|
3150
|
-
if (
|
|
2638
|
+
if (externalIndex != null) {
|
|
3151
2639
|
return undefined;
|
|
3152
2640
|
}
|
|
3153
|
-
const
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
setMapTick(lastTickRef.current);
|
|
3163
|
-
}
|
|
3164
|
-
});
|
|
3165
|
-
sortedMap.forEach((_, node) => {
|
|
3166
|
-
if (node.parentElement) {
|
|
3167
|
-
mutationObserver.observe(node.parentElement, {
|
|
3168
|
-
childList: true
|
|
3169
|
-
});
|
|
3170
|
-
}
|
|
3171
|
-
});
|
|
3172
|
-
return () => {
|
|
3173
|
-
mutationObserver.disconnect();
|
|
3174
|
-
};
|
|
3175
|
-
}, [sortedMap]);
|
|
2641
|
+
const node = componentRef.current;
|
|
2642
|
+
if (node) {
|
|
2643
|
+
register(node, metadata);
|
|
2644
|
+
return () => {
|
|
2645
|
+
unregister(node);
|
|
2646
|
+
};
|
|
2647
|
+
}
|
|
2648
|
+
return undefined;
|
|
2649
|
+
}, [externalIndex, register, unregister, metadata]);
|
|
3176
2650
|
useIsoLayoutEffect(() => {
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
2651
|
+
if (externalIndex != null) {
|
|
2652
|
+
return undefined;
|
|
2653
|
+
}
|
|
2654
|
+
return subscribeMapChange(map => {
|
|
2655
|
+
const i = componentRef.current ? map.get(componentRef.current)?.index : null;
|
|
2656
|
+
if (i != null) {
|
|
2657
|
+
setIndex(i);
|
|
3181
2658
|
}
|
|
3182
|
-
|
|
3183
|
-
|
|
2659
|
+
});
|
|
2660
|
+
}, [externalIndex, subscribeMapChange, setIndex]);
|
|
2661
|
+
return React.useMemo(() => ({
|
|
2662
|
+
ref,
|
|
2663
|
+
index
|
|
2664
|
+
}), [index, ref]);
|
|
2665
|
+
}
|
|
2666
|
+
|
|
2667
|
+
/**
|
|
2668
|
+
* A button that closes the dialog.
|
|
2669
|
+
* Renders a `<button>` element.
|
|
2670
|
+
*
|
|
2671
|
+
* Documentation: [Base UI Dialog](https://base-ui.com/react/components/dialog)
|
|
2672
|
+
*/
|
|
2673
|
+
const DialogClose = /*#__PURE__*/React.forwardRef(function DialogClose(componentProps, forwardedRef) {
|
|
2674
|
+
const {
|
|
2675
|
+
render,
|
|
2676
|
+
className,
|
|
2677
|
+
disabled = false,
|
|
2678
|
+
nativeButton = true,
|
|
2679
|
+
...elementProps
|
|
2680
|
+
} = componentProps;
|
|
2681
|
+
const {
|
|
2682
|
+
store
|
|
2683
|
+
} = useDialogRootContext();
|
|
2684
|
+
const open = store.useState('open');
|
|
2685
|
+
function handleClick(event) {
|
|
2686
|
+
if (open) {
|
|
2687
|
+
store.setOpen(false, createChangeEventDetails(closePress, event.nativeEvent));
|
|
2688
|
+
}
|
|
2689
|
+
}
|
|
2690
|
+
const {
|
|
2691
|
+
getButtonProps,
|
|
2692
|
+
buttonRef
|
|
2693
|
+
} = useButton({
|
|
2694
|
+
disabled,
|
|
2695
|
+
native: nativeButton
|
|
2696
|
+
});
|
|
2697
|
+
const state = {
|
|
2698
|
+
disabled
|
|
2699
|
+
};
|
|
2700
|
+
return useRenderElement('button', componentProps, {
|
|
2701
|
+
state,
|
|
2702
|
+
ref: [forwardedRef, buttonRef],
|
|
2703
|
+
props: [{
|
|
2704
|
+
onClick: handleClick
|
|
2705
|
+
}, elementProps, getButtonProps]
|
|
2706
|
+
});
|
|
2707
|
+
});
|
|
2708
|
+
if (process.env.NODE_ENV !== "production") DialogClose.displayName = "DialogClose";
|
|
2709
|
+
|
|
2710
|
+
/**
|
|
2711
|
+
* A button that closes the drawer.
|
|
2712
|
+
* Renders a `<button>` element.
|
|
2713
|
+
*
|
|
2714
|
+
* Documentation: [Base UI Drawer](https://base-ui.com/react/components/drawer)
|
|
2715
|
+
*/
|
|
2716
|
+
const DrawerClose = DialogClose;
|
|
2717
|
+
|
|
2718
|
+
/**
|
|
2719
|
+
* A heading that labels the dialog.
|
|
2720
|
+
* Renders an `<h2>` element.
|
|
2721
|
+
*
|
|
2722
|
+
* Documentation: [Base UI Dialog](https://base-ui.com/react/components/dialog)
|
|
2723
|
+
*/
|
|
2724
|
+
const DialogTitle = /*#__PURE__*/React.forwardRef(function DialogTitle(componentProps, forwardedRef) {
|
|
2725
|
+
const {
|
|
2726
|
+
render,
|
|
2727
|
+
className,
|
|
2728
|
+
id: idProp,
|
|
2729
|
+
...elementProps
|
|
2730
|
+
} = componentProps;
|
|
2731
|
+
const {
|
|
2732
|
+
store
|
|
2733
|
+
} = useDialogRootContext();
|
|
2734
|
+
const id = useBaseUiId(idProp);
|
|
2735
|
+
store.useSyncedValueWithCleanup('titleElementId', id);
|
|
2736
|
+
return useRenderElement('h2', componentProps, {
|
|
2737
|
+
ref: forwardedRef,
|
|
2738
|
+
props: [{
|
|
2739
|
+
id
|
|
2740
|
+
}, elementProps]
|
|
2741
|
+
});
|
|
2742
|
+
});
|
|
2743
|
+
if (process.env.NODE_ENV !== "production") DialogTitle.displayName = "DialogTitle";
|
|
2744
|
+
|
|
2745
|
+
/**
|
|
2746
|
+
* A heading that labels the drawer.
|
|
2747
|
+
* Renders an `<h2>` element.
|
|
2748
|
+
*
|
|
2749
|
+
* Documentation: [Base UI Drawer](https://base-ui.com/react/components/drawer)
|
|
2750
|
+
*/
|
|
2751
|
+
const DrawerTitle = DialogTitle;
|
|
2752
|
+
|
|
2753
|
+
const MenuPositionerContext = /*#__PURE__*/React.createContext(undefined);
|
|
2754
|
+
if (process.env.NODE_ENV !== "production") MenuPositionerContext.displayName = "MenuPositionerContext";
|
|
2755
|
+
function useMenuPositionerContext(optional) {
|
|
2756
|
+
const context = React.useContext(MenuPositionerContext);
|
|
2757
|
+
if (context === undefined && !optional) {
|
|
2758
|
+
throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: MenuPositionerContext is missing. MenuPositioner parts must be placed within <Menu.Positioner>.' : formatErrorMessage(33));
|
|
2759
|
+
}
|
|
2760
|
+
return context;
|
|
2761
|
+
}
|
|
2762
|
+
|
|
2763
|
+
const MenuRootContext = /*#__PURE__*/React.createContext(undefined);
|
|
2764
|
+
if (process.env.NODE_ENV !== "production") MenuRootContext.displayName = "MenuRootContext";
|
|
2765
|
+
function useMenuRootContext(optional) {
|
|
2766
|
+
const context = React.useContext(MenuRootContext);
|
|
2767
|
+
if (context === undefined && !optional) {
|
|
2768
|
+
throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: MenuRootContext is missing. Menu parts must be placed within <Menu.Root>.' : formatErrorMessage(36));
|
|
2769
|
+
}
|
|
2770
|
+
return context;
|
|
2771
|
+
}
|
|
2772
|
+
|
|
2773
|
+
const ContextMenuRootContext = /*#__PURE__*/React.createContext(undefined);
|
|
2774
|
+
if (process.env.NODE_ENV !== "production") ContextMenuRootContext.displayName = "ContextMenuRootContext";
|
|
2775
|
+
function useContextMenuRootContext(optional = true) {
|
|
2776
|
+
const context = React.useContext(ContextMenuRootContext);
|
|
2777
|
+
if (context === undefined && !optional) {
|
|
2778
|
+
throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: ContextMenuRootContext is missing. ContextMenu parts must be placed within <ContextMenu.Root>.' : formatErrorMessage(25));
|
|
2779
|
+
}
|
|
2780
|
+
return context;
|
|
2781
|
+
}
|
|
2782
|
+
|
|
2783
|
+
/**
|
|
2784
|
+
* Returns common props shared by all menu item types.
|
|
2785
|
+
* This hook extracts the shared logic for id, role, tabIndex, onKeyDown,
|
|
2786
|
+
* onMouseMove, onClick, and onMouseUp handlers.
|
|
2787
|
+
*/
|
|
2788
|
+
function useMenuItemCommonProps(params) {
|
|
2789
|
+
const {
|
|
2790
|
+
closeOnClick,
|
|
2791
|
+
highlighted,
|
|
2792
|
+
id,
|
|
2793
|
+
nodeId,
|
|
2794
|
+
store,
|
|
2795
|
+
typingRef,
|
|
2796
|
+
itemRef,
|
|
2797
|
+
itemMetadata
|
|
2798
|
+
} = params;
|
|
2799
|
+
const {
|
|
2800
|
+
events: menuEvents
|
|
2801
|
+
} = store.useState('floatingTreeRoot');
|
|
2802
|
+
const contextMenuContext = useContextMenuRootContext(true);
|
|
2803
|
+
const isContextMenu = contextMenuContext !== undefined;
|
|
2804
|
+
return React.useMemo(() => ({
|
|
2805
|
+
id,
|
|
2806
|
+
role: 'menuitem',
|
|
2807
|
+
tabIndex: highlighted ? 0 : -1,
|
|
2808
|
+
onKeyDown(event) {
|
|
2809
|
+
if (event.key === ' ' && typingRef?.current) {
|
|
2810
|
+
event.preventDefault();
|
|
2811
|
+
}
|
|
2812
|
+
},
|
|
2813
|
+
onMouseMove(event) {
|
|
2814
|
+
if (!nodeId) {
|
|
2815
|
+
return;
|
|
2816
|
+
}
|
|
2817
|
+
|
|
2818
|
+
// Inform the floating tree that a menu item within this menu was hovered/moved over
|
|
2819
|
+
// so unrelated descendant submenus can be closed.
|
|
2820
|
+
menuEvents.emit('itemhover', {
|
|
2821
|
+
nodeId,
|
|
2822
|
+
target: event.currentTarget
|
|
2823
|
+
});
|
|
2824
|
+
},
|
|
2825
|
+
onClick(event) {
|
|
2826
|
+
if (closeOnClick) {
|
|
2827
|
+
menuEvents.emit('close', {
|
|
2828
|
+
domEvent: event,
|
|
2829
|
+
reason: itemPress
|
|
2830
|
+
});
|
|
2831
|
+
}
|
|
2832
|
+
},
|
|
2833
|
+
onMouseUp(event) {
|
|
2834
|
+
if (contextMenuContext) {
|
|
2835
|
+
const initialCursorPoint = contextMenuContext.initialCursorPointRef.current;
|
|
2836
|
+
contextMenuContext.initialCursorPointRef.current = null;
|
|
2837
|
+
if (isContextMenu && initialCursorPoint && Math.abs(event.clientX - initialCursorPoint.x) <= 1 && Math.abs(event.clientY - initialCursorPoint.y) <= 1) {
|
|
2838
|
+
return;
|
|
2839
|
+
}
|
|
2840
|
+
|
|
2841
|
+
// On non-macOS platforms, this mouseup belongs to the right-click gesture
|
|
2842
|
+
// that opened the context menu, so it must not activate an item.
|
|
2843
|
+
if (isContextMenu && !isMac && event.button === 2) {
|
|
2844
|
+
return;
|
|
2845
|
+
}
|
|
2846
|
+
}
|
|
2847
|
+
if (itemRef.current && store.context.allowMouseUpTriggerRef.current && (!isContextMenu || event.button === 2)) {
|
|
2848
|
+
// This fires whenever the user clicks on the trigger, moves the cursor, and releases it over the item.
|
|
2849
|
+
// We trigger the click and override the `closeOnClick` preference to always close the menu.
|
|
2850
|
+
if (!itemMetadata || itemMetadata.type === 'regular-item') {
|
|
2851
|
+
itemRef.current.click();
|
|
2852
|
+
}
|
|
2853
|
+
}
|
|
2854
|
+
}
|
|
2855
|
+
}), [closeOnClick, highlighted, id, menuEvents, nodeId, store, typingRef, itemRef, contextMenuContext, isContextMenu, itemMetadata]);
|
|
2856
|
+
}
|
|
2857
|
+
|
|
2858
|
+
const REGULAR_ITEM = {
|
|
2859
|
+
type: 'regular-item'
|
|
2860
|
+
};
|
|
2861
|
+
function useMenuItem(params) {
|
|
2862
|
+
const {
|
|
2863
|
+
closeOnClick,
|
|
2864
|
+
disabled = false,
|
|
2865
|
+
highlighted,
|
|
2866
|
+
id,
|
|
2867
|
+
store,
|
|
2868
|
+
typingRef = store.context.typingRef,
|
|
2869
|
+
nativeButton,
|
|
2870
|
+
itemMetadata,
|
|
2871
|
+
nodeId
|
|
2872
|
+
} = params;
|
|
2873
|
+
const itemRef = React.useRef(null);
|
|
2874
|
+
const {
|
|
2875
|
+
getButtonProps,
|
|
2876
|
+
buttonRef
|
|
2877
|
+
} = useButton({
|
|
2878
|
+
disabled,
|
|
2879
|
+
focusableWhenDisabled: true,
|
|
2880
|
+
native: nativeButton,
|
|
2881
|
+
composite: true
|
|
2882
|
+
});
|
|
2883
|
+
const commonProps = useMenuItemCommonProps({
|
|
2884
|
+
closeOnClick,
|
|
2885
|
+
highlighted,
|
|
2886
|
+
id,
|
|
2887
|
+
nodeId,
|
|
2888
|
+
store,
|
|
2889
|
+
typingRef,
|
|
2890
|
+
itemRef,
|
|
2891
|
+
itemMetadata
|
|
2892
|
+
});
|
|
2893
|
+
const getItemProps = React.useCallback(externalProps => {
|
|
2894
|
+
return mergeProps(commonProps, {
|
|
2895
|
+
onMouseEnter() {
|
|
2896
|
+
if (itemMetadata.type !== 'submenu-trigger') {
|
|
2897
|
+
return;
|
|
2898
|
+
}
|
|
2899
|
+
itemMetadata.setActive();
|
|
2900
|
+
}
|
|
2901
|
+
}, externalProps, getButtonProps);
|
|
2902
|
+
}, [commonProps, getButtonProps, itemMetadata]);
|
|
2903
|
+
const mergedRef = useMergedRefs(itemRef, buttonRef);
|
|
2904
|
+
return React.useMemo(() => ({
|
|
2905
|
+
getItemProps,
|
|
2906
|
+
itemRef: mergedRef
|
|
2907
|
+
}), [getItemProps, mergedRef]);
|
|
2908
|
+
}
|
|
2909
|
+
|
|
2910
|
+
let MenuCheckboxItemDataAttributes = /*#__PURE__*/function (MenuCheckboxItemDataAttributes) {
|
|
2911
|
+
/**
|
|
2912
|
+
* Present when the menu checkbox item is checked.
|
|
2913
|
+
*/
|
|
2914
|
+
MenuCheckboxItemDataAttributes["checked"] = "data-checked";
|
|
2915
|
+
/**
|
|
2916
|
+
* Present when the menu checkbox item is not checked.
|
|
2917
|
+
*/
|
|
2918
|
+
MenuCheckboxItemDataAttributes["unchecked"] = "data-unchecked";
|
|
2919
|
+
/**
|
|
2920
|
+
* Present when the menu checkbox item is disabled.
|
|
2921
|
+
*/
|
|
2922
|
+
MenuCheckboxItemDataAttributes["disabled"] = "data-disabled";
|
|
2923
|
+
/**
|
|
2924
|
+
* Present when the menu checkbox item is highlighted.
|
|
2925
|
+
*/
|
|
2926
|
+
MenuCheckboxItemDataAttributes["highlighted"] = "data-highlighted";
|
|
2927
|
+
return MenuCheckboxItemDataAttributes;
|
|
2928
|
+
}({});
|
|
2929
|
+
|
|
2930
|
+
const itemMapping = {
|
|
2931
|
+
checked(value) {
|
|
2932
|
+
if (value) {
|
|
2933
|
+
return {
|
|
2934
|
+
[MenuCheckboxItemDataAttributes.checked]: ''
|
|
2935
|
+
};
|
|
2936
|
+
}
|
|
2937
|
+
return {
|
|
2938
|
+
[MenuCheckboxItemDataAttributes.unchecked]: ''
|
|
2939
|
+
};
|
|
2940
|
+
},
|
|
2941
|
+
...transitionStatusMapping
|
|
2942
|
+
};
|
|
2943
|
+
|
|
2944
|
+
const MenuGroupContext = /*#__PURE__*/React.createContext(undefined);
|
|
2945
|
+
if (process.env.NODE_ENV !== "production") MenuGroupContext.displayName = "MenuGroupContext";
|
|
2946
|
+
function useMenuGroupRootContext() {
|
|
2947
|
+
const context = React.useContext(MenuGroupContext);
|
|
2948
|
+
if (context === undefined) {
|
|
2949
|
+
throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: MenuGroupRootContext is missing. Menu group parts must be used within <Menu.Group>.' : formatErrorMessage(31));
|
|
2950
|
+
}
|
|
2951
|
+
return context;
|
|
2952
|
+
}
|
|
2953
|
+
|
|
2954
|
+
const MenuGroup = /*#__PURE__*/React.forwardRef(function MenuGroup(componentProps, forwardedRef) {
|
|
2955
|
+
const {
|
|
2956
|
+
render,
|
|
2957
|
+
className,
|
|
2958
|
+
...elementProps
|
|
2959
|
+
} = componentProps;
|
|
2960
|
+
const [labelId, setLabelId] = React.useState(undefined);
|
|
2961
|
+
const context = React.useMemo(() => ({
|
|
2962
|
+
setLabelId
|
|
2963
|
+
}), [setLabelId]);
|
|
2964
|
+
const element = useRenderElement('div', componentProps, {
|
|
2965
|
+
ref: forwardedRef,
|
|
2966
|
+
props: {
|
|
2967
|
+
role: 'group',
|
|
2968
|
+
'aria-labelledby': labelId,
|
|
2969
|
+
...elementProps
|
|
2970
|
+
}
|
|
2971
|
+
});
|
|
2972
|
+
return /*#__PURE__*/jsx(MenuGroupContext.Provider, {
|
|
2973
|
+
value: context,
|
|
2974
|
+
children: element
|
|
2975
|
+
});
|
|
2976
|
+
});
|
|
2977
|
+
if (process.env.NODE_ENV !== "production") MenuGroup.displayName = "MenuGroup";
|
|
2978
|
+
|
|
2979
|
+
/**
|
|
2980
|
+
* An accessible label that is automatically associated with its parent group.
|
|
2981
|
+
* Renders a `<div>` element.
|
|
2982
|
+
*
|
|
2983
|
+
* Documentation: [Base UI Menu](https://base-ui.com/react/components/menu)
|
|
2984
|
+
*/
|
|
2985
|
+
const MenuGroupLabel = /*#__PURE__*/React.forwardRef(function MenuGroupLabelComponent(componentProps, forwardedRef) {
|
|
2986
|
+
const {
|
|
2987
|
+
className,
|
|
2988
|
+
render,
|
|
2989
|
+
id: idProp,
|
|
2990
|
+
...elementProps
|
|
2991
|
+
} = componentProps;
|
|
2992
|
+
const id = useBaseUiId(idProp);
|
|
2993
|
+
const {
|
|
2994
|
+
setLabelId
|
|
2995
|
+
} = useMenuGroupRootContext();
|
|
2996
|
+
useIsoLayoutEffect(() => {
|
|
2997
|
+
setLabelId(id);
|
|
2998
|
+
return () => {
|
|
2999
|
+
setLabelId(undefined);
|
|
3000
|
+
};
|
|
3001
|
+
}, [setLabelId, id]);
|
|
3002
|
+
return useRenderElement('div', componentProps, {
|
|
3003
|
+
ref: forwardedRef,
|
|
3004
|
+
props: {
|
|
3005
|
+
id,
|
|
3006
|
+
role: 'presentation',
|
|
3007
|
+
...elementProps
|
|
3008
|
+
}
|
|
3009
|
+
});
|
|
3010
|
+
});
|
|
3011
|
+
if (process.env.NODE_ENV !== "production") MenuGroupLabel.displayName = "MenuGroupLabel";
|
|
3012
|
+
|
|
3013
|
+
/**
|
|
3014
|
+
* An individual interactive item in the menu.
|
|
3015
|
+
* Renders a `<div>` element.
|
|
3016
|
+
*
|
|
3017
|
+
* Documentation: [Base UI Menu](https://base-ui.com/react/components/menu)
|
|
3018
|
+
*/
|
|
3019
|
+
const MenuItem = /*#__PURE__*/React.forwardRef(function MenuItem(componentProps, forwardedRef) {
|
|
3020
|
+
const {
|
|
3021
|
+
render,
|
|
3022
|
+
className,
|
|
3023
|
+
id: idProp,
|
|
3024
|
+
label,
|
|
3025
|
+
nativeButton = false,
|
|
3026
|
+
disabled = false,
|
|
3027
|
+
closeOnClick = true,
|
|
3028
|
+
...elementProps
|
|
3029
|
+
} = componentProps;
|
|
3030
|
+
const listItem = useCompositeListItem({
|
|
3031
|
+
label
|
|
3032
|
+
});
|
|
3033
|
+
const menuPositionerContext = useMenuPositionerContext(true);
|
|
3034
|
+
const id = useBaseUiId(idProp);
|
|
3035
|
+
const {
|
|
3036
|
+
store
|
|
3037
|
+
} = useMenuRootContext();
|
|
3038
|
+
const highlighted = store.useState('isActive', listItem.index);
|
|
3039
|
+
const itemProps = store.useState('itemProps');
|
|
3040
|
+
const {
|
|
3041
|
+
getItemProps,
|
|
3042
|
+
itemRef
|
|
3043
|
+
} = useMenuItem({
|
|
3044
|
+
closeOnClick,
|
|
3045
|
+
disabled,
|
|
3046
|
+
highlighted,
|
|
3047
|
+
id,
|
|
3048
|
+
store,
|
|
3049
|
+
nativeButton,
|
|
3050
|
+
nodeId: menuPositionerContext?.nodeId,
|
|
3051
|
+
itemMetadata: REGULAR_ITEM
|
|
3052
|
+
});
|
|
3053
|
+
const state = {
|
|
3054
|
+
disabled,
|
|
3055
|
+
highlighted
|
|
3056
|
+
};
|
|
3057
|
+
return useRenderElement('div', componentProps, {
|
|
3058
|
+
state,
|
|
3059
|
+
props: [itemProps, elementProps, getItemProps],
|
|
3060
|
+
ref: [itemRef, forwardedRef, listItem.ref]
|
|
3061
|
+
});
|
|
3062
|
+
});
|
|
3063
|
+
if (process.env.NODE_ENV !== "production") MenuItem.displayName = "MenuItem";
|
|
3064
|
+
|
|
3065
|
+
/**
|
|
3066
|
+
* A link in the menu that can be used to navigate to a different page or section.
|
|
3067
|
+
* Renders an `<a>` element.
|
|
3068
|
+
*
|
|
3069
|
+
* Documentation: [Base UI Menu](https://base-ui.com/react/components/menu)
|
|
3070
|
+
*/
|
|
3071
|
+
const MenuLinkItem = /*#__PURE__*/React.forwardRef(function MenuLinkItem(componentProps, forwardedRef) {
|
|
3072
|
+
const {
|
|
3073
|
+
render,
|
|
3074
|
+
className,
|
|
3075
|
+
id: idProp,
|
|
3076
|
+
label,
|
|
3077
|
+
closeOnClick = false,
|
|
3078
|
+
...elementProps
|
|
3079
|
+
} = componentProps;
|
|
3080
|
+
const linkRef = React.useRef(null);
|
|
3081
|
+
const listItem = useCompositeListItem({
|
|
3082
|
+
label
|
|
3083
|
+
});
|
|
3084
|
+
const menuPositionerContext = useMenuPositionerContext(true);
|
|
3085
|
+
const nodeId = menuPositionerContext?.nodeId;
|
|
3086
|
+
const id = useBaseUiId(idProp);
|
|
3087
|
+
const {
|
|
3088
|
+
store
|
|
3089
|
+
} = useMenuRootContext();
|
|
3090
|
+
const highlighted = store.useState('isActive', listItem.index);
|
|
3091
|
+
const itemProps = store.useState('itemProps');
|
|
3092
|
+
const typingRef = store.context.typingRef;
|
|
3093
|
+
const {
|
|
3094
|
+
getButtonProps,
|
|
3095
|
+
buttonRef
|
|
3096
|
+
} = useButton({
|
|
3097
|
+
native: false,
|
|
3098
|
+
composite: true
|
|
3099
|
+
});
|
|
3100
|
+
const commonProps = useMenuItemCommonProps({
|
|
3101
|
+
closeOnClick,
|
|
3102
|
+
highlighted,
|
|
3103
|
+
id,
|
|
3104
|
+
nodeId,
|
|
3105
|
+
store,
|
|
3106
|
+
typingRef,
|
|
3107
|
+
itemRef: linkRef
|
|
3108
|
+
});
|
|
3109
|
+
function getItemProps(externalProps) {
|
|
3110
|
+
return mergeProps(commonProps, externalProps, getButtonProps);
|
|
3111
|
+
}
|
|
3112
|
+
const state = React.useMemo(() => ({
|
|
3113
|
+
highlighted
|
|
3114
|
+
}), [highlighted]);
|
|
3115
|
+
return useRenderElement('a', componentProps, {
|
|
3116
|
+
state,
|
|
3117
|
+
props: [itemProps, elementProps, getItemProps],
|
|
3118
|
+
ref: [linkRef, buttonRef, forwardedRef, listItem.ref]
|
|
3119
|
+
});
|
|
3120
|
+
});
|
|
3121
|
+
if (process.env.NODE_ENV !== "production") MenuLinkItem.displayName = "MenuLinkItem";
|
|
3122
|
+
|
|
3123
|
+
const ToolbarRootContext = /*#__PURE__*/React.createContext(undefined);
|
|
3124
|
+
if (process.env.NODE_ENV !== "production") ToolbarRootContext.displayName = "ToolbarRootContext";
|
|
3125
|
+
function useToolbarRootContext(optional) {
|
|
3126
|
+
const context = React.useContext(ToolbarRootContext);
|
|
3127
|
+
if (context === undefined && !optional) {
|
|
3128
|
+
throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: ToolbarRootContext is missing. Toolbar parts must be placed within <Toolbar.Root>.' : formatErrorMessage(69));
|
|
3129
|
+
}
|
|
3130
|
+
return context;
|
|
3131
|
+
}
|
|
3132
|
+
|
|
3133
|
+
const stateAttributesMapping = {
|
|
3134
|
+
...popupStateMapping,
|
|
3135
|
+
...transitionStatusMapping
|
|
3136
|
+
};
|
|
3137
|
+
|
|
3138
|
+
/**
|
|
3139
|
+
* A container for the menu items.
|
|
3140
|
+
* Renders a `<div>` element.
|
|
3141
|
+
*
|
|
3142
|
+
* Documentation: [Base UI Menu](https://base-ui.com/react/components/menu)
|
|
3143
|
+
*/
|
|
3144
|
+
const MenuPopup = /*#__PURE__*/React.forwardRef(function MenuPopup(componentProps, forwardedRef) {
|
|
3145
|
+
const {
|
|
3146
|
+
render,
|
|
3147
|
+
className,
|
|
3148
|
+
finalFocus,
|
|
3149
|
+
...elementProps
|
|
3150
|
+
} = componentProps;
|
|
3151
|
+
const {
|
|
3152
|
+
store
|
|
3153
|
+
} = useMenuRootContext();
|
|
3154
|
+
const {
|
|
3155
|
+
side,
|
|
3156
|
+
align
|
|
3157
|
+
} = useMenuPositionerContext();
|
|
3158
|
+
const insideToolbar = useToolbarRootContext(true) != null;
|
|
3159
|
+
const open = store.useState('open');
|
|
3160
|
+
const transitionStatus = store.useState('transitionStatus');
|
|
3161
|
+
const popupProps = store.useState('popupProps');
|
|
3162
|
+
const mounted = store.useState('mounted');
|
|
3163
|
+
const instantType = store.useState('instantType');
|
|
3164
|
+
const triggerElement = store.useState('activeTriggerElement');
|
|
3165
|
+
const parent = store.useState('parent');
|
|
3166
|
+
const lastOpenChangeReason = store.useState('lastOpenChangeReason');
|
|
3167
|
+
const rootId = store.useState('rootId');
|
|
3168
|
+
const floatingContext = store.useState('floatingRootContext');
|
|
3169
|
+
const floatingTreeRoot = store.useState('floatingTreeRoot');
|
|
3170
|
+
const closeDelay = store.useState('closeDelay');
|
|
3171
|
+
const activeTriggerElement = store.useState('activeTriggerElement');
|
|
3172
|
+
const isContextMenu = parent.type === 'context-menu';
|
|
3173
|
+
useOpenChangeComplete({
|
|
3174
|
+
open,
|
|
3175
|
+
ref: store.context.popupRef,
|
|
3176
|
+
onComplete() {
|
|
3177
|
+
if (open) {
|
|
3178
|
+
store.context.onOpenChangeComplete?.(true);
|
|
3184
3179
|
}
|
|
3185
|
-
nextIndexRef.current = sortedMap.size;
|
|
3186
3180
|
}
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
}, [elementsRef]);
|
|
3194
|
-
useIsoLayoutEffect(() => {
|
|
3195
|
-
return () => {
|
|
3196
|
-
if (labelsRef) {
|
|
3197
|
-
labelsRef.current = [];
|
|
3198
|
-
}
|
|
3199
|
-
};
|
|
3200
|
-
}, [labelsRef]);
|
|
3201
|
-
const subscribeMapChange = useStableCallback(fn => {
|
|
3202
|
-
listeners.add(fn);
|
|
3181
|
+
});
|
|
3182
|
+
React.useEffect(() => {
|
|
3183
|
+
function handleClose(event) {
|
|
3184
|
+
store.setOpen(false, createChangeEventDetails(event.reason, event.domEvent));
|
|
3185
|
+
}
|
|
3186
|
+
floatingTreeRoot.events.on('close', handleClose);
|
|
3203
3187
|
return () => {
|
|
3204
|
-
|
|
3188
|
+
floatingTreeRoot.events.off('close', handleClose);
|
|
3205
3189
|
};
|
|
3190
|
+
}, [floatingTreeRoot.events, store]);
|
|
3191
|
+
const hoverEnabled = store.useState('hoverEnabled');
|
|
3192
|
+
const disabled = store.useState('disabled');
|
|
3193
|
+
useHoverFloatingInteraction(floatingContext, {
|
|
3194
|
+
enabled: hoverEnabled && !disabled && !isContextMenu && parent.type !== 'menubar',
|
|
3195
|
+
closeDelay
|
|
3206
3196
|
});
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
}
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3197
|
+
const state = {
|
|
3198
|
+
transitionStatus,
|
|
3199
|
+
side,
|
|
3200
|
+
align,
|
|
3201
|
+
open,
|
|
3202
|
+
nested: parent.type === 'menu',
|
|
3203
|
+
instant: instantType
|
|
3204
|
+
};
|
|
3205
|
+
const setPopupElement = React.useCallback(element => {
|
|
3206
|
+
store.set('popupElement', element);
|
|
3207
|
+
}, [store]);
|
|
3208
|
+
const element = useRenderElement('div', componentProps, {
|
|
3209
|
+
state,
|
|
3210
|
+
ref: [forwardedRef, store.context.popupRef, setPopupElement],
|
|
3211
|
+
stateAttributesMapping,
|
|
3212
|
+
props: [popupProps, {
|
|
3213
|
+
onKeyDown(event) {
|
|
3214
|
+
if (insideToolbar && COMPOSITE_KEYS.has(event.key)) {
|
|
3215
|
+
event.stopPropagation();
|
|
3216
|
+
}
|
|
3217
|
+
}
|
|
3218
|
+
}, getDisabledMountTransitionStyles(transitionStatus), elementProps, {
|
|
3219
|
+
'data-rootownerid': rootId
|
|
3220
|
+
}]
|
|
3221
3221
|
});
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
}
|
|
3226
|
-
function createListeners() {
|
|
3227
|
-
return new Set();
|
|
3228
|
-
}
|
|
3229
|
-
function sortByDocumentPosition(a, b) {
|
|
3230
|
-
const position = a.compareDocumentPosition(b);
|
|
3231
|
-
if (position & Node.DOCUMENT_POSITION_FOLLOWING || position & Node.DOCUMENT_POSITION_CONTAINED_BY) {
|
|
3232
|
-
return -1;
|
|
3222
|
+
let returnFocus = parent.type === undefined || isContextMenu;
|
|
3223
|
+
if (triggerElement || parent.type === 'menubar' && lastOpenChangeReason !== outsidePress) {
|
|
3224
|
+
returnFocus = true;
|
|
3233
3225
|
}
|
|
3234
|
-
|
|
3235
|
-
|
|
3226
|
+
return /*#__PURE__*/jsx(FloatingFocusManager, {
|
|
3227
|
+
context: floatingContext,
|
|
3228
|
+
modal: isContextMenu,
|
|
3229
|
+
disabled: !mounted,
|
|
3230
|
+
returnFocus: finalFocus === undefined ? returnFocus : finalFocus,
|
|
3231
|
+
initialFocus: parent.type !== 'menu',
|
|
3232
|
+
restoreFocus: true,
|
|
3233
|
+
externalTree: parent.type !== 'menubar' ? floatingTreeRoot : undefined,
|
|
3234
|
+
previousFocusableElement: activeTriggerElement,
|
|
3235
|
+
nextFocusableElement: parent.type === undefined ? store.context.triggerFocusTargetRef : undefined,
|
|
3236
|
+
beforeContentFocusGuardRef: parent.type === undefined ? store.context.beforeContentFocusGuardRef : undefined,
|
|
3237
|
+
children: element
|
|
3238
|
+
});
|
|
3239
|
+
});
|
|
3240
|
+
if (process.env.NODE_ENV !== "production") MenuPopup.displayName = "MenuPopup";
|
|
3241
|
+
|
|
3242
|
+
const MenuPortalContext = /*#__PURE__*/React.createContext(undefined);
|
|
3243
|
+
if (process.env.NODE_ENV !== "production") MenuPortalContext.displayName = "MenuPortalContext";
|
|
3244
|
+
function useMenuPortalContext() {
|
|
3245
|
+
const value = React.useContext(MenuPortalContext);
|
|
3246
|
+
if (value === undefined) {
|
|
3247
|
+
throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: <Menu.Portal> is missing.' : formatErrorMessage(32));
|
|
3236
3248
|
}
|
|
3237
|
-
return
|
|
3249
|
+
return value;
|
|
3238
3250
|
}
|
|
3239
3251
|
|
|
3252
|
+
const MenuPortal = /*#__PURE__*/React.forwardRef(function MenuPortal(props, forwardedRef) {
|
|
3253
|
+
const {
|
|
3254
|
+
keepMounted = false,
|
|
3255
|
+
...portalProps
|
|
3256
|
+
} = props;
|
|
3257
|
+
const {
|
|
3258
|
+
store
|
|
3259
|
+
} = useMenuRootContext();
|
|
3260
|
+
const mounted = store.useState('mounted');
|
|
3261
|
+
const shouldRender = mounted || keepMounted;
|
|
3262
|
+
if (!shouldRender) {
|
|
3263
|
+
return null;
|
|
3264
|
+
}
|
|
3265
|
+
return /*#__PURE__*/jsx(MenuPortalContext.Provider, {
|
|
3266
|
+
value: keepMounted,
|
|
3267
|
+
children: /*#__PURE__*/jsx(FloatingPortal, {
|
|
3268
|
+
ref: forwardedRef,
|
|
3269
|
+
...portalProps
|
|
3270
|
+
})
|
|
3271
|
+
});
|
|
3272
|
+
});
|
|
3273
|
+
if (process.env.NODE_ENV !== "production") MenuPortal.displayName = "MenuPortal";
|
|
3274
|
+
|
|
3240
3275
|
const MenuPositioner = /*#__PURE__*/React.forwardRef(function MenuPositioner(componentProps, forwardedRef) {
|
|
3241
3276
|
const {
|
|
3242
3277
|
anchor: anchorProp,
|
|
@@ -4247,41 +4282,6 @@ function MenuSubmenuRoot(props) {
|
|
|
4247
4282
|
});
|
|
4248
4283
|
}
|
|
4249
4284
|
|
|
4250
|
-
function getPseudoElementBounds(element) {
|
|
4251
|
-
const elementRect = element.getBoundingClientRect();
|
|
4252
|
-
|
|
4253
|
-
// Avoid "Not implemented: window.getComputedStyle(elt, pseudoElt)"
|
|
4254
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
4255
|
-
return elementRect;
|
|
4256
|
-
}
|
|
4257
|
-
const beforeStyles = window.getComputedStyle(element, '::before');
|
|
4258
|
-
const afterStyles = window.getComputedStyle(element, '::after');
|
|
4259
|
-
const hasPseudoElements = beforeStyles.content !== 'none' || afterStyles.content !== 'none';
|
|
4260
|
-
if (!hasPseudoElements) {
|
|
4261
|
-
return elementRect;
|
|
4262
|
-
}
|
|
4263
|
-
|
|
4264
|
-
// Get dimensions of pseudo-elements
|
|
4265
|
-
const beforeWidth = parseFloat(beforeStyles.width) || 0;
|
|
4266
|
-
const beforeHeight = parseFloat(beforeStyles.height) || 0;
|
|
4267
|
-
const afterWidth = parseFloat(afterStyles.width) || 0;
|
|
4268
|
-
const afterHeight = parseFloat(afterStyles.height) || 0;
|
|
4269
|
-
|
|
4270
|
-
// Calculate max dimensions including pseudo-elements
|
|
4271
|
-
const totalWidth = Math.max(elementRect.width, beforeWidth, afterWidth);
|
|
4272
|
-
const totalHeight = Math.max(elementRect.height, beforeHeight, afterHeight);
|
|
4273
|
-
|
|
4274
|
-
// Calculate the differences to extend the bounds
|
|
4275
|
-
const widthDiff = totalWidth - elementRect.width;
|
|
4276
|
-
const heightDiff = totalHeight - elementRect.height;
|
|
4277
|
-
return {
|
|
4278
|
-
left: elementRect.left - widthDiff / 2,
|
|
4279
|
-
right: elementRect.right + widthDiff / 2,
|
|
4280
|
-
top: elementRect.top - heightDiff / 2,
|
|
4281
|
-
bottom: elementRect.bottom + heightDiff / 2
|
|
4282
|
-
};
|
|
4283
|
-
}
|
|
4284
|
-
|
|
4285
4285
|
function useCompositeItem(params = {}) {
|
|
4286
4286
|
const {
|
|
4287
4287
|
highlightItemOnHover,
|
|
@@ -4797,4 +4797,4 @@ const MenuSubmenuTrigger = /*#__PURE__*/React.forwardRef(function SubmenuTrigger
|
|
|
4797
4797
|
});
|
|
4798
4798
|
if (process.env.NODE_ENV !== "production") MenuSubmenuTrigger.displayName = "MenuSubmenuTrigger";
|
|
4799
4799
|
|
|
4800
|
-
export {
|
|
4800
|
+
export { MenuStore as A, CompositeList as C, DrawerTitle as D, IndexGuessBehavior as I, MenuTrigger as M, REGULAR_ITEM as R, DrawerClose as a, MenuLinkItem as b, MenuItem as c, MenuRadioItem as d, MenuRadioItemIndicator as e, MenuSubmenuTrigger as f, MenuRoot as g, MenuPortal as h, MenuPositioner as i, MenuPopup as j, MenuRadioGroup as k, MenuGroup as l, MenuSubmenuRoot as m, MenuGroupLabel as n, useListNavigation as o, useTypeahead as p, getPseudoElementBounds as q, useAnchorPositioning as r, getDisabledMountTransitionStyles as s, useCompositeListItem as t, useFloatingRootContext as u, useMenuRootContext as v, useMenuPositionerContext as w, useContextMenuRootContext as x, useMenuItem as y, itemMapping as z };
|