@wix/design-system
Version:
@wix/design-system
112 lines • 5.26 kB
JavaScript
import React from 'react';
import { ChevronDownSmall } from '@wix/wix-ui-icons-common';
import { classes } from './BadgeSelect.st.css.js';
import DropdownLayout from '../DropdownLayout';
import PopoverNext from '../PopoverNext';
import Badge from '../Badge';
import { badgeSelectItemBuilder } from '../BadgeSelectItem';
import * as DATA_ATTR from './DataAttr';
import { IconThemeContext } from '../WixDesignSystemIconThemeProvider/IconThemeContext';
class BadgeSelect extends React.Component {
constructor(props) {
super(props);
this._isControlled = () => {
return typeof this.props.selectedId !== 'undefined';
};
/**
* Determine if a certain key should open the DropdownLayout
*
* @param {KeyboardEvent.key} key - The key name
* @return {boolean} - Whether the key should cause the DropdownLayout to open
*/
this._isOpenKey = key => {
return ['Enter', 'Spacebar', ' ', 'ArrowDown'].includes(key);
};
this._getBadgeOptionById = (options, wantedId) => {
return options.find(({ id }) => id === wantedId);
};
this._handleSelect = ({ id: selectedId }) => {
const { onSelect, options } = this.props;
const selectedBadge = this._getBadgeOptionById(options, selectedId);
const newState = { visible: false };
if (!this._isControlled()) {
newState.selectedBadge = selectedBadge;
}
this.setState(newState);
onSelect && onSelect(selectedBadge);
};
this._onKeyDown = event => {
// Delegate the event to the DropdownLayout. It'll handle the navigation,
// option selection and closing of the dropdown.
const isHandledByDropdownLayout = this.dropdownLayout
? this.dropdownLayout._onSelectListKeyDown(event)
: false;
// If the event wasn't handled by the DropdownLayout correctly, check if
// the pressed key should open the dropdown and act accordingly.
if (!isHandledByDropdownLayout) {
if (this._isOpenKey(event.key)) {
this.showDropdown();
event.preventDefault();
}
}
};
this.getSelectedOption = props => {
return (this._getBadgeOptionById(props.options, props.selectedId) ||
props.options[0]);
};
this.hideDropdown = () => {
this.setState({ visible: false });
};
this.showDropdown = () => {
this.setState({ visible: true });
};
this.toggleDropdown = () => {
this.setState({ visible: !this.state.visible });
};
this.state = {
visible: false,
selectedBadge: this.getSelectedOption(props),
};
}
get options() {
const { options } = this.props;
return Array.isArray(options)
? options.map(option => badgeSelectItemBuilder({ ...option }))
: [];
}
UNSAFE_componentWillReceiveProps(nextProps) {
if (this.props.selectedId !== nextProps.selectedId) {
this.setState({
selectedBadge: this.getSelectedOption(nextProps),
});
}
}
render() {
const { type, size, uppercase, dataHook, popoverProps } = this.props;
const { visible, selectedBadge } = this.state;
return (React.createElement(IconThemeContext.Consumer, null, ({ icons = {} }) => {
const ChevronDownSmallIcon = icons.BadgeSelect?.ChevronDownSmall || ChevronDownSmall;
return (React.createElement(PopoverNext, { open: visible, onOpenChange: (open, reason) => {
if (!open &&
(reason === 'outside-press' || reason === 'escape-key')) {
this.hideDropdown();
}
}, focusManagerEnabled: false, dataHook: dataHook, placement: "bottom", moveBy: { y: 4 }, maxWidth: "300px", onKeyDown: this._onKeyDown, autoUpdateOptions: { animationFrame: true }, ...popoverProps, className: classes.root },
React.createElement(PopoverNext.Trigger, null,
React.createElement("span", null,
React.createElement(Badge, { type: type, size: size, uppercase: uppercase, suffixIcon: React.createElement(ChevronDownSmallIcon, null), skin: this.state.selectedBadge.skin, onClick: this.toggleDropdown, dataHook: DATA_ATTR.DATA_BADGE }, this.state.selectedBadge.text))),
React.createElement(PopoverNext.Content, null,
React.createElement(DropdownLayout, { ref: r => {
this.dropdownLayout = r;
}, dataHook: DATA_ATTR.DATA_DROPDOWN, visible: true, selectedId: selectedBadge.id, options: this.options, onSelect: this._handleSelect, onClose: this.hideDropdown, inContainer: true }))));
}));
}
}
BadgeSelect.displayName = 'BadgeSelect';
BadgeSelect.defaultProps = {
size: 'medium',
type: 'solid',
uppercase: true,
};
export default BadgeSelect;
//# sourceMappingURL=BadgeSelect.js.map