mirror of
https://github.com/nextui-org/nextui.git
synced 2025-12-08 19:26:11 +00:00
refactor(menu): Use useMenu and useMenuItem from RA (#3261)
* refactor(menu): use useMenu from react-aria instead * refactor(menu): use useMenuItem from react-aria instead * feat(changeset): add changeset * chore: merged with canary * fix: dropdown tests --------- Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
This commit is contained in:
parent
90cb5b14ab
commit
2aebfcca59
5
.changeset/sour-seas-buy.md
Normal file
5
.changeset/sour-seas-buy.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"@nextui-org/menu": patch
|
||||
---
|
||||
|
||||
Use `useMenu` and `useMenuItem` from `@react-aria` instead of custom hooks
|
||||
@ -1,3 +1,4 @@
|
||||
import "@testing-library/jest-dom";
|
||||
import * as React from "react";
|
||||
import {within, render, renderHook, act} from "@testing-library/react";
|
||||
import userEvent, {UserEvent} from "@testing-library/user-event";
|
||||
|
||||
@ -837,9 +837,6 @@ describe("Dropdown", () => {
|
||||
let menuItems = wrapper.getAllByRole("menuitem");
|
||||
|
||||
await user.click(menuItems[0]);
|
||||
expect(onOpenChange).toHaveBeenCalledTimes(1);
|
||||
|
||||
await user.click(menuItems[1]);
|
||||
expect(onOpenChange).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
||||
|
||||
@ -12,7 +12,8 @@ import {
|
||||
import {useFocusRing} from "@react-aria/focus";
|
||||
import {TreeState} from "@react-stately/tree";
|
||||
import {clsx, dataAttr, objectToDeps, removeEvents} from "@nextui-org/shared-utils";
|
||||
import {useAriaMenuItem} from "@nextui-org/use-aria-menu";
|
||||
import {useMenuItem as useAriaMenuItem} from "@react-aria/menu";
|
||||
import {isFocusVisible as AriaIsFocusVisible, useHover} from "@react-aria/interactions";
|
||||
import {mergeProps} from "@react-aria/utils";
|
||||
import {useIsMobile} from "@nextui-org/use-is-mobile";
|
||||
import {filterDOMProps} from "@nextui-org/react-utils";
|
||||
@ -44,12 +45,14 @@ export function useMenuItem<T extends object>(originalProps: UseMenuItemProps<T>
|
||||
classNames,
|
||||
onAction,
|
||||
autoFocus,
|
||||
onClick,
|
||||
onPress,
|
||||
onPressStart,
|
||||
onPressUp,
|
||||
onPressEnd,
|
||||
onPressChange,
|
||||
onHoverStart: hoverStartProp,
|
||||
onHoverChange,
|
||||
onHoverEnd,
|
||||
hideSelectedIcon = false,
|
||||
isReadOnly = false,
|
||||
closeOnSelect,
|
||||
@ -67,7 +70,7 @@ export function useMenuItem<T extends object>(originalProps: UseMenuItemProps<T>
|
||||
|
||||
const {rendered, key} = item;
|
||||
|
||||
const isDisabled = state.disabledKeys.has(key) || originalProps.isDisabled;
|
||||
const isDisabledProp = state.disabledKeys.has(key) || originalProps.isDisabled;
|
||||
const isSelectable = state.selectionManager.selectionMode !== "none";
|
||||
|
||||
const isMobile = useIsMobile();
|
||||
@ -77,10 +80,10 @@ export function useMenuItem<T extends object>(originalProps: UseMenuItemProps<T>
|
||||
});
|
||||
|
||||
const {
|
||||
isHovered,
|
||||
isPressed,
|
||||
isFocused,
|
||||
isSelected,
|
||||
isDisabled,
|
||||
menuItemProps,
|
||||
labelProps,
|
||||
descriptionProps,
|
||||
@ -89,9 +92,8 @@ export function useMenuItem<T extends object>(originalProps: UseMenuItemProps<T>
|
||||
{
|
||||
key,
|
||||
onClose,
|
||||
isDisabled,
|
||||
isDisabled: isDisabledProp,
|
||||
onPress,
|
||||
onClick,
|
||||
onPressStart,
|
||||
onPressUp,
|
||||
onPressEnd,
|
||||
@ -105,6 +107,21 @@ export function useMenuItem<T extends object>(originalProps: UseMenuItemProps<T>
|
||||
domRef,
|
||||
);
|
||||
|
||||
// `useMenuItem` from react-aria doesn't expose `isHovered`
|
||||
// hence, cover the logic here
|
||||
let {hoverProps, isHovered} = useHover({
|
||||
isDisabled,
|
||||
onHoverStart(e) {
|
||||
if (!AriaIsFocusVisible()) {
|
||||
state.selectionManager.setFocused(true);
|
||||
state.selectionManager.setFocusedKey(key);
|
||||
}
|
||||
hoverStartProp?.(e);
|
||||
},
|
||||
onHoverChange,
|
||||
onHoverEnd,
|
||||
});
|
||||
|
||||
let itemProps = menuItemProps;
|
||||
|
||||
const slots = useMemo(
|
||||
@ -131,6 +148,7 @@ export function useMenuItem<T extends object>(originalProps: UseMenuItemProps<T>
|
||||
enabled: shouldFilterDOMProps,
|
||||
}),
|
||||
itemProps,
|
||||
hoverProps,
|
||||
props,
|
||||
),
|
||||
"data-focus": dataAttr(isFocused),
|
||||
|
||||
@ -3,7 +3,7 @@ import type {HTMLNextUIProps, PropGetter, SharedSelection} from "@nextui-org/sys
|
||||
import {useProviderContext} from "@nextui-org/system";
|
||||
import {AriaMenuProps} from "@react-types/menu";
|
||||
import {AriaMenuOptions} from "@react-aria/menu";
|
||||
import {useAriaMenu} from "@nextui-org/use-aria-menu";
|
||||
import {useMenu as useAriaMenu} from "@react-aria/menu";
|
||||
import {menu, MenuVariantProps, SlotsToClasses, MenuSlots} from "@nextui-org/theme";
|
||||
import {TreeState, useTreeState} from "@react-stately/tree";
|
||||
import {ReactRef, filterDOMProps, useDOMRef} from "@nextui-org/react-utils";
|
||||
|
||||
@ -34,15 +34,16 @@
|
||||
"postpack": "clean-package restore"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nextui-org/use-safe-layout-effect": "workspace:*"
|
||||
"@nextui-org/use-safe-layout-effect": "workspace:*",
|
||||
"@testing-library/react-hooks": "^8.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=18"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nextui-org/test-utils": "workspace:*",
|
||||
"clean-package": "2.2.0",
|
||||
"react": "^18.0.0",
|
||||
"@nextui-org/test-utils": "workspace:*"
|
||||
"react": "^18.0.0"
|
||||
},
|
||||
"clean-package": "../../../clean-package.config.json",
|
||||
"tsup": {
|
||||
|
||||
11197
pnpm-lock.yaml
generated
11197
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user