@shopify/polaris
Version:
Shopify’s admin product component library
92 lines (89 loc) • 3.28 kB
JavaScript
import React, { useState, Children, useCallback, useMemo } from 'react';
import styles from './Combobox.scss.js';
import { ComboboxTextFieldContext, ComboboxListboxContext, ComboboxListboxOptionContext } from '../../utilities/combobox/context.js';
import { TextField } from './components/TextField/TextField.js';
import { Popover } from '../Popover/Popover.js';
function Combobox({
children,
activator,
allowMultiple,
onScrolledToBottom,
preferredPosition = 'below'
}) {
const [popoverActive, setPopoverActive] = useState(false);
const [activeOptionId, setActiveOptionId] = useState();
const [textFieldLabelId, setTextFieldLabelId] = useState();
const [listboxId, setListboxId] = useState();
const [textFieldFocused, setTextFieldFocused] = useState(false);
const shouldOpen = Boolean(!popoverActive && Children.count(children) > 0);
const onOptionSelected = useCallback(() => {
if (!allowMultiple) {
setPopoverActive(false);
setActiveOptionId(undefined);
}
}, [allowMultiple]);
const handleClose = useCallback(() => {
setPopoverActive(false);
setActiveOptionId(undefined);
}, []);
const handleFocus = useCallback(() => {
if (shouldOpen) {
setPopoverActive(true);
}
}, [shouldOpen]);
const handleChange = useCallback(() => {
if (shouldOpen) {
setPopoverActive(true);
}
}, [shouldOpen]);
const handleBlur = useCallback(() => {
if (popoverActive) {
setPopoverActive(false);
setActiveOptionId(undefined);
}
}, [popoverActive]);
const textFieldContextValue = useMemo(() => ({
activeOptionId,
expanded: popoverActive,
listboxId,
setTextFieldFocused,
setTextFieldLabelId,
onTextFieldFocus: handleFocus,
onTextFieldChange: handleChange,
onTextFieldBlur: handleBlur
}), [activeOptionId, popoverActive, listboxId, setTextFieldFocused, setTextFieldLabelId, handleFocus, handleChange, handleBlur]);
const listboxOptionContextValue = useMemo(() => ({
allowMultiple
}), [allowMultiple]);
const listboxContextValue = useMemo(() => ({
setActiveOptionId,
setListboxId,
listboxId,
textFieldLabelId,
onOptionSelected,
textFieldFocused,
onKeyToBottom: onScrolledToBottom
}), [setActiveOptionId, setListboxId, listboxId, textFieldLabelId, onOptionSelected, textFieldFocused, onScrolledToBottom]);
return /*#__PURE__*/React.createElement(Popover, {
active: popoverActive,
onClose: handleClose,
activator: /*#__PURE__*/React.createElement(ComboboxTextFieldContext.Provider, {
value: textFieldContextValue
}, activator),
autofocusTarget: "none",
preventFocusOnClose: true,
fullWidth: true,
preferInputActivator: false,
preferredPosition: preferredPosition
}, /*#__PURE__*/React.createElement(Popover.Pane, {
onScrolledToBottom: onScrolledToBottom
}, Children.count(children) > 0 ? /*#__PURE__*/React.createElement(ComboboxListboxContext.Provider, {
value: listboxContextValue
}, /*#__PURE__*/React.createElement(ComboboxListboxOptionContext.Provider, {
value: listboxOptionContextValue
}, /*#__PURE__*/React.createElement("div", {
className: styles.Listbox
}, children))) : null));
}
Combobox.TextField = TextField;
export { Combobox };