| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| import Tooltip from '@/common/components/Tooltip'; |
| import {ArrowPathIcon, CheckIcon, XMarkIcon} from '@heroicons/react/24/solid'; |
| import {ChangeEvent, KeyboardEvent, useEffect, useMemo, useState} from 'react'; |
| import {Button, Form, Input, Join} from 'react-daisyui'; |
|
|
| type Props<T extends string | number> = Omit< |
| React.InputHTMLAttributes<HTMLInputElement>, |
| 'size' | 'color' | 'onChange' |
| > & { |
| label: string; |
| defaultValue: T; |
| initialValue: T; |
| onChange: (value: string) => void; |
| }; |
|
|
| function getStep(value: number) { |
| const stringValue = String(value); |
| const decimals = stringValue.split('.')[1]; |
| if (decimals != null) { |
| |
| |
| return 1 / 10 ** decimals.length; |
| } |
| return 1; |
| } |
|
|
| export default function ApprovableInput<T extends string | number>({ |
| label, |
| defaultValue, |
| initialValue, |
| onChange, |
| ...otherProps |
| }: Props<T>) { |
| const [value, setValue] = useState<string>(`${initialValue}`); |
|
|
| useEffect(() => { |
| setValue(`${initialValue}`); |
| }, [initialValue]); |
|
|
| const step = useMemo(() => { |
| return typeof defaultValue === 'number' && isFinite(defaultValue) |
| ? getStep(defaultValue) |
| : undefined; |
| }, [defaultValue]); |
|
|
| return ( |
| <div> |
| <Form.Label className="flex-col items-start gap-2" title={label}> |
| <Join className="w-full"> |
| <Input |
| {...otherProps} |
| className="w-full join-item" |
| value={value} |
| step={step} |
| placeholder={`${defaultValue}`} |
| onChange={(event: ChangeEvent<HTMLInputElement>) => { |
| setValue(event.target.value); |
| }} |
| onKeyDown={(event: KeyboardEvent<HTMLInputElement>) => { |
| if (event.key === 'Enter') { |
| event.preventDefault(); |
| onChange(value); |
| } |
| }} |
| /> |
| <Tooltip message="Reset to default"> |
| <Button |
| className="join-item" |
| onClick={event => { |
| event.preventDefault(); |
| setValue(`${defaultValue}`); |
| }}> |
| <ArrowPathIcon className="h-4 w-4" /> |
| </Button> |
| </Tooltip> |
| <Tooltip message="Revert change"> |
| <Button |
| className="join-item" |
| color="neutral" |
| disabled={initialValue == value} |
| onClick={event => { |
| event.preventDefault(); |
| setValue(`${initialValue}`); |
| }}> |
| <XMarkIcon className="h-4 w-4" /> |
| </Button> |
| </Tooltip> |
| <Tooltip message="Apply change"> |
| <Button |
| className="join-item" |
| color="primary" |
| disabled={initialValue == value} |
| onClick={event => { |
| event.preventDefault(); |
| onChange(value); |
| }}> |
| <CheckIcon className="h-4 w-4" /> |
| </Button> |
| </Tooltip> |
| </Join> |
| </Form.Label> |
| </div> |
| ); |
| } |
|
|