Skip to content

Commit

Permalink
feat: add input masking for numbers only in TimeField (#158)
Browse files Browse the repository at this point in the history
  • Loading branch information
jaredcwhite authored Sep 9, 2024
1 parent 329d8c3 commit 9dd1d9e
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 11 deletions.
2 changes: 2 additions & 0 deletions src/forms/DateField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ const DateField = (props: DateFieldProps) => {
validate: {
monthRange: (value: string) => {
if (!props.required && !value?.length) return true

return parseInt(value) > 0 && parseInt(value) <= 12
},
},
Expand All @@ -95,6 +96,7 @@ const DateField = (props: DateFieldProps) => {
validate: {
dayRange: (value: string) => {
if (!props.required && !value?.length) return true

return parseInt(value) > 0 && parseInt(value) <= 31
},
},
Expand Down
3 changes: 2 additions & 1 deletion src/forms/TimeField.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default {
}

export const Default = () => {
const { register, watch, errors } = useForm({ mode: "onChange" })
const { register, setValue, watch, errors } = useForm({ mode: "onChange" })

return (
<TimeField
Expand All @@ -17,6 +17,7 @@ export const Default = () => {
name="time"
required={true}
register={register}
setValue={setValue}
watch={watch}
error={!!errors?.time}
/>
Expand Down
38 changes: 28 additions & 10 deletions src/forms/TimeField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ErrorMessage } from "../notifications/ErrorMessage"
import { Field } from "./Field"
import { Select } from "../forms/Select"
import { UseFormMethods } from "react-hook-form"
import { maskNumber } from "./DateField"

export type TimeFieldPeriod = "am" | "pm"

Expand All @@ -26,6 +27,7 @@ export type TimeFieldProps = {
readerOnly?: boolean
register: UseFormMethods["register"]
required?: boolean
setValue?: UseFormMethods["setValue"]
watch: UseFormMethods["watch"]
seconds?: boolean
dataTestId?: string
Expand Down Expand Up @@ -54,9 +56,10 @@ const TimeField = ({
required = false,
error,
register,
setValue,
watch,
name,
id,
id = "time",
label,
labelClass,
readerOnly,
Expand All @@ -66,16 +69,16 @@ const TimeField = ({
dataTestId,
strings,
}: TimeFieldProps) => {
const fieldName = (baseName: string) => {
const getFieldName = (baseName: string) => {
return [name, baseName].filter((item) => item).join(".")
}

// it prevents partial fill, all fields should be filled or nothing
const [innerRequiredRule, setInnerRequiredRule] = useState(false)

const hoursField = watch(fieldName("hours"))
const minutesField = watch(fieldName("minutes"))
const secondsField = watch(fieldName("seconds"))
const hoursField = watch(getFieldName("hours"))
const minutesField = watch(getFieldName("minutes"))
const secondsField = watch(getFieldName("seconds"))

useEffect(() => {
const someFieldsFilled = hoursField || minutesField || secondsField
Expand All @@ -90,7 +93,7 @@ const TimeField = ({
<legend className={labelClasses.join(" ")}>{label}</legend>
<div className="field-group--date">
<Field
name={fieldName("hours")}
name={getFieldName("hours")}
label={strings?.hour ?? t("t.hour")}
defaultValue={defaultValues?.hours ?? ""}
readerOnly={true}
Expand All @@ -108,13 +111,18 @@ const TimeField = ({
}}
inputProps={{ maxLength: 2 }}
register={register}
onChange={(e) => {
if (!setValue) return

setValue(getFieldName("hours"), maskNumber(e.target.value))
}}
describedBy={`${id}-error`}
disabled={disabled}
dataTestId={dataTestId ? `${dataTestId}-hours` : undefined}
/>

<Field
name={fieldName("minutes")}
name={getFieldName("minutes")}
label={strings?.minutes ?? t("t.minutes")}
defaultValue={defaultValues?.minutes ?? ""}
readerOnly={true}
Expand All @@ -132,6 +140,11 @@ const TimeField = ({
}}
inputProps={{ maxLength: 2 }}
register={register}
onChange={(e) => {
if (!setValue) return

setValue(getFieldName("minutes"), maskNumber(e.target.value))
}}
describedBy={`${id}-error`}
disabled={disabled}
dataTestId={dataTestId ? `${dataTestId}-minutes` : undefined}
Expand All @@ -141,7 +154,7 @@ const TimeField = ({
<Field
label={strings?.seconds ?? t("t.seconds")}
defaultValue={defaultValues?.seconds ?? ""}
name={fieldName("seconds")}
name={getFieldName("seconds")}
readerOnly={true}
placeholder="SS"
error={error}
Expand All @@ -157,15 +170,20 @@ const TimeField = ({
}}
inputProps={{ maxLength: 2 }}
register={register}
onChange={(e) => {
if (!setValue) return

setValue(getFieldName("seconds"), maskNumber(e.target.value))
}}
describedBy={`${id}-error`}
disabled={disabled}
dataTestId={dataTestId ? `${dataTestId}-seconds` : undefined}
/>
)}

<Select
name={fieldName("period")}
id={fieldName("period")}
name={getFieldName("period")}
id={getFieldName("period")}
labelClassName="sr-only"
label={strings?.time ?? t("t.time")}
register={register}
Expand Down

0 comments on commit 9dd1d9e

Please sign in to comment.