@jobber/components 9.6.1 → 9.6.2
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/Autocomplete/index.cjs +2 -0
- package/dist/Autocomplete/index.mjs +2 -0
- package/dist/Autocomplete-cjs.js +5 -4
- package/dist/Autocomplete-es.js +2 -1
- package/dist/Card/index.cjs +2 -1
- package/dist/Card/index.mjs +2 -1
- package/dist/Chip/index.cjs +2 -0
- package/dist/Chip/index.mjs +2 -0
- package/dist/Chips/InternalChipDismissible/hooks/index.cjs +2 -0
- package/dist/Chips/InternalChipDismissible/hooks/index.mjs +2 -0
- package/dist/Chips/InternalChipDismissible/index.cjs +2 -0
- package/dist/Chips/InternalChipDismissible/index.mjs +2 -0
- package/dist/Chips/index.cjs +2 -0
- package/dist/Chips/index.mjs +2 -0
- package/dist/Combobox/index.cjs +4 -2
- package/dist/Combobox/index.mjs +4 -2
- package/dist/{ComboboxSeparator-cjs.js → ComboboxChipRemove-cjs.js} +455 -501
- package/dist/{ComboboxSeparator-es.js → ComboboxChipRemove-es.js} +456 -500
- package/dist/ComboboxPrimitive-cjs.js +30 -29
- package/dist/ComboboxPrimitive-es.js +3 -2
- package/dist/ConfirmationModal/index.cjs +2 -0
- package/dist/ConfirmationModal/index.mjs +2 -0
- package/dist/DataDump/index.cjs +2 -1
- package/dist/DataDump/index.mjs +2 -1
- package/dist/DataList/components/DataListActions/index.cjs +2 -0
- package/dist/DataList/components/DataListActions/index.mjs +2 -0
- package/dist/DataList/components/DataListBulkActions/index.cjs +2 -0
- package/dist/DataList/components/DataListBulkActions/index.mjs +2 -0
- package/dist/DataList/components/DataListFilters/components/DataListSort/index.cjs +2 -0
- package/dist/DataList/components/DataListFilters/components/DataListSort/index.mjs +2 -0
- package/dist/DataList/components/DataListFilters/index.cjs +2 -0
- package/dist/DataList/components/DataListFilters/index.mjs +2 -0
- package/dist/DataList/components/DataListHeader/index.cjs +2 -0
- package/dist/DataList/components/DataListHeader/index.mjs +2 -0
- package/dist/DataList/components/DataListItem/index.cjs +2 -0
- package/dist/DataList/components/DataListItem/index.mjs +2 -0
- package/dist/DataList/components/DataListItemActions/index.cjs +2 -0
- package/dist/DataList/components/DataListItemActions/index.mjs +2 -0
- package/dist/DataList/components/DataListItemActionsOverflow/index.cjs +2 -0
- package/dist/DataList/components/DataListItemActionsOverflow/index.mjs +2 -0
- package/dist/DataList/components/DataListItems/index.cjs +2 -0
- package/dist/DataList/components/DataListItems/index.mjs +2 -0
- package/dist/DataList/components/DataListLayout/index.cjs +2 -0
- package/dist/DataList/components/DataListLayout/index.mjs +2 -0
- package/dist/DataList/components/DataListLayoutActions/index.cjs +2 -0
- package/dist/DataList/components/DataListLayoutActions/index.mjs +2 -0
- package/dist/DataList/index.cjs +2 -0
- package/dist/DataList/index.mjs +2 -0
- package/dist/DatePicker/index.cjs +2 -0
- package/dist/DatePicker/index.mjs +2 -0
- package/dist/DatePicker-cjs.js +5 -4
- package/dist/DatePicker-es.js +2 -1
- package/dist/Dialog/index.cjs +2 -1
- package/dist/Dialog/index.mjs +2 -1
- package/dist/DrawerDescription-cjs.js +99 -268
- package/dist/DrawerDescription-es.js +103 -270
- package/dist/DrawerTitle-cjs.js +6 -2
- package/dist/DrawerTitle-es.js +7 -3
- package/dist/FieldDescription-cjs.js +181 -184
- package/dist/FieldDescription-es.js +184 -187
- package/dist/FilterPicker/components/FilterPickerActivator/index.cjs +2 -0
- package/dist/FilterPicker/components/FilterPickerActivator/index.mjs +2 -0
- package/dist/FilterPicker/components/FilterPickerContent/index.cjs +2 -0
- package/dist/FilterPicker/components/FilterPickerContent/index.mjs +2 -0
- package/dist/FilterPicker/components/FilterPickerTrigger/index.cjs +2 -0
- package/dist/FilterPicker/components/FilterPickerTrigger/index.mjs +2 -0
- package/dist/FilterPicker/index.cjs +2 -0
- package/dist/FilterPicker/index.mjs +2 -0
- package/dist/FilterPickerContent-cjs.js +5 -4
- package/dist/FilterPickerContent-es.js +2 -1
- package/dist/FormatFile/index.cjs +2 -0
- package/dist/FormatFile/index.mjs +2 -0
- package/dist/Gallery/index.cjs +2 -0
- package/dist/Gallery/index.mjs +2 -0
- package/dist/InputDate/index.cjs +2 -0
- package/dist/InputDate/index.mjs +2 -0
- package/dist/InputNumber/index.cjs +2 -1
- package/dist/InputNumber/index.mjs +2 -1
- package/dist/LightBox/index.cjs +2 -0
- package/dist/LightBox/index.mjs +2 -0
- package/dist/Menu/index.cjs +2 -1
- package/dist/Menu/index.mjs +2 -1
- package/dist/Menu-cjs.js +5 -4
- package/dist/Menu-es.js +2 -1
- package/dist/MenuSubmenuTrigger-cjs.js +164 -206
- package/dist/MenuSubmenuTrigger-es.js +152 -194
- package/dist/Modal/index.cjs +2 -0
- package/dist/Modal/index.mjs +3 -1
- package/dist/NumberFieldInput-cjs.js +308 -187
- package/dist/NumberFieldInput-es.js +308 -187
- package/dist/Page/index.cjs +2 -1
- package/dist/Page/index.mjs +2 -1
- package/dist/Popover/index.cjs +2 -0
- package/dist/Popover/index.mjs +2 -0
- package/dist/Popover-cjs.js +8 -7
- package/dist/Popover-es.js +2 -1
- package/dist/ScrollAreaViewport-cjs.js +1093 -747
- package/dist/ScrollAreaViewport-es.js +1081 -734
- package/dist/Select/index.cjs +2 -1
- package/dist/Select/index.mjs +2 -1
- package/dist/SelectGroupLabel-cjs.js +306 -207
- package/dist/SelectGroupLabel-es.js +302 -203
- package/dist/Tooltip/index.cjs +2 -0
- package/dist/Tooltip/index.mjs +2 -0
- package/dist/Tooltip-cjs.js +7 -6
- package/dist/Tooltip-es.js +2 -1
- package/dist/dialogReturnFocus-cjs.js +1 -1
- package/dist/dialogReturnFocus-es.js +2 -2
- package/dist/floating-ui.react-cjs.js +192 -2564
- package/dist/floating-ui.react-dom-cjs.js +2103 -0
- package/dist/floating-ui.react-dom-es.js +2072 -0
- package/dist/floating-ui.react-es.js +156 -2519
- package/dist/floating-ui.utils-cjs.js +342 -0
- package/dist/floating-ui.utils-es.js +300 -0
- package/dist/index.cjs +4 -3
- package/dist/index.mjs +4 -3
- package/dist/primitives/BottomSheet/index.cjs +1 -1
- package/dist/primitives/BottomSheet/index.mjs +1 -1
- package/dist/primitives/ComboboxPrimitive/index.cjs +4 -2
- package/dist/primitives/ComboboxPrimitive/index.mjs +4 -2
- package/dist/primitives/SelectPrimitive/index.cjs +2 -0
- package/dist/primitives/SelectPrimitive/index.mjs +2 -0
- package/dist/primitives/index.cjs +3 -2
- package/dist/primitives/index.mjs +3 -2
- package/dist/scrollEdges-cjs.js +11 -1
- package/dist/scrollEdges-es.js +11 -1
- package/dist/unstyledPrimitives/index.cjs +478 -720
- package/dist/unstyledPrimitives/index.mjs +421 -663
- package/dist/useCompositeListItem-cjs.js +361 -2108
- package/dist/useCompositeListItem-es.js +331 -2076
- package/dist/useLabel-cjs.js +3 -2
- package/dist/useLabel-es.js +3 -2
- package/dist/useRenderElement-cjs.js +7 -9
- package/dist/useRenderElement-es.js +7 -9
- package/dist/useScrollLock-cjs.js +344 -819
- package/dist/useScrollLock-es.js +296 -732
- package/dist/useScrollToActive-cjs.js +5 -4
- package/dist/useScrollToActive-es.js +2 -1
- package/package.json +3 -3
- package/dist/scrollable-cjs.js +0 -58
- package/dist/scrollable-es.js +0 -54
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { a as useRefWithInit, f as formatErrorMessage, u as useRenderElement, m as mergeProps, b as useMergedRefs,
|
|
3
|
-
import {
|
|
2
|
+
import { a as useRefWithInit, f as formatErrorMessage, u as useRenderElement, m as mergeProps, b as useMergedRefs, E as EMPTY_OBJECT, c as EMPTY_ARRAY, w as warn } from './useRenderElement-es.js';
|
|
3
|
+
import { aw as isMouseLikePointerType, k as useTimeout, ax as mergeCleanups, s as addEventListener, g as getTarget, ay as isTypeableElement, az as matchesFocusVisible, aA as isTargetInsideEnabledTrigger, d as createChangeEventDetails, aB as triggerFocus, aC as createAttribute, D as activeElement, o as ownerDocument, _ as contains, aD as mac, a6 as webkit, aE as triggerPress, aF as escapeKey, H as useOnMount, T as Timeout, ae as useFloatingTree, ab as useFloatingParentNodeId, b as useStableCallback, a as useIsoLayoutEffect, aG as isInteractiveElement, aH as getNodeChildren, aI as triggerHover, q as useValueAsRef, p as popupStateMapping, t as transitionStatusMapping, a9 as itemPress, c as useButton, u as useBaseUiId, f as useOpenChangeComplete, X as outsidePress, i as FloatingFocusManager, a0 as FloatingPortal, aJ as useAnimationsFinished, aK as POPUP_COLLISION_AVOIDANCE, a1 as InternalBackdrop, a2 as inertValue, aL as FloatingNode, a3 as DROPDOWN_COLLISION_AVOIDANCE, aM as siblingOpen, n as useControlled, m as useTransitionStatus, N as createSelector, aN as ReactStore, ad as PopupTriggerMap, aO as FloatingTreeStore, aP as fastComponent, aQ as useInitialOpenSync, aa as useId, aR as useFloatingNodeId, O as useOpenInteractionType, aS as useImplicitActiveTrigger, aT as useOpenStateTransitions, aU as attachPreventUnmountOnClose, aV as setPopupOpenState, W as focusOut, aj as listNavigation, aW as useSyncedFloatingRootContext, j as imperativeAction, R as useDismiss, a4 as useDirection, aX as TYPEAHEAD_RESET_MS, F as FOCUSABLE_POPUP_PROPS, aY as usePopupInteractionProps, aZ as FloatingTree, a_ as useCompositeRootContext, a$ as getTabbableBeforeElement, b0 as isOutsideEvent, b1 as getTabbableAfterElement, b2 as getNextTabbable, b3 as fastComponentRef, b4 as useTriggerDataForwarding, $ as cancelOpen, Q as useClick, Y as pressableTriggerOpenStateMapping, b5 as FocusGuard, b6 as PATIENT_CLICK_THRESHOLD, b7 as useTriggerRegistration, S as SafeReact, b8 as triggerOpenStateMapping } from './useScrollLock-es.js';
|
|
4
4
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
5
|
-
import {
|
|
5
|
+
import { z as useCompositeListItem, y as getDisabledMountTransitionStyles, v as useAnchorPositioning, B as adaptiveOrigin, t as useAnchoredPopupScrollLock, w as usePositioner, C as CompositeList, j as useListNavigation, k as useTypeahead, o as getPseudoElementBounds } from './useCompositeListItem-es.js';
|
|
6
6
|
import { u as useToolbarRootContext, l as isElementDisabled } from './SelectGroupLabel-es.js';
|
|
7
7
|
import { C as COMPOSITE_KEYS } from './scrollEdges-es.js';
|
|
8
|
-
import {
|
|
8
|
+
import { K as getWindow, b as isElement, i as isHTMLElement, d as isLastTraversableNode, e as getParentNode } from './floating-ui.utils-es.js';
|
|
9
|
+
import { p as popupStoreSelectors, n as createInitialPopupStoreState } from './ScrollAreaViewport-es.js';
|
|
9
10
|
import * as ReactDOM from 'react-dom';
|
|
10
11
|
|
|
11
12
|
function resolveValue(value, pointerType) {
|
|
@@ -437,8 +438,7 @@ function useHoverReferenceInteraction(context, props = {}) {
|
|
|
437
438
|
isActiveTrigger = true,
|
|
438
439
|
getHandleCloseContext,
|
|
439
440
|
isClosing,
|
|
440
|
-
shouldOpen: shouldOpenProp
|
|
441
|
-
guardStaleOpen = false
|
|
441
|
+
shouldOpen: shouldOpenProp
|
|
442
442
|
} = props;
|
|
443
443
|
const store = 'rootStore' in context ? context.rootStore : context;
|
|
444
444
|
const {
|
|
@@ -640,24 +640,13 @@ function useHoverReferenceInteraction(context, props = {}) {
|
|
|
640
640
|
closeWithDelay(event);
|
|
641
641
|
}
|
|
642
642
|
}
|
|
643
|
-
|
|
644
|
-
// Backup cancellation for Chrome's dropped `mouseleave` — see `guardStaleOpen`.
|
|
645
|
-
function onMouseOut(event) {
|
|
646
|
-
if (contains(trigger, event.relatedTarget)) {
|
|
647
|
-
return; // moved within the trigger's own subtree
|
|
648
|
-
}
|
|
649
|
-
instance.openChangeTimeout.clear();
|
|
650
|
-
instance.restTimeout.clear();
|
|
651
|
-
instance.restTimeoutPending = false;
|
|
652
|
-
}
|
|
653
|
-
const staleOpenGuard = guardStaleOpen ? addEventListener(trigger, 'mouseout', onMouseOut) : undefined;
|
|
654
643
|
if (move) {
|
|
655
644
|
return mergeCleanups(addEventListener(trigger, 'mousemove', onMouseEnter, {
|
|
656
645
|
once: true
|
|
657
|
-
}), addEventListener(trigger, 'mouseenter', onMouseEnter), addEventListener(trigger, 'mouseleave', onMouseLeave)
|
|
646
|
+
}), addEventListener(trigger, 'mouseenter', onMouseEnter), addEventListener(trigger, 'mouseleave', onMouseLeave));
|
|
658
647
|
}
|
|
659
|
-
return mergeCleanups(addEventListener(trigger, 'mouseenter', onMouseEnter), addEventListener(trigger, 'mouseleave', onMouseLeave)
|
|
660
|
-
}, [cleanupMouseMoveHandler, clearPointerEvents, dataRef, delayRef, store, enabled, handleCloseRef, instance, isActiveTrigger, isOverInactiveTrigger, isClickLikeOpenEvent$1, mouseOnly, move, restMsRef, triggerElementRef, tree, enabledRef, getHandleCloseContext, isClosingRef, checkShouldOpen
|
|
648
|
+
return mergeCleanups(addEventListener(trigger, 'mouseenter', onMouseEnter), addEventListener(trigger, 'mouseleave', onMouseLeave));
|
|
649
|
+
}, [cleanupMouseMoveHandler, clearPointerEvents, dataRef, delayRef, store, enabled, handleCloseRef, instance, isActiveTrigger, isOverInactiveTrigger, isClickLikeOpenEvent$1, mouseOnly, move, restMsRef, triggerElementRef, tree, enabledRef, getHandleCloseContext, isClosingRef, checkShouldOpen]);
|
|
661
650
|
return React.useMemo(() => {
|
|
662
651
|
if (!enabled) {
|
|
663
652
|
return undefined;
|
|
@@ -998,6 +987,11 @@ function useContextMenuRootContext(optional = true) {
|
|
|
998
987
|
return context;
|
|
999
988
|
}
|
|
1000
989
|
|
|
990
|
+
const stateAttributesMapping$1 = {
|
|
991
|
+
...popupStateMapping,
|
|
992
|
+
...transitionStatusMapping
|
|
993
|
+
};
|
|
994
|
+
|
|
1001
995
|
/**
|
|
1002
996
|
* An overlay displayed beneath the menu popup.
|
|
1003
997
|
* Renders a `<div>` element.
|
|
@@ -1026,7 +1020,7 @@ const MenuBackdrop = /*#__PURE__*/React.forwardRef(function MenuBackdrop(compone
|
|
|
1026
1020
|
return useRenderElement('div', componentProps, {
|
|
1027
1021
|
ref: contextMenuContext?.backdropRef ? [forwardedRef, contextMenuContext.backdropRef] : forwardedRef,
|
|
1028
1022
|
state,
|
|
1029
|
-
stateAttributesMapping:
|
|
1023
|
+
stateAttributesMapping: stateAttributesMapping$1,
|
|
1030
1024
|
props: [{
|
|
1031
1025
|
role: 'presentation',
|
|
1032
1026
|
hidden: !mounted,
|
|
@@ -1108,12 +1102,8 @@ function useMenuItemCommonProps(params) {
|
|
|
1108
1102
|
if (itemRef.current && store.context.allowMouseUpTriggerRef.current && (!isContextMenu || event.button === 2)) {
|
|
1109
1103
|
// This fires whenever the user clicks on the trigger, moves the cursor, and releases it over the item.
|
|
1110
1104
|
// We trigger the click and override the `closeOnClick` preference to always close the menu.
|
|
1111
|
-
if (itemMetadata.type === 'regular-item') {
|
|
1112
|
-
|
|
1113
|
-
// treat it as a keyboard activation (`detail === 0` → `data-instant`).
|
|
1114
|
-
dispatchClickWithModifiers(itemRef.current, event, {
|
|
1115
|
-
detail: 1
|
|
1116
|
-
});
|
|
1105
|
+
if (!itemMetadata || itemMetadata.type === 'regular-item') {
|
|
1106
|
+
itemRef.current.click();
|
|
1117
1107
|
}
|
|
1118
1108
|
}
|
|
1119
1109
|
}
|
|
@@ -1126,7 +1116,7 @@ const REGULAR_ITEM = {
|
|
|
1126
1116
|
function useMenuItem(params) {
|
|
1127
1117
|
const {
|
|
1128
1118
|
closeOnClick,
|
|
1129
|
-
disabled,
|
|
1119
|
+
disabled: disabledProp = false,
|
|
1130
1120
|
highlighted,
|
|
1131
1121
|
id,
|
|
1132
1122
|
store,
|
|
@@ -1135,6 +1125,8 @@ function useMenuItem(params) {
|
|
|
1135
1125
|
itemMetadata,
|
|
1136
1126
|
nodeId
|
|
1137
1127
|
} = params;
|
|
1128
|
+
const rootDisabled = store.useState('disabled');
|
|
1129
|
+
const disabled = disabledProp || rootDisabled;
|
|
1138
1130
|
const itemRef = React.useRef(null);
|
|
1139
1131
|
const {
|
|
1140
1132
|
getButtonProps,
|
|
@@ -1258,7 +1250,7 @@ const MenuGroupLabel = /*#__PURE__*/React.forwardRef(function MenuGroupLabel(com
|
|
|
1258
1250
|
useIsoLayoutEffect(() => {
|
|
1259
1251
|
setLabelId(id);
|
|
1260
1252
|
return () => {
|
|
1261
|
-
setLabelId(
|
|
1253
|
+
setLabelId(undefined);
|
|
1262
1254
|
};
|
|
1263
1255
|
}, [setLabelId, id]);
|
|
1264
1256
|
return useRenderElement('div', componentProps, {
|
|
@@ -1285,13 +1277,12 @@ const MenuItem = /*#__PURE__*/React.forwardRef(function MenuItem(componentProps,
|
|
|
1285
1277
|
id: idProp,
|
|
1286
1278
|
label,
|
|
1287
1279
|
nativeButton = false,
|
|
1288
|
-
disabled
|
|
1280
|
+
disabled = false,
|
|
1289
1281
|
closeOnClick = true,
|
|
1290
1282
|
style,
|
|
1291
1283
|
...elementProps
|
|
1292
1284
|
} = componentProps;
|
|
1293
1285
|
const listItem = useCompositeListItem({
|
|
1294
|
-
guess: true,
|
|
1295
1286
|
label
|
|
1296
1287
|
});
|
|
1297
1288
|
const menuPositionerContext = useMenuPositionerContext(true);
|
|
@@ -1299,8 +1290,6 @@ const MenuItem = /*#__PURE__*/React.forwardRef(function MenuItem(componentProps,
|
|
|
1299
1290
|
const {
|
|
1300
1291
|
store
|
|
1301
1292
|
} = useMenuRootContext();
|
|
1302
|
-
const rootDisabled = store.useState('disabled');
|
|
1303
|
-
const disabled = disabledProp || rootDisabled;
|
|
1304
1293
|
const highlighted = store.useState('isActive', listItem.index);
|
|
1305
1294
|
const itemProps = store.useState('itemProps');
|
|
1306
1295
|
const {
|
|
@@ -1346,7 +1335,6 @@ const MenuLinkItem = /*#__PURE__*/React.forwardRef(function MenuLinkItem(compone
|
|
|
1346
1335
|
} = componentProps;
|
|
1347
1336
|
const linkRef = React.useRef(null);
|
|
1348
1337
|
const listItem = useCompositeListItem({
|
|
1349
|
-
guess: true,
|
|
1350
1338
|
label
|
|
1351
1339
|
});
|
|
1352
1340
|
const menuPositionerContext = useMenuPositionerContext(true);
|
|
@@ -1372,8 +1360,7 @@ const MenuLinkItem = /*#__PURE__*/React.forwardRef(function MenuLinkItem(compone
|
|
|
1372
1360
|
nodeId,
|
|
1373
1361
|
store,
|
|
1374
1362
|
typingRef,
|
|
1375
|
-
itemRef: linkRef
|
|
1376
|
-
itemMetadata: REGULAR_ITEM
|
|
1363
|
+
itemRef: linkRef
|
|
1377
1364
|
});
|
|
1378
1365
|
function getItemProps(externalProps) {
|
|
1379
1366
|
return mergeProps(commonProps, externalProps, getButtonProps);
|
|
@@ -1389,6 +1376,17 @@ const MenuLinkItem = /*#__PURE__*/React.forwardRef(function MenuLinkItem(compone
|
|
|
1389
1376
|
});
|
|
1390
1377
|
if (process.env.NODE_ENV !== "production") MenuLinkItem.displayName = "MenuLinkItem";
|
|
1391
1378
|
|
|
1379
|
+
const stateAttributesMapping = {
|
|
1380
|
+
...popupStateMapping,
|
|
1381
|
+
...transitionStatusMapping
|
|
1382
|
+
};
|
|
1383
|
+
|
|
1384
|
+
/**
|
|
1385
|
+
* A container for the menu items.
|
|
1386
|
+
* Renders a `<div>` element.
|
|
1387
|
+
*
|
|
1388
|
+
* Documentation: [Base UI Menu](https://base-ui.com/react/components/menu)
|
|
1389
|
+
*/
|
|
1392
1390
|
const MenuPopup = /*#__PURE__*/React.forwardRef(function MenuPopup(componentProps, forwardedRef) {
|
|
1393
1391
|
const {
|
|
1394
1392
|
render,
|
|
@@ -1410,13 +1408,14 @@ const MenuPopup = /*#__PURE__*/React.forwardRef(function MenuPopup(componentProp
|
|
|
1410
1408
|
const popupProps = store.useState('popupProps');
|
|
1411
1409
|
const mounted = store.useState('mounted');
|
|
1412
1410
|
const instantType = store.useState('instantType');
|
|
1413
|
-
const
|
|
1411
|
+
const triggerElement = store.useState('activeTriggerElement');
|
|
1414
1412
|
const parent = store.useState('parent');
|
|
1415
1413
|
const lastOpenChangeReason = store.useState('lastOpenChangeReason');
|
|
1416
1414
|
const rootId = store.useState('rootId');
|
|
1417
1415
|
const floatingContext = store.useState('floatingRootContext');
|
|
1418
1416
|
const floatingTreeRoot = store.useState('floatingTreeRoot');
|
|
1419
1417
|
const closeDelay = store.useState('closeDelay');
|
|
1418
|
+
const activeTriggerElement = store.useState('activeTriggerElement');
|
|
1420
1419
|
const hoverEnabled = store.useState('hoverEnabled');
|
|
1421
1420
|
const disabled = store.useState('disabled');
|
|
1422
1421
|
const openMethod = store.useState('openMethod');
|
|
@@ -1443,7 +1442,9 @@ const MenuPopup = /*#__PURE__*/React.forwardRef(function MenuPopup(componentProp
|
|
|
1443
1442
|
enabled: hoverEnabled && !disabled && !isContextMenu && parent.type !== 'menubar',
|
|
1444
1443
|
closeDelay
|
|
1445
1444
|
});
|
|
1446
|
-
const setPopupElement =
|
|
1445
|
+
const setPopupElement = React.useCallback(element => {
|
|
1446
|
+
store.set('popupElement', element);
|
|
1447
|
+
}, [store]);
|
|
1447
1448
|
const state = {
|
|
1448
1449
|
transitionStatus,
|
|
1449
1450
|
side,
|
|
@@ -1455,7 +1456,7 @@ const MenuPopup = /*#__PURE__*/React.forwardRef(function MenuPopup(componentProp
|
|
|
1455
1456
|
const element = useRenderElement('div', componentProps, {
|
|
1456
1457
|
state,
|
|
1457
1458
|
ref: [forwardedRef, store.context.popupRef, setPopupElement],
|
|
1458
|
-
stateAttributesMapping
|
|
1459
|
+
stateAttributesMapping,
|
|
1459
1460
|
props: [popupProps, {
|
|
1460
1461
|
onKeyDown(event) {
|
|
1461
1462
|
if (insideToolbar && COMPOSITE_KEYS.has(event.key)) {
|
|
@@ -1467,7 +1468,7 @@ const MenuPopup = /*#__PURE__*/React.forwardRef(function MenuPopup(componentProp
|
|
|
1467
1468
|
}]
|
|
1468
1469
|
});
|
|
1469
1470
|
let returnFocus = parent.type === undefined || isContextMenu;
|
|
1470
|
-
if (
|
|
1471
|
+
if (triggerElement || parent.type === 'menubar' && lastOpenChangeReason !== outsidePress) {
|
|
1471
1472
|
returnFocus = true;
|
|
1472
1473
|
}
|
|
1473
1474
|
return /*#__PURE__*/jsx(FloatingFocusManager, {
|
|
@@ -1555,13 +1556,13 @@ const MenuPositioner = /*#__PURE__*/React.forwardRef(function MenuPositioner(com
|
|
|
1555
1556
|
const transitionStatus = store.useState('transitionStatus');
|
|
1556
1557
|
const positionerElement = store.useState('positionerElement');
|
|
1557
1558
|
const instantType = store.useState('instantType');
|
|
1558
|
-
const
|
|
1559
|
+
const hasViewport = store.useState('hasViewport');
|
|
1559
1560
|
const lastOpenChangeReason = store.useState('lastOpenChangeReason');
|
|
1560
1561
|
const floatingNodeId = store.useState('floatingNodeId');
|
|
1561
1562
|
const floatingParentNodeId = store.useState('floatingParentNodeId');
|
|
1562
1563
|
const domReference = floatingRootContext.useState('domReferenceElement');
|
|
1563
1564
|
const previousTriggerRef = React.useRef(null);
|
|
1564
|
-
const runOnceAnimationsFinish = useAnimationsFinished(positionerElement);
|
|
1565
|
+
const runOnceAnimationsFinish = useAnimationsFinished(positionerElement, false, false);
|
|
1565
1566
|
let anchor = anchorProp;
|
|
1566
1567
|
let sideOffset = sideOffsetProp;
|
|
1567
1568
|
let alignOffset = alignOffsetProp;
|
|
@@ -1603,12 +1604,9 @@ const MenuPositioner = /*#__PURE__*/React.forwardRef(function MenuPositioner(com
|
|
|
1603
1604
|
keepMounted,
|
|
1604
1605
|
disableAnchorTracking,
|
|
1605
1606
|
collisionAvoidance,
|
|
1606
|
-
|
|
1607
|
-
crossAxis: !('side' in collisionAvoidance && collisionAvoidance.side === 'flip'),
|
|
1608
|
-
rootBoundary: 'layoutViewport'
|
|
1609
|
-
} : undefined,
|
|
1607
|
+
shiftCrossAxis: contextMenu && !('side' in collisionAvoidance && collisionAvoidance.side === 'flip'),
|
|
1610
1608
|
externalTree: floatingTreeRoot,
|
|
1611
|
-
adaptiveOrigin
|
|
1609
|
+
adaptiveOrigin: hasViewport ? adaptiveOrigin : undefined
|
|
1612
1610
|
});
|
|
1613
1611
|
React.useEffect(() => {
|
|
1614
1612
|
function onMenuOpenChange(details) {
|
|
@@ -1848,7 +1846,6 @@ const MenuRadioItem = /*#__PURE__*/React.forwardRef(function MenuRadioItem(compo
|
|
|
1848
1846
|
...elementProps
|
|
1849
1847
|
} = componentProps;
|
|
1850
1848
|
const listItem = useCompositeListItem({
|
|
1851
|
-
guess: true,
|
|
1852
1849
|
label
|
|
1853
1850
|
});
|
|
1854
1851
|
const menuPositionerContext = useMenuPositionerContext(true);
|
|
@@ -1863,8 +1860,7 @@ const MenuRadioItem = /*#__PURE__*/React.forwardRef(function MenuRadioItem(compo
|
|
|
1863
1860
|
setValue: setSelectedValue,
|
|
1864
1861
|
disabled: groupDisabled
|
|
1865
1862
|
} = useMenuRadioGroupContext();
|
|
1866
|
-
const
|
|
1867
|
-
const disabled = disabledProp || groupDisabled || rootDisabled;
|
|
1863
|
+
const disabled = groupDisabled || disabledProp;
|
|
1868
1864
|
const checked = selectedValue === value;
|
|
1869
1865
|
const {
|
|
1870
1866
|
getItemProps,
|
|
@@ -1886,7 +1882,7 @@ const MenuRadioItem = /*#__PURE__*/React.forwardRef(function MenuRadioItem(compo
|
|
|
1886
1882
|
}), [disabled, highlighted, checked]);
|
|
1887
1883
|
function handleClick(event) {
|
|
1888
1884
|
const details = createChangeEventDetails(itemPress, event.nativeEvent, undefined, {
|
|
1889
|
-
preventUnmountOnClose
|
|
1885
|
+
preventUnmountOnClose() {}
|
|
1890
1886
|
});
|
|
1891
1887
|
setSelectedValue(value, details);
|
|
1892
1888
|
}
|
|
@@ -1925,7 +1921,6 @@ const MenuRadioItemIndicator = /*#__PURE__*/React.forwardRef(function MenuRadioI
|
|
|
1925
1921
|
const indicatorRef = React.useRef(null);
|
|
1926
1922
|
const {
|
|
1927
1923
|
transitionStatus,
|
|
1928
|
-
mounted,
|
|
1929
1924
|
setMounted
|
|
1930
1925
|
} = useTransitionStatus(item.checked);
|
|
1931
1926
|
useOpenChangeComplete({
|
|
@@ -1951,7 +1946,7 @@ const MenuRadioItemIndicator = /*#__PURE__*/React.forwardRef(function MenuRadioI
|
|
|
1951
1946
|
'aria-hidden': true,
|
|
1952
1947
|
...elementProps
|
|
1953
1948
|
},
|
|
1954
|
-
enabled: keepMounted ||
|
|
1949
|
+
enabled: keepMounted || item.checked
|
|
1955
1950
|
});
|
|
1956
1951
|
return element;
|
|
1957
1952
|
});
|
|
@@ -1969,35 +1964,36 @@ function useMenubarContext(optional) {
|
|
|
1969
1964
|
|
|
1970
1965
|
const selectors = {
|
|
1971
1966
|
...popupStoreSelectors,
|
|
1972
|
-
disabled: state => state.parent.type === 'menubar' ? state.parent.context.disabled || state.disabled : state.disabled,
|
|
1973
|
-
modal: state => (state.parent.type === undefined || state.parent.type === 'context-menu') && (state.modal ?? true),
|
|
1974
|
-
openMethod: state => state.openMethod,
|
|
1975
|
-
allowMouseEnter: state => state.allowMouseEnter,
|
|
1976
|
-
highlightItemOnHover: state => state.highlightItemOnHover,
|
|
1977
|
-
|
|
1978
|
-
|
|
1967
|
+
disabled: createSelector(state => state.parent.type === 'menubar' ? state.parent.context.disabled || state.disabled : state.disabled),
|
|
1968
|
+
modal: createSelector(state => (state.parent.type === undefined || state.parent.type === 'context-menu') && (state.modal ?? true)),
|
|
1969
|
+
openMethod: createSelector(state => state.openMethod),
|
|
1970
|
+
allowMouseEnter: createSelector(state => state.allowMouseEnter),
|
|
1971
|
+
highlightItemOnHover: createSelector(state => state.highlightItemOnHover),
|
|
1972
|
+
stickIfOpen: createSelector(state => state.stickIfOpen),
|
|
1973
|
+
parent: createSelector(state => state.parent),
|
|
1974
|
+
rootId: createSelector(state => {
|
|
1979
1975
|
if (state.parent.type === 'menu') {
|
|
1980
1976
|
return state.parent.store.select('rootId');
|
|
1981
1977
|
}
|
|
1982
1978
|
return state.parent.type !== undefined ? state.parent.context.rootId : state.rootId;
|
|
1983
|
-
},
|
|
1984
|
-
activeIndex: state => state.activeIndex,
|
|
1985
|
-
isActive: (state, itemIndex) => state.activeIndex === itemIndex,
|
|
1986
|
-
hoverEnabled: state => state.hoverEnabled,
|
|
1987
|
-
instantType: state => state.instantType,
|
|
1988
|
-
lastOpenChangeReason: state => state.openChangeReason,
|
|
1989
|
-
floatingTreeRoot: state => {
|
|
1979
|
+
}),
|
|
1980
|
+
activeIndex: createSelector(state => state.activeIndex),
|
|
1981
|
+
isActive: createSelector((state, itemIndex) => state.activeIndex === itemIndex),
|
|
1982
|
+
hoverEnabled: createSelector(state => state.hoverEnabled),
|
|
1983
|
+
instantType: createSelector(state => state.instantType),
|
|
1984
|
+
lastOpenChangeReason: createSelector(state => state.openChangeReason),
|
|
1985
|
+
floatingTreeRoot: createSelector(state => {
|
|
1990
1986
|
if (state.parent.type === 'menu') {
|
|
1991
1987
|
return state.parent.store.select('floatingTreeRoot');
|
|
1992
1988
|
}
|
|
1993
1989
|
return state.floatingTreeRoot;
|
|
1994
|
-
},
|
|
1995
|
-
floatingNodeId: state => state.floatingNodeId,
|
|
1996
|
-
floatingParentNodeId: state => state.floatingParentNodeId,
|
|
1997
|
-
itemProps: state => state.itemProps,
|
|
1998
|
-
closeDelay: state => state.closeDelay,
|
|
1999
|
-
|
|
2000
|
-
keyboardEventRelay: state => {
|
|
1990
|
+
}),
|
|
1991
|
+
floatingNodeId: createSelector(state => state.floatingNodeId),
|
|
1992
|
+
floatingParentNodeId: createSelector(state => state.floatingParentNodeId),
|
|
1993
|
+
itemProps: createSelector(state => state.itemProps),
|
|
1994
|
+
closeDelay: createSelector(state => state.closeDelay),
|
|
1995
|
+
hasViewport: createSelector(state => state.hasViewport),
|
|
1996
|
+
keyboardEventRelay: createSelector(state => {
|
|
2001
1997
|
if (state.keyboardEventRelay) {
|
|
2002
1998
|
return state.keyboardEventRelay;
|
|
2003
1999
|
}
|
|
@@ -2005,23 +2001,33 @@ const selectors = {
|
|
|
2005
2001
|
return state.parent.store.select('keyboardEventRelay');
|
|
2006
2002
|
}
|
|
2007
2003
|
return undefined;
|
|
2008
|
-
}
|
|
2004
|
+
})
|
|
2009
2005
|
};
|
|
2010
|
-
|
|
2011
|
-
/**
|
|
2012
|
-
* The store view that detached handle-backed triggers read from. Both the real `MenuStore` and the
|
|
2013
|
-
* inert fallback store satisfy it, so a trigger can read from whichever store the handle currently
|
|
2014
|
-
* exposes. Narrowed to the members a trigger actually uses — the trigger-data members plus `setOpen`
|
|
2015
|
-
* (called by the focus guards) — so the exposed surface can't bypass the open-change pipeline; on
|
|
2016
|
-
* the detached fallback store every one of these mutations is a no-op.
|
|
2017
|
-
*/
|
|
2018
|
-
|
|
2019
2006
|
class MenuStore extends ReactStore {
|
|
2020
2007
|
constructor(initialState) {
|
|
2021
2008
|
super({
|
|
2022
2009
|
...createInitialState(),
|
|
2023
2010
|
...initialState
|
|
2024
|
-
},
|
|
2011
|
+
}, {
|
|
2012
|
+
positionerRef: /*#__PURE__*/React.createRef(),
|
|
2013
|
+
popupRef: /*#__PURE__*/React.createRef(),
|
|
2014
|
+
typingRef: {
|
|
2015
|
+
current: false
|
|
2016
|
+
},
|
|
2017
|
+
itemDomElements: {
|
|
2018
|
+
current: []
|
|
2019
|
+
},
|
|
2020
|
+
itemLabels: {
|
|
2021
|
+
current: []
|
|
2022
|
+
},
|
|
2023
|
+
allowMouseUpTriggerRef: {
|
|
2024
|
+
current: false
|
|
2025
|
+
},
|
|
2026
|
+
triggerFocusTargetRef: /*#__PURE__*/React.createRef(),
|
|
2027
|
+
beforeContentFocusGuardRef: /*#__PURE__*/React.createRef(),
|
|
2028
|
+
onOpenChangeComplete: undefined,
|
|
2029
|
+
triggerElements: new PopupTriggerMap()
|
|
2030
|
+
}, selectors);
|
|
2025
2031
|
|
|
2026
2032
|
// Set up propagation of state from parent menu if applicable.
|
|
2027
2033
|
this.unsubscribeParentListener = this.observe('parent', parent => {
|
|
@@ -2057,44 +2063,15 @@ class MenuStore extends ReactStore {
|
|
|
2057
2063
|
eventDetails
|
|
2058
2064
|
});
|
|
2059
2065
|
}
|
|
2066
|
+
static useStore(externalStore, initialState) {
|
|
2067
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
2068
|
+
const internalStore = useRefWithInit(() => {
|
|
2069
|
+
return new MenuStore(initialState);
|
|
2070
|
+
}).current;
|
|
2071
|
+
return externalStore ?? internalStore;
|
|
2072
|
+
}
|
|
2060
2073
|
unsubscribeParentListener = null;
|
|
2061
2074
|
}
|
|
2062
|
-
|
|
2063
|
-
/**
|
|
2064
|
-
* Creates the inert fallback store used by detached handle-backed triggers while no `Menu.Root` is
|
|
2065
|
-
* attached. It preserves a menu-specific trigger registry in context so detached triggers can
|
|
2066
|
-
* register before migrating to the live root store. `setOpen` is a no-op (matching the inert
|
|
2067
|
-
* reads/writes of `NullStore`), so a trigger can hand the store to focus-guard helpers that expect
|
|
2068
|
-
* `setOpen` without it ever taking effect while detached.
|
|
2069
|
-
*/
|
|
2070
|
-
function createNullMenuStore() {
|
|
2071
|
-
const store = new NullStore(Object.freeze(createInitialState()), Object.freeze(createInitialContext()), selectors);
|
|
2072
|
-
return Object.assign(store, {
|
|
2073
|
-
setOpen: NOOP
|
|
2074
|
-
});
|
|
2075
|
-
}
|
|
2076
|
-
function createInitialContext() {
|
|
2077
|
-
return {
|
|
2078
|
-
positionerRef: /*#__PURE__*/React.createRef(),
|
|
2079
|
-
popupRef: /*#__PURE__*/React.createRef(),
|
|
2080
|
-
typingRef: {
|
|
2081
|
-
current: false
|
|
2082
|
-
},
|
|
2083
|
-
itemDomElements: {
|
|
2084
|
-
current: []
|
|
2085
|
-
},
|
|
2086
|
-
itemLabels: {
|
|
2087
|
-
current: []
|
|
2088
|
-
},
|
|
2089
|
-
allowMouseUpTriggerRef: {
|
|
2090
|
-
current: false
|
|
2091
|
-
},
|
|
2092
|
-
triggerFocusTargetRef: /*#__PURE__*/React.createRef(),
|
|
2093
|
-
beforeContentFocusGuardRef: /*#__PURE__*/React.createRef(),
|
|
2094
|
-
onOpenChangeComplete: undefined,
|
|
2095
|
-
triggerElements: new PopupTriggerMap()
|
|
2096
|
-
};
|
|
2097
|
-
}
|
|
2098
2075
|
function createInitialState() {
|
|
2099
2076
|
return {
|
|
2100
2077
|
...createInitialPopupStoreState(),
|
|
@@ -2103,6 +2080,7 @@ function createInitialState() {
|
|
|
2103
2080
|
openMethod: null,
|
|
2104
2081
|
allowMouseEnter: false,
|
|
2105
2082
|
highlightItemOnHover: true,
|
|
2083
|
+
stickIfOpen: true,
|
|
2106
2084
|
parent: {
|
|
2107
2085
|
type: undefined
|
|
2108
2086
|
},
|
|
@@ -2117,7 +2095,7 @@ function createInitialState() {
|
|
|
2117
2095
|
itemProps: EMPTY_OBJECT,
|
|
2118
2096
|
keyboardEventRelay: undefined,
|
|
2119
2097
|
closeDelay: 0,
|
|
2120
|
-
|
|
2098
|
+
hasViewport: false
|
|
2121
2099
|
};
|
|
2122
2100
|
}
|
|
2123
2101
|
|
|
@@ -2176,13 +2154,14 @@ const MenuRoot = fastComponent(function MenuRoot(props) {
|
|
|
2176
2154
|
type: undefined
|
|
2177
2155
|
};
|
|
2178
2156
|
}, [contextMenuContext, parentMenuRootContext, menubarContext, isSubmenu]);
|
|
2179
|
-
const store =
|
|
2157
|
+
const store = MenuStore.useStore(handle?.store, {
|
|
2180
2158
|
open: defaultOpen,
|
|
2181
2159
|
openProp,
|
|
2182
2160
|
activeTriggerId: defaultTriggerIdProp,
|
|
2183
2161
|
triggerIdProp,
|
|
2184
2162
|
parent: parentFromContext
|
|
2185
2163
|
});
|
|
2164
|
+
useInitialOpenSync(store, openProp, defaultOpen, defaultTriggerIdProp);
|
|
2186
2165
|
store.useControlledProp('openProp', openProp);
|
|
2187
2166
|
store.useControlledProp('triggerIdProp', triggerIdProp);
|
|
2188
2167
|
store.useContextCallback('onOpenChangeComplete', onOpenChangeComplete);
|
|
@@ -2227,7 +2206,10 @@ const MenuRoot = fastComponent(function MenuRoot(props) {
|
|
|
2227
2206
|
const {
|
|
2228
2207
|
forceUnmount
|
|
2229
2208
|
} = useOpenStateTransitions(open, store, () => {
|
|
2230
|
-
store.
|
|
2209
|
+
store.update({
|
|
2210
|
+
allowMouseEnter: false,
|
|
2211
|
+
stickIfOpen: true
|
|
2212
|
+
});
|
|
2231
2213
|
});
|
|
2232
2214
|
useIsoLayoutEffect(() => {
|
|
2233
2215
|
if (contextMenuContext && !parentMenuRootContext) {
|
|
@@ -2275,12 +2257,6 @@ const MenuRoot = fastComponent(function MenuRoot(props) {
|
|
|
2275
2257
|
}, [open, hoverEnabled, store]);
|
|
2276
2258
|
const setOpen = useStableCallback((nextOpen, eventDetails) => {
|
|
2277
2259
|
const reason = eventDetails.reason;
|
|
2278
|
-
|
|
2279
|
-
// Read the store directly, as relayed tree events and stale hover timers can request
|
|
2280
|
-
// a close after the state changed but before this component re-rendered.
|
|
2281
|
-
if (!nextOpen && !store.select('open')) {
|
|
2282
|
-
return;
|
|
2283
|
-
}
|
|
2284
2260
|
if (open === nextOpen && eventDetails.trigger === activeTriggerElement && lastOpenChangeReason === reason) {
|
|
2285
2261
|
return;
|
|
2286
2262
|
}
|
|
@@ -2313,17 +2289,13 @@ const MenuRoot = fastComponent(function MenuRoot(props) {
|
|
|
2313
2289
|
allowTouchToCloseRef.current = true;
|
|
2314
2290
|
allowTouchToCloseTimeout.clear();
|
|
2315
2291
|
}
|
|
2316
|
-
|
|
2317
|
-
// Keyboard and assistive-technology activations produce `detail === 0` clicks;
|
|
2318
|
-
// mouse-gesture clicks (including the synthesized drag-release click from
|
|
2319
|
-
// `useMenuItemCommonProps`) carry `detail >= 1`.
|
|
2320
|
-
const isKeyboardClick = (reason === triggerPress || reason === itemPress) && nativeEvent.detail === 0;
|
|
2292
|
+
const isKeyboardClick = (reason === triggerPress || reason === itemPress) && nativeEvent.detail === 0 && nativeEvent?.isTrusted;
|
|
2321
2293
|
const isDismissClose = !nextOpen && (reason === escapeKey || reason == null);
|
|
2322
2294
|
const updatedState = {
|
|
2323
2295
|
open: nextOpen,
|
|
2324
2296
|
openChangeReason: reason
|
|
2325
2297
|
};
|
|
2326
|
-
openEventRef.current = eventDetails.event;
|
|
2298
|
+
openEventRef.current = eventDetails.event ?? null;
|
|
2327
2299
|
setPopupOpenState(updatedState, nextOpen, eventDetails.trigger, shouldPreventUnmountOnClose());
|
|
2328
2300
|
store.update(updatedState);
|
|
2329
2301
|
if (parent.type === 'menubar' && (reason === triggerFocus || reason === focusOut || reason === triggerHover || reason === listNavigation || reason === siblingOpen)) {
|
|
@@ -2341,11 +2313,7 @@ const MenuRoot = fastComponent(function MenuRoot(props) {
|
|
|
2341
2313
|
onOpenChange: setOpen
|
|
2342
2314
|
});
|
|
2343
2315
|
const floatingEvents = floatingRootContext.context.events;
|
|
2344
|
-
|
|
2345
|
-
// Registered in a layout effect (not a passive one) so `setOpen` emits from imperative
|
|
2346
|
-
// `MenuHandle.open()` calls made in the same commit this root mounts — e.g. from another layout
|
|
2347
|
-
// effect during a route-transition handoff — are received instead of being silently dropped.
|
|
2348
|
-
useIsoLayoutEffect(() => {
|
|
2316
|
+
React.useEffect(() => {
|
|
2349
2317
|
const handleSetOpenEvent = ({
|
|
2350
2318
|
open: nextOpen,
|
|
2351
2319
|
eventDetails
|
|
@@ -2474,14 +2442,11 @@ const MenuRoot = fastComponent(function MenuRoot(props) {
|
|
|
2474
2442
|
store,
|
|
2475
2443
|
parent: parentFromContext
|
|
2476
2444
|
}), [store, parentFromContext]);
|
|
2477
|
-
const content = /*#__PURE__*/
|
|
2445
|
+
const content = /*#__PURE__*/jsx(MenuRootContext.Provider, {
|
|
2478
2446
|
value: context,
|
|
2479
|
-
children:
|
|
2480
|
-
handle: handle,
|
|
2481
|
-
store: store
|
|
2482
|
-
}), typeof children === 'function' ? children({
|
|
2447
|
+
children: typeof children === 'function' ? children({
|
|
2483
2448
|
payload
|
|
2484
|
-
}) : children
|
|
2449
|
+
}) : children
|
|
2485
2450
|
});
|
|
2486
2451
|
if (parent.type === undefined || parent.type === 'context-menu') {
|
|
2487
2452
|
// set up a FloatingTree to provide the context to nested menus
|
|
@@ -2493,15 +2458,6 @@ const MenuRoot = fastComponent(function MenuRoot(props) {
|
|
|
2493
2458
|
return content;
|
|
2494
2459
|
});
|
|
2495
2460
|
if (process.env.NODE_ENV !== "production") MenuRoot.displayName = "MenuRoot";
|
|
2496
|
-
function useMenuRootStore(initialState) {
|
|
2497
|
-
// The store is owned by this Root instance and created exactly once. It is not tied to the handle:
|
|
2498
|
-
// the handle attaches to it, so swapping the handle re-attaches rather than recreating state.
|
|
2499
|
-
// Default values are only initial values; controlled values and root state are synced after creation.
|
|
2500
|
-
// Unlike other popups, Menu wires its floating root context separately (it relays open changes
|
|
2501
|
-
// through an event).
|
|
2502
|
-
const store = useRefWithInit(() => new MenuStore(initialState)).current;
|
|
2503
|
-
return store;
|
|
2504
|
-
}
|
|
2505
2461
|
|
|
2506
2462
|
/**
|
|
2507
2463
|
* Groups all parts of a submenu.
|
|
@@ -2558,6 +2514,9 @@ function useCompositeItem(params = {}) {
|
|
|
2558
2514
|
};
|
|
2559
2515
|
}
|
|
2560
2516
|
|
|
2517
|
+
/**
|
|
2518
|
+
* @internal
|
|
2519
|
+
*/
|
|
2561
2520
|
function CompositeItem(componentProps) {
|
|
2562
2521
|
const {
|
|
2563
2522
|
render,
|
|
@@ -2579,8 +2538,7 @@ function CompositeItem(componentProps) {
|
|
|
2579
2538
|
});
|
|
2580
2539
|
return useRenderElement(tag, componentProps, {
|
|
2581
2540
|
state,
|
|
2582
|
-
|
|
2583
|
-
ref: [compositeRef, ...refs],
|
|
2541
|
+
ref: [...refs, compositeRef],
|
|
2584
2542
|
props: [compositeProps, ...props, elementProps],
|
|
2585
2543
|
stateAttributesMapping
|
|
2586
2544
|
});
|
|
@@ -2588,7 +2546,7 @@ function CompositeItem(componentProps) {
|
|
|
2588
2546
|
|
|
2589
2547
|
function findRootOwnerId(node) {
|
|
2590
2548
|
if (isHTMLElement(node) && node.hasAttribute('data-rootownerid')) {
|
|
2591
|
-
return node.getAttribute('data-rootownerid');
|
|
2549
|
+
return node.getAttribute('data-rootownerid') ?? undefined;
|
|
2592
2550
|
}
|
|
2593
2551
|
if (isLastTraversableNode(node)) {
|
|
2594
2552
|
return undefined;
|
|
@@ -2680,6 +2638,14 @@ function useMixedToggleClickHandler(params) {
|
|
|
2680
2638
|
}, [enabled, mouseDownAction, open]);
|
|
2681
2639
|
}
|
|
2682
2640
|
|
|
2641
|
+
const BOUNDARY_OFFSET = 2;
|
|
2642
|
+
|
|
2643
|
+
/**
|
|
2644
|
+
* A button that opens the menu.
|
|
2645
|
+
* Renders a `<button>` element.
|
|
2646
|
+
*
|
|
2647
|
+
* Documentation: [Base UI Menu](https://base-ui.com/react/components/menu)
|
|
2648
|
+
*/
|
|
2683
2649
|
const MenuTrigger = fastComponentRef(function MenuTrigger(componentProps, forwardedRef) {
|
|
2684
2650
|
const {
|
|
2685
2651
|
render,
|
|
@@ -2696,8 +2662,7 @@ const MenuTrigger = fastComponentRef(function MenuTrigger(componentProps, forwar
|
|
|
2696
2662
|
...elementProps
|
|
2697
2663
|
} = componentProps;
|
|
2698
2664
|
const rootContext = useMenuRootContext(true);
|
|
2699
|
-
const
|
|
2700
|
-
const store = handleStore ?? rootContext?.store;
|
|
2665
|
+
const store = handle?.store ?? rootContext?.store;
|
|
2701
2666
|
if (!store) {
|
|
2702
2667
|
throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: <Menu.Trigger> must be either used within a <Menu.Root> component or provided with a handle.' : formatErrorMessage(85));
|
|
2703
2668
|
}
|
|
@@ -2757,7 +2722,8 @@ const MenuTrigger = fastComponentRef(function MenuTrigger(componentProps, forwar
|
|
|
2757
2722
|
if (mouseUpTarget != null && findRootOwnerId(mouseUpTarget) === store.select('rootId')) {
|
|
2758
2723
|
return;
|
|
2759
2724
|
}
|
|
2760
|
-
|
|
2725
|
+
const bounds = getPseudoElementBounds(triggerRef.current);
|
|
2726
|
+
if (mouseEvent.clientX >= bounds.left - BOUNDARY_OFFSET && mouseEvent.clientX <= bounds.right + BOUNDARY_OFFSET && mouseEvent.clientY >= bounds.top - BOUNDARY_OFFSET && mouseEvent.clientY <= bounds.bottom + BOUNDARY_OFFSET) {
|
|
2761
2727
|
return;
|
|
2762
2728
|
}
|
|
2763
2729
|
floatingTreeRoot.events.emit('close', {
|
|
@@ -2776,7 +2742,7 @@ const MenuTrigger = fastComponentRef(function MenuTrigger(componentProps, forwar
|
|
|
2776
2742
|
const parentMenubarHasSubmenuOpen = isInMenubar && parent.context.hasSubmenuOpen;
|
|
2777
2743
|
const openOnHover = openOnHoverProp ?? parentMenubarHasSubmenuOpen;
|
|
2778
2744
|
const hoverProps = useHoverReferenceInteraction(floatingRootContext, {
|
|
2779
|
-
enabled: openOnHover && !disabled && (!isInMenubar || parentMenubarHasSubmenuOpen && !isMountedByThisTrigger),
|
|
2745
|
+
enabled: openOnHover && !disabled && parent.type !== 'context-menu' && (!isInMenubar || parentMenubarHasSubmenuOpen && !isMountedByThisTrigger),
|
|
2780
2746
|
handleClose: safePolygon({
|
|
2781
2747
|
blockPointerEvents: !isInMenubar
|
|
2782
2748
|
}),
|
|
@@ -2797,7 +2763,7 @@ const MenuTrigger = fastComponentRef(function MenuTrigger(componentProps, forwar
|
|
|
2797
2763
|
// only when `isOpenedByThisTrigger` changes.
|
|
2798
2764
|
const stickIfOpen = useStickIfOpen(isOpenedByThisTrigger, store.select('lastOpenChangeReason'));
|
|
2799
2765
|
const click = useClick(floatingRootContext, {
|
|
2800
|
-
enabled: !disabled,
|
|
2766
|
+
enabled: !disabled && parent.type !== 'context-menu',
|
|
2801
2767
|
event: isOpenedByThisTrigger && isInMenubar ? 'click' : 'mousedown',
|
|
2802
2768
|
toggle: true,
|
|
2803
2769
|
ignoreMouse: false,
|
|
@@ -2892,7 +2858,7 @@ function useStickIfOpen(open, openReason) {
|
|
|
2892
2858
|
const stickIfOpenTimeout = useTimeout();
|
|
2893
2859
|
const [stickIfOpen, setStickIfOpen] = React.useState(false);
|
|
2894
2860
|
useIsoLayoutEffect(() => {
|
|
2895
|
-
if (open && openReason ===
|
|
2861
|
+
if (open && openReason === 'trigger-hover') {
|
|
2896
2862
|
// Only allow "patient" clicks to close the menu if it's open.
|
|
2897
2863
|
// If they clicked within 500ms of the menu opening, keep it open.
|
|
2898
2864
|
setStickIfOpen(true);
|
|
@@ -2907,6 +2873,8 @@ function useStickIfOpen(open, openReason) {
|
|
|
2907
2873
|
return stickIfOpen;
|
|
2908
2874
|
}
|
|
2909
2875
|
function useMenuParent() {
|
|
2876
|
+
const contextMenuContext = useContextMenuRootContext(true);
|
|
2877
|
+
const parentContext = useMenuRootContext(true);
|
|
2910
2878
|
const menubarContext = useMenubarContext(true);
|
|
2911
2879
|
const parent = React.useMemo(() => {
|
|
2912
2880
|
if (menubarContext) {
|
|
@@ -2915,17 +2883,23 @@ function useMenuParent() {
|
|
|
2915
2883
|
context: menubarContext
|
|
2916
2884
|
};
|
|
2917
2885
|
}
|
|
2886
|
+
|
|
2887
|
+
// Ensure this is not a Menu nested inside ContextMenu.Trigger.
|
|
2888
|
+
// ContextMenu parentContext is always undefined as ContextMenu.Root is instantiated with
|
|
2889
|
+
// <MenuRootContext.Provider value={undefined}>
|
|
2890
|
+
if (contextMenuContext && !parentContext) {
|
|
2891
|
+
return {
|
|
2892
|
+
type: 'context-menu',
|
|
2893
|
+
context: contextMenuContext
|
|
2894
|
+
};
|
|
2895
|
+
}
|
|
2918
2896
|
return {
|
|
2919
2897
|
type: undefined
|
|
2920
2898
|
};
|
|
2921
|
-
}, [menubarContext]);
|
|
2899
|
+
}, [contextMenuContext, parentContext, menubarContext]);
|
|
2922
2900
|
return parent;
|
|
2923
2901
|
}
|
|
2924
2902
|
|
|
2925
|
-
const VOICE_OVER_EXPANDED_PROPS = {
|
|
2926
|
-
'aria-expanded': undefined
|
|
2927
|
-
};
|
|
2928
|
-
|
|
2929
2903
|
/**
|
|
2930
2904
|
* A menu item that opens a submenu.
|
|
2931
2905
|
* Renders a `<div>` element.
|
|
@@ -2946,12 +2920,7 @@ const MenuSubmenuTrigger = /*#__PURE__*/React.forwardRef(function MenuSubmenuTri
|
|
|
2946
2920
|
disabled: disabledProp = false,
|
|
2947
2921
|
...elementProps
|
|
2948
2922
|
} = componentProps;
|
|
2949
|
-
const submenuRootContext = useMenuSubmenuRootContext();
|
|
2950
|
-
if (!submenuRootContext?.parentMenu) {
|
|
2951
|
-
throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: <Menu.SubmenuTrigger> must be placed in <Menu.SubmenuRoot>.' : formatErrorMessage(37));
|
|
2952
|
-
}
|
|
2953
2923
|
const listItem = useCompositeListItem({
|
|
2954
|
-
guess: true,
|
|
2955
2924
|
label
|
|
2956
2925
|
});
|
|
2957
2926
|
const menuPositionerContext = useMenuPositionerContext();
|
|
@@ -2980,6 +2949,10 @@ const MenuSubmenuTrigger = /*#__PURE__*/React.forwardRef(function MenuSubmenuTri
|
|
|
2980
2949
|
triggerElementRef.current = el;
|
|
2981
2950
|
store.set('activeTriggerElement', el);
|
|
2982
2951
|
}, [store]);
|
|
2952
|
+
const submenuRootContext = useMenuSubmenuRootContext();
|
|
2953
|
+
if (!submenuRootContext?.parentMenu) {
|
|
2954
|
+
throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: <Menu.SubmenuTrigger> must be placed in <Menu.SubmenuRoot>.' : formatErrorMessage(37));
|
|
2955
|
+
}
|
|
2983
2956
|
store.useSyncedValue('closeDelay', closeDelay);
|
|
2984
2957
|
const parentMenuStore = submenuRootContext.parentMenu;
|
|
2985
2958
|
const rootDisabled = store.useState('disabled');
|
|
@@ -2987,7 +2960,7 @@ const MenuSubmenuTrigger = /*#__PURE__*/React.forwardRef(function MenuSubmenuTri
|
|
|
2987
2960
|
const disabled = disabledProp || rootDisabled || parentDisabled;
|
|
2988
2961
|
if (process.env.NODE_ENV !== 'production') {
|
|
2989
2962
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
2990
|
-
|
|
2963
|
+
useIsoLayoutEffect(() => {
|
|
2991
2964
|
const element = triggerElementRef.current;
|
|
2992
2965
|
if (element && isElementDisabled(element) && !disabled) {
|
|
2993
2966
|
const ownerStackMessage = SafeReact.captureOwnerStack?.() || '';
|
|
@@ -3035,10 +3008,7 @@ const MenuSubmenuTrigger = /*#__PURE__*/React.forwardRef(function MenuSubmenuTri
|
|
|
3035
3008
|
shouldOpen: delay > 0 ? () => parentMenuStore.select('allowMouseEnter') : undefined,
|
|
3036
3009
|
triggerElementRef,
|
|
3037
3010
|
externalTree: floatingTreeRoot,
|
|
3038
|
-
isClosing: () => store.select('transitionStatus') === 'ending'
|
|
3039
|
-
// Chrome can drop the trigger's `mouseleave` during a fast pointer sweep,
|
|
3040
|
-
// leaving a stale submenu open (see #5152) — cancel from `mouseout` too.
|
|
3041
|
-
guardStaleOpen: true
|
|
3011
|
+
isClosing: () => store.select('transitionStatus') === 'ending'
|
|
3042
3012
|
});
|
|
3043
3013
|
const click = useClick(floatingRootContext, {
|
|
3044
3014
|
enabled: !disabled,
|
|
@@ -3055,22 +3025,10 @@ const MenuSubmenuTrigger = /*#__PURE__*/React.forwardRef(function MenuSubmenuTri
|
|
|
3055
3025
|
highlighted,
|
|
3056
3026
|
open
|
|
3057
3027
|
};
|
|
3058
|
-
const openMethod = store.useState('openMethod');
|
|
3059
|
-
const lastOpenChangeReason = store.useState('lastOpenChangeReason');
|
|
3060
|
-
// Arrow keys open the submenu through list navigation without dispatching a click, so
|
|
3061
|
-
// `openMethod` stays null there; Enter and Space do dispatch one and report `keyboard`.
|
|
3062
|
-
const openedByKeyboard = lastOpenChangeReason === listNavigation || openMethod === 'keyboard';
|
|
3063
|
-
const shouldOmitExpanded = open && openedByKeyboard && voiceOver;
|
|
3064
3028
|
const element = useRenderElement('div', componentProps, {
|
|
3065
3029
|
state,
|
|
3066
3030
|
stateAttributesMapping: triggerOpenStateMapping,
|
|
3067
|
-
props: [localInteractionProps, hoverProps, rootTriggerProps, itemProps,
|
|
3068
|
-
// Opening a submenu changes the trigger's expanded state while the trigger still holds
|
|
3069
|
-
// focus, and VoiceOver announces that state change instead of the submenu item that focus
|
|
3070
|
-
// moves to a moment later, so the first item is never announced. Dropping the state while
|
|
3071
|
-
// the submenu is open avoids the announcement without claiming the submenu is collapsed;
|
|
3072
|
-
// `aria-haspopup` still conveys that the item opens a submenu.
|
|
3073
|
-
shouldOmitExpanded ? VOICE_OVER_EXPANDED_PROPS : undefined, {
|
|
3031
|
+
props: [localInteractionProps, hoverProps, rootTriggerProps, itemProps, {
|
|
3074
3032
|
'aria-controls': popupId,
|
|
3075
3033
|
tabIndex: open || highlighted ? 0 : -1,
|
|
3076
3034
|
onBlur() {
|
|
@@ -3085,4 +3043,4 @@ const MenuSubmenuTrigger = /*#__PURE__*/React.forwardRef(function MenuSubmenuTri
|
|
|
3085
3043
|
});
|
|
3086
3044
|
if (process.env.NODE_ENV !== "production") MenuSubmenuTrigger.displayName = "MenuSubmenuTrigger";
|
|
3087
3045
|
|
|
3088
|
-
export { MenuTrigger as M, REGULAR_ITEM as R, MenuLinkItem as a, MenuItem as b, MenuRadioItem as c, MenuRadioItemIndicator as d, MenuSubmenuTrigger as e, MenuRoot as f, MenuPortal as g, MenuBackdrop as h, MenuPositioner as i, MenuPopup as j, MenuRadioGroup as k, MenuGroup as l, MenuSubmenuRoot as m, MenuGroupLabel as n, useMenuPositionerContext as o, useMenuItem as p, itemMapping as q,
|
|
3046
|
+
export { MenuTrigger as M, REGULAR_ITEM as R, MenuLinkItem as a, MenuItem as b, MenuRadioItem as c, MenuRadioItemIndicator as d, MenuSubmenuTrigger as e, MenuRoot as f, MenuPortal as g, MenuBackdrop as h, MenuPositioner as i, MenuPopup as j, MenuRadioGroup as k, MenuGroup as l, MenuSubmenuRoot as m, MenuGroupLabel as n, useMenuPositionerContext as o, useMenuItem as p, itemMapping as q, MenuStore as r, useMenuRootContext as u };
|