diff --git a/lib/component/input/date/DateInput.tsx b/lib/component/input/date/DateInput.tsx index 35dd999..6994bde 100644 --- a/lib/component/input/date/DateInput.tsx +++ b/lib/component/input/date/DateInput.tsx @@ -1,26 +1,47 @@ import type { DateInputProps } from "$/types/InputTypes"; import clsx from "clsx"; -import moment from "moment"; +import { type ChangeEvent } from "react"; export default function DateInput({ - id, className, - defaultValue, value, - onChange -}: DateInputProps){ + onChange, + ...inputProps +}: Readonly){ + //Used to translate the string from the input to a date for onChange + const changeDate = (e: ChangeEvent) => { + const [ year, month, day ] = e.target.value.split("-").map(Number); + const newDate = new Date(year, month - 1, day); + + onChange(Number.isNaN(newDate.getTime()) ? undefined : newDate); + }; + + return ( onChange?.(new Date(moment(e.target.value, "YYYY-MM-DD").toDate()))} + value={formatDate(value)} + onChange={changeDate} + {...inputProps} /> ); } + + +//Used to translate the date to a string for the input +function formatDate(date: Date | undefined): string{ + if(!date || Number.isNaN(date.getTime())){ + return ""; + } + + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, "0"); + const day = String(date.getDate()).padStart(2, "0"); + + return `${year}-${month}-${day}`; +} diff --git a/lib/component/input/date/DateTimeInput.tsx b/lib/component/input/date/DateTimeInput.tsx index d1f1af0..1c9f228 100644 --- a/lib/component/input/date/DateTimeInput.tsx +++ b/lib/component/input/date/DateTimeInput.tsx @@ -1,15 +1,38 @@ import type { DateInputProps } from "$/types/InputTypes"; import clsx from "clsx"; -import moment from "moment"; +import type { ChangeEvent } from "react"; export default function DateTimeInput({ id, className, - defaultValue, + step = 60, value, - onChange -}: DateInputProps){ + onChange, + ...inputProps +}: Readonly){ + const changeDateTime = (e: ChangeEvent) => { + const match = new RegExp(/^(\d+)-(\d+)-(\d+)T(\d+):(\d+)(?::(\d+)(?:\.(\d+))?)?$/).exec(e.target.value); + + if(!match){ + onChange(undefined); + return; + } + + const [ , + y, mo, d, + h, mi, s = "0", ms = "0" + ] = match; + + const date = new Date( + Number(y), Number(mo) - 1, Number(d), + Number(h), Number(mi), Number(s), Number(ms) + ); + + onChange(Number.isNaN(date.getTime()) ? undefined : date); + } + + return ( onChange?.(new Date(moment(e.target.value, "YYYY-MM-DDTHH:mm").toDate()))} + value={formatDateTime(value)} + onChange={changeDateTime} + step={step} + {...inputProps} /> ); } + + +function formatDateTime(date: Date | undefined){ + if(!date || Number.isNaN(date.getTime())){ + return ""; + } + + const y = date.getFullYear(); + const mo = String(date.getMonth() + 1).padStart(2, "0"); + const d = String(date.getDate()).padStart(2, "0"); + + const h = String(date.getHours()).padStart(2, "0"); + const mi = String(date.getMinutes()).padStart(2, "0"); + const s = String(date.getSeconds()).padStart(2, "0"); + const ms = String(date.getMilliseconds()).padStart(2, "0"); + + return `${y}-${mo}-${d}T${h}:${mi}:${s}.${ms}`; +} diff --git a/lib/component/input/date/TimeInput.tsx b/lib/component/input/date/TimeInput.tsx index 52eb33c..b50f780 100644 --- a/lib/component/input/date/TimeInput.tsx +++ b/lib/component/input/date/TimeInput.tsx @@ -1,15 +1,33 @@ import type { DateInputProps } from "$/types/InputTypes"; import clsx from "clsx"; -import moment from "moment"; +import type { ChangeEvent } from "react"; export default function TimeInput({ id, className, - defaultValue, + step = 60, value, - onChange -}: DateInputProps){ + onChange, + ...inputProps +}: Readonly){ + const changeTime = (e: ChangeEvent) => { + const match = new RegExp(/^(\d+):(\d+)(?::(\d+)(?:\.(\d+))?)?$/).exec(e.target.value); + + if(!match){ + onChange(undefined); + return; + } + + const [ , h, m, s = "0", ms = "0"] = match; + + const newDate = new Date(); + newDate.setHours(Number(h), Number(m), Number(s), Number(ms)); + + onChange(Number.isNaN(newDate) ? undefined : newDate); + } + + return ( onChange?.(new Date(moment(e.target.value, "YYYY-MM-DDTHH:mm").toDate()))} + value={formatTime(value, step)} + onChange={changeTime} + step={step} + {...inputProps} /> ); } + + +function formatTime(date: Date | undefined, step: number){ + if(!date || Number.isNaN(date.getTime())){ + return ""; + } + + const h = String(date.getHours()).padStart(2, "0"); + const m = String(date.getMinutes()).padStart(2, "0"); + const s = String(date.getSeconds()).padStart(2, "0"); + const ms = String(date.getMilliseconds()).padStart(3, "0"); + + let time = `${h}:${m}`; + if(step < 60){ + time += `:${s}`; + } + if(step < 1){ + time += `.${ms}`; + } + + return time; +} diff --git a/lib/types/InputTypes.ts b/lib/types/InputTypes.ts index cc41190..8200003 100644 --- a/lib/types/InputTypes.ts +++ b/lib/types/InputTypes.ts @@ -1,5 +1,5 @@ import type React from "react"; -import type { ChangeEventHandler } from "react"; +import type { ChangeEventHandler, InputHTMLAttributes } from "react"; export interface TextInputProps { @@ -164,10 +164,8 @@ export interface RadioListProps { } -export interface DateInputProps { - id?: string; - className?: string; - defaultValue?: Date; - value?: Date; - onChange?: (newValue: Date) => void; +export interface DateInputProps extends Omit, "value" | "onChange" | "step">{ + step?: number; + value: Date | undefined; + onChange: (newValue: Date | undefined) => void; } diff --git a/src/routes/input/index.tsx b/src/routes/input/index.tsx index 6a7eeec..6672bea 100644 --- a/src/routes/input/index.tsx +++ b/src/routes/input/index.tsx @@ -2,6 +2,7 @@ import { MattrixwvTabGroup } from "$/component/tab"; import type { TabGroupContent } from "$/types/TabTypes"; import { CheckboxContent, DateContent, FileContent, RadioContent, SwitchContent, TextContent } from "@/util/InputUtils"; import { createFileRoute } from "@tanstack/react-router"; +import { useState } from "react"; export const Route = createFileRoute('/input/')({ @@ -10,15 +11,21 @@ export const Route = createFileRoute('/input/')({ function InputPage(){ + const [ date, setDate ] = useState(); + const [ dateTime, setDateTime ] = useState(); + const [ time, setTime ] = useState(); + + const tabs: TabGroupContent[] = [ { tab: "Checkbox", content: }, { tab: "Radio", content: }, - { tab: "Date", content: }, + { tab: "Date", content: }, { tab: "File", content: }, { tab: "Switch", content: }, { tab: "Text", content: } ]; + return (
void; + dateTime: Date | undefined; + setDateTime: (newDateTime: Date | undefined) => void; + time: Date | undefined; + setTime: (newTime: Date | undefined) => void; +}>){ return (
);