UNPKG

@re-flex/ui

Version:
87 lines (86 loc) 4.53 kB
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;