UNPKG

@react-aria/listbox

Version:
218 lines (194 loc) • 6.13 kB
var { isFocusVisible, useHover, usePress } = require("@react-aria/interactions"); var { useSelectableList, useSelectableItem } = require("@react-aria/selection"); var { useLabel } = require("@react-aria/label"); var { filterDOMProps, mergeProps, useId, useSlotId } = require("@react-aria/utils"); var _babelRuntimeHelpersExtends = $parcel$interopDefault(require("@babel/runtime/helpers/extends")); function $parcel$interopDefault(a) { return a && a.__esModule ? a.default : a; } /* * Copyright 2020 Adobe. All rights reserved. * This file is licensed to you under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS * OF ANY KIND, either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ const listIds = new WeakMap(); exports.listIds = listIds; function $e25442753cf4918277b5a7f1d4$var$normalizeKey(key) { if (typeof key === 'string') { return key.replace(/\s*/g, ''); } return '' + key; } function getItemId(state, itemKey) { let listId = listIds.get(state); if (!listId) { throw new Error('Unknown list'); } return listId + "-option-" + $e25442753cf4918277b5a7f1d4$var$normalizeKey(itemKey); } exports.getItemId = getItemId; /** * Provides the behavior and accessibility implementation for a listbox component. * A listbox displays a list of options and allows a user to select one or more of them. * @param props - Props for the listbox. * @param state - State for the listbox, as returned by `useListState`. */ function useListBox(props, state, ref) { let domProps = filterDOMProps(props, { labelable: true }); let { listProps } = useSelectableList(_babelRuntimeHelpersExtends({}, props, { ref, selectionManager: state.selectionManager, collection: state.collection, disabledKeys: state.disabledKeys })); let id = useId(props.id); listIds.set(state, id); let { labelProps, fieldProps } = useLabel(_babelRuntimeHelpersExtends({}, props, { id, // listbox is not an HTML input element so it // shouldn't be labeled by a <label> element. labelElementType: 'span' })); return { labelProps, listBoxProps: mergeProps(domProps, state.selectionManager.selectionMode === 'multiple' ? { 'aria-multiselectable': 'true' } : {}, _babelRuntimeHelpersExtends({ role: 'listbox' }, mergeProps(fieldProps, listProps))) }; } exports.useListBox = useListBox; const $f10fc7bba5e201cb95788604af75$var$isSafariMacOS = typeof window !== 'undefined' && window.navigator != null ? /^Mac/.test(window.navigator.platform) && /Safari/.test(window.navigator.userAgent) && !/Chrome/.test(window.navigator.userAgent) : false; /** * Provides the behavior and accessibility implementation for an option in a listbox. * See `useListBox` for more details about listboxes. * @param props - Props for the option. * @param state - State for the listbox, as returned by `useListState`. */ function useOption(props, state, ref) { let { isSelected, isDisabled, key, shouldSelectOnPressUp, shouldFocusOnHover, isVirtualized, shouldUseVirtualFocus } = props; let labelId = useSlotId(); let descriptionId = useSlotId(); let optionProps = { role: 'option', 'aria-disabled': isDisabled, 'aria-selected': isSelected }; // Safari with VoiceOver on macOS misreads options with aria-labelledby or aria-label as simply "text". // We should not map slots to the label and description on Safari and instead just have VoiceOver read the textContent. // https://bugs.webkit.org/show_bug.cgi?id=209279 if (!$f10fc7bba5e201cb95788604af75$var$isSafariMacOS) { optionProps['aria-label'] = props['aria-label']; optionProps['aria-labelledby'] = labelId; optionProps['aria-describedby'] = descriptionId; } if (isVirtualized) { optionProps['aria-posinset'] = state.collection.getItem(key).index + 1; optionProps['aria-setsize'] = state.collection.size; } let { itemProps } = useSelectableItem({ selectionManager: state.selectionManager, key, ref, shouldSelectOnPressUp, isVirtualized, shouldUseVirtualFocus }); let { pressProps } = usePress(_babelRuntimeHelpersExtends({}, itemProps, { isDisabled, preventFocusOnPress: shouldUseVirtualFocus })); let { hoverProps } = useHover({ isDisabled: isDisabled || !shouldFocusOnHover, onHoverStart() { if (!isFocusVisible()) { state.selectionManager.setFocused(true); state.selectionManager.setFocusedKey(key); } } }); return { optionProps: _babelRuntimeHelpersExtends({}, optionProps, mergeProps(pressProps, hoverProps), { id: getItemId(state, key) }), labelProps: { id: labelId }, descriptionProps: { id: descriptionId } }; } exports.useOption = useOption; /** * Provides the behavior and accessibility implementation for a section in a listbox. * See `useListBox` for more details about listboxes. * @param props - Props for the section. */ function useListBoxSection(props) { let { heading, 'aria-label': ariaLabel } = props; let headingId = useId(); return { itemProps: { role: 'presentation' }, headingProps: heading ? { // Techincally, listbox cannot contain headings according to ARIA. // We hide the heading from assistive technology, and only use it // as a label for the nested group. id: headingId, 'aria-hidden': true } : {}, groupProps: { role: 'group', 'aria-label': ariaLabel, 'aria-labelledby': heading ? headingId : undefined } }; } exports.useListBoxSection = useListBoxSection; //# sourceMappingURL=main.js.map