UNPKG

@workday/canvas-kit-labs-react

Version:

Canvas Kit Labs is an incubator for new and experimental components. Since we have a rather rigorous process for getting components in at a production level, it can be valuable to make them available earlier while we continuously iterate on the API/functi

70 lines (69 loc) 3.17 kB
import React, { Fragment, useState } from 'react'; import styled from '@emotion/styled'; import { space } from '@workday/canvas-kit-react/tokens'; import { accessibleHide, generateUniqueId } from '@workday/canvas-kit-react/common'; import { getOptionId, listBoxIdPart, getTextFromElement } from './Combobox'; const Autocomplete = styled('ul')({ margin: 0, maxHeight: 200, boxSizing: 'border-box', overflowY: 'auto', padding: `${space.xxs} 0`, }); const AccessibleHide = styled('span')(accessibleHide); export const AutocompleteList = ({ autocompleteItems, comboboxId, selectedIndex, handleAutocompleteClick, labelId, showGroupText, }) => { const [randomComponentId] = useState(generateUniqueId); // https://codesandbox.io/s/p2ndq const componentId = comboboxId || randomComponentId; const listBoxProps = { role: 'listbox', id: `${componentId}-${listBoxIdPart}`, 'aria-labelledby': labelId, }; const createListItem = (listboxItem, itemIndex, groupMessage) => { const children = [ React.createElement(AccessibleHide, { key: `group-message-${itemIndex}` }, groupMessage), ...React.Children.toArray(listboxItem.props.children), ]; return (React.createElement(Fragment, { key: itemIndex }, React.cloneElement(listboxItem, { children: children, id: getOptionId(componentId, itemIndex), role: 'option', isFocused: selectedIndex === itemIndex, 'aria-selected': selectedIndex === itemIndex ? true : undefined, onMouseDown: (event) => { // prevent focus from shifting away from the the combobox event.preventDefault(); }, onClick: (event) => { event.preventDefault(); handleAutocompleteClick(event, listboxItem.props); }, }))); }; if (!autocompleteItems.length) { return null; } else if (autocompleteItems[0].hasOwnProperty('header')) { let itemIndex = 0; return (React.createElement(Autocomplete, { ...listBoxProps }, autocompleteItems.map(({ header, items }, groupIndex) => { const groupLabel = `itemGroup-${componentId}-${groupIndex}`; return (React.createElement(Fragment, { key: groupLabel }, React.cloneElement(header, { role: 'presentation', style: { pointerEvents: `none` }, }), items.map((listboxItem) => { const headerName = getTextFromElement(header); const groupMessage = showGroupText ? `Entering group ${headerName}, with ${items.length} options.` : undefined; const item = createListItem(listboxItem, itemIndex, groupMessage); itemIndex++; return item; }))); }))); } else { return (React.createElement(Autocomplete, { ...listBoxProps }, autocompleteItems.map((listboxItem, index) => createListItem(listboxItem, index)))); } };