UNPKG

@etsoo/materialui

Version:

TypeScript Material-UI Implementation

94 lines (93 loc) 3.86 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { useDelayedExecutor } from "@etsoo/react"; import CheckBoxIcon from "@mui/icons-material/CheckBox"; import React from "react"; import { VBox } from "./FlexBox"; import ListItemButton from "@mui/material/ListItemButton"; import List from "@mui/material/List"; import TextField from "@mui/material/TextField"; import ListItem from "@mui/material/ListItem"; import ListItemText from "@mui/material/ListItemText"; /** * List chooser * @param props Props * @returns Component */ export function ListChooser(props) { // Selected ids state const [selectedIds, setSelectedIds] = React.useState([]); const selectProps = (id) => ({ selected: selectedIds.includes(id), onClick: () => { if (multiple) { const index = selectedIds.indexOf(id); if (index === -1) selectedIds.push(id); else selectedIds.splice(index, 1); setSelectedIds([...selectedIds]); } else { setSelectedIds([id]); } } }); // Destruct const { conditionField = "title", conditionRenderer = (rq, delayed) => (_jsx(TextField, { autoFocus: true, margin: "dense", name: conditionField, label: title, fullWidth: true, variant: "standard", slotProps: { htmlInput: { maxLength: 128 } }, onChange: (event) => { Reflect.set(rq, "title", event.target.value); delayed.call(); } })), itemRenderer = (item, selectProps) => { const id = item[idField]; const sp = selectProps(id); const label = typeof labelField === "function" ? labelField(item) : Reflect.get(item, labelField); return (_jsx(ListItem, { disableGutters: true, secondaryAction: sp.selected ? _jsx(CheckBoxIcon, { fontSize: "small" }) : undefined, children: _jsx(ListItemButton, { ...sp, children: _jsx(ListItemText, { primary: label }) }) }, `${id}`)); }, idField = "id", labelField = "label", loadData, multiple = false, onItemChange, title, doubleClickEnabled = false, onDoubleClick, ...rest } = props; // Default minimum height rest.sx ??= { minHeight: "220px" }; // State const [items, setItems] = React.useState([]); // Query request data const mounted = React.useRef(false); const rq = React.useRef({}); // Delayed execution const delayed = useDelayedExecutor(async () => { const result = await loadData(rq.current); if (result == null || !mounted.current) return; if (!multiple && selectedIds.length > 0 && !result.some((item) => selectedIds.includes(item[idField]))) { setSelectedIds([]); } setItems(result); }, 480); React.useEffect(() => { if (!mounted.current) return; onItemChange(items.filter((item) => selectedIds.includes(item[idField])), selectedIds); }, [selectedIds]); React.useEffect(() => { mounted.current = true; delayed.call(0); return () => { mounted.current = false; delayed.clear(); }; }, [delayed]); const onDoubleClickLocal = (event) => { if (onDoubleClick) onDoubleClick(event); if (doubleClickEnabled) { const button = event.currentTarget .closest("form") ?.elements.namedItem("okButton"); if (button) { button.click(); } } }; // Layout return (_jsxs(VBox, { children: [conditionRenderer(rq.current, delayed), _jsx(List, { onDoubleClick: onDoubleClickLocal, disablePadding: true, dense: true, ...rest, children: items.map((item) => itemRenderer(item, selectProps)) })] })); }