UNPKG

react-aria

Version:
1 lines • 17.5 kB
{"mappings":"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","sources":["packages/react-aria/src/menu/useMenuItem.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n DOMAttributes,\n DOMProps,\n FocusableElement,\n FocusEvents,\n HoverEvents,\n Key,\n KeyboardEvents,\n PressEvent,\n PressEvents,\n RefObject\n} from '@react-types/shared';\nimport {filterDOMProps} from '../utils/filterDOMProps';\nimport {getEventTarget} from '../utils/shadowdom/DOMFunctions';\nimport {getItemCount} from 'react-stately/private/collections/getItemCount';\nimport {handleLinkClick, useLinkProps, useRouter} from '../utils/openLink';\nimport {isFocusVisible, setInteractionModality} from '../interactions/useFocusVisible';\nimport {menuData} from './utils';\nimport {mergeProps} from '../utils/mergeProps';\nimport {MouseEvent, useRef} from 'react';\nimport {SelectionManager} from 'react-stately/private/selection/SelectionManager';\nimport {TreeState} from 'react-stately/useTreeState';\nimport {useFocusable} from '../interactions/useFocusable';\nimport {useHover} from '../interactions/useHover';\nimport {useKeyboard} from '../interactions/useKeyboard';\nimport {usePress} from '../interactions/usePress';\nimport {useSelectableItem} from '../selection/useSelectableItem';\nimport {useSlotId} from '../utils/useId';\n\nexport interface MenuItemAria {\n /** Props for the menu item element. */\n menuItemProps: DOMAttributes;\n\n /** Props for the main text element inside the menu item. */\n labelProps: DOMAttributes;\n\n /** Props for the description text element inside the menu item, if any. */\n descriptionProps: DOMAttributes;\n\n /** Props for the keyboard shortcut text element inside the item, if any. */\n keyboardShortcutProps: DOMAttributes;\n\n /** Whether the item is currently focused. */\n isFocused: boolean;\n /** Whether the item is keyboard focused. */\n isFocusVisible: boolean;\n /** Whether the item is currently selected. */\n isSelected: boolean;\n /** Whether the item is currently in a pressed state. */\n isPressed: boolean;\n /** Whether the item is disabled. */\n isDisabled: boolean;\n}\n\nexport interface AriaMenuItemProps\n extends DOMProps, PressEvents, HoverEvents, KeyboardEvents, FocusEvents {\n /**\n * Whether the menu item is disabled.\n *\n * @deprecated - pass disabledKeys to useTreeState instead.\n */\n isDisabled?: boolean;\n\n /**\n * Whether the menu item is selected.\n *\n * @deprecated - pass selectedKeys to useTreeState instead.\n */\n isSelected?: boolean;\n\n /** A screen reader only label for the menu item. */\n 'aria-label'?: string;\n\n /** The unique key for the menu item. */\n key: Key;\n\n /**\n * Handler that is called when the menu should close after selecting an item.\n *\n * @deprecated - pass to the menu instead.\n */\n onClose?: () => void;\n\n /**\n * Whether the menu should close when the menu item is selected.\n *\n * @deprecated - use shouldCloseOnSelect instead.\n */\n closeOnSelect?: boolean;\n\n /** Whether the menu should close when the menu item is selected. */\n shouldCloseOnSelect?: boolean;\n\n /** Whether the menu item is contained in a virtual scrolling menu. */\n isVirtualized?: boolean;\n\n /**\n * Handler that is called when the user activates the item.\n *\n * @deprecated - pass to the menu instead.\n */\n onAction?: (key: Key) => void;\n\n /** What kind of popup the item opens. */\n 'aria-haspopup'?: 'menu' | 'dialog';\n\n /** Indicates whether the menu item's popup element is expanded or collapsed. */\n 'aria-expanded'?: boolean | 'true' | 'false';\n\n /**\n * Identifies the menu item's popup element whose contents or presence is controlled by the menu\n * item.\n */\n 'aria-controls'?: string;\n\n /** Identifies the element(s) that describe the menu item. */\n 'aria-describedby'?: string;\n\n /** Override of the selection manager. By default, `state.selectionManager` is used. */\n selectionManager?: SelectionManager;\n}\n\n/**\n * Provides the behavior and accessibility implementation for an item in a menu.\n * See `useMenu` for more details about menus.\n *\n * @param props - Props for the item.\n * @param state - State for the menu, as returned by `useTreeState`.\n */\nexport function useMenuItem<T>(\n props: AriaMenuItemProps,\n state: TreeState<T>,\n ref: RefObject<FocusableElement | null>\n): MenuItemAria {\n let {\n id,\n key,\n closeOnSelect,\n shouldCloseOnSelect,\n isVirtualized,\n 'aria-haspopup': hasPopup,\n onPressStart,\n onPressUp: pressUpProp,\n onPress,\n onPressChange: pressChangeProp,\n onPressEnd,\n onClick: onClickProp,\n onHoverStart: hoverStartProp,\n onHoverChange,\n onHoverEnd,\n onKeyDown,\n onKeyUp,\n onFocus,\n onFocusChange,\n onBlur,\n selectionManager = state.selectionManager\n } = props;\n\n let isTrigger = !!hasPopup;\n let isTriggerExpanded = isTrigger && props['aria-expanded'] === 'true';\n let isDisabled = props.isDisabled ?? selectionManager.isDisabled(key);\n let isSelected = props.isSelected ?? selectionManager.isSelected(key);\n let data = menuData.get(state)!;\n let item = state.collection.getItem(key);\n let onClose = props.onClose || data.onClose;\n let router = useRouter();\n let performAction = () => {\n if (isTrigger) {\n return;\n }\n\n if (item?.props?.onAction) {\n item.props.onAction();\n } else if (props.onAction) {\n props.onAction(key);\n }\n\n if (data.onAction) {\n // Must reassign to variable otherwise `this` binding gets messed up. Something to do with WeakMap.\n let onAction = data.onAction;\n onAction(key, item?.value);\n }\n };\n\n let role = 'menuitem';\n if (!isTrigger) {\n if (selectionManager.selectionMode === 'single') {\n role = 'menuitemradio';\n } else if (selectionManager.selectionMode === 'multiple') {\n role = 'menuitemcheckbox';\n }\n }\n\n let labelId = useSlotId();\n let descriptionId = useSlotId();\n let keyboardId = useSlotId();\n\n let ariaProps = {\n id,\n 'aria-disabled': isDisabled || undefined,\n role,\n 'aria-label': props['aria-label'],\n 'aria-labelledby': labelId,\n 'aria-describedby':\n [props['aria-describedby'], descriptionId, keyboardId].filter(Boolean).join(' ') || undefined,\n 'aria-controls': props['aria-controls'],\n 'aria-haspopup': hasPopup,\n 'aria-expanded': props['aria-expanded']\n };\n\n if (selectionManager.selectionMode !== 'none' && !isTrigger) {\n ariaProps['aria-checked'] = isSelected;\n }\n\n if (isVirtualized) {\n let index = Number(item?.index);\n ariaProps['aria-posinset'] = Number.isNaN(index) ? undefined : index + 1;\n ariaProps['aria-setsize'] = getItemCount(state.collection);\n }\n\n let isPressedRef = useRef(false);\n let onPressChange = (isPressed: boolean) => {\n pressChangeProp?.(isPressed);\n isPressedRef.current = isPressed;\n };\n\n let interaction = useRef<{pointerType: string; key?: string} | null>(null);\n let onPressUp = (e: PressEvent) => {\n if (e.pointerType !== 'keyboard') {\n interaction.current = {pointerType: e.pointerType};\n }\n\n // If interacting with mouse, allow the user to mouse down on the trigger button,\n // drag, and release over an item (matching native behavior).\n if (e.pointerType === 'mouse') {\n if (!isPressedRef.current) {\n (e.target as HTMLElement).click();\n }\n }\n\n pressUpProp?.(e);\n };\n\n let onClick = (e: MouseEvent<FocusableElement>) => {\n onClickProp?.(e);\n performAction();\n handleLinkClick(e, router, item!.props.href, item?.props.routerOptions);\n\n let shouldClose =\n interaction.current?.pointerType === 'keyboard'\n ? // Always close when pressing Enter key, or if item is not selectable.\n interaction.current?.key === 'Enter' ||\n selectionManager.selectionMode === 'none' ||\n selectionManager.isLink(key)\n : // Close except if multi-select is enabled.\n selectionManager.selectionMode !== 'multiple' || selectionManager.isLink(key);\n\n shouldClose = shouldCloseOnSelect ?? closeOnSelect ?? shouldClose;\n\n if (onClose && !isTrigger && shouldClose) {\n onClose();\n }\n\n interaction.current = null;\n };\n\n let {itemProps, isFocused} = useSelectableItem({\n id,\n selectionManager: selectionManager,\n key,\n ref,\n shouldSelectOnPressUp: true,\n allowsDifferentPressOrigin: true,\n // Disable all handling of links in useSelectable item\n // because we handle it ourselves. The behavior of menus\n // is slightly different from other collections because\n // actions are performed on key down rather than key up.\n linkBehavior: 'none',\n shouldUseVirtualFocus: data.shouldUseVirtualFocus\n });\n\n let {pressProps, isPressed} = usePress({\n onPressStart,\n onPress,\n onPressUp,\n onPressChange,\n onPressEnd,\n isDisabled\n });\n let {hoverProps} = useHover({\n isDisabled,\n onHoverStart(e) {\n // Hovering over an already expanded sub dialog trigger should keep focus in the dialog.\n if (!isFocusVisible() && !(isTriggerExpanded && hasPopup)) {\n selectionManager.setFocused(true);\n selectionManager.setFocusedKey(key);\n }\n hoverStartProp?.(e);\n },\n onHoverChange,\n onHoverEnd\n });\n\n let {keyboardProps} = useKeyboard({\n onKeyDown: e => {\n // Ignore repeating events, which may have started on the menu trigger before moving\n // focus to the menu item. We want to wait for a second complete key press sequence.\n if (e.repeat) {\n e.continuePropagation();\n return;\n }\n\n switch (e.key) {\n case ' ':\n interaction.current = {pointerType: 'keyboard', key: ' '};\n (getEventTarget(e) as HTMLElement).click();\n\n // click above sets modality to \"virtual\", need to set interaction modality back to 'keyboard' so focusSafely calls properly move focus\n // to the newly opened submenu's first item.\n setInteractionModality('keyboard');\n break;\n case 'Enter':\n interaction.current = {pointerType: 'keyboard', key: 'Enter'};\n\n // Trigger click unless this is a link. Links trigger click natively.\n if ((getEventTarget(e) as HTMLElement).tagName !== 'A') {\n (getEventTarget(e) as HTMLElement).click();\n }\n\n // click above sets modality to \"virtual\", need to set interaction modality back to 'keyboard' so focusSafely calls properly move focus\n // to the newly opened submenu's first item.\n setInteractionModality('keyboard');\n break;\n default:\n if (!isTrigger) {\n e.continuePropagation();\n }\n\n onKeyDown?.(e);\n break;\n }\n },\n onKeyUp\n });\n\n let {focusableProps} = useFocusable({onBlur, onFocus, onFocusChange}, ref);\n let domProps = filterDOMProps(item?.props);\n delete domProps.id;\n let linkProps = useLinkProps(item?.props);\n\n return {\n menuItemProps: {\n ...ariaProps,\n ...mergeProps(\n domProps,\n linkProps,\n isTrigger\n ? {\n onFocus: itemProps.onFocus,\n 'data-collection': itemProps['data-collection'],\n 'data-key': itemProps['data-key']\n }\n : itemProps,\n pressProps,\n hoverProps,\n keyboardProps,\n focusableProps,\n // Prevent DOM focus from moving on mouse down when using virtual focus or this is a submenu/subdialog trigger.\n data.shouldUseVirtualFocus || isTrigger\n ? {onMouseDown: e => e.preventDefault()}\n : undefined,\n isDisabled ? undefined : {onClick}\n ),\n // 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.\n tabIndex:\n itemProps.tabIndex != null && isTriggerExpanded && !data.shouldUseVirtualFocus\n ? -1\n : itemProps.tabIndex\n },\n labelProps: {\n id: labelId\n },\n descriptionProps: {\n id: descriptionId\n },\n keyboardShortcutProps: {\n id: keyboardId\n },\n isFocused,\n isFocusVisible:\n isFocused && selectionManager.isFocused && isFocusVisible() && !isTriggerExpanded,\n isSelected,\n isPressed,\n isDisabled\n };\n}\n"],"names":[],"version":3,"file":"useMenuItem.mjs.map"}