@etsoo/materialui
Version:
TypeScript Material-UI Implementation
127 lines (126 loc) • 6.5 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import Button from "@mui/material/Button";
import Chip from "@mui/material/Chip";
import React from "react";
import { NumberUtils } from "@etsoo/shared";
import Grid from "@mui/material/Grid";
import Typography from "@mui/material/Typography";
import AddIcon from "@mui/icons-material/Add";
import FormControlLabel from "@mui/material/FormControlLabel";
import Radio from "@mui/material/Radio";
import TextField from "@mui/material/TextField";
import FormLabel from "@mui/material/FormLabel";
import RadioGroup from "@mui/material/RadioGroup";
import { HBox, VBox } from "./FlexBox";
import { useRequiredAppContext } from "./app/ReactApp";
function ButtonPopupList(props) {
// Destruct
const { addSplitter = /\s*[,;]\s*/, value, items, labelFormatter, labels, onAdd, onValueChange } = props;
// Ref
const inputRef = React.useRef(null);
// State
const [currentValue, setCurrentValue] = React.useState();
React.useEffect(() => {
setCurrentValue(value);
}, [value]);
return (_jsxs(VBox, { gap: 2, children: [_jsx(RadioGroup, { value: currentValue ?? "", name: "radio-buttons-group", onChange: (e, v) => {
const checked = e.target.checked;
const value = checked
? typeof items[0].id === "number"
? NumberUtils.parse(v)
: v
: undefined;
setCurrentValue(value);
onValueChange(value);
}, children: _jsx(Grid, { container: true, spacing: 0, children: items.map((item) => (_jsx(Grid, { size: { xs: 12, md: 6, lg: 4 }, display: "flex", justifyContent: "flex-start", alignItems: "center", gap: 1, children: _jsx(FormControlLabel, { control: _jsx(Radio, { value: item.id }), label: `${labelFormatter(item)}` }) }, item.id))) }) }), onAdd && (_jsxs(HBox, { gap: 1, children: [_jsx(TextField, { variant: "outlined", label: labels?.more, fullWidth: true, inputRef: inputRef }), _jsx(Button, { sx: { width: "120px" }, variant: "contained", startIcon: _jsx(AddIcon, {}), size: "small", onClick: async () => {
if (inputRef.current == null)
return;
const input = inputRef.current.value.trim();
if (input === "") {
inputRef.current.focus();
return;
}
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;
}
inputRef.current.value = "";
inputRef.current.focus();
}, children: labels?.add })] }))] }));
}
export function ButtonPopupRadio(props) {
// App
const app = useRequiredAppContext();
// Destruct
const { addSplitter, 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" }, value, 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.useState([]);
const [currentValue, setCurrentValue] = React.useState();
const item = currentValue
? items.find((item) => item.id === currentValue)
: undefined;
React.useEffect(() => {
if (typeof loadData === "function") {
// Load data
loadData().then((data) => {
if (data != null) {
setItems(data);
}
});
}
else {
setItems(loadData);
}
}, [loadData]);
React.useEffect(() => {
setCurrentValue(value);
}, [value]);
// Selected id
const tempSelectedId = React.useRef();
// Click handler
const clickHandler = () => {
app.showInputDialog({
title: popupTitle,
message: popupMessage,
callback: (form) => {
if (form == null || tempSelectedId.current == null)
return;
const id = tempSelectedId.current;
setCurrentValue(id);
onValueChange?.(id);
},
inputs: (_jsx(ButtonPopupList, { addSplitter: addSplitter, value: currentValue, items: items, labelFormatter: labelFormatter, labels: labels, onAdd: onAdd, onValueChange: (id) => {
tempSelectedId.current = id;
} })),
fullScreen: app.smDown
});
};
return (_jsxs(React.Fragment, { children: [_jsx("input", { type: "text", style: { position: "absolute", opacity: 0, width: 0 }, name: inputName, required: required, defaultValue: currentValue }), _jsxs(Button, { variant: variant, sx: sx, onClick: () => clickHandler(), ...rest, disabled: !items || items.length === 0, children: [label && (_jsx(FormLabel, { required: required, sx: { fontSize: (theme) => theme.typography.body2.fontSize }, children: label })), item ? (_jsx(Chip, { sx: {
height: "auto",
pointerEvents: "none",
"& .MuiChip-label": {
display: "block",
whiteSpace: "normal"
}
}, size: "small", label: labelFormatter(item) })) : undefined, labelEnd && _jsx(Typography, { variant: "caption", children: labelEnd })] })] }));
}