UNPKG

@etsoo/materialui

Version:

TypeScript Material-UI Implementation

198 lines (197 loc) 13.2 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.CustomAttributeArea = CustomAttributeArea; const jsx_runtime_1 = require("react/jsx-runtime"); const IconButton_1 = __importDefault(require("@mui/material/IconButton")); const Add_1 = __importDefault(require("@mui/icons-material/Add")); const Edit_1 = __importDefault(require("@mui/icons-material/Edit")); const Delete_1 = __importDefault(require("@mui/icons-material/Delete")); const DragIndicator_1 = __importDefault(require("@mui/icons-material/DragIndicator")); const react_1 = __importDefault(require("react")); const Card_1 = __importDefault(require("@mui/material/Card")); const CardContent_1 = __importDefault(require("@mui/material/CardContent")); const Grid_1 = __importDefault(require("@mui/material/Grid")); const appscript_1 = require("@etsoo/appscript"); const Button_1 = __importDefault(require("@mui/material/Button")); const material_1 = require("@mui/material"); const shared_1 = require("@etsoo/shared"); const CustomFieldUtils_1 = require("./CustomFieldUtils"); const ComboBox_1 = require("../ComboBox"); const InputField_1 = require("../InputField"); const JsonTextField_1 = require("../JsonTextField"); const FlexBox_1 = require("../FlexBox"); const DnDSortableList_1 = require("../DnDSortableList"); const ReactApp_1 = require("../app/ReactApp"); const size = { xs: 6, sm: 4, lg: 3, xl: 2 }; const smallSize = { xs: 3, sm: 2, xl: 1 }; const random4Digit = () => { return Math.floor(1000 + Math.random() * 9000); }; const isCamelCase = (name) => { return /^[a-z][a-zA-Z0-9]*$/.test(name); }; function InputItemUIs({ data }) { // Global app const app = (0, ReactApp_1.useRequiredAppContext)(); // Labels const labels = app.getLabels("gridItemProps", "helperText", "label", "mainSlotProps", "nameB", "options", "optionsFormat", "refs", "size", "type"); const types = Object.keys(CustomFieldUtils_1.CustomFieldUtils.customFieldCreators); const nameRef = react_1.default.useRef(null); const optionsRef = react_1.default.useRef(null); return ((0, jsx_runtime_1.jsxs)(Grid_1.default, { container: true, spacing: 2, marginTop: 1, children: [(0, jsx_runtime_1.jsx)(Grid_1.default, { size: { xs: 12, sm: 6 }, children: (0, jsx_runtime_1.jsx)(ComboBox_1.ComboBox, { name: "type", label: labels.type, inputRequired: true, size: "small", loadData: () => Promise.resolve(types.map((t) => ({ id: t, label: t }))), onValueChange: (item) => { const type = item?.id; optionsRef.current.disabled = type !== "combobox" && type !== "select" && type !== "checkbox" && type !== "radio"; const nameInput = nameRef.current; if (nameInput.value === "" && (type === "amountlabel" || type === "divider" || type === "label")) { nameInput.value = type + random4Digit(); } }, idValue: data?.type, fullWidth: true }) }), (0, jsx_runtime_1.jsx)(Grid_1.default, { size: { xs: 12, sm: 6 }, children: (0, jsx_runtime_1.jsx)(ComboBox_1.ComboBox, { name: "space", label: labels.size, inputRequired: true, size: "small", loadData: () => Promise.resolve(appscript_1.CustomFieldSpaceValues.map((t) => ({ id: t, label: t }))), idValue: data?.space, fullWidth: true }) }), (0, jsx_runtime_1.jsx)(Grid_1.default, { size: { xs: 12, sm: 6 }, children: (0, jsx_runtime_1.jsx)(InputField_1.InputField, { fullWidth: true, required: true, name: "name", size: "small", inputRef: nameRef, slotProps: { htmlInput: { maxLength: 128, readOnly: !!data } }, label: labels.nameB, defaultValue: data?.name ?? "" }) }), (0, jsx_runtime_1.jsx)(Grid_1.default, { size: { xs: 12, sm: 6 }, children: (0, jsx_runtime_1.jsx)(InputField_1.InputField, { fullWidth: true, name: "label", size: "small", slotProps: { htmlInput: { maxLength: 128 } }, label: labels.label, defaultValue: data?.label ?? "" }) }), (0, jsx_runtime_1.jsx)(Grid_1.default, { size: { xs: 12, sm: 12 }, children: (0, jsx_runtime_1.jsx)(InputField_1.InputField, { fullWidth: true, name: "helperText", size: "small", label: labels.helperText, defaultValue: data?.helperText ?? "" }) }), (0, jsx_runtime_1.jsx)(Grid_1.default, { size: { xs: 12, sm: 12 }, children: (0, jsx_runtime_1.jsx)(InputField_1.InputField, { fullWidth: true, name: "options", size: "small", multiline: true, rows: 2, label: labels.options, inputRef: optionsRef, helperText: labels.optionsFormat, slotProps: { htmlInput: { disabled: true } }, defaultValue: data?.options ? data.options .map((o) => `${o.id}=${shared_1.DataTypes.getListItemLabel(o)}`) .join("\n") : "" }) }), (0, jsx_runtime_1.jsx)(Grid_1.default, { size: { xs: 12, sm: 12 }, children: (0, jsx_runtime_1.jsx)(JsonTextField_1.JsonTextField, { isArray: true, name: "refs", size: "small", multiline: false, label: labels.refs + " (JSON)", defaultValue: data?.refs ? JSON.stringify(data.refs) : "" }) }), (0, jsx_runtime_1.jsx)(Grid_1.default, { size: { xs: 12, sm: 12 }, children: (0, jsx_runtime_1.jsx)(JsonTextField_1.JsonTextField, { name: "gridItemProps", size: "small", multiline: false, label: labels.gridItemProps + " (JSON)", defaultValue: data?.gridItemProps ? JSON.stringify(data.gridItemProps) : "" }) }), (0, jsx_runtime_1.jsx)(Grid_1.default, { size: { xs: 12, sm: 12 }, children: (0, jsx_runtime_1.jsx)(JsonTextField_1.JsonTextField, { name: "mainSlotProps", size: "small", multiline: false, label: labels.mainSlotProps + " (JSON)", defaultValue: data?.mainSlotProps ? JSON.stringify(data.mainSlotProps) : "", helperText: '{"required":true}' }) })] })); } function InputUIs({ source, onChange }) { // Global app const app = (0, ReactApp_1.useRequiredAppContext)(); // Labels const labels = app.getLabels("add", "delete", "edit", "sortTip", "dragIndicator"); const [items, setItems] = react_1.default.useState([]); const doChange = (items) => { setItems(items); onChange(items); }; const editItem = (item) => { app.showInputDialog({ title: item ? labels.edit : labels.add, message: "", callback: async (form) => { // Cancelled if (form == null) { return; } // Validate form if (!form.reportValidity()) { return false; } // Form data const { typeInput: type, spaceInput: space, name, label, helperText, options, refs, gridItemProps, mainSlotProps } = shared_1.DomUtils.dataAs(new FormData(form), { typeInput: "string", spaceInput: "string", name: "string", label: "string", helperText: "string", options: "string", refs: "string", gridItemProps: "string", mainSlotProps: "string" }); if (!type || !space || !name) { return app.get("noData"); } if (!isCamelCase(name)) { shared_1.DomUtils.setFocus("name", form); return app.get("invalidNaming") + " (camelCase)"; } if (type !== "divider" && !label) { shared_1.DomUtils.setFocus("label", form); return false; } if (item == null && items.some((item) => item.name === name)) { return app.get("itemExists")?.format(name); } const optionsJson = options ? options.split("\n").map((line) => { const [id, ...labelParts] = line.split("="); return { id, label: labelParts.join("=") }; }) : undefined; const refsJson = refs ? JSON.parse(refs) : undefined; const gridItemPropsJson = gridItemProps ? JSON.parse(gridItemProps) : undefined; const mainSlotPropsJson = mainSlotProps ? JSON.parse(mainSlotProps) : undefined; if (item == null) { const newItem = { type, name, space: space, label, helperText, options: optionsJson, refs: refsJson, gridItemProps: gridItemPropsJson, mainSlotProps: mainSlotPropsJson }; doChange([...items, newItem]); } else { item.type = type; item.space = space; item.name = name; item.label = label; item.helperText = helperText; item.options = optionsJson; item.refs = refsJson; item.gridItemProps = gridItemPropsJson; item.mainSlotProps = mainSlotPropsJson; doChange([...items]); } return; }, inputs: (0, jsx_runtime_1.jsx)(InputItemUIs, { data: item }) }); }; react_1.default.useEffect(() => { try { if (source) { const parsed = JSON.parse(source); if (Array.isArray(parsed)) { setItems(parsed); } } } catch (error) { console.error("Failed to parse source:", error); } }, [source]); return ((0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [(0, jsx_runtime_1.jsxs)(FlexBox_1.HBox, { marginBottom: 0.5, gap: 1, alignItems: "center", children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { children: labels.sortTip }), (0, jsx_runtime_1.jsx)(Button_1.default, { size: "small", color: "primary", variant: "outlined", startIcon: (0, jsx_runtime_1.jsx)(Add_1.default, {}), onClick: () => editItem(), children: labels.add })] }), (0, jsx_runtime_1.jsx)(Card_1.default, { children: (0, jsx_runtime_1.jsx)(CardContent_1.default, { children: (0, jsx_runtime_1.jsx)(Grid_1.default, { container: true, spacing: 0, children: (0, jsx_runtime_1.jsx)(DnDSortableList_1.DnDSortableList, { items: items, idField: (item) => item.name, labelField: (item) => item.label || item.name, onChange: (items) => doChange(items), itemRenderer: (data, style, { sortable: { index }, ref, handleRef }) => ((0, jsx_runtime_1.jsxs)(Grid_1.default, { container: true, size: { xs: 12, sm: 12 }, ref: ref, style: style, gap: 1, children: [(0, jsx_runtime_1.jsx)(Grid_1.default, { size: smallSize, children: (0, jsx_runtime_1.jsx)(IconButton_1.default, { style: { cursor: "move" }, size: "small", title: labels.dragIndicator, ref: handleRef, children: (0, jsx_runtime_1.jsx)(DragIndicator_1.default, {}) }) }), (0, jsx_runtime_1.jsxs)(Grid_1.default, { size: size, children: [index + 1, " - ", data.type, " / ", data.space] }), (0, jsx_runtime_1.jsxs)(Grid_1.default, { size: size, children: [data.name, " - ", data.label] }), (0, jsx_runtime_1.jsxs)(Grid_1.default, { size: smallSize, children: [(0, jsx_runtime_1.jsx)(IconButton_1.default, { size: "small", title: labels.delete, onClick: () => doChange(items.filter((item) => item.name !== data.name)), children: (0, jsx_runtime_1.jsx)(Delete_1.default, {}) }), (0, jsx_runtime_1.jsx)(IconButton_1.default, { size: "small", title: labels.edit, onClick: () => editItem(data), children: (0, jsx_runtime_1.jsx)(Edit_1.default, {}) })] })] })) }) }) }) })] })); } /** * Custom attribute area * @param props Properties * @returns Component */ function CustomAttributeArea(props) { // Global app const app = (0, ReactApp_1.useRequiredAppContext)(); // Destruct const { label = app.get("attributeDefinition"), ...rest } = props; const ref = react_1.default.useRef([]); const showUI = (input) => { app.showInputDialog({ title: label, message: "", fullScreen: true, callback: (form) => { if (form == null) { return; } input.value = ref.current.length > 0 ? JSON.stringify(ref.current) : ""; }, inputs: ((0, jsx_runtime_1.jsx)(InputUIs, { source: input.value, onChange: (items) => (ref.current = items) })) }); }; // Layout return (0, jsx_runtime_1.jsx)(JsonTextField_1.JsonTextField, { label: label, onEdit: showUI, isArray: true, ...rest }); }