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:
աӄա 2024-11-05 05:09:03 +08:00 committed by GitHub
parent 90cb5b14ab
commit 2aebfcca59
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 5729 additions and 5516 deletions

View File

@ -0,0 +1,5 @@
---
"@nextui-org/menu": patch
---
Use `useMenu` and `useMenuItem` from `@react-aria` instead of custom hooks

View File

@ -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";

View File

@ -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);
});
});

View File

@ -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),

View File

@ -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";

View File

@ -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

File diff suppressed because it is too large Load Diff