@patreon/studio
Version:
Patreon Studio Design System
105 lines (104 loc) • 4.27 kB
JSX
'use client';
import React from 'react';
import { styled } from 'styled-components';
import { tokens } from '~/tokens';
import { convertLegacyUnitValue } from '~/utilities/legacy-units';
import { List } from './components/List';
import { keyCodes } from './lib/keycodes';
const HANDLED_KEYCODES = [keyCodes.ENTER, keyCodes.UP, keyCodes.DOWN];
/** @deprecated use `OverlayTriggerMenu` instead. */
// TODO (legacied react-prefer-function-component/react-prefer-function-component)
// This failure is legacied in and should be updated. DO NOT COPY.
// eslint-disable-next-line react-prefer-function-component/react-prefer-function-component
export class DropdownList extends React.Component {
static defaultProps = {
keyboardNav: true,
};
state = {
currentIndex: -1,
};
get items() {
return this.props.items.map((item, i) => i === this.state.currentIndex
? {
...item,
isHighlighted: true,
}
: item);
}
componentDidMount() {
if (this.props.keyboardNav) {
document.addEventListener('keydown', this.handleKeyDown);
}
}
componentWillUnmount() {
if (this.props.keyboardNav) {
document.removeEventListener('keydown', this.handleKeyDown);
}
}
handleKeyDown = (e) => {
const { onSelectItem, selectedIndex } = this.props;
if (!HANDLED_KEYCODES.includes(e.key)) {
return;
}
const currentIndex = this.state.currentIndex;
let index = this.state.currentIndex;
let startingIndex;
const itemsLength = this.props.items.length;
switch (e.key) {
case keyCodes.ENTER: {
if (currentIndex > -1) {
e.preventDefault();
const item = this.props.items[currentIndex];
if (item && onSelectItem) {
onSelectItem(item, currentIndex, e);
}
this.setState({ currentIndex: -1 });
}
break;
}
case keyCodes.UP: {
e.preventDefault();
const prevIndex = (i) => (i - 1 < 0 ? itemsLength - 1 : i - 1);
index = prevIndex(index);
startingIndex = currentIndex > -1 ? currentIndex : index;
while (index === selectedIndex || this.items[index].disabled) {
index = prevIndex(index);
if (index === startingIndex) {
index = currentIndex;
break;
}
}
this.setState({ currentIndex: index });
break;
}
case keyCodes.DOWN: {
e.preventDefault();
const nextIndex = (i) => (i + 1 > itemsLength - 1 ? 0 : i + 1);
index = nextIndex(currentIndex);
startingIndex = currentIndex > -1 ? currentIndex : index;
while (index === selectedIndex || this.items[index].disabled) {
index = nextIndex(index);
if (index === startingIndex) {
index = currentIndex;
break;
}
}
this.setState({ currentIndex: index });
break;
}
}
};
render() {
const { emptyState, hideLines, maxHeight, itemRenderer, noWrap, onSelectItem, selectedIndex, keyboardNav } = this.props;
return (<ListContainer maxHeight={maxHeight} noWrap={noWrap}>
<List emptyState={emptyState} hideLines={hideLines} itemRenderer={itemRenderer} items={this.items} onSelectItem={onSelectItem} selectedIndex={selectedIndex} keyboardNav={keyboardNav}/>
</ListContainer>);
}
}
const ListContainer = styled.div `
overflow-y: ${(props) => (props.maxHeight ? 'auto' : 'visible')};
white-space: ${(props) => (props.noWrap ? 'nowrap' : 'normal')};
margin: calc(-1 * ${tokens.global.space.x16});
max-height: ${(props) => typeof props.maxHeight === 'number' ? convertLegacyUnitValue(props.maxHeight) : props.maxHeight};
`;
//# sourceMappingURL=DropdownList.jsx.map