|
- import React, {
- ChangeEventHandler,
- useCallback,
- useEffect,
- useRef,
- useState,
- } from "react";
- import { Box, Input, SxProps, TableCell } from "@mui/material";
-
- interface Props<T> {
- value: T;
- onChange: (newValue?: T) => void;
- renderValue?: (value: T) => string;
- convertValue: (inputValue?: string) => T;
- cellSx?: SxProps;
- inputSx?: SxProps;
- }
-
- const TableCellEdit = <T,>({
- value,
- renderValue = (val) => `${val}`,
- convertValue,
- onChange,
- cellSx,
- inputSx,
- }: Props<T>) => {
- const [editMode, setEditMode] = useState(false);
- const [input, setInput] = useState<string>();
- const inputRef = useRef<HTMLInputElement>(null);
-
- const onClick = useCallback(() => {
- setEditMode(true);
- setInput(`${value}`);
- }, [value]);
-
- const onInputChange = useCallback<ChangeEventHandler<HTMLInputElement>>(
- (e) => setInput(e.target.value),
- [],
- );
-
- const onBlur = useCallback(() => {
- setEditMode(false);
- onChange(convertValue(input));
- setInput(undefined);
- }, [convertValue, input, onChange]);
-
- useEffect(() => {
- if (editMode && inputRef.current) {
- inputRef.current?.focus();
- }
- }, [editMode]);
-
- return (
- <TableCell
- sx={{
- outline: editMode ? "1px solid" : undefined,
- outlineColor: editMode ? "primary.main" : undefined,
- ...cellSx,
- }}
- >
- <Input
- sx={{
- display: editMode ? "block" : "none",
- "::after": { display: "none " },
- "::before": { display: "none " },
- height: "inherit",
- width: "inherit",
- padding: 0,
- fontWeight: "inherit",
- lineHeight: "inherit",
- ...inputSx,
- }}
- inputRef={inputRef}
- value={input}
- onChange={onInputChange}
- onBlur={onBlur}
- type={typeof value === "number" ? "number" : "text"}
- />
- <Box sx={{ display: editMode ? "none" : "block" }} onClick={onClick}>
- {renderValue(value)}
- </Box>
- </TableCell>
- );
- };
-
- export default TableCellEdit;
|