87 lines
2.3 KiB
TypeScript
87 lines
2.3 KiB
TypeScript
import React, { FC, ReactNode, useEffect, useRef, useState } from "react";
|
|
import { TextInput } from "@mantine/core";
|
|
import { Styles } from "@mantine/core/lib/core/styles-api/styles-api.types";
|
|
|
|
type Props = {
|
|
value?: string;
|
|
onChange: (value: string) => void;
|
|
placeholder?: string;
|
|
getChildren: (startEditing: () => void) => ReactNode;
|
|
inputStyles?: Styles<any>;
|
|
};
|
|
|
|
const InPlaceInputDesktop: FC<Props> = ({
|
|
onChange,
|
|
placeholder,
|
|
inputStyles,
|
|
getChildren,
|
|
value = "",
|
|
}) => {
|
|
const [isWriting, setIsWriting] = useState<boolean>(false);
|
|
const [localValue, setLocalValue] = useState<string>(value);
|
|
const inputRef = useRef<HTMLInputElement>(null);
|
|
|
|
useEffect(() => {
|
|
if (isWriting && inputRef.current) {
|
|
inputRef.current.focus();
|
|
}
|
|
}, [isWriting]);
|
|
|
|
useEffect(() => {
|
|
const handleClickOutside = (event: MouseEvent) => {
|
|
if (
|
|
isWriting &&
|
|
inputRef.current &&
|
|
!inputRef.current.contains(event.target as Node)
|
|
) {
|
|
onCompleteCreating();
|
|
}
|
|
};
|
|
|
|
document.addEventListener("mousedown", handleClickOutside);
|
|
return () =>
|
|
document.removeEventListener("mousedown", handleClickOutside);
|
|
}, [isWriting, localValue]);
|
|
|
|
const onStartCreating = () => {
|
|
setLocalValue(localValue);
|
|
setIsWriting(true);
|
|
};
|
|
|
|
const onCancelCreating = () => {
|
|
setLocalValue(localValue);
|
|
setIsWriting(false);
|
|
};
|
|
|
|
const onCompleteCreating = () => {
|
|
const val = localValue.trim();
|
|
if (val) {
|
|
onChange(val);
|
|
}
|
|
setIsWriting(false);
|
|
};
|
|
|
|
if (isWriting) {
|
|
return (
|
|
<TextInput
|
|
ref={inputRef}
|
|
placeholder={placeholder}
|
|
variant={"unstyled"}
|
|
value={localValue}
|
|
onChange={e => setLocalValue(e.target.value)}
|
|
onKeyDown={e => {
|
|
e.stopPropagation();
|
|
if (e.key === "Enter") onCompleteCreating();
|
|
if (e.key === "Escape") onCancelCreating();
|
|
}}
|
|
styles={inputStyles}
|
|
miw={150}
|
|
/>
|
|
);
|
|
}
|
|
|
|
return getChildren(onStartCreating);
|
|
};
|
|
|
|
export default InPlaceInputDesktop;
|