Improve time inputs
Split into multiple inputs. Intercept pastes to fill out all fields.
This commit is contained in:
parent
3d70be22e3
commit
67ce9077b6
@ -1,8 +1,8 @@
|
|||||||
import { useEffect, useRef, useState } from "preact/hooks";
|
import { useEffect, useRef, useState } from "preact/hooks";
|
||||||
import { DateTime } from "luxon";
|
import { DateTime } from "luxon";
|
||||||
|
import { useFlash } from "../App/FlashContext";
|
||||||
|
|
||||||
export const TimeInput = ({ defaultValue, onInput }) => {
|
export const TimeInput = ({ defaultValue, onInput }) => {
|
||||||
const format = "yyyy-LL-dd, HH:mm:ss";
|
|
||||||
const ref = useRef(null);
|
const ref = useRef(null);
|
||||||
|
|
||||||
const [time, setTime] = useState(defaultValue);
|
const [time, setTime] = useState(defaultValue);
|
||||||
@ -11,23 +11,144 @@ export const TimeInput = ({ defaultValue, onInput }) => {
|
|||||||
onInput(time);
|
onInput(time);
|
||||||
}, [time]);
|
}, [time]);
|
||||||
|
|
||||||
|
const flash = useFlash();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div class={"input"}>
|
<div
|
||||||
<input
|
class={"input"}
|
||||||
placeholder={"YYYY-MM-DD, hh:mm:ss"}
|
onPaste={(ev) => {
|
||||||
style={{
|
ev.preventDefault();
|
||||||
border: "none",
|
const pasteValue = ev.clipboardData.getData("text/plain");
|
||||||
fontSize: "16px",
|
let dt = DateTime.fromISO(pasteValue);
|
||||||
}}
|
|
||||||
value={time && time.toFormat(format)}
|
|
||||||
onBlur={(ev) => {
|
|
||||||
const dt = DateTime.fromFormat(ev.currentTarget.value, format);
|
|
||||||
if (dt.isValid) {
|
if (dt.isValid) {
|
||||||
setTime(dt);
|
setTime(dt);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dt = DateTime.fromSQL(pasteValue);
|
||||||
|
|
||||||
|
if (dt.isValid) {
|
||||||
|
setTime(dt);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
flash({
|
||||||
|
message: `Couldn't parse your clipboard data as a valid date-time`,
|
||||||
|
type: "error",
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
></input>
|
>
|
||||||
|
<div style={{ flexGrow: "1" }}>
|
||||||
|
<label>
|
||||||
|
<span class="is-sr-only">Years input</span>
|
||||||
|
<input
|
||||||
|
style={{
|
||||||
|
borderStyle: "none",
|
||||||
|
fontFamily: "monospace",
|
||||||
|
width: "calc(4ch + 4px)",
|
||||||
|
fontSize: "1rem",
|
||||||
|
}}
|
||||||
|
type="text"
|
||||||
|
pattern="\d*"
|
||||||
|
maxlength={4}
|
||||||
|
placeholder="2023"
|
||||||
|
value={time?.year.toLocaleString("en-US", {
|
||||||
|
minimumIntegerDigits: 4,
|
||||||
|
useGrouping: false,
|
||||||
|
})}
|
||||||
|
></input>{" "}
|
||||||
|
</label>
|
||||||
|
-
|
||||||
|
<label>
|
||||||
|
<span class="is-sr-only">Months input</span>
|
||||||
|
<input
|
||||||
|
style={{
|
||||||
|
borderStyle: "none",
|
||||||
|
fontFamily: "monospace",
|
||||||
|
width: "calc(2ch + 4px)",
|
||||||
|
fontSize: "1rem",
|
||||||
|
}}
|
||||||
|
type="text"
|
||||||
|
pattern="\d*"
|
||||||
|
maxlength={2}
|
||||||
|
placeholder="12"
|
||||||
|
value={time?.month.toLocaleString("en-US", { minimumIntegerDigits: 2 })}
|
||||||
|
></input>{" "}
|
||||||
|
</label>
|
||||||
|
-
|
||||||
|
<label>
|
||||||
|
<span class="is-sr-only">Days input</span>
|
||||||
|
<input
|
||||||
|
style={{
|
||||||
|
borderStyle: "none",
|
||||||
|
fontFamily: "monospace",
|
||||||
|
width: "calc(2ch + 4px)",
|
||||||
|
fontSize: "1rem",
|
||||||
|
}}
|
||||||
|
type="text"
|
||||||
|
pattern="\d*"
|
||||||
|
maxlength={2}
|
||||||
|
placeholder="25"
|
||||||
|
value={time?.day.toLocaleString("en-US", { minimumIntegerDigits: 2 })}
|
||||||
|
></input>{" "}
|
||||||
|
</label>
|
||||||
|
<label style={{ marginLeft: "8px" }}>
|
||||||
|
<span class="is-sr-only">Hours input</span>
|
||||||
|
<input
|
||||||
|
style={{
|
||||||
|
borderStyle: "none",
|
||||||
|
fontFamily: "monospace",
|
||||||
|
width: "calc(2ch + 4px)",
|
||||||
|
fontSize: "1rem",
|
||||||
|
}}
|
||||||
|
type="text"
|
||||||
|
pattern="\d*"
|
||||||
|
maxlength={2}
|
||||||
|
placeholder="12"
|
||||||
|
value={time?.hour.toLocaleString("en-US", { minimumIntegerDigits: 2 })}
|
||||||
|
></input>{" "}
|
||||||
|
</label>
|
||||||
|
:
|
||||||
|
<label>
|
||||||
|
<span class="is-sr-only">Minutes input</span>
|
||||||
|
<input
|
||||||
|
style={{
|
||||||
|
borderStyle: "none",
|
||||||
|
fontFamily: "monospace",
|
||||||
|
width: "calc(2ch + 4px)",
|
||||||
|
fontSize: "1rem",
|
||||||
|
}}
|
||||||
|
type="text"
|
||||||
|
pattern="\d*"
|
||||||
|
maxlength={2}
|
||||||
|
placeholder="30"
|
||||||
|
value={time?.minute.toLocaleString("en-US", {
|
||||||
|
minimumIntegerDigits: 2,
|
||||||
|
})}
|
||||||
|
></input>{" "}
|
||||||
|
</label>
|
||||||
|
:
|
||||||
|
<label>
|
||||||
|
<span class="is-sr-only">Seconds input</span>
|
||||||
|
<input
|
||||||
|
style={{
|
||||||
|
borderStyle: "none",
|
||||||
|
fontFamily: "monospace",
|
||||||
|
width: "calc(2ch + 4px)",
|
||||||
|
fontSize: "1rem",
|
||||||
|
}}
|
||||||
|
type="text"
|
||||||
|
pattern="\d*"
|
||||||
|
maxlength={2}
|
||||||
|
placeholder="00"
|
||||||
|
value={time?.second.toLocaleString("en-US", {
|
||||||
|
minimumIntegerDigits: 2,
|
||||||
|
})}
|
||||||
|
></input>{" "}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
<button
|
<button
|
||||||
style={{
|
style={{
|
||||||
background: "none",
|
background: "none",
|
||||||
@ -39,7 +160,7 @@ export const TimeInput = ({ defaultValue, onInput }) => {
|
|||||||
ref.current.showPicker();
|
ref.current.showPicker();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span class="is-sr-only">Clear interval</span>
|
<span class="is-sr-only">Show time picker</span>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<i class="fas fa-calendar"></i>
|
<i class="fas fa-calendar"></i>
|
||||||
</span>
|
</span>
|
||||||
@ -54,8 +175,11 @@ export const TimeInput = ({ defaultValue, onInput }) => {
|
|||||||
class={"input"}
|
class={"input"}
|
||||||
type="datetime-local"
|
type="datetime-local"
|
||||||
step="1"
|
step="1"
|
||||||
name="time"
|
value={
|
||||||
value={time && time.toFormat("yyyy-LL-dd'T'HH:mm:ss")}
|
time
|
||||||
|
? time.toFormat("yyyy-LL-dd'T'HH:mm:ss")
|
||||||
|
: DateTime.now().toFormat("yyyy-LL-dd'T'HH:mm:ss")
|
||||||
|
}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
onInput={(ev) => {
|
onInput={(ev) => {
|
||||||
setTime(DateTime.fromISO(ev.currentTarget.value));
|
setTime(DateTime.fromISO(ev.currentTarget.value));
|
||||||
|
Loading…
Reference in New Issue
Block a user