@mantine/core
Version:
React components library focused on usability, accessibility and developer experience
342 lines (335 loc) • 11.5 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
var React = require('react');
var cx = require('clsx');
var hooks = require('@mantine/hooks');
var InputWrapper = require('../InputWrapper/InputWrapper.js');
var CloseButton = require('../ActionIcon/CloseButton/CloseButton.js');
var Input = require('../Input/Input.js');
var Paper = require('../Paper/Paper.js');
var Text = require('../Text/Text.js');
var ChevronIcon = require('../NativeSelect/ChevronIcon.js');
var NativeSelect = require('../NativeSelect/NativeSelect.js');
var Transition = require('../Transition/Transition.js');
var DefaultItem = require('./DefaultItem/DefaultItem.js');
var scrollIntoView = require('./scroll-into-view/scroll-into-view.js');
var Select_styles = require('./Select.styles.js');
var useMantineTheme = require('../../theme/use-mantine-theme/use-mantine-theme.js');
var mergeStyles = require('../../theme/utils/merge-styles/merge-styles.js');
var getSizeValue = require('../../theme/utils/get-size-value/get-size-value.js');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e['default'] : e; }
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
var cx__default = /*#__PURE__*/_interopDefaultLegacy(cx);
var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
var __objRest = (source, exclude) => {
var target = {};
for (var prop in source)
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
target[prop] = source[prop];
if (source != null && __getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(source)) {
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
target[prop] = source[prop];
}
return target;
};
function defaultFilter(value, item) {
return item.label.toLowerCase().trim().includes(value.toLowerCase().trim());
}
function Select(_a) {
var _b = _a, {
className,
style,
required = false,
label,
id,
error,
description,
size = "sm",
shadow = "sm",
data,
value,
defaultValue,
onChange,
itemComponent: Item = DefaultItem.DefaultItem,
onKeyDown,
onFocus,
onBlur,
transition = "fade",
transitionDuration = 0,
initiallyOpened = false,
transitionTimingFunction,
wrapperProps,
elementRef,
themeOverride,
classNames,
styles,
filter = defaultFilter,
maxDropdownHeight = 220,
searchable = false,
clearable = false,
nothingFound,
clearButtonLabel
} = _b, others = __objRest(_b, [
"className",
"style",
"required",
"label",
"id",
"error",
"description",
"size",
"shadow",
"data",
"value",
"defaultValue",
"onChange",
"itemComponent",
"onKeyDown",
"onFocus",
"onBlur",
"transition",
"transitionDuration",
"initiallyOpened",
"transitionTimingFunction",
"wrapperProps",
"elementRef",
"themeOverride",
"classNames",
"styles",
"filter",
"maxDropdownHeight",
"searchable",
"clearable",
"nothingFound",
"clearButtonLabel"
]);
const theme = useMantineTheme.useMantineTheme(themeOverride);
const classes = Select_styles['default']({ theme, size }, classNames, "select");
const _styles = mergeStyles.mergeStyles(classes, styles);
const [dropdownOpened, setDropdownOpened] = React.useState(initiallyOpened);
const [hovered, setHovered] = React.useState(-1);
const inputRef = React.useRef();
const dropdownRef = React.useRef();
const itemsRefs = React.useRef({});
const uuid = hooks.useId(id);
const [_value, handleChange] = hooks.useUncontrolled({
value,
defaultValue,
finalValue: null,
onChange,
rule: (val) => typeof val === "string"
});
const selectedValue = data.find((item) => item.value === _value);
const [inputValue, setInputValue] = React.useState((selectedValue == null ? void 0 : selectedValue.label) || "");
const handleClear = () => {
var _a2;
handleChange(null);
setInputValue("");
(_a2 = inputRef.current) == null ? void 0 : _a2.focus();
};
React.useEffect(() => {
const newSelectedValue = data.find((item) => item.value === value);
if (newSelectedValue) {
setInputValue(newSelectedValue.label);
}
}, [value]);
const handleItemSelect = (item) => {
handleChange(item.value);
setHovered(-1);
setInputValue(item.label);
setDropdownOpened(false);
inputRef.current.focus();
};
const shouldFilter = searchable && data.every((item) => item.label !== inputValue);
const filteredData = shouldFilter ? data.filter((item) => filter(inputValue, item)) : data;
const items = filteredData.map((item, index) => /* @__PURE__ */ React__default.createElement(Item, __spreadValues({
key: item.value,
className: cx__default(classes.item, {
[classes.hovered]: hovered === index,
[classes.selected]: item.value === _value
}),
style: __spreadValues(__spreadValues({}, _styles.item), hovered === index ? _styles.hovered : null),
onMouseEnter: () => setHovered(index),
id: `${uuid}-${index}`,
role: "option",
"aria-selected": hovered === index,
elementRef: (node) => {
itemsRefs.current[item.value] = node;
},
onMouseDown: (event) => {
event.preventDefault();
handleItemSelect(item);
}
}, item)));
const handleInputKeydown = (event) => {
typeof onKeyDown === "function" && onKeyDown(event);
switch (event.nativeEvent.code) {
case "ArrowUp": {
event.preventDefault();
setDropdownOpened(true);
setHovered((current) => {
var _a2;
const nextIndex = current > 0 ? current - 1 : current;
scrollIntoView.scrollIntoView(dropdownRef.current, itemsRefs.current[(_a2 = filteredData[nextIndex]) == null ? void 0 : _a2.value]);
return nextIndex;
});
break;
}
case "ArrowDown": {
event.preventDefault();
setDropdownOpened(true);
setHovered((current) => {
var _a2;
const nextIndex = current < filteredData.length - 1 ? current + 1 : current;
scrollIntoView.scrollIntoView(dropdownRef.current, itemsRefs.current[(_a2 = filteredData[nextIndex]) == null ? void 0 : _a2.value]);
return nextIndex;
});
break;
}
case "Escape": {
event.preventDefault();
setDropdownOpened(false);
setHovered(-1);
break;
}
case "Space": {
if (!searchable && !dropdownOpened) {
event.preventDefault();
setDropdownOpened(true);
setHovered(0);
}
break;
}
case "Enter": {
if (filteredData[hovered]) {
event.preventDefault();
handleItemSelect(filteredData[hovered]);
}
}
}
};
const handleInputFocus = (event) => {
typeof onFocus === "function" && onFocus(event);
setDropdownOpened(true);
};
const handleInputBlur = (event) => {
typeof onBlur === "function" && onBlur(event);
const selected = data.find((item) => item.value === _value);
setInputValue((selected == null ? void 0 : selected.label) || "");
setDropdownOpened(false);
};
const handleInputChange = (event) => {
if (clearable && event.currentTarget.value === "") {
handleChange(null);
setInputValue("");
} else {
setInputValue(event.currentTarget.value);
}
setHovered(0);
setDropdownOpened(true);
};
const shouldShowClear = clearable && !!selectedValue;
const rightSection = shouldShowClear ? /* @__PURE__ */ React__default.createElement(CloseButton.CloseButton, {
themeOverride,
variant: "transparent",
"aria-label": clearButtonLabel,
onClick: handleClear,
size
}) : /* @__PURE__ */ React__default.createElement(ChevronIcon.ChevronIcon, {
error,
size,
themeOverride
});
return /* @__PURE__ */ React__default.createElement(InputWrapper.InputWrapper, __spreadValues({
required,
id: uuid,
label,
error,
description,
size,
className,
style,
themeOverride,
classNames,
styles,
__staticSelector: "select"
}, wrapperProps), /* @__PURE__ */ React__default.createElement("div", {
className: classes.wrapper,
style: _styles.wrapper,
role: "combobox",
"aria-haspopup": "listbox",
"aria-owns": `${uuid}-items`,
"aria-controls": uuid,
"aria-expanded": dropdownOpened,
onMouseLeave: () => setHovered(-1),
tabIndex: -1
}, /* @__PURE__ */ React__default.createElement(Input.Input, __spreadProps(__spreadValues({}, others), {
type: "text",
required,
elementRef: hooks.useMergedRef(elementRef, inputRef),
id: uuid,
invalid: !!error,
size,
onKeyDown: handleInputKeydown,
themeOverride,
classNames: __spreadProps(__spreadValues({}, classNames), {
input: cx__default({ [classes.notSearchable]: !searchable }, classNames == null ? void 0 : classNames.input)
}),
styles: __spreadProps(__spreadValues({}, styles), {
rightSection: __spreadProps(__spreadValues({}, styles == null ? void 0 : styles.rightSection), {
pointerEvents: shouldShowClear ? void 0 : "none"
})
}),
__staticSelector: "select",
value: inputValue,
onChange: handleInputChange,
"aria-autocomplete": "list",
"aria-controls": dropdownOpened ? `${uuid}-items` : null,
"aria-activedescendant": hovered !== -1 ? `${uuid}-${hovered}` : null,
onClick: () => setDropdownOpened(true),
onFocus: handleInputFocus,
onBlur: handleInputBlur,
readOnly: !searchable,
rightSection,
rightSectionWidth: getSizeValue.getSizeValue({ size, sizes: NativeSelect.rightSectionWidth })
})), /* @__PURE__ */ React__default.createElement(Transition.Transition, {
mounted: dropdownOpened,
transition,
duration: transitionDuration,
timingFunction: transitionTimingFunction
}, (transitionStyles) => /* @__PURE__ */ React__default.createElement(Paper.Paper, {
id: `${uuid}-items`,
"aria-labelledby": `${uuid}-label`,
role: "listbox",
className: classes.dropdown,
shadow,
elementRef: dropdownRef,
style: __spreadProps(__spreadValues(__spreadValues({}, _styles.dropdown), transitionStyles), { maxHeight: maxDropdownHeight })
}, items.length > 0 ? items : /* @__PURE__ */ React__default.createElement(Text.Text, {
size,
className: classes.nothingFound,
style: _styles.nothingFound
}, nothingFound)))));
}
Select.displayName = "@mantine/core/Select";
exports.Select = Select;
//# sourceMappingURL=Select.js.map