@re-flex/ui
Version:
Re-Flex ui library
87 lines (86 loc) • 4.53 kB
JavaScript
import { css } from "@re-flex/styles";
import { convertUnit2Rem } from "@re-flex/utils";
import React, { useCallback, useMemo, useRef } from "react";
import Chip from "../Chip";
import Divider from "../Divider";
import IconButton from "../IconButton";
import ListItem from "../ListItem";
import Popper from "../Popper";
import TextField from "../TextField";
const Select = ({ onChange, value, mode = "single", variant = "select", previewType = "text", renderInput = TextField, renderValue = ({ title }) => React.createElement(Chip, { label: title, size: "md" }), inputProps = { variant: "outlined" }, fieldKeyName = "value", children, dataSource, renderListItem, renderSeperator = React.createElement(Divider, { spacing: 0 }), }) => {
const popperRef = useRef(null);
const checkControl = useCallback((item) => {
return ((mode === "multiple" &&
Array.isArray(value) &&
value.find((a) => a === item.value)) ||
(mode === "single" && value === item.value));
}, [value, dataSource, mode]);
const selectOptionList = useMemo(() => {
const contentSource = [];
for (let dataIndex = 0; dataIndex < dataSource.length; dataIndex++) {
const { key, value: optionValue, title, description, prefixIcon, } = dataSource[dataIndex];
const isChecked = mode === "multiple" &&
Array.isArray(value) &&
checkControl(dataSource[dataIndex]);
const element = (React.createElement(ListItem, { title: title, description: description, leftItem: prefixIcon, key: key || `${dataIndex}`, button: true, onClick: () => {
onChange(mode === "multiple"
? isChecked && value.includes(optionValue)
? value.filter((a) => a !== optionValue)
: [...(value || []), optionValue]
: optionValue);
popperRef.current?.close();
}, rightItem: React.createElement("span", { className: css({
opacity: isChecked ? 1 : 0,
transition: "all .2s ease-in-out",
}, "material-icons") }, "done") }));
contentSource.push(element);
if (dataIndex !== dataSource.length) {
contentSource.push(renderSeperator);
}
}
return contentSource;
}, [dataSource, renderListItem, renderSeperator]);
const renderInputValue = useMemo(() => {
const inputValue = dataSource.filter(checkControl);
return inputValue.length === 0 ? null : inputValue.map(renderValue);
}, [value, dataSource]);
return (React.createElement(Popper, { popperRef: popperRef, content: selectOptionList, placement: "auto" },
React.createElement("div", { className: css({
display: "flex",
flexWrap: "wrap",
}) }, renderInput &&
renderInput({
...inputProps,
onChange,
value: renderInputValue,
tag: "button",
readOnly: true,
fullWidth: true,
sx: {
"&>div": {
p: "0",
minHeight: "48px",
},
},
endAdornment: (React.createElement("div", { className: css({
display: "flex",
marginRight: convertUnit2Rem(8),
gap: convertUnit2Rem(8),
alignItems: "center",
}) },
!!value && (React.createElement(IconButton, { onClick: (e) => {
e.preventDefault();
e.stopPropagation();
if (onChange) {
onChange(mode === "multiple" ? [] : null);
}
}, hidden: mode === "multiple"
? !(Array.isArray(value) && value.length > 0)
: !(value !== undefined &&
value !== null &&
value !== "") },
React.createElement("span", { className: css({ fontSize: convertUnit2Rem(20) }, "material-icons") }, "clear"))),
React.createElement("span", { className: "material-icons" }, "arrow_drop_down"))),
}))));
};
export default Select;