@itwin/itwinui-react
Version:
A react component library for iTwinUI
184 lines (183 loc) • 5.3 kB
JavaScript
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';