wisesplit/components/EditBox.tsx

77 lines
1.7 KiB
TypeScript
Raw Normal View History

2022-10-25 18:26:48 +00:00
import { PrimitiveAtom, useAtom } from "jotai";
import { SyntheticEvent, useState } from "react";
2022-10-24 07:40:14 +00:00
import styled from "styled-components";
2022-10-24 07:10:52 +00:00
2022-10-25 18:26:48 +00:00
export interface Props<T> {
valueAtom: PrimitiveAtom<T>;
2022-10-24 19:00:16 +00:00
formatter?: (arg: T) => string;
inputType?: string;
validator: (arg: string) => T | null;
2022-10-24 07:18:22 +00:00
}
2022-10-24 07:40:14 +00:00
const ClickableContainer = styled.span`
display: inline-block;
padding: 4px 10px;
margin: 4px;
border: 1px solid #eee;
border-radius: 5px;
2022-10-24 07:40:14 +00:00
&:hover {
background-color: #eee;
}
`;
const EditingBox = styled.input`
display: inline-block;
padding: 4px 10px;
margin: 4px;
border: 1px solid #eee;
border-radius: 5px;
`;
2022-10-25 18:26:48 +00:00
export default function EditBox<T>({
2022-10-24 19:00:16 +00:00
valueAtom,
formatter,
inputType,
validator,
}: Props<T>) {
2022-10-24 07:10:52 +00:00
const [value, setValue] = useAtom(valueAtom);
const [valueInput, setValueInput] = useState("");
const [editing, setEditing] = useState(false);
2022-10-24 07:18:22 +00:00
const startEditing = (_: any) => {
2022-10-25 18:26:48 +00:00
setValueInput(String(value));
2022-10-24 07:10:52 +00:00
setEditing(true);
};
2022-10-25 18:26:48 +00:00
const finalize = (e: SyntheticEvent) => {
2022-10-24 07:10:52 +00:00
e.preventDefault();
2022-10-24 19:00:16 +00:00
const validateResult = validator(valueInput);
if (validateResult !== null) {
setValue(validateResult);
2022-10-24 07:10:52 +00:00
setEditing(false);
}
};
if (editing) {
return (
<form onSubmit={finalize} style={{ display: "inline" }}>
<EditingBox
2022-10-24 07:10:52 +00:00
autoFocus={true}
2022-10-24 19:00:16 +00:00
type={inputType ?? "text"}
2022-10-24 07:10:52 +00:00
step="0.01"
value={valueInput}
onBlur={finalize}
2022-10-25 18:26:48 +00:00
onInput={(e) => setValueInput(e.currentTarget.value)}
2022-10-24 07:10:52 +00:00
/>
</form>
);
} else {
2022-10-24 07:40:14 +00:00
return (
<ClickableContainer onClick={startEditing}>
2022-10-25 18:26:48 +00:00
{formatter ? formatter(value) : String(value)}
2022-10-24 07:40:14 +00:00
</ClickableContainer>
);
2022-10-24 07:10:52 +00:00
}
}