Skip to content
Source
Sign inSign up
Open History to see the last commit

IntervalSecondsField.tsx

77 lines2.1 KB

1import { useState } from "react";
2import {
3 NumberField,
4 NumberFieldDecrement,
5 NumberFieldGroup,
6 NumberFieldIncrement,
7 NumberFieldInput,
8} from "../ui/number-field";
9import { normalizeIntervalSeconds } from "./SettingsPanels.logic";
10​
11export function IntervalSecondsField({
12 label,
13 value,
14 min,
15 step,
16 onCommit,
17}: {
18 label: string;
19 value: number;
20 min: number;
21 step: number;
22 onCommit: (seconds: number, options: { onFailed: () => void }) => void;
23}) {
24 const [field, setField] = useState({
25 saved: value,
26 draft: value as number | null,
27 committed: value,
28 revision: 0,
29 });
30 if (field.saved !== value) {
31 setField({ ...field, saved: value, draft: value, committed: value });
32 }
33​
34 return (
35 <NumberField
36 value={field.draft}
37 min={min}
38 step={step}
39 size="compact"
40 className="w-32"
41 onValueChange={(draft) => setField((current) => ({ ...current, draft }))}
42 onValueCommitted={(next) => {
43 if (next === null) {
44 setField((current) => ({ ...current, draft: current.saved }));
45 return;
46 }
47 const seconds = normalizeIntervalSeconds(next, min);
48 if (seconds === field.committed) {
49 setField((current) => ({ ...current, draft: seconds }));
50 return;
51 }
52 const revision = field.revision + 1;
53 setField((current) => ({ ...current, draft: seconds, committed: seconds, revision }));
54 onCommit(seconds, {
55 onFailed: () =>
56 setField((current) =>
57 current.revision !== revision
58 ? current
59 : {
60 ...current,
61 committed: current.saved,
62 draft: current.draft === seconds ? current.saved : current.draft,
63 },
64 ),
65 });
66 }}
67 >
68 <NumberFieldGroup>
69 <NumberFieldDecrement aria-label={`Decrease ${label}`} />
70 <NumberFieldInput
71 aria-label={`${label.charAt(0).toUpperCase()}${label.slice(1)} in seconds`}
72 />
73 <NumberFieldIncrement aria-label={`Increase ${label}`} />
74 </NumberFieldGroup>
75 </NumberField>
76 );