import { FieldName, useField, useControl } from "@conform-to/react/future"; import { Field, FieldProps } from "../field/Field"; import { Input } from "../text/Input"; import { useRef } from "react"; interface Props extends Omit { name: FieldName; type?: "datetime-local" | "date"; } function pad(n: number): string { return n.toString().padStart(2, "0"); } function toDateLocalValue(date: Date, type: "datetime-local" | "date"): string { const year = date.getFullYear(); const month = pad(date.getMonth() + 1); const day = pad(date.getDate()); const hours = pad(date.getHours()); const minutes = pad(date.getMinutes()); return type === "datetime-local" ? `${year}-${month}-${day}T${hours}:${minutes}` : `${year}-${month}-${day}`; } function fromDatetimeLocalValue(value: string): Date { const [datePart, timePart] = value.split("T"); const [year, month, day] = datePart.split("-").map(Number); const [hours, minutes] = timePart?.split(":").map(Number) ?? [0, 0]; return new Date(year, month - 1, day, hours, minutes); } export function DateField({ name, type = "datetime-local", id: forcedId, ...rest }: Props) { const field = useField(name); const id = forcedId ?? field.id; const dateInputRef = useRef(null!); const control = useControl({ defaultValue: field.defaultValue, // only for control.payload parse(payload) { if (typeof payload !== "string") { throw new Error("date input must return string"); } return new Date(payload); }, serialize(value) { return value.toISOString(); }, }); return ( <> { console.log("onChange", e.target.value, fromDatetimeLocalValue(e.target.value)); control.change(fromDatetimeLocalValue(e.target.value)); }} onBlur={() => control.blur()} /> ); }