import type { ChangeEvent, ReactNode, RefObject } from "react"; import type React from "react"; import type { RegisterOptions } from "react-hook-form"; import type { XOR } from "ts-xor"; import type { Clearable } from "@jobber/hooks"; import type { IconNames } from "../Icon"; export type FormFieldTypes = "text" | "password" | "number" | "time" | "textarea" | "select" | "tel" | "email"; export type KeyBoardTypes = "text" | "none" | "tel" | "url" | "email" | "numeric" | "decimal"; export type AutocompleteTypes = "on" | "one-time-code" | "address-line1" | "address-line2"; export interface FieldActionsRef { setValue(value: string | number): void; } export interface Affix { readonly label?: string; readonly icon?: IconNames; } interface BaseSuffix extends Affix { readonly icon: IconNames; onClick?(): void; } export interface Suffix extends BaseSuffix { onClick(): void; readonly ariaLabel: string; } export interface CommonFormFieldProps { /** * A unique identifier for the input. */ readonly id?: string; /** * Determines the alignment of the text inside the input. */ readonly align?: "center" | "right"; /** * Further description of the input, can be used for a hint. */ readonly description?: ReactNode; /** * Disable the input */ readonly disabled?: boolean; /** * Controls the visibility of the mini label that appears inside the input * when a value is entered. By default, the placeholder text moves up to * become a mini label. Set to false to disable this behavior. * * @default true */ readonly showMiniLabel?: boolean; /** * Highlights the field red to indicate an error. */ readonly invalid?: boolean; /** * Adjusts the form field to go inline with a content. This also silences the * given `validations` prop. You'd have to used the `onValidate` prop to * capture the message and render it somewhere else using the * `InputValidation` component. */ readonly inline?: boolean; /** * Show a spinner to indicate loading */ loading?: boolean; /** * Name of the input. */ readonly name?: string; /** * onChange handler that provides the new value (or event) * @param newValue * @param event */ onChange?(newValue: string | number | boolean | Date, event?: ChangeEvent): void; /** * Callback to get the the status and message when validating a field * @param message */ onValidation?(message: string): void; /** * Text that appears inside the input when empty and floats above the value * as a mini label once the user enters a value. * When showMiniLabel is false, this text only serves as a standard placeholder and * disappears when the user types. */ readonly placeholder?: string; /** * Adjusts the interface to either have small or large spacing. */ readonly size?: "small" | "large"; /** * Set the component to the given value. */ readonly value?: string | number | Date; /** * Add a clear action on the input that clears the value. * * You should always use `while-editing` if you want the input to be * clearable. if the input value isn't editable (i.e. `InputTime`) you can * set it to `always`. */ readonly clearable?: Clearable; /** * Experimental: * Determine which version of the FormField to use. * Right now this isn't used but it will be used in the future * to allow us to release new versions of our form inputs without breaking existing functionality. */ version?: 1; } export interface FormFieldProps extends CommonFormFieldProps { actionsRef?: RefObject; /** * Determines if the input should be auto-focused, using the HTML attribute */ readonly autofocus?: boolean; /** * Determines if browser form autocomplete is enabled. * Note that "one-time-code" is experimental and should not be used without * consultation. "address-line1" and "address-line2" are * used for billing address information. * * Prefer the **on** option over the boolean **true** value to explicitly indicate auto-completion behavior. */ readonly autocomplete?: boolean | AutocompleteTypes; /** * If you need to pass in a children. For example, `` inside * `