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 { DateTime } from "luxon";
|
||||
import { useFlash } from "../App/FlashContext";
|
||||
|
||||
export const TimeInput = ({ defaultValue, onInput }) => {
|
||||
const format = "yyyy-LL-dd, HH:mm:ss";
|
||||
const ref = useRef(null);
|
||||
|
||||
const [time, setTime] = useState(defaultValue);
|
||||
@ -11,23 +11,144 @@ export const TimeInput = ({ defaultValue, onInput }) => {
|
||||
onInput(time);
|
||||
}, [time]);
|
||||
|
||||
const flash = useFlash();
|
||||
|
||||
return (
|
||||
<>
|
||||
<div class={"input"}>
|
||||
<input
|
||||
placeholder={"YYYY-MM-DD, hh:mm:ss"}
|
||||
style={{
|
||||
border: "none",
|
||||
fontSize: "16px",
|
||||
}}
|
||||
value={time && time.toFormat(format)}
|
||||
onBlur={(ev) => {
|
||||
const dt = DateTime.fromFormat(ev.currentTarget.value, format);
|
||||
if (dt.isValid) {
|
||||
setTime(dt);
|
||||
}
|
||||
}}
|
||||
></input>
|
||||
<div
|
||||
class={"input"}
|
||||
onPaste={(ev) => {
|
||||
ev.preventDefault();
|
||||
const pasteValue = ev.clipboardData.getData("text/plain");
|
||||
let dt = DateTime.fromISO(pasteValue);
|
||||
|
||||
if (dt.isValid) {
|
||||
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",
|
||||
});
|
||||
}}
|
||||
>
|
||||
<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
|
||||
style={{
|
||||
background: "none",
|
||||
@ -39,7 +160,7 @@ export const TimeInput = ({ defaultValue, onInput }) => {
|
||||
ref.current.showPicker();
|
||||
}}
|
||||
>
|
||||
<span class="is-sr-only">Clear interval</span>
|
||||
<span class="is-sr-only">Show time picker</span>
|
||||
<span class="icon">
|
||||
<i class="fas fa-calendar"></i>
|
||||
</span>
|
||||
@ -54,8 +175,11 @@ export const TimeInput = ({ defaultValue, onInput }) => {
|
||||
class={"input"}
|
||||
type="datetime-local"
|
||||
step="1"
|
||||
name="time"
|
||||
value={time && time.toFormat("yyyy-LL-dd'T'HH:mm:ss")}
|
||||
value={
|
||||
time
|
||||
? time.toFormat("yyyy-LL-dd'T'HH:mm:ss")
|
||||
: DateTime.now().toFormat("yyyy-LL-dd'T'HH:mm:ss")
|
||||
}
|
||||
ref={ref}
|
||||
onInput={(ev) => {
|
||||
setTime(DateTime.fromISO(ev.currentTarget.value));
|
||||
|
Loading…
Reference in New Issue
Block a user