import { FieldValues, RegisterOptions, useFormContext } from "react-hook-form" import { FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, FormRequiredIndicator, useFormField } from "@/components/ui/form" import _ from "@/lib/translate" import { Input } from "./input" import { ComponentProps, FocusEventHandler, useCallback, useState } from "react" import { parseDate } from "chrono-node" import { formatDate, getUserDateFormat, toDate } from "@/lib/date" import { Popover, PopoverContent, PopoverTrigger } from "./popover" import { Button } from "./button" import { CalendarIcon } from "lucide-react" import { Calendar } from "./calendar" import dayjs from "dayjs" import { Textarea } from "./textarea" import AccountsDropdown, { AccountsDropdownProps } from "../common/AccountsDropdown" import PartyTypeDropdown, { PartyTypeDropdownProps } from "../common/PartyTypeDropdown" import CurrencyInput from "react-currency-input-field" import { getSystemDefault } from "@/lib/frappe" import { getCurrencySymbol } from "@/lib/currency" import { getCurrencyFormatInfo } from "@/lib/numbers" import LinkFieldCombobox, { LinkFieldComboboxProps } from "../common/LinkFieldCombobox" import { Select, SelectContent, SelectTrigger, SelectValue } from "./select" import { InputGroup, InputGroupAddon } from "./input-group" interface FormElementProps { name: string, rules?: Omit, "disabled" | "valueAsNumber" | "valueAsDate" | "setValueAs">, label: string, isRequired?: boolean, disabled?: boolean, formDescription?: string, hideLabel?: boolean, readOnly?: boolean, } interface DataFieldProps extends FormElementProps { inputProps?: Omit, "value" | "onChange" | "onBlur" | "name" | "ref"> } export const DataField = ({ name, rules, label, isRequired, formDescription, inputProps, hideLabel, disabled, readOnly }: DataFieldProps) => { const { control } = useFormContext() return ( {label}{isRequired && } {formDescription && {formDescription}} )} /> } interface SelectFieldProps extends FormElementProps { children: React.ReactNode } export const SelectFormField = ({ name, rules, label, isRequired, formDescription, hideLabel, children, disabled, readOnly }: SelectFieldProps) => { const { control } = useFormContext() return ( {label}{isRequired && } {formDescription && {formDescription}} )} /> } interface DateFieldProps extends FormElementProps { inputProps?: Omit, "value" | "onChange" | "onBlur" | "name" | "ref"> } export const DateField = ({ name, rules, label, isRequired, formDescription, inputProps, hideLabel, disabled }: DateFieldProps) => { const { control } = useFormContext() const DatePicker = ({ field }: { field: FieldValues }) => { const userDateFormat = getUserDateFormat() const [open, setOpen] = useState(false) const [value, setValue] = useState(field.value ? formatDate(field.value) : undefined) const date = field.value ? toDate(field.value) : undefined return
{ setValue(formatDate(field.value)) field.onBlur() }} placeholder={userDateFormat} value={value} onChange={(e) => { setValue(e.target.value) if (e.target.value) { // On change in value, try computing date usning standard formats first const dateObj = toDate(e.target.value, userDateFormat) // If we find a valid date, use it if (dateObj && !isNaN(dateObj.getTime())) { field.onChange(formatDate(dateObj, "YYYY-MM-DD")) } else { // If not, try parsing using chrono-node for things like "1st July 2025" const date = parseDate(e.target.value) if (date) { field.onChange(formatDate(date, "YYYY-MM-DD")) } } } else { field.onChange("") } }} onKeyDown={(e) => { if (e.key === "ArrowDown") { e.preventDefault() setOpen(true) } }} maxLength={140} {...inputProps} /> { setValue(formatDate(date)) field.onChange(formatDate(date, "YYYY-MM-DD")) setOpen(false) }} />
} return ( {label}{isRequired && } {formDescription && {formDescription}} )} /> } interface SmallTextFieldProps extends FormElementProps { inputProps?: Omit, "value" | "onChange" | "onBlur" | "name" | "ref"> } export const SmallTextField = ({ name, rules, label, isRequired, formDescription, inputProps, hideLabel, disabled, readOnly }: SmallTextFieldProps) => { const { control } = useFormContext() return ( {label}{isRequired && }