UNPKG

@itwin/itwinui-react

Version:

A react component library for iTwinUI

184 lines (183 loc) 5.3 kB
import * as React from 'react'; import cx from 'classnames'; import { getFocusableElements, useMergedRefs, useId, useSafeContext, Box, polymorphic, } from '../../utils/index.js'; import { List } from '../List/List.js'; import { ListItem } from '../List/ListItem.js'; import { Label } from '../Label/Label.js'; import { ButtonGroup } from '../ButtonGroup/ButtonGroup.js'; let TransferListComponent = polymorphic.div('iui-transfer-list-wrapper'); if ('development' === process.env.NODE_ENV) TransferListComponent.displayName = 'TransferList'; let TransferListListboxWrapper = React.forwardRef((props, ref) => { let { className, children, ...rest } = props; let uid = useId(); let [labelId, setLabelId] = React.useState(uid); return React.createElement( Box, { as: 'div', className: cx('iui-transfer-list-listbox-wrapper', className), ref: ref, ...rest, }, React.createElement( TransferListContext.Provider, { value: { labelId, setLabelId, }, }, children, ), ); }); if ('development' === process.env.NODE_ENV) TransferListListboxWrapper.displayName = 'TransferList.ListboxWrapper'; let TransferListListbox = React.forwardRef((props, ref) => { let { children, className, ...rest } = props; let { labelId } = useSafeContext(TransferListContext); let [focusedIndex, setFocusedIndex] = React.useState(); let listRef = React.useRef(null); let refs = useMergedRefs(listRef, ref); let getFocusableNodes = React.useCallback(() => { let focusableItems = getFocusableElements(listRef.current); return focusableItems.filter( (i) => !focusableItems.some((p) => p.contains(i.parentElement)), ); }, []); React.useEffect(() => { let items = getFocusableNodes(); if (null != focusedIndex) return void items?.[focusedIndex]?.focus(); }, [focusedIndex, getFocusableNodes]); let onKeyDown = (event) => { if (event.altKey) return; let items = getFocusableNodes(); if (!items?.length) return; let currentIndex = focusedIndex ?? 0; switch (event.key) { case 'ArrowDown': setFocusedIndex(Math.min(currentIndex + 1, items.length - 1)); event.preventDefault(); event.stopPropagation(); break; case 'ArrowUp': setFocusedIndex(Math.max(currentIndex - 1, 0)); event.preventDefault(); event.stopPropagation(); break; default: break; } }; return React.createElement( List, { className: cx('iui-transfer-list-listbox', className), onKeyDown: onKeyDown, role: 'listbox', 'aria-multiselectable': true, 'aria-labelledby': labelId, tabIndex: 0, ref: refs, ...rest, }, children, ); }); if ('development' === process.env.NODE_ENV) TransferListListbox.displayName = 'TransferList.Listbox'; let TransferListItem = React.forwardRef((props, ref) => { let { actionable = true, disabled, onActiveChange, children, active, ...rest } = props; let onClickEvents = () => actionable && onActiveChange && onActiveChange(!active); let onKeyDown = (event) => { if (event.altKey) return; if ( 'Enter' === event.key || ' ' === event.key || 'Spacebar' === event.key ) { disabled || onClickEvents(); event.preventDefault(); } }; return React.createElement( ListItem, { ref: ref, onClick: onClickEvents, onKeyDown: onKeyDown, active: active, actionable: actionable, tabIndex: -1, role: 'option', 'aria-disabled': disabled ? 'true' : void 0, 'aria-selected': active ? 'true' : void 0, disabled: disabled, ...rest, }, children, ); }); if ('development' === process.env.NODE_ENV) TransferListItem.displayName = 'TransferList.Item'; let TransferListListboxLabel = React.forwardRef((props, ref) => { let { children, id, ...rest } = props; let { labelId, setLabelId } = useSafeContext(TransferListContext); React.useEffect(() => { if (id && id !== labelId) setLabelId(id); }, [id, labelId, setLabelId]); return React.createElement( Label, { as: 'div', id: labelId, ref: ref, ...rest, }, children, ); }); if ('development' === process.env.NODE_ENV) TransferListListboxLabel.displayName = 'TransferList.ListboxLabel'; let TransferListToolbar = React.forwardRef((props, ref) => { let { className, children, ...rest } = props; return React.createElement( ButtonGroup, { role: 'toolbar', ref: ref, ...rest, orientation: 'vertical', className: cx('iui-transfer-list-toolbar', className), }, children, ); }); if ('development' === process.env.NODE_ENV) TransferListToolbar.displayName = 'TransferList.Toolbar'; export const TransferList = Object.assign(TransferListComponent, { ListboxWrapper: TransferListListboxWrapper, Listbox: TransferListListbox, Item: TransferListItem, ListboxLabel: TransferListListboxLabel, Toolbar: TransferListToolbar, }); export const TransferListContext = React.createContext(void 0); if ('development' === process.env.NODE_ENV) TransferListContext.displayName = 'TransferListContext';