chakra-ui-select
Version:
Chakra ui select
739 lines (667 loc) • 22.9 kB
JavaScript
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var themeTools = require('@chakra-ui/theme-tools');
var React = require('react');
var React__default = _interopDefault(React);
var system = require('@chakra-ui/system');
var utils = require('@chakra-ui/utils');
var Icon = _interopDefault(require('@chakra-ui/icon'));
var Downshift = require('downshift');
var Downshift__default = _interopDefault(Downshift);
var formControl = require('@chakra-ui/form-control');
var reactUtils = require('@chakra-ui/react-utils');
var tag = require('@chakra-ui/tag');
var parts = ['control', 'menu', 'list', 'option', 'label', 'button'];
var baseStyleMenu = {
pos: 'absolute',
mt: 1,
w: 'full',
zIndex: 2,
overflow: 'auto',
maxH: 60,
rounded: 'md'
};
function baseStyleList(props) {
return {
py: 1,
rounded: 'md',
w: 'full',
bg: themeTools.mode("#fff", "gray.700")(props),
boxShadow: themeTools.mode("lg", "dark-lg")(props),
border: '1px',
borderColor: 'gray.100'
};
}
function baseStyleOption(props) {
return {
py: 2,
pl: 3,
pr: 9,
color: themeTools.mode("gray.900", "gray.50")(props),
pos: 'relative',
userSelect: 'none',
cursor: 'default',
fontWeight: 'normal',
transition: 'background 50ms ease-in 0s',
_focus: {
bg: themeTools.mode("gray.100", "whiteAlpha.100")(props)
},
_active: {
bg: themeTools.mode("gray.100", "whiteAlpha.200")(props)
},
_expanded: {
bg: themeTools.mode("gray.100", "whitxeAlpha.100")(props)
},
_selected: {
bg: 'gray.50',
fontWeight: 'semibold'
},
_disabled: {
opacity: 0.4,
cursor: 'not-allowed'
}
};
}
function baseStyleControl(props) {
var theme = props.theme;
return {
bg: 'white',
position: 'relative',
w: 'full',
border: '1px',
borderColor: 'gray.300',
rounded: 'md',
shadow: 'base',
textAlign: 'left',
cursor: 'default',
display: 'flex',
alignItems: 'center',
flexWrap: 'wrap',
justifyContent: 'space-between',
minH: 10,
transition: 'all 0.2s',
outline: 0,
_focusWithin: {
outline: 'none',
borderColor: 'gray.400',
boxShadow: "0 0 0 1px " + themeTools.getColor(theme, 'gray.400')
},
_focus: {
outline: 'none',
borderColor: 'gray.400',
boxShadow: "0 0 0 1px " + themeTools.getColor(theme, 'gray.400')
},
_readOnly: {
boxShadow: 'none !important',
userSelect: 'all'
},
_disabled: {
opacity: 0.4,
cursor: 'not-allowed'
},
_hover: {
borderColor: 'gray.400',
_disabled: {
borderColor: 'gray.300'
}
}
};
}
function baseStyleLabel(props) {
return {
d: 'block',
fontSize: 'sm',
fontWeight: 'medium',
color: themeTools.mode("gray.700", "gray.50")(props)
};
}
var baseStyleButton = {
zIndex: 0,
pos: 'absolute',
inset: 0,
w: '100%',
h: '100%',
cursor: 'default',
_focus: {
outline: 'none'
},
_disabled: {
opacity: 0.4,
cursor: 'not-allowed'
}
};
var baseStyle = function baseStyle(props) {
return {
menu: baseStyleMenu,
list: baseStyleList(props),
option: baseStyleOption(props),
control: baseStyleControl(props),
label: baseStyleLabel(props),
button: baseStyleButton
};
};
var SelectSingle = {
parts: parts,
baseStyle: baseStyle
};
var parts$1 = ['control', 'menu', 'list', 'option', 'label', 'button'];
var baseStyle$1 = SelectSingle.baseStyle;
var SelectMultiple = {
parts: parts$1,
baseStyle: baseStyle$1
};
var index = {
SelectSingle: SelectSingle,
SelectMultiple: SelectMultiple
};
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
function _objectWithoutPropertiesLoose(source, excluded) {
if (source == null) return {};
var target = {};
var sourceKeys = Object.keys(source);
var key, i;
for (i = 0; i < sourceKeys.length; i++) {
key = sourceKeys[i];
if (excluded.indexOf(key) >= 0) continue;
target[key] = source[key];
}
return target;
}
var sizerStyle = {
position: 'absolute',
top: 0,
left: 0,
visibility: 'hidden',
height: 0,
overflow: 'scroll',
whiteSpace: 'pre'
};
var copyStyles = function copyStyles(styles, node) {
node.style.fontSize = styles.fontSize;
node.style.fontFamily = styles.fontFamily;
node.style.fontWeight = styles.fontWeight;
node.style.fontStyle = styles.fontStyle;
node.style.letterSpacing = styles.letterSpacing;
node.style.textTransform = styles.textTransform;
};
var SearchInput = system.forwardRef(function (props, ref) {
var wrapperStyle = props.wrapperStyle,
className = props.className,
placeholder = props.placeholder,
minWidth = props.minWidth,
placeholderIsMinWidth = props.placeholderIsMinWidth,
isDisabled = props.isDisabled,
inputProps = _objectWithoutPropertiesLoose(props, ["wrapperStyle", "className", "placeholder", "minWidth", "placeholderIsMinWidth", "isDisabled"]);
var _useState = React.useState(minWidth),
inputWidth = _useState[0],
setInputWidth = _useState[1];
var inputRef = React.useRef(null);
var sizerRef = React.useRef(null);
var placeHolderSizerRef = React.useRef(null);
var _className = utils.cx('chakra-select__search-input', className);
var sizerValue = props.defaultValue || props.value || '';
React.useImperativeHandle(ref, function () {
return {
focus: function focus() {
var _inputRef$current;
inputRef === null || inputRef === void 0 ? void 0 : (_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 ? void 0 : _inputRef$current.focus();
}
};
});
React.useEffect(function () {
copyInputStyles();
}, []);
React.useEffect(function () {
var _sizerRef$current;
if (!sizerRef || typeof ((_sizerRef$current = sizerRef.current) === null || _sizerRef$current === void 0 ? void 0 : _sizerRef$current.scrollWidth) === 'undefined') {
return;
}
var newInputWidth;
if (placeholder && (!props.value || props.value && placeholderIsMinWidth)) {
var _placeHolderSizerRef$;
newInputWidth = Math.max(sizerRef.current.scrollWidth, (_placeHolderSizerRef$ = placeHolderSizerRef.current) === null || _placeHolderSizerRef$ === void 0 ? void 0 : _placeHolderSizerRef$.scrollWidth) + 2;
} else {
var _sizerRef$current2;
newInputWidth = ((_sizerRef$current2 = sizerRef.current) === null || _sizerRef$current2 === void 0 ? void 0 : _sizerRef$current2.scrollWidth) + 2;
}
if (minWidth && newInputWidth < minWidth) {
newInputWidth = minWidth;
}
if (newInputWidth !== inputWidth) {
setInputWidth(newInputWidth);
}
}, [sizerValue, minWidth, inputWidth, placeholderIsMinWidth, placeholder]);
var copyInputStyles = function copyInputStyles() {
if (!window.getComputedStyle || !(inputRef !== null && inputRef !== void 0 && inputRef.current)) {
return;
}
var inputNode = inputRef.current;
var inputStyles = inputNode && window.getComputedStyle(inputNode);
if (!inputStyles) {
return;
}
if (sizerRef.current) {
copyStyles(inputStyles, sizerRef.current);
}
if (placeHolderSizerRef.current) {
copyStyles(inputStyles, placeHolderSizerRef.current);
}
};
var _wrapperStyle = _extends({
d: 'inline-block',
visibility: isDisabled ? 'hidden' : 'visible',
color: 'gray.800'
}, wrapperStyle);
var _inputProps = _extends({
w: inputWidth + "px",
border: 0,
fontSize: 'inherit',
outline: 0,
padding: 0,
color: 'inherit',
boxSizing: 'content-box',
background: '0px center'
}, inputProps);
return React__default.createElement(system.chakra.div, Object.assign({
className: _className
}, _wrapperStyle), React__default.createElement(system.chakra.input, Object.assign({
placeholder: placeholder
}, _inputProps, {
ref: inputRef
})), React__default.createElement(system.chakra.div, {
ref: sizerRef,
sx: sizerStyle
}, sizerValue), placeholder && React__default.createElement(system.chakra.div, {
ref: placeHolderSizerRef,
sx: sizerStyle
}, placeholder));
});
var _createContext = reactUtils.createContext({
strict: false,
name: 'DownshiftContext'
}),
SelectProvider = _createContext[0],
useSelect = _createContext[1];
function SelectValueContainer(props) {
return React__default.createElement(system.chakra.div, Object.assign({
d: 'flex',
alignItems: 'center',
flex: '1 1 0%',
flexWrap: 'wrap',
padding: '2px 8px',
pos: 'relative',
overflow: 'hidden'
}, props));
}
var ArrowIndicator = system.forwardRef(function (props, ref) {
return React__default.createElement(system.chakra.div, Object.assign({
ref: ref,
pos: 'absolute',
insetY: 0,
right: 0,
pr: 2,
display: 'flex',
alignItems: 'center',
pointerEvents: 'none',
color: 'gray.500'
}, props));
});
var SelectClearIndicator = system.forwardRef(function (props, ref) {
var onClick = props.onClick,
className = props.className,
rest = _objectWithoutPropertiesLoose(props, ["onClick", "className"]);
var _useSelect = useSelect(),
selectedItem = _useSelect.selectedItem,
clearSelection = _useSelect.clearSelection,
inputRef = _useSelect.inputRef,
isDisabled = _useSelect.isDisabled;
var _className = utils.cx('chakra-select__clean-btn', className);
if (!selectedItem || isDisabled) return null;
return React__default.createElement(system.chakra.div, Object.assign({
d: 'flex',
p: 2,
ref: ref,
"aria-hidden": true,
className: _className,
zIndex: 1,
tabIndex: -1,
outline: 'none',
color: 'gray.500',
w: '100%',
h: '100%',
alignItems: 'center',
justifyContent: 'center',
_hover: {
color: 'gray.600'
}
}, rest, {
onClick: utils.callAllHandlers(onClick, function (event) {
var _inputRef$current;
event.stopPropagation();
clearSelection();
inputRef === null || inputRef === void 0 ? void 0 : (_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 ? void 0 : _inputRef$current.focus();
})
}), React__default.createElement(Icon, {
focusable: 'false',
"aria-hidden": true,
boxSize: '1em',
stroke: 'currentColor'
}, React__default.createElement("path", {
strokeLinecap: 'round',
strokeLinejoin: 'round',
strokeWidth: '2',
d: 'M6 18L18 6M6 6l12 12'
})));
});
var SelectControl = system.forwardRef(function (props, ref) {
var _useSelect2 = useSelect(),
isDisabled = _useSelect2.isDisabled;
var ownProps = formControl.useFormControl(_extends({
isDisabled: isDisabled
}, props));
var styles = system.useStyles();
return React__default.createElement(system.chakra.div, Object.assign({
ref: ref,
__css: styles.control
}, ownProps));
});
var SelectButton = system.forwardRef(function (props, ref) {
var onClick = props.onClick;
var _useSelect3 = useSelect(),
getToggleButtonProps = _useSelect3.getToggleButtonProps,
inputRef = _useSelect3.inputRef,
isDisabled = _useSelect3.isDisabled,
isOpen = _useSelect3.isOpen,
getDropdownProps = _useSelect3.getDropdownProps;
var button = formControl.useFormControl(_extends({
isDisabled: isDisabled
}, props));
var styles = system.useStyles();
return React__default.createElement(system.chakra.button, Object.assign({
__css: styles.button,
ref: ref
}, button, getToggleButtonProps(_extends({}, getDropdownProps === null || getDropdownProps === void 0 ? void 0 : getDropdownProps({
preventKeyAction: isOpen
}), {
onClick: utils.callAllHandlers(onClick, function (event) {
var _inputRef$current2;
event.stopPropagation();
inputRef === null || inputRef === void 0 ? void 0 : (_inputRef$current2 = inputRef.current) === null || _inputRef$current2 === void 0 ? void 0 : _inputRef$current2.focus();
})
}))));
});
var SelectSearchInput = system.forwardRef(function (props, ref) {
var _useSelect4 = useSelect(),
getInputProps = _useSelect4.getInputProps,
isDisabled = _useSelect4.isDisabled,
inputRef = _useSelect4.inputRef,
getDropdownProps = _useSelect4.getDropdownProps,
selectedItems = _useSelect4.selectedItems;
var input = formControl.useFormControl(_extends({
isDisabled: isDisabled
}, props));
React.useImperativeHandle(ref, function () {
return {
focus: function focus() {
var _inputRef$current3;
inputRef === null || inputRef === void 0 ? void 0 : (_inputRef$current3 = inputRef.current) === null || _inputRef$current3 === void 0 ? void 0 : _inputRef$current3.focus();
}
};
});
var placeholder = selectedItems && selectedItems.length > 0 ? '' : props.placeholder;
return React__default.createElement(React.Fragment, null, React__default.createElement(system.chakra.div, {
zIndex: 1,
m: 0.5,
pb: 0.5,
pt: 0.5,
visibility: isDisabled ? 'hidden' : 'visible'
}, React__default.createElement(SearchInput, Object.assign({
tabIndex: -1,
isDisabled: isDisabled,
type: 'text',
autoCapitalize: 'none'
}, input, getInputProps(_extends({
ref: inputRef
}, getDropdownProps === null || getDropdownProps === void 0 ? void 0 : getDropdownProps({
placeholder: placeholder,
ref: inputRef
})))))));
});
function SelectOption(_ref) {
var children = _ref.children,
value = _ref.value,
index = _ref.index,
isDisabled = _ref.isDisabled,
props = _objectWithoutPropertiesLoose(_ref, ["children", "value", "index", "isDisabled"]);
var _useSelect5 = useSelect(),
getItemProps = _useSelect5.getItemProps,
selectedItem = _useSelect5.selectedItem,
highlightedIndex = _useSelect5.highlightedIndex;
var styles = system.useStyles();
var isSelected = selectedItem === value;
var isActive = highlightedIndex === index;
return React__default.createElement(system.chakra.li, Object.assign({
bg: isActive ? 'gray.50' : 'white',
"data-disabled": utils.dataAttr(isDisabled)
}, getItemProps({
item: value,
index: index
}), {
"aria-selected": props.isSelected ? 'true' : "" + isSelected,
__css: styles.option
}, props), utils.runIfFn(children, {
isSelected: isSelected,
isActive: isActive
}));
}
var SelectMenuList = system.forwardRef(function (props, ref) {
var _useSelect6 = useSelect(),
isOpen = _useSelect6.isOpen;
var styles = system.useStyles();
if (!isOpen) return null;
return React__default.createElement(system.chakra.ul, Object.assign({
ref: ref,
__css: styles.list
}, props));
});
var SelectMenu = system.forwardRef(function (props, ref) {
var styles = system.useStyles();
var _useSelect7 = useSelect(),
getMenuProps = _useSelect7.getMenuProps;
return React__default.createElement(system.chakra.div, Object.assign({
ref: ref,
__css: styles.menu
}, getMenuProps(), props));
});
function SelectSingle$1(_ref2) {
var id = _ref2.id,
children = _ref2.children,
isOpen = _ref2.isOpen,
defaultValue = _ref2.defaultValue,
defaultIsOpen = _ref2.defaultIsOpen,
_ref2$defaultHighligh = _ref2.defaultHighlightedIndex,
defaultHighlightedIndex = _ref2$defaultHighligh === void 0 ? 0 : _ref2$defaultHighligh,
onChange = _ref2.onChange,
itemToString = _ref2.itemToString,
isDisabled = _ref2.isDisabled,
props = _objectWithoutPropertiesLoose(_ref2, ["id", "children", "isOpen", "defaultValue", "defaultIsOpen", "defaultHighlightedIndex", "onChange", "itemToString", "isDisabled"]);
var styles = system.useMultiStyleConfig('SelectSingle', {});
var inputRef = React.useRef(null);
return React__default.createElement(Downshift__default, {
id: id,
onChange: onChange,
initialSelectedItem: defaultValue,
initialIsOpen: defaultIsOpen,
isOpen: isOpen,
itemToString: itemToString,
initialHighlightedIndex: defaultHighlightedIndex
}, function (downshift) {
return React__default.createElement(system.chakra.div, Object.assign({
pos: 'relative'
}, props, downshift.getRootProps()), React__default.createElement(system.StylesProvider, {
value: styles
}, React__default.createElement(SelectProvider, {
value: _extends({}, downshift, {
isDisabled: isDisabled,
inputRef: inputRef
})
}, utils.runIfFn(children, {
inputValue: downshift.inputValue,
isOpen: downshift.isOpen,
highlightedIndex: downshift.highlightedIndex,
selectedItem: downshift.selectedItem,
getLabelProps: downshift.getLabelProps
}))));
});
}
function SelectedItemTag(_ref) {
var children = _ref.children,
selectedItem = _ref.selectedItem,
index = _ref.index,
props = _objectWithoutPropertiesLoose(_ref, ["children", "selectedItem", "index"]);
var _useSelect = useSelect(),
removeSelectedItem = _useSelect.removeSelectedItem,
getSelectedItemProps = _useSelect.getSelectedItemProps,
inputRef = _useSelect.inputRef;
return React__default.createElement(tag.Tag, Object.assign({
size: 'sm',
m: '2px',
zIndex: 1
}, props, getSelectedItemProps === null || getSelectedItemProps === void 0 ? void 0 : getSelectedItemProps({
selectedItem: selectedItem,
index: index
})), React__default.createElement(tag.TagLabel, {
color: 'primary',
fontWeight: 'semibold'
}, children), React__default.createElement(tag.TagCloseButton, {
cursor: 'default',
_focus: {
outline: 'none'
},
onClick: function onClick(e) {
var _inputRef$current;
e.stopPropagation();
removeSelectedItem === null || removeSelectedItem === void 0 ? void 0 : removeSelectedItem(selectedItem);
(_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 ? void 0 : _inputRef$current.focus();
}
}));
}
function SelectMultiple$1(_ref2) {
var id = _ref2.id,
children = _ref2.children,
onChange = _ref2.onChange,
_ref2$initialSelected = _ref2.initialSelectedItems,
initialSelectedItems = _ref2$initialSelected === void 0 ? [] : _ref2$initialSelected,
defaultSelectedItems = _ref2.defaultSelectedItems,
itemToString = _ref2.itemToString,
value = _ref2.value,
isDisabled = _ref2.isDisabled,
_ref2$defaultHighligh = _ref2.defaultHighlightedIndex,
defaultHighlightedIndex = _ref2$defaultHighligh === void 0 ? 0 : _ref2$defaultHighligh,
defaultIsOpen = _ref2.defaultIsOpen,
isOpen = _ref2.isOpen,
props = _objectWithoutPropertiesLoose(_ref2, ["id", "children", "onChange", "initialSelectedItems", "defaultSelectedItems", "itemToString", "value", "isDisabled", "defaultHighlightedIndex", "defaultIsOpen", "isOpen"]);
var inputRef = React.useRef(null);
var styles = system.useMultiStyleConfig('SelectMultiple', {});
var _useMultipleSelection = Downshift.useMultipleSelection(_extends({
defaultSelectedItems: defaultSelectedItems,
initialSelectedItems: initialSelectedItems,
onSelectedItemsChange: onChange
}, value && {
selectedItems: value
})),
getSelectedItemProps = _useMultipleSelection.getSelectedItemProps,
getDropdownProps = _useMultipleSelection.getDropdownProps,
addSelectedItem = _useMultipleSelection.addSelectedItem,
removeSelectedItem = _useMultipleSelection.removeSelectedItem,
selectedItems = _useMultipleSelection.selectedItems;
var getStateAndHelpers = React.useCallback(function (downshift) {
return _extends({}, downshift, {
selectedItems: selectedItems,
getDropdownProps: getDropdownProps,
getSelectedItemProps: getSelectedItemProps,
removeSelectedItem: removeSelectedItem
});
}, [selectedItems, getDropdownProps, getSelectedItemProps, removeSelectedItem]);
var stateReducer = React.useCallback(function (state, changes) {
switch (changes.type) {
case Downshift__default.stateChangeTypes.keyDownEnter:
case Downshift__default.stateChangeTypes.keyDownSpaceButton:
case Downshift__default.stateChangeTypes.clickItem:
return _extends({}, changes, {
highlightedIndex: state.highlightedIndex,
isOpen: true,
inputValue: ''
});
default:
return changes;
}
}, []);
var onStateChange = React.useCallback(function (_ref3) {
var type = _ref3.type,
selectedItem = _ref3.selectedItem;
switch (type) {
case Downshift__default.stateChangeTypes.keyDownEnter:
case Downshift__default.stateChangeTypes.keyDownSpaceButton:
case Downshift__default.stateChangeTypes.clickItem:
if (selectedItem) {
addSelectedItem(selectedItem);
}
break;
}
}, [addSelectedItem]);
return React__default.createElement(Downshift__default, {
id: id,
stateReducer: stateReducer,
onStateChange: onStateChange,
selectedItem: null,
itemToString: itemToString,
initialHighlightedIndex: defaultHighlightedIndex,
initialIsOpen: defaultIsOpen,
isOpen: isOpen
}, function (downshift) {
var ctx = _extends({}, getStateAndHelpers(downshift), {
isDisabled: isDisabled,
inputRef: inputRef
});
return React__default.createElement(system.chakra.div, Object.assign({
position: 'relative'
}, props, downshift.getRootProps()), React__default.createElement(system.StylesProvider, {
value: styles
}, React__default.createElement(SelectProvider, {
value: ctx
}, utils.runIfFn(children, {
inputValue: downshift.inputValue,
isOpen: downshift.isOpen,
highlightedIndex: downshift.highlightedIndex,
selectedItems: selectedItems,
getLabelProps: downshift.getLabelProps
}))));
});
}
exports.ArrowIndicator = ArrowIndicator;
exports.SelectButton = SelectButton;
exports.SelectClearIndicator = SelectClearIndicator;
exports.SelectControl = SelectControl;
exports.SelectMenu = SelectMenu;
exports.SelectMenuList = SelectMenuList;
exports.SelectMultiple = SelectMultiple$1;
exports.SelectOption = SelectOption;
exports.SelectSearchInput = SelectSearchInput;
exports.SelectSingle = SelectSingle$1;
exports.SelectValueContainer = SelectValueContainer;
exports.SelectedItemTag = SelectedItemTag;
exports.theme = index;
//# sourceMappingURL=index.js.map