UNPKG

react-aria

Version:
1 lines • 22.7 kB
{"mappings":"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","sources":["packages/react-aria/src/gridlist/useGridListItem.ts"],"sourcesContent":["/*\n * Copyright 2022 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 {chain} from '../utils/chain';\n\nimport {\n Collection,\n DOMAttributes,\n FocusableElement,\n Key,\n RefObject,\n Node as RSNode\n} from '@react-types/shared';\nimport {focusSafely} from '../interactions/focusSafely';\nimport {\n getActiveElement,\n getEventTarget,\n isFocusWithin,\n nodeContains\n} from '../utils/shadowdom/DOMFunctions';\nimport {getFocusableTreeWalker} from '../focus/FocusScope';\nimport {getRowId, listMap} from './utils';\nimport {getScrollParent} from '../utils/getScrollParent';\nimport {HTMLAttributes, KeyboardEvent as ReactKeyboardEvent, useRef} from 'react';\nimport {isFocusVisible} from '../interactions/useFocusVisible';\nimport type {ListState} from 'react-stately/useListState';\nimport {mergeProps} from '../utils/mergeProps';\nimport {scrollIntoViewport} from '../utils/scrollIntoView';\nimport {SelectableItemStates, useSelectableItem} from '../selection/useSelectableItem';\nimport type {TreeState} from 'react-stately/useTreeState';\nimport {useLocale} from '../i18n/I18nProvider';\nimport {useSlotId} from '../utils/useId';\nimport {useSyntheticLinkProps} from '../utils/openLink';\n\nexport interface AriaGridListItemOptions {\n /**\n * An object representing the list item. Contains all the relevant information that makes up the\n * list row.\n */\n node: RSNode<unknown>;\n /** Whether the list row is contained in a virtual scroller. */\n isVirtualized?: boolean;\n /** Whether selection should occur on press up instead of press down. */\n shouldSelectOnPressUp?: boolean;\n /** Whether this item has children, even if not loaded yet. */\n hasChildItems?: boolean;\n}\n\nexport interface GridListItemAria extends SelectableItemStates {\n /** Props for the list row element. */\n rowProps: DOMAttributes;\n /** Props for the grid cell element within the list row. */\n gridCellProps: DOMAttributes;\n /** Props for the list item description element, if any. */\n descriptionProps: DOMAttributes;\n}\n\nconst EXPANSION_KEYS = {\n expand: {\n ltr: 'ArrowRight',\n rtl: 'ArrowLeft'\n },\n collapse: {\n ltr: 'ArrowLeft',\n rtl: 'ArrowRight'\n }\n};\n\n/**\n * Provides the behavior and accessibility implementation for a row in a grid list.\n *\n * @param props - Props for the row.\n * @param state - State of the parent list, as returned by `useListState`.\n * @param ref - The ref attached to the row element.\n */\nexport function useGridListItem<T>(\n props: AriaGridListItemOptions,\n state: ListState<T> | TreeState<T>,\n ref: RefObject<FocusableElement | null>\n): GridListItemAria {\n // Copied from useGridCell + some modifications to make it not so grid specific\n let {node, isVirtualized} = props;\n\n // let stringFormatter = useLocalizedStringFormatter(intlMessages, '@react-aria/gridlist');\n let {direction} = useLocale();\n let {onAction, linkBehavior, keyboardNavigationBehavior, shouldSelectOnPressUp} =\n listMap.get(state)!;\n let descriptionId = useSlotId();\n\n // We need to track the key of the item at the time it was last focused so that we force\n // focus to go to the item when the DOM node is reused for a different item in a virtualizer.\n let keyWhenFocused = useRef<Key | null>(null);\n let focus = () => {\n // Don't shift focus to the row if the active element is a element within the row already\n // (e.g. clicking on a row button)\n if (\n ref.current !== null &&\n ((keyWhenFocused.current != null && node.key !== keyWhenFocused.current) ||\n !isFocusWithin(ref.current))\n ) {\n focusSafely(ref.current);\n }\n };\n\n let treeGridRowProps: HTMLAttributes<HTMLElement> = {};\n let hasChildRows = props.hasChildItems;\n let hasLink = state.selectionManager.isLink(node.key);\n if (node != null && 'expandedKeys' in state) {\n // TODO: ideally node.hasChildNodes would be a way to tell if a row has child nodes, but the row's contents make it so that value is always\n // true...\n let children = state.collection.getChildren?.(node.key);\n hasChildRows = hasChildRows || [...(children ?? [])].length > 1;\n\n if (\n onAction == null &&\n !hasLink &&\n state.selectionManager.selectionMode === 'none' &&\n hasChildRows\n ) {\n onAction = () => state.toggleKey(node.key);\n }\n\n let isExpanded = hasChildRows ? state.expandedKeys.has(node.key) : undefined;\n let setSize = 1;\n let index = node.index;\n if (node.level >= 0 && node?.parentKey != null) {\n let parent = state.collection.getItem(node.parentKey);\n if (parent) {\n // siblings must exist because our original node exists\n let siblings = getDirectChildren(parent, state.collection);\n setSize = [...siblings].filter(row => row.type === 'item').length;\n if (index > 0 && siblings[0].type !== 'item') {\n index -= 1; // subtract one for the parent item's content node\n }\n }\n } else {\n setSize = [...state.collection].filter(row => row.level === 0 && row.type === 'item').length;\n }\n\n treeGridRowProps = {\n 'aria-expanded': isExpanded,\n 'aria-level': node.level + 1,\n 'aria-posinset': index + 1,\n 'aria-setsize': setSize\n };\n }\n\n let {itemProps, ...itemStates} = useSelectableItem({\n selectionManager: state.selectionManager,\n key: node.key,\n ref,\n isVirtualized,\n shouldSelectOnPressUp: props.shouldSelectOnPressUp || shouldSelectOnPressUp,\n onAction:\n onAction || node.props?.onAction\n ? chain(node.props?.onAction, onAction ? () => onAction(node.key) : undefined)\n : undefined,\n focus,\n linkBehavior\n });\n\n let onKeyDownCapture = (e: ReactKeyboardEvent) => {\n let activeElement = getActiveElement();\n if (\n !nodeContains(e.currentTarget, getEventTarget(e) as Element) ||\n !ref.current ||\n !activeElement\n ) {\n return;\n }\n\n let walker = getFocusableTreeWalker(ref.current);\n walker.currentNode = activeElement;\n\n if ('expandedKeys' in state && activeElement === ref.current) {\n if (\n e.key === EXPANSION_KEYS['expand'][direction] &&\n state.selectionManager.focusedKey === node.key &&\n hasChildRows &&\n !state.expandedKeys.has(node.key)\n ) {\n state.toggleKey(node.key);\n e.stopPropagation();\n return;\n } else if (\n e.key === EXPANSION_KEYS['collapse'][direction] &&\n state.selectionManager.focusedKey === node.key\n ) {\n // If item is collapsible, collapse it; else move to parent\n if (hasChildRows && state.expandedKeys.has(node.key)) {\n state.toggleKey(node.key);\n e.stopPropagation();\n return;\n } else if (\n !state.expandedKeys.has(node.key) &&\n node.parentKey &&\n state.collection.getItem(node.parentKey)?.type === 'item'\n ) {\n // Item is a leaf or already collapsed, move focus to parent\n state.selectionManager.setFocusedKey(node.parentKey);\n e.stopPropagation();\n return;\n }\n }\n }\n\n switch (e.key) {\n case 'ArrowLeft': {\n if (keyboardNavigationBehavior === 'arrow') {\n // Find the next focusable element within the row.\n let focusable =\n direction === 'rtl'\n ? (walker.nextNode() as FocusableElement)\n : (walker.previousNode() as FocusableElement);\n\n if (focusable) {\n e.preventDefault();\n e.stopPropagation();\n focusSafely(focusable);\n scrollIntoViewport(focusable, {containingElement: getScrollParent(ref.current)});\n } else {\n // If there is no next focusable child, then return focus back to the row\n e.preventDefault();\n e.stopPropagation();\n if (direction === 'rtl') {\n focusSafely(ref.current);\n scrollIntoViewport(ref.current, {containingElement: getScrollParent(ref.current)});\n } else {\n walker.currentNode = ref.current;\n let lastElement = last(walker);\n // oxlint-disable-next-line max-depth\n if (lastElement) {\n focusSafely(lastElement);\n scrollIntoViewport(lastElement, {containingElement: getScrollParent(ref.current)});\n }\n }\n }\n }\n break;\n }\n case 'ArrowRight': {\n if (keyboardNavigationBehavior === 'arrow') {\n let focusable =\n direction === 'rtl'\n ? (walker.previousNode() as FocusableElement)\n : (walker.nextNode() as FocusableElement);\n\n if (focusable) {\n e.preventDefault();\n e.stopPropagation();\n focusSafely(focusable);\n scrollIntoViewport(focusable, {containingElement: getScrollParent(ref.current)});\n } else {\n e.preventDefault();\n e.stopPropagation();\n if (direction === 'ltr') {\n focusSafely(ref.current);\n scrollIntoViewport(ref.current, {containingElement: getScrollParent(ref.current)});\n } else {\n walker.currentNode = ref.current;\n let lastElement = last(walker);\n // oxlint-disable-next-line max-depth\n if (lastElement) {\n focusSafely(lastElement);\n scrollIntoViewport(lastElement, {containingElement: getScrollParent(ref.current)});\n }\n }\n }\n }\n break;\n }\n case 'ArrowUp':\n case 'ArrowDown':\n // Prevent this event from reaching row children, e.g. menu buttons. We want arrow keys to navigate\n // to the row above/below instead. We need to re-dispatch the event from a higher parent so it still\n // bubbles and gets handled by useSelectableCollection.\n if (!e.altKey && nodeContains(ref.current, getEventTarget(e) as Element)) {\n e.stopPropagation();\n e.preventDefault();\n ref.current.parentElement?.dispatchEvent(\n new KeyboardEvent(e.nativeEvent.type, e.nativeEvent)\n );\n }\n break;\n }\n };\n\n let onFocus = e => {\n keyWhenFocused.current = node.key;\n if (getEventTarget(e) !== ref.current) {\n // useSelectableItem only handles setting the focused key when\n // the focused element is the row itself. We also want to\n // set the focused key when a child element receives focus.\n // If focus is currently visible (e.g. the user is navigating with the keyboard),\n // then skip this. We want to restore focus to the previously focused row\n // in that case since the list should act like a single tab stop.\n if (!isFocusVisible()) {\n state.selectionManager.setFocusedKey(node.key);\n }\n return;\n }\n };\n\n let onKeyDown = e => {\n let activeElement = getActiveElement();\n if (\n !nodeContains(e.currentTarget, getEventTarget(e) as Element) ||\n !ref.current ||\n !activeElement\n ) {\n return;\n }\n\n switch (e.key) {\n case 'Tab': {\n if (keyboardNavigationBehavior === 'tab') {\n // If there is another focusable element within this item, stop propagation so the tab key\n // is handled by the browser and not by useSelectableCollection (which would take us out of the list).\n let walker = getFocusableTreeWalker(ref.current, {tabbable: true});\n walker.currentNode = activeElement;\n let next = e.shiftKey ? walker.previousNode() : walker.nextNode();\n\n if (next) {\n e.stopPropagation();\n }\n }\n }\n }\n };\n\n let syntheticLinkProps = useSyntheticLinkProps(node.props);\n let linkProps = itemStates.hasAction ? syntheticLinkProps : {};\n // TODO: re-add when we get translations and fix this for iOS VO\n // let rowAnnouncement;\n // if (onAction) {\n // rowAnnouncement = stringFormatter.format('hasActionAnnouncement');\n // } else if (hasLink) {\n // rowAnnouncement = stringFormatter.format('hasLinkAnnouncement', {\n // link: node.props.href\n // });\n // }\n\n let rowProps: DOMAttributes = mergeProps(itemProps, linkProps, {\n role: 'row',\n onKeyDownCapture,\n onKeyDown,\n onFocus,\n // 'aria-label': [(node.textValue || undefined), rowAnnouncement].filter(Boolean).join(', '),\n 'aria-label': node['aria-label'] || node.textValue || undefined,\n 'aria-selected': state.selectionManager.canSelectItem(node.key)\n ? state.selectionManager.isSelected(node.key)\n : undefined,\n 'aria-disabled': state.selectionManager.isDisabled(node.key) || undefined,\n 'aria-labelledby':\n descriptionId && (node['aria-label'] || node.textValue)\n ? `${getRowId(state, node.key)} ${descriptionId}`\n : undefined,\n id: getRowId(state, node.key)\n });\n\n if (isVirtualized) {\n let {collection} = state;\n let nodes = [...collection];\n // TODO: refactor ListCollection to store an absolute index of a node's position?\n rowProps['aria-rowindex'] = nodes.find(node => node.type === 'section')\n ? [...collection.getKeys()]\n .filter(key => collection.getItem(key)?.type !== 'section')\n .findIndex(key => key === node.key) + 1\n : node.index + 1;\n }\n\n let gridCellProps = {\n role: 'gridcell',\n 'aria-colindex': 1\n };\n\n // TODO: should isExpanded and hasChildRows be a item state that gets returned by the hook?\n return {\n rowProps: {...mergeProps(rowProps, treeGridRowProps)},\n gridCellProps,\n descriptionProps: {\n id: descriptionId\n },\n ...itemStates\n };\n}\n\nfunction last(walker: TreeWalker) {\n let next: FocusableElement | null = null;\n let last: FocusableElement | null = null;\n do {\n last = walker.lastChild() as FocusableElement | null;\n if (last) {\n next = last;\n }\n } while (last);\n return next;\n}\n\nfunction getDirectChildren<T>(parent: RSNode<T>, collection: Collection<RSNode<T>>) {\n // We can't assume that we can use firstChildKey because if a person builds a tree using hooks, they would not have access to that property (using type Node vs CollectionNode)\n // Instead, get all children and start at the first node (rather than just using firstChildKey) and only look at its siblings\n let children = collection.getChildren?.(parent.key);\n let childArray = children ? Array.from(children) : [];\n let node = childArray.length > 0 ? childArray[0] : null;\n let siblings: RSNode<T>[] = [];\n while (node) {\n siblings.push(node);\n node = node.nextKey != null ? collection.getItem(node.nextKey) : null;\n }\n return siblings;\n}\n"],"names":[],"version":3,"file":"useGridListItem.mjs.map"}