UNPKG

@etsoo/materialui

Version:

TypeScript Material-UI Implementation

141 lines (140 loc) 8.45 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ButtonPopupCheckbox = ButtonPopupCheckbox; const jsx_runtime_1 = require("react/jsx-runtime"); const Button_1 = __importDefault(require("@mui/material/Button")); const Chip_1 = __importDefault(require("@mui/material/Chip")); const react_1 = __importDefault(require("react")); const Grid_1 = __importDefault(require("@mui/material/Grid")); const Typography_1 = __importDefault(require("@mui/material/Typography")); const DragIndicator_1 = __importDefault(require("@mui/icons-material/DragIndicator")); const Add_1 = __importDefault(require("@mui/icons-material/Add")); const IconButton_1 = __importDefault(require("@mui/material/IconButton")); const FormControlLabel_1 = __importDefault(require("@mui/material/FormControlLabel")); const Checkbox_1 = __importDefault(require("@mui/material/Checkbox")); const TextField_1 = __importDefault(require("@mui/material/TextField")); const FlexBox_1 = require("./FlexBox"); const ReactApp_1 = require("./app/ReactApp"); const FormLabel_1 = __importDefault(require("@mui/material/FormLabel")); const DnDList_1 = require("./DnDList"); function ButtonPopupList(props) { // Destruct const { addSplitter = /\s*[,;]\s*/, value = [], items, labelField, labelFormatter, labels, onAdd, onValueChange } = props; // Methods const dndRef = react_1.default.createRef(); // Ref const inputRef = react_1.default.useRef(null); // State const [selectedIds, setSelectedIds] = react_1.default.useState([]); react_1.default.useEffect(() => { // Sort items by ids for first load items.sortByProperty("id", value); // Set selected ids setSelectedIds([...value]); }, [value]); return ((0, jsx_runtime_1.jsxs)(FlexBox_1.VBox, { gap: 2, children: [(0, jsx_runtime_1.jsx)(DnDList_1.DnDList, { component: Grid_1.default, componentProps: { container: true, spacing: 0 }, items: items, labelField: labelField, onFormChange: (items) => { const ids = items .filter((item) => selectedIds.includes(item.id)) .map((item) => item.id); onValueChange(ids); }, itemRenderer: (item, index, nodeRef, actionNodeRef) => ((0, jsx_runtime_1.jsxs)(Grid_1.default, { size: { xs: 12, md: 6, lg: 4 }, display: "flex", justifyContent: "flex-start", alignItems: "center", gap: 1, ...nodeRef, children: [(0, jsx_runtime_1.jsx)(IconButton_1.default, { style: { cursor: "move" }, size: "small", title: labels?.dragIndicator, ...actionNodeRef, children: (0, jsx_runtime_1.jsx)(DragIndicator_1.default, {}) }), (0, jsx_runtime_1.jsx)(FormControlLabel_1.default, { control: (0, jsx_runtime_1.jsx)(Checkbox_1.default, { name: "item", value: item.id, checked: selectedIds.includes(item.id), onChange: (e) => { const checked = e.target.checked; const newIds = [ ...selectedIds.toggleItem(item.id, checked) ]; setSelectedIds(newIds); } }), label: `${index + 1}. ${labelFormatter(item)}` })] })), height: 200, mRef: dndRef }), onAdd && ((0, jsx_runtime_1.jsxs)(FlexBox_1.HBox, { gap: 1, children: [(0, jsx_runtime_1.jsx)(TextField_1.default, { variant: "outlined", label: labels?.more, fullWidth: true, inputRef: inputRef }), (0, jsx_runtime_1.jsx)(Button_1.default, { sx: { width: "120px" }, variant: "contained", startIcon: (0, jsx_runtime_1.jsx)(Add_1.default, {}), size: "small", onClick: async () => { if (inputRef.current == null) return; const input = inputRef.current.value.trim(); if (input === "") { inputRef.current.focus(); return; } const items = dndRef.current?.getItems() ?? []; const inputIds = input .split(addSplitter) .filter((id) => !items.some((item) => item.id == id)); if (inputIds.length === 0) { inputRef.current.focus(); return; } const result = await onAdd(inputIds); if (result === false) { inputRef.current.focus(); return; } dndRef.current?.addItems(result); inputRef.current.value = ""; inputRef.current.focus(); }, children: labels?.add })] }))] })); } function ButtonPopupCheckbox(props) { // App const app = (0, ReactApp_1.useRequiredAppContext)(); // Destruct const { addSplitter, value = [], inputName, label, labelEnd, labelFormatter = (data) => { if (labelField in data) { return data[labelField]; } return data.id.toString(); }, labelField, labels = {}, loadData, onAdd, onValueChange, popupTitle = label, popupMessage, required = false, sx = { gap: 1, justifyContent: "flex-start", minHeight: "56px" }, variant = "outlined", ...rest } = props; // Default labels if (!labels.add) labels.add = app.get("add"); if (!labels.dragIndicator) labels.dragIndicator = app.get("dragIndicator"); if (!labels.more) labels.more = app.get("more"); // State const [items, setItems] = react_1.default.useState([]); const [selectedIds, setSelectedIds] = react_1.default.useState(); react_1.default.useEffect(() => { if (typeof loadData === "function") { // Load data loadData().then((data) => { if (data != null) { setItems(data); } }); } else { setItems(loadData); } }, [loadData]); react_1.default.useEffect(() => { // Set selected ids setSelectedIds(value); }, [value]); // Selected ids const tempSelectedIds = react_1.default.useRef(); // Click handler const clickHandler = () => { app.showInputDialog({ title: popupTitle, message: popupMessage, callback: (form) => { if (form == null || tempSelectedIds.current == null) return; const ids = tempSelectedIds.current; setSelectedIds(ids); onValueChange?.(ids); }, inputs: ((0, jsx_runtime_1.jsx)(ButtonPopupList, { addSplitter: addSplitter, value: selectedIds, items: items, labelFormatter: labelFormatter, labelField: labelField, labels: labels, onAdd: onAdd, onValueChange: (ids) => { tempSelectedIds.current = ids; } })), fullScreen: app.smDown }); }; return ((0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [(0, jsx_runtime_1.jsx)("input", { type: "text", style: { position: "absolute", opacity: 0, width: 0 }, name: inputName, required: required, defaultValue: selectedIds?.join(",") }), (0, jsx_runtime_1.jsxs)(Button_1.default, { variant: variant, sx: sx, onClick: () => clickHandler(), ...rest, disabled: !items || items.length === 0, children: [label && ((0, jsx_runtime_1.jsx)(FormLabel_1.default, { required: required, sx: { fontSize: (theme) => theme.typography.body2.fontSize }, children: label })), selectedIds?.map((id) => { const item = items.find((item) => item.id === id); if (item == null) return null; return ((0, jsx_runtime_1.jsx)(Chip_1.default, { sx: { pointerEvents: "none" }, size: "small", label: labelFormatter(item) }, id)); }), labelEnd && (0, jsx_runtime_1.jsx)(Typography_1.default, { variant: "caption", children: labelEnd })] })] })); }