UNPKG

@patreon/studio

Version:

Patreon Studio Design System

107 lines (106 loc) 4.37 kB
'use client'; import React from 'react'; import styled from 'styled-components'; import { tokens } from '../../../tokens'; import getDocument from '../../../utilities/get-document'; import { convertLegacyUnitValue } from '../../../utilities/legacy-units'; import { keyCodes } from '../lib/keycodes'; import { List } from './components/List'; const HANDLED_KEYCODES = [keyCodes.ENTER, keyCodes.UP, keyCodes.DOWN]; const document = getDocument(); /** @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=index.jsx.map