New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@react-aria/menu

Package Overview
Dependencies
Maintainers
2
Versions
914
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@react-aria/menu - npm Package Compare versions

Comparing version

to
3.0.0-nightly-993de98ad-241210

dist/utils.main.js

11

dist/types.d.ts

@@ -6,2 +6,3 @@ import { AriaMenuProps, MenuTriggerType } from "@react-types/menu";

import { MenuTriggerState, SubmenuTriggerState } from "@react-stately/menu";
import { SelectionManager } from "@react-stately/selection";
import { ReactNode } from "react";

@@ -21,2 +22,6 @@ import { AriaPopoverProps, OverlayProps } from "@react-aria/overlays";

keyboardDelegate?: KeyboardDelegate;
/**
* Whether the menu items should use virtual focus instead of being focused directly.
*/
shouldUseVirtualFocus?: boolean;
}

@@ -83,3 +88,3 @@ /**

/** The unique key for the menu item. */
key?: Key;
key: Key;
/**

@@ -108,2 +113,4 @@ * Handler that is called when the menu should close after selecting an item.

'aria-controls'?: string;
/** Override of the selection manager. By default, `state.selectionManager` is used. */
selectionManager?: SelectionManager;
}

@@ -157,3 +164,3 @@ /**

}
interface SubmenuTriggerProps extends AriaMenuItemProps {
interface SubmenuTriggerProps extends Omit<AriaMenuItemProps, 'key'> {
/** Whether the submenu trigger is in an expanded state. */

@@ -160,0 +167,0 @@ isOpen: boolean;

12

dist/useMenu.main.js

@@ -0,1 +1,2 @@

var $815e346b11b84016$exports = require("./utils.main.js");
var $6CumN$reactariautils = require("@react-aria/utils");

@@ -9,3 +10,2 @@ var $6CumN$reactariaselection = require("@react-aria/selection");

$parcel$export(module.exports, "menuData", () => $a3815f0132802737$export$6f49b4016bfc8d56);
$parcel$export(module.exports, "useMenu", () => $a3815f0132802737$export$38eaa17faae8f579);

@@ -24,3 +24,3 @@ /*

const $a3815f0132802737$export$6f49b4016bfc8d56 = new WeakMap();
function $a3815f0132802737$export$38eaa17faae8f579(props, state, ref) {

@@ -41,5 +41,6 @@ let { shouldFocusWrap: shouldFocusWrap = true, onKeyDown: onKeyDown, onKeyUp: onKeyUp, ...otherProps } = props;

});
$a3815f0132802737$export$6f49b4016bfc8d56.set(state, {
(0, $815e346b11b84016$exports.menuData).set(state, {
onClose: props.onClose,
onAction: props.onAction
onAction: props.onAction,
shouldUseVirtualFocus: props.shouldUseVirtualFocus
});

@@ -54,4 +55,5 @@ return {

onKeyDown: (e)=>{
var _listProps_onKeyDown;
// don't clear the menu selected keys if the user is presses escape since escape closes the menu
if (e.key !== 'Escape') listProps.onKeyDown(e);
if (e.key !== 'Escape' || props.shouldUseVirtualFocus) (_listProps_onKeyDown = listProps.onKeyDown) === null || _listProps_onKeyDown === void 0 ? void 0 : _listProps_onKeyDown.call(listProps, e);
}

@@ -58,0 +60,0 @@ })

@@ -0,1 +1,2 @@

import {menuData as $fc79756100351201$export$6f49b4016bfc8d56} from "./utils.module.js";
import {filterDOMProps as $ieN2F$filterDOMProps, mergeProps as $ieN2F$mergeProps} from "@react-aria/utils";

@@ -16,3 +17,3 @@ import {useSelectableList as $ieN2F$useSelectableList} from "@react-aria/selection";

const $d5336fe17ce95402$export$6f49b4016bfc8d56 = new WeakMap();
function $d5336fe17ce95402$export$38eaa17faae8f579(props, state, ref) {

@@ -33,5 +34,6 @@ let { shouldFocusWrap: shouldFocusWrap = true, onKeyDown: onKeyDown, onKeyUp: onKeyUp, ...otherProps } = props;

});
$d5336fe17ce95402$export$6f49b4016bfc8d56.set(state, {
(0, $fc79756100351201$export$6f49b4016bfc8d56).set(state, {
onClose: props.onClose,
onAction: props.onAction
onAction: props.onAction,
shouldUseVirtualFocus: props.shouldUseVirtualFocus
});

@@ -46,4 +48,5 @@ return {

onKeyDown: (e)=>{
var _listProps_onKeyDown;
// don't clear the menu selected keys if the user is presses escape since escape closes the menu
if (e.key !== 'Escape') listProps.onKeyDown(e);
if (e.key !== 'Escape' || props.shouldUseVirtualFocus) (_listProps_onKeyDown = listProps.onKeyDown) === null || _listProps_onKeyDown === void 0 ? void 0 : _listProps_onKeyDown.call(listProps, e);
}

@@ -55,3 +58,3 @@ })

export {$d5336fe17ce95402$export$6f49b4016bfc8d56 as menuData, $d5336fe17ce95402$export$38eaa17faae8f579 as useMenu};
export {$d5336fe17ce95402$export$38eaa17faae8f579 as useMenu};
//# sourceMappingURL=useMenu.module.js.map

@@ -1,2 +0,2 @@

var $a3815f0132802737$exports = require("./useMenu.main.js");
var $815e346b11b84016$exports = require("./utils.main.js");
var $byVdR$reactariautils = require("@react-aria/utils");

@@ -29,9 +29,10 @@ var $byVdR$reactstatelycollections = require("@react-stately/collections");

function $38191ed02615ec07$export$9d32628fc2aea7da(props, state, ref) {
let { id: id, key: key, closeOnSelect: closeOnSelect, isVirtualized: isVirtualized, 'aria-haspopup': hasPopup, onPressStart: pressStartProp, onPressUp: pressUpProp, onPress: onPress, onPressChange: onPressChange, onPressEnd: onPressEnd, onHoverStart: hoverStartProp, onHoverChange: onHoverChange, onHoverEnd: onHoverEnd, onKeyDown: onKeyDown, onKeyUp: onKeyUp, onFocus: onFocus, onFocusChange: onFocusChange, onBlur: onBlur } = props;
let { id: id, key: key, closeOnSelect: closeOnSelect, isVirtualized: isVirtualized, 'aria-haspopup': hasPopup, onPressStart: pressStartProp, onPressUp: pressUpProp, onPress: pressProp, onPressChange: onPressChange, onPressEnd: onPressEnd, onHoverStart: hoverStartProp, onHoverChange: onHoverChange, onHoverEnd: onHoverEnd, onKeyDown: onKeyDown, onKeyUp: onKeyUp, onFocus: onFocus, onFocusChange: onFocusChange, onBlur: onBlur, selectionManager: selectionManager = state.selectionManager } = props;
let isTrigger = !!hasPopup;
let isTriggerExpanded = isTrigger && props['aria-expanded'] === 'true';
var _props_isDisabled;
let isDisabled = (_props_isDisabled = props.isDisabled) !== null && _props_isDisabled !== void 0 ? _props_isDisabled : state.selectionManager.isDisabled(key);
let isDisabled = (_props_isDisabled = props.isDisabled) !== null && _props_isDisabled !== void 0 ? _props_isDisabled : selectionManager.isDisabled(key);
var _props_isSelected;
let isSelected = (_props_isSelected = props.isSelected) !== null && _props_isSelected !== void 0 ? _props_isSelected : state.selectionManager.isSelected(key);
let data = (0, $a3815f0132802737$exports.menuData).get(state);
let isSelected = (_props_isSelected = props.isSelected) !== null && _props_isSelected !== void 0 ? _props_isSelected : selectionManager.isSelected(key);
let data = (0, $815e346b11b84016$exports.menuData).get(state);
let item = state.collection.getItem(key);

@@ -50,8 +51,8 @@ let onClose = props.onClose || data.onClose;

}
if (e.target instanceof HTMLAnchorElement) router.open(e.target, e, item.props.href, item.props.routerOptions);
if (e.target instanceof HTMLAnchorElement && item) router.open(e.target, e, item.props.href, item.props.routerOptions);
};
let role = 'menuitem';
if (!isTrigger) {
if (state.selectionManager.selectionMode === 'single') role = 'menuitemradio';
else if (state.selectionManager.selectionMode === 'multiple') role = 'menuitemcheckbox';
if (selectionManager.selectionMode === 'single') role = 'menuitemradio';
else if (selectionManager.selectionMode === 'multiple') role = 'menuitemcheckbox';
}

@@ -75,3 +76,3 @@ let labelId = (0, $byVdR$reactariautils.useSlotId)();

};
if (state.selectionManager.selectionMode !== 'none' && !isTrigger) ariaProps['aria-checked'] = isSelected;
if (selectionManager.selectionMode !== 'none' && !isTrigger) ariaProps['aria-checked'] = isSelected;
if (isVirtualized) {

@@ -85,13 +86,26 @@ ariaProps['aria-posinset'] = item === null || item === void 0 ? void 0 : item.index;

};
let maybeClose = ()=>{
// Pressing a menu item should close by default in single selection mode but not multiple
// selection mode, except if overridden by the closeOnSelect prop.
if (!isTrigger && onClose && (closeOnSelect !== null && closeOnSelect !== void 0 ? closeOnSelect : selectionManager.selectionMode !== 'multiple' || selectionManager.isLink(key))) onClose();
};
let onPressUp = (e)=>{
if (e.pointerType !== 'keyboard') {
// If interacting with mouse, allow the user to mouse down on the trigger button,
// drag, and release over an item (matching native behavior).
if (e.pointerType === 'mouse') {
performAction(e);
// Pressing a menu item should close by default in single selection mode but not multiple
// selection mode, except if overridden by the closeOnSelect prop.
if (!isTrigger && onClose && (closeOnSelect !== null && closeOnSelect !== void 0 ? closeOnSelect : state.selectionManager.selectionMode !== 'multiple' || state.selectionManager.isLink(key))) onClose();
maybeClose();
}
pressUpProp === null || pressUpProp === void 0 ? void 0 : pressUpProp(e);
};
let onPress = (e)=>{
if (e.pointerType !== 'keyboard' && e.pointerType !== 'mouse') {
performAction(e);
maybeClose();
}
pressProp === null || pressProp === void 0 ? void 0 : pressProp(e);
};
let { itemProps: itemProps, isFocused: isFocused } = (0, $byVdR$reactariaselection.useSelectableItem)({
selectionManager: state.selectionManager,
id: id,
selectionManager: selectionManager,
key: key,

@@ -105,3 +119,4 @@ ref: ref,

// actions are performed on key down rather than key up.
linkBehavior: 'none'
linkBehavior: 'none',
shouldUseVirtualFocus: data.shouldUseVirtualFocus
});

@@ -119,5 +134,6 @@ let { pressProps: pressProps, isPressed: isPressed } = (0, $byVdR$reactariainteractions.usePress)({

onHoverStart (e) {
if (!(0, $byVdR$reactariainteractions.isFocusVisible)()) {
state.selectionManager.setFocused(true);
state.selectionManager.setFocusedKey(key);
// Hovering over an already expanded sub dialog trigger should keep focus in the dialog.
if (!(0, $byVdR$reactariainteractions.isFocusVisible)() && !(isTriggerExpanded && hasPopup === 'dialog')) {
selectionManager.setFocused(true);
selectionManager.setFocusedKey(key);
}

@@ -139,3 +155,3 @@ hoverStartProp === null || hoverStartProp === void 0 ? void 0 : hoverStartProp(e);

case ' ':
if (!isDisabled && state.selectionManager.selectionMode === 'none' && !isTrigger && closeOnSelect !== false && onClose) onClose();
if (!isDisabled && selectionManager.selectionMode === 'none' && !isTrigger && closeOnSelect !== false && onClose) onClose();
break;

@@ -159,5 +175,5 @@ case 'Enter':

});
let domProps = (0, $byVdR$reactariautils.filterDOMProps)(item.props);
let domProps = (0, $byVdR$reactariautils.filterDOMProps)(item === null || item === void 0 ? void 0 : item.props);
delete domProps.id;
let linkProps = (0, $byVdR$reactariautils.useLinkProps)(item.props);
let linkProps = (0, $byVdR$reactariautils.useLinkProps)(item === null || item === void 0 ? void 0 : item.props);
return {

@@ -170,3 +186,4 @@ menuItemProps: {

} : itemProps, pressProps, hoverProps, keyboardProps, focusProps),
tabIndex: itemProps.tabIndex != null ? -1 : undefined
// If a submenu is expanded, set the tabIndex to -1 so that shift tabbing goes out of the menu instead of the parent menu item.
tabIndex: itemProps.tabIndex != null && isTriggerExpanded ? -1 : itemProps.tabIndex
},

@@ -173,0 +190,0 @@ labelProps: {

@@ -1,2 +0,2 @@

import {menuData as $d5336fe17ce95402$export$6f49b4016bfc8d56} from "./useMenu.module.js";
import {menuData as $fc79756100351201$export$6f49b4016bfc8d56} from "./utils.module.js";
import {useRouter as $7Kjv5$useRouter, useSlotId as $7Kjv5$useSlotId, filterDOMProps as $7Kjv5$filterDOMProps, useLinkProps as $7Kjv5$useLinkProps, mergeProps as $7Kjv5$mergeProps} from "@react-aria/utils";

@@ -23,9 +23,10 @@ import {getItemCount as $7Kjv5$getItemCount} from "@react-stately/collections";

function $a2e5df62f93c7633$export$9d32628fc2aea7da(props, state, ref) {
let { id: id, key: key, closeOnSelect: closeOnSelect, isVirtualized: isVirtualized, 'aria-haspopup': hasPopup, onPressStart: pressStartProp, onPressUp: pressUpProp, onPress: onPress, onPressChange: onPressChange, onPressEnd: onPressEnd, onHoverStart: hoverStartProp, onHoverChange: onHoverChange, onHoverEnd: onHoverEnd, onKeyDown: onKeyDown, onKeyUp: onKeyUp, onFocus: onFocus, onFocusChange: onFocusChange, onBlur: onBlur } = props;
let { id: id, key: key, closeOnSelect: closeOnSelect, isVirtualized: isVirtualized, 'aria-haspopup': hasPopup, onPressStart: pressStartProp, onPressUp: pressUpProp, onPress: pressProp, onPressChange: onPressChange, onPressEnd: onPressEnd, onHoverStart: hoverStartProp, onHoverChange: onHoverChange, onHoverEnd: onHoverEnd, onKeyDown: onKeyDown, onKeyUp: onKeyUp, onFocus: onFocus, onFocusChange: onFocusChange, onBlur: onBlur, selectionManager: selectionManager = state.selectionManager } = props;
let isTrigger = !!hasPopup;
let isTriggerExpanded = isTrigger && props['aria-expanded'] === 'true';
var _props_isDisabled;
let isDisabled = (_props_isDisabled = props.isDisabled) !== null && _props_isDisabled !== void 0 ? _props_isDisabled : state.selectionManager.isDisabled(key);
let isDisabled = (_props_isDisabled = props.isDisabled) !== null && _props_isDisabled !== void 0 ? _props_isDisabled : selectionManager.isDisabled(key);
var _props_isSelected;
let isSelected = (_props_isSelected = props.isSelected) !== null && _props_isSelected !== void 0 ? _props_isSelected : state.selectionManager.isSelected(key);
let data = (0, $d5336fe17ce95402$export$6f49b4016bfc8d56).get(state);
let isSelected = (_props_isSelected = props.isSelected) !== null && _props_isSelected !== void 0 ? _props_isSelected : selectionManager.isSelected(key);
let data = (0, $fc79756100351201$export$6f49b4016bfc8d56).get(state);
let item = state.collection.getItem(key);

@@ -44,8 +45,8 @@ let onClose = props.onClose || data.onClose;

}
if (e.target instanceof HTMLAnchorElement) router.open(e.target, e, item.props.href, item.props.routerOptions);
if (e.target instanceof HTMLAnchorElement && item) router.open(e.target, e, item.props.href, item.props.routerOptions);
};
let role = 'menuitem';
if (!isTrigger) {
if (state.selectionManager.selectionMode === 'single') role = 'menuitemradio';
else if (state.selectionManager.selectionMode === 'multiple') role = 'menuitemcheckbox';
if (selectionManager.selectionMode === 'single') role = 'menuitemradio';
else if (selectionManager.selectionMode === 'multiple') role = 'menuitemcheckbox';
}

@@ -69,3 +70,3 @@ let labelId = (0, $7Kjv5$useSlotId)();

};
if (state.selectionManager.selectionMode !== 'none' && !isTrigger) ariaProps['aria-checked'] = isSelected;
if (selectionManager.selectionMode !== 'none' && !isTrigger) ariaProps['aria-checked'] = isSelected;
if (isVirtualized) {

@@ -79,13 +80,26 @@ ariaProps['aria-posinset'] = item === null || item === void 0 ? void 0 : item.index;

};
let maybeClose = ()=>{
// Pressing a menu item should close by default in single selection mode but not multiple
// selection mode, except if overridden by the closeOnSelect prop.
if (!isTrigger && onClose && (closeOnSelect !== null && closeOnSelect !== void 0 ? closeOnSelect : selectionManager.selectionMode !== 'multiple' || selectionManager.isLink(key))) onClose();
};
let onPressUp = (e)=>{
if (e.pointerType !== 'keyboard') {
// If interacting with mouse, allow the user to mouse down on the trigger button,
// drag, and release over an item (matching native behavior).
if (e.pointerType === 'mouse') {
performAction(e);
// Pressing a menu item should close by default in single selection mode but not multiple
// selection mode, except if overridden by the closeOnSelect prop.
if (!isTrigger && onClose && (closeOnSelect !== null && closeOnSelect !== void 0 ? closeOnSelect : state.selectionManager.selectionMode !== 'multiple' || state.selectionManager.isLink(key))) onClose();
maybeClose();
}
pressUpProp === null || pressUpProp === void 0 ? void 0 : pressUpProp(e);
};
let onPress = (e)=>{
if (e.pointerType !== 'keyboard' && e.pointerType !== 'mouse') {
performAction(e);
maybeClose();
}
pressProp === null || pressProp === void 0 ? void 0 : pressProp(e);
};
let { itemProps: itemProps, isFocused: isFocused } = (0, $7Kjv5$useSelectableItem)({
selectionManager: state.selectionManager,
id: id,
selectionManager: selectionManager,
key: key,

@@ -99,3 +113,4 @@ ref: ref,

// actions are performed on key down rather than key up.
linkBehavior: 'none'
linkBehavior: 'none',
shouldUseVirtualFocus: data.shouldUseVirtualFocus
});

@@ -113,5 +128,6 @@ let { pressProps: pressProps, isPressed: isPressed } = (0, $7Kjv5$usePress)({

onHoverStart (e) {
if (!(0, $7Kjv5$isFocusVisible)()) {
state.selectionManager.setFocused(true);
state.selectionManager.setFocusedKey(key);
// Hovering over an already expanded sub dialog trigger should keep focus in the dialog.
if (!(0, $7Kjv5$isFocusVisible)() && !(isTriggerExpanded && hasPopup === 'dialog')) {
selectionManager.setFocused(true);
selectionManager.setFocusedKey(key);
}

@@ -133,3 +149,3 @@ hoverStartProp === null || hoverStartProp === void 0 ? void 0 : hoverStartProp(e);

case ' ':
if (!isDisabled && state.selectionManager.selectionMode === 'none' && !isTrigger && closeOnSelect !== false && onClose) onClose();
if (!isDisabled && selectionManager.selectionMode === 'none' && !isTrigger && closeOnSelect !== false && onClose) onClose();
break;

@@ -153,5 +169,5 @@ case 'Enter':

});
let domProps = (0, $7Kjv5$filterDOMProps)(item.props);
let domProps = (0, $7Kjv5$filterDOMProps)(item === null || item === void 0 ? void 0 : item.props);
delete domProps.id;
let linkProps = (0, $7Kjv5$useLinkProps)(item.props);
let linkProps = (0, $7Kjv5$useLinkProps)(item === null || item === void 0 ? void 0 : item.props);
return {

@@ -164,3 +180,4 @@ menuItemProps: {

} : itemProps, pressProps, hoverProps, keyboardProps, focusProps),
tabIndex: itemProps.tabIndex != null ? -1 : undefined
// If a submenu is expanded, set the tabIndex to -1 so that shift tabbing goes out of the menu instead of the parent menu item.
tabIndex: itemProps.tabIndex != null && isTriggerExpanded ? -1 : itemProps.tabIndex
},

@@ -167,0 +184,0 @@ labelProps: {

@@ -87,2 +87,3 @@ var $d1742ec2644a0949$exports = require("./intlStrings.main.js");

return {
// @ts-ignore - TODO we pass out both DOMAttributes AND AriaButtonProps, but useButton will discard the longPress event handlers, it's only through PressResponder magic that this works for RSP and RAC. it does not work in aria examples
menuTriggerProps: {

@@ -89,0 +90,0 @@ ...triggerProps,

@@ -81,2 +81,3 @@ import $czs6v$intlStringsmodulejs from "./intlStrings.module.js";

return {
// @ts-ignore - TODO we pass out both DOMAttributes AND AriaButtonProps, but useButton will discard the longPress event handlers, it's only through PressResponder magic that this works for RSP and RAC. it does not work in aria examples
menuTriggerProps: {

@@ -83,0 +84,0 @@ ...triggerProps,

@@ -54,3 +54,3 @@ var $g3RPq$react = require("react");

let menu = menuRef.current;
if (isDisabled || !submenu || !isOpen || modality !== 'pointer') {
if (isDisabled || !submenu || !isOpen || modality !== 'pointer' || !menu) {
reset();

@@ -57,0 +57,0 @@ return;

@@ -48,3 +48,3 @@ import {useRef as $fUfeP$useRef, useState as $fUfeP$useState, useEffect as $fUfeP$useEffect} from "react";

let menu = menuRef.current;
if (isDisabled || !submenu || !isOpen || modality !== 'pointer') {
if (isDisabled || !submenu || !isOpen || modality !== 'pointer' || !menu) {
reset();

@@ -51,0 +51,0 @@ return;

@@ -59,5 +59,6 @@ var $62347d8c4183e713$exports = require("./useSafelyMouseToSubmenu.main.js");

if (direction === 'ltr' && e.currentTarget.contains(e.target)) {
var _ref_current;
e.stopPropagation();
onSubmenuClose();
ref.current.focus();
(_ref_current = ref.current) === null || _ref_current === void 0 ? void 0 : _ref_current.focus();
}

@@ -67,5 +68,6 @@ break;

if (direction === 'rtl' && e.currentTarget.contains(e.target)) {
var _ref_current1;
e.stopPropagation();
onSubmenuClose();
ref.current.focus();
(_ref_current1 = ref.current) === null || _ref_current1 === void 0 ? void 0 : _ref_current1.focus();
}

@@ -79,2 +81,3 @@ break;

};
var _state_focusStrategy;
let submenuProps = {

@@ -86,3 +89,3 @@ id: overlayId,

onClose: state.closeAll,
autoFocus: state.focusStrategy,
autoFocus: (_state_focusStrategy = state.focusStrategy) !== null && _state_focusStrategy !== void 0 ? _state_focusStrategy : undefined,
onKeyDown: submenuKeyDown

@@ -138,3 +141,4 @@ }

let onBlur = (e)=>{
if (state.isOpen && parentMenuRef.current.contains(e.relatedTarget)) onSubmenuClose();
var _parentMenuRef_current;
if (state.isOpen && ((_parentMenuRef_current = parentMenuRef.current) === null || _parentMenuRef_current === void 0 ? void 0 : _parentMenuRef_current.contains(e.relatedTarget))) onSubmenuClose();
};

@@ -141,0 +145,0 @@ let shouldCloseOnInteractOutside = (target)=>{

@@ -53,5 +53,6 @@ import {useSafelyMouseToSubmenu as $d275435c250248f8$export$85ec83e04c95f50a} from "./useSafelyMouseToSubmenu.module.js";

if (direction === 'ltr' && e.currentTarget.contains(e.target)) {
var _ref_current;
e.stopPropagation();
onSubmenuClose();
ref.current.focus();
(_ref_current = ref.current) === null || _ref_current === void 0 ? void 0 : _ref_current.focus();
}

@@ -61,5 +62,6 @@ break;

if (direction === 'rtl' && e.currentTarget.contains(e.target)) {
var _ref_current1;
e.stopPropagation();
onSubmenuClose();
ref.current.focus();
(_ref_current1 = ref.current) === null || _ref_current1 === void 0 ? void 0 : _ref_current1.focus();
}

@@ -73,2 +75,3 @@ break;

};
var _state_focusStrategy;
let submenuProps = {

@@ -80,3 +83,3 @@ id: overlayId,

onClose: state.closeAll,
autoFocus: state.focusStrategy,
autoFocus: (_state_focusStrategy = state.focusStrategy) !== null && _state_focusStrategy !== void 0 ? _state_focusStrategy : undefined,
onKeyDown: submenuKeyDown

@@ -132,3 +135,4 @@ }

let onBlur = (e)=>{
if (state.isOpen && parentMenuRef.current.contains(e.relatedTarget)) onSubmenuClose();
var _parentMenuRef_current;
if (state.isOpen && ((_parentMenuRef_current = parentMenuRef.current) === null || _parentMenuRef_current === void 0 ? void 0 : _parentMenuRef_current.contains(e.relatedTarget))) onSubmenuClose();
};

@@ -135,0 +139,0 @@ let shouldCloseOnInteractOutside = (target)=>{

{
"name": "@react-aria/menu",
"version": "3.0.0-nightly-987f174ba-241015",
"version": "3.0.0-nightly-993de98ad-241210",
"description": "Spectrum UI components in React",

@@ -25,19 +25,20 @@ "license": "Apache-2.0",

"dependencies": {
"@react-aria/focus": "^3.0.0-nightly-987f174ba-241015",
"@react-aria/i18n": "^3.0.0-nightly-987f174ba-241015",
"@react-aria/interactions": "^3.0.0-nightly-987f174ba-241015",
"@react-aria/overlays": "^3.0.0-nightly-987f174ba-241015",
"@react-aria/selection": "^3.0.0-nightly-987f174ba-241015",
"@react-aria/utils": "^3.0.0-nightly-987f174ba-241015",
"@react-stately/collections": "^3.0.0-nightly-987f174ba-241015",
"@react-stately/menu": "^3.0.0-nightly-987f174ba-241015",
"@react-stately/tree": "^3.0.0-nightly-987f174ba-241015",
"@react-types/button": "^3.0.0-nightly-987f174ba-241015",
"@react-types/menu": "^3.0.0-nightly-987f174ba-241015",
"@react-types/shared": "^3.0.0-nightly-987f174ba-241015",
"@react-aria/focus": "^3.0.0-nightly-993de98ad-241210",
"@react-aria/i18n": "^3.0.0-nightly-993de98ad-241210",
"@react-aria/interactions": "^3.0.0-nightly-993de98ad-241210",
"@react-aria/overlays": "^3.0.0-nightly-993de98ad-241210",
"@react-aria/selection": "^3.0.0-nightly-993de98ad-241210",
"@react-aria/utils": "^3.0.0-nightly-993de98ad-241210",
"@react-stately/collections": "^3.0.0-nightly-993de98ad-241210",
"@react-stately/menu": "^3.0.0-nightly-993de98ad-241210",
"@react-stately/selection": "^3.0.0-nightly-993de98ad-241210",
"@react-stately/tree": "^3.0.0-nightly-993de98ad-241210",
"@react-types/button": "^3.0.0-nightly-993de98ad-241210",
"@react-types/menu": "^3.0.0-nightly-993de98ad-241210",
"@react-types/shared": "^3.0.0-nightly-993de98ad-241210",
"@swc/helpers": "^0.5.0"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0",
"react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0"
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1",
"react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
},

@@ -47,3 +48,3 @@ "publishConfig": {

},
"stableVersion": "3.15.5"
"stableVersion": "3.16.0"
}

@@ -14,4 +14,5 @@ /*

import {AriaMenuProps} from '@react-types/menu';
import {DOMAttributes, Key, KeyboardDelegate, KeyboardEvents, RefObject} from '@react-types/shared';
import {DOMAttributes, KeyboardDelegate, KeyboardEvents, RefObject} from '@react-types/shared';
import {filterDOMProps, mergeProps} from '@react-aria/utils';
import {menuData} from './utils';
import {TreeState} from '@react-stately/tree';

@@ -28,3 +29,2 @@ import {useSelectableList} from '@react-aria/selection';

isVirtualized?: boolean,
/**

@@ -34,12 +34,9 @@ * An optional keyboard delegate implementation for type to select,

*/
keyboardDelegate?: KeyboardDelegate
keyboardDelegate?: KeyboardDelegate,
/**
* Whether the menu items should use virtual focus instead of being focused directly.
*/
shouldUseVirtualFocus?: boolean
}
interface MenuData {
onClose?: () => void,
onAction?: (key: Key) => void
}
export const menuData = new WeakMap<TreeState<unknown>, MenuData>();
/**

@@ -76,3 +73,4 @@ * Provides the behavior and accessibility implementation for a menu component.

onClose: props.onClose,
onAction: props.onAction
onAction: props.onAction,
shouldUseVirtualFocus: props.shouldUseVirtualFocus
});

@@ -86,4 +84,4 @@

// don't clear the menu selected keys if the user is presses escape since escape closes the menu
if (e.key !== 'Escape') {
listProps.onKeyDown(e);
if (e.key !== 'Escape' || props.shouldUseVirtualFocus) {
listProps.onKeyDown?.(e);
}

@@ -90,0 +88,0 @@ }

@@ -17,3 +17,4 @@ /*

import {isFocusVisible, useFocus, useHover, useKeyboard, usePress} from '@react-aria/interactions';
import {menuData} from './useMenu';
import {menuData} from './utils';
import {SelectionManager} from '@react-stately/selection';
import {TreeState} from '@react-stately/tree';

@@ -62,3 +63,3 @@ import {useSelectableItem} from '@react-aria/selection';

/** The unique key for the menu item. */
key?: Key,
key: Key,

@@ -93,3 +94,6 @@ /**

/** Identifies the menu item's popup element whose contents or presence is controlled by the menu item. */
'aria-controls'?: string
'aria-controls'?: string,
/** Override of the selection manager. By default, `state.selectionManager` is used. */
selectionManager?: SelectionManager
}

@@ -112,3 +116,3 @@

onPressUp: pressUpProp,
onPress,
onPress: pressProp,
onPressChange,

@@ -123,9 +127,11 @@ onPressEnd,

onFocusChange,
onBlur
onBlur,
selectionManager = state.selectionManager
} = props;
let isTrigger = !!hasPopup;
let isDisabled = props.isDisabled ?? state.selectionManager.isDisabled(key);
let isSelected = props.isSelected ?? state.selectionManager.isSelected(key);
let data = menuData.get(state);
let isTriggerExpanded = isTrigger && props['aria-expanded'] === 'true';
let isDisabled = props.isDisabled ?? selectionManager.isDisabled(key);
let isSelected = props.isSelected ?? selectionManager.isSelected(key);
let data = menuData.get(state)!;
let item = state.collection.getItem(key);

@@ -151,3 +157,3 @@ let onClose = props.onClose || data.onClose;

if (e.target instanceof HTMLAnchorElement) {
if (e.target instanceof HTMLAnchorElement && item) {
router.open(e.target, e, item.props.href, item.props.routerOptions as RouterOptions);

@@ -159,5 +165,5 @@ }

if (!isTrigger) {
if (state.selectionManager.selectionMode === 'single') {
if (selectionManager.selectionMode === 'single') {
role = 'menuitemradio';
} else if (state.selectionManager.selectionMode === 'multiple') {
} else if (selectionManager.selectionMode === 'multiple') {
role = 'menuitemcheckbox';

@@ -183,3 +189,3 @@ }

if (state.selectionManager.selectionMode !== 'none' && !isTrigger) {
if (selectionManager.selectionMode !== 'none' && !isTrigger) {
ariaProps['aria-checked'] = isSelected;

@@ -201,11 +207,16 @@ }

let maybeClose = () => {
// Pressing a menu item should close by default in single selection mode but not multiple
// selection mode, except if overridden by the closeOnSelect prop.
if (!isTrigger && onClose && (closeOnSelect ?? (selectionManager.selectionMode !== 'multiple' || selectionManager.isLink(key)))) {
onClose();
}
};
let onPressUp = (e: PressEvent) => {
if (e.pointerType !== 'keyboard') {
// If interacting with mouse, allow the user to mouse down on the trigger button,
// drag, and release over an item (matching native behavior).
if (e.pointerType === 'mouse') {
performAction(e);
// Pressing a menu item should close by default in single selection mode but not multiple
// selection mode, except if overridden by the closeOnSelect prop.
if (!isTrigger && onClose && (closeOnSelect ?? (state.selectionManager.selectionMode !== 'multiple' || state.selectionManager.isLink(key)))) {
onClose();
}
maybeClose();
}

@@ -216,4 +227,14 @@

let onPress = (e: PressEvent) => {
if (e.pointerType !== 'keyboard' && e.pointerType !== 'mouse') {
performAction(e);
maybeClose();
}
pressProp?.(e);
};
let {itemProps, isFocused} = useSelectableItem({
selectionManager: state.selectionManager,
id,
selectionManager: selectionManager,
key,

@@ -227,3 +248,4 @@ ref,

// actions are performed on key down rather than key up.
linkBehavior: 'none'
linkBehavior: 'none',
shouldUseVirtualFocus: data.shouldUseVirtualFocus
});

@@ -242,5 +264,6 @@

onHoverStart(e) {
if (!isFocusVisible()) {
state.selectionManager.setFocused(true);
state.selectionManager.setFocusedKey(key);
// Hovering over an already expanded sub dialog trigger should keep focus in the dialog.
if (!isFocusVisible() && !(isTriggerExpanded && hasPopup === 'dialog')) {
selectionManager.setFocused(true);
selectionManager.setFocusedKey(key);
}

@@ -264,3 +287,3 @@ hoverStartProp?.(e);

case ' ':
if (!isDisabled && state.selectionManager.selectionMode === 'none' && !isTrigger && closeOnSelect !== false && onClose) {
if (!isDisabled && selectionManager.selectionMode === 'none' && !isTrigger && closeOnSelect !== false && onClose) {
onClose();

@@ -288,5 +311,5 @@ }

let {focusProps} = useFocus({onBlur, onFocus, onFocusChange});
let domProps = filterDOMProps(item.props);
let domProps = filterDOMProps(item?.props);
delete domProps.id;
let linkProps = useLinkProps(item.props);
let linkProps = useLinkProps(item?.props);

@@ -297,3 +320,4 @@ return {

...mergeProps(domProps, linkProps, isTrigger ? {onFocus: itemProps.onFocus, 'data-key': itemProps['data-key']} : itemProps, pressProps, hoverProps, keyboardProps, focusProps),
tabIndex: itemProps.tabIndex != null ? -1 : undefined
// If a submenu is expanded, set the tabIndex to -1 so that shift tabbing goes out of the menu instead of the parent menu item.
tabIndex: itemProps.tabIndex != null && isTriggerExpanded ? -1 : itemProps.tabIndex
},

@@ -300,0 +324,0 @@ labelProps: {

@@ -50,3 +50,3 @@ /*

let {
type = 'menu' as AriaMenuTriggerProps['type'],
type = 'menu',
isDisabled,

@@ -132,2 +132,3 @@ trigger = 'press'

return {
// @ts-ignore - TODO we pass out both DOMAttributes AND AriaButtonProps, but useButton will discard the longPress event handlers, it's only through PressResponder magic that this works for RSP and RAC. it does not work in aria examples
menuTriggerProps: {

@@ -134,0 +135,0 @@ ...triggerProps,

@@ -66,3 +66,3 @@

if (isDisabled || !submenu || !isOpen || modality !== 'pointer') {
if (isDisabled || !submenu || !isOpen || modality !== 'pointer' || !menu) {
reset();

@@ -69,0 +69,0 @@ return;

@@ -44,3 +44,3 @@ /*

interface SubmenuTriggerProps extends AriaMenuItemProps {
interface SubmenuTriggerProps extends Omit<AriaMenuItemProps, 'key'> {
/** Whether the submenu trigger is in an expanded state. */

@@ -105,3 +105,3 @@ isOpen: boolean

onSubmenuClose();
ref.current.focus();
ref.current?.focus();
}

@@ -113,3 +113,3 @@ break;

onSubmenuClose();
ref.current.focus();
ref.current?.focus();
}

@@ -130,3 +130,3 @@ break;

onClose: state.closeAll,
autoFocus: state.focusStrategy,
autoFocus: state.focusStrategy ?? undefined,
onKeyDown: submenuKeyDown

@@ -212,3 +212,3 @@ })

let onBlur = (e) => {
if (state.isOpen && parentMenuRef.current.contains(e.relatedTarget)) {
if (state.isOpen && parentMenuRef.current?.contains(e.relatedTarget)) {
onSubmenuClose();

@@ -215,0 +215,0 @@ }

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet