UNPKG

@mmstack/form-adapters

Version:

Provides a collection of **headless, reusable state adapters** for common form field types. Built upon [@mmstack/form-core](https://www.npmjs.com/package/@mmstack/form-core) and integrating with [@mmstack/form-validation](https://www.npmjs.com/package/@mm

934 lines (927 loc) 115 kB
import * as _angular_core from '@angular/core'; import { Signal, WritableSignal } from '@angular/core'; import { FormControlSignal, CreateFormControlOptions, DerivedSignal, CreateFormGroupOptions, FormGroupSignal } from '@mmstack/form-core'; import { DerivedSignal as DerivedSignal$1 } from '@mmstack/primitives'; import { DateValidatorOptions, DateRange, NumberValidatorOptions, ArrayValidatorOptions, StringValidatorOptions } from '@mmstack/form-validation'; import { HttpResourceRequest } from '@angular/common/http'; import { Validator } from '@angular/forms'; /** * Represents the reactive state for a boolean form control (e.g., checkbox). * Extends the base `FormControlSignal<boolean>` and includes a `type` discriminator. * Intended for use with checkbox-like UI elements. For toggle switches, see `ToggleState`. * * @template TParent The type of the parent form group's value, if applicable. * @see ToggleState */ type BooleanState<TParent = undefined> = FormControlSignal<boolean, TParent> & { /** signal for error tooltip, default is shortened when error is longer than 40 chars */ errorTooltip: Signal<string>; /** signal for hint tooltip, default is shortened when hint is longer than 40 chars */ hintTooltip: Signal<string>; /** Type discriminator for boolean controls. */ type: 'boolean'; }; /** * Configuration options for creating a `BooleanState`, used with `createBooleanState`. * * Inherits options from `CreateFormControlOptions<boolean>` but omits `required`, * as boolean "required" validation typically means "must be true", which is handled * via the `validation` option in `injectCreateBooleanState`. * * @see CreateFormControlOptions * @see injectCreateBooleanState */ type BooleanStateOptions = Omit<CreateFormControlOptions<boolean, 'control'>, 'required'> & { maxErrorHintLength?: () => number; }; /** * Creates the reactive state object (`BooleanState`) for a boolean form control * without relying on Angular's dependency injection for validation setup. * * Use this function directly if: * - You don't need validation or are providing a pre-built `validator` function manually. * - You are creating state outside of an Angular injection context. * * For easier integration with `@mmstack/form-validation`, prefer `injectCreateBooleanState`. * * @template TParent The type of the parent form group's value, if applicable. * @param value The initial boolean value, or a `DerivedSignal` linking it to a parent state. * @param opt Optional configuration (`BooleanStateOptions`), potentially including a `validator` function. * @returns A `BooleanState` instance managing the control's reactive state. * @see injectCreateBooleanState */ declare function createBooleanState<TParent = undefined>(value: boolean | DerivedSignal<TParent, boolean>, opt?: BooleanStateOptions): BooleanState<TParent>; /** * Configuration options specifically for the factory function returned by * `injectCreateBooleanState`. * * This type is derived from `BooleanStateOptions` but explicitly excludes the * `validator` property (as validation rules are configured via the `validation` * property below) and adds the `validation` configuration specific to boolean controls. * * @see injectCreateBooleanState * @see BooleanStateOptions */ type InjectedBooleanStateOptions = Omit<BooleanStateOptions, 'validator'> & { /** * Optional configuration for boolean-specific validation rules. * The factory function uses the injected `validators` service based on this configuration. */ validation?: () => { /** * If `true`, applies the `validators.boolean.mustBeTrue()` validator, * requiring the control's value to be `true` to be considered valid. */ requireTrue?: boolean; }; }; /** * Factory function (returned by `injectCreateBooleanState`) that creates `BooleanState`. * Integrates with `@mmstack/form-validation` via DI to apply validation rules. * * @template TParent The type of the parent form group's value, if applicable. * @param value The initial boolean value, or a `DerivedSignal` linking it to a parent state. * @param opt Configuration options specific to this injected factory, defined by * the `InjectedBooleanStateOptions` type, including the `validation` property. * @returns A `BooleanState` instance managing the control's reactive state. */ declare function injectCreateBooleanState(): <TParent = undefined>(value: boolean | DerivedSignal<TParent, boolean>, opt?: InjectedBooleanStateOptions) => BooleanState<TParent>; /** * Represents the reactive state for a toggle switch form control (e.g., `mat-slide-toggle`). * * This type is functionally equivalent to `BooleanState` but overrides the `type` * discriminator to `'toggle'` for specific identification if needed. * * @template TParent The type of the parent form group's value, if applicable. * @see BooleanState */ type ToggleState<TParent = undefined> = Omit<BooleanState<TParent>, 'type'> & { /** Type discriminator for toggle switch controls. */ type: 'toggle'; }; /** * Configuration options for `createToggleState`. * This is a direct type alias for `BooleanStateOptions`. * * @see BooleanStateOptions * @see createToggleState */ type ToggleStateOptions = BooleanStateOptions; /** * Configuration options for the factory function returned by `injectCreateToggleState`. * This is a direct type alias for `InjectedBooleanStateOptions`. * * @see InjectedBooleanStateOptions * @see injectCreateToggleState */ type InjectedToggleStateOptions = InjectedBooleanStateOptions; /** * Creates the reactive state object (`ToggleState`) for a toggle switch form control * without relying on Angular's dependency injection for validation setup. * * This function wraps `createBooleanState` and simply overrides the `type` property * to `'toggle'`. Use this function if creating state outside an injection context * or providing a manual `validator` function via the options. * * For easier validation integration (like `requireTrue`), prefer `injectCreateToggleState`. * * @template TParent The type of the parent form group's value, if applicable. * @param value The initial boolean value (`true`/`false`), or a `DerivedSignal` linking it to a parent state. * @param opt Optional configuration (`ToggleStateOptions`, alias for `BooleanStateOptions`). * @returns A `ToggleState` object managing the toggle's reactive state. * @see createBooleanState * @see injectCreateToggleState */ declare function createToggleState<TParent = undefined>(value: boolean | DerivedSignal$1<TParent, boolean>, opt?: ToggleStateOptions): ToggleState<TParent>; /** * Creates and returns a factory function for generating `ToggleState` instances. * * This factory utilizes Angular's dependency injection by wrapping the factory * returned from `injectCreateBooleanState`. It simplifies validation integration * (e.g., setting `requireTrue` via the `validation` option). * * This is the **recommended** way to create `ToggleState` when working within * an Angular injection context, especially if validation is needed. * * @returns A factory function: `(value: boolean | DerivedSignal<TParent, boolean>, opt?: InjectedToggleStateOptions) => ToggleState<TParent>`. * @see injectCreateBooleanState * @see InjectedToggleStateOptions * @example * // Within an Angular injection context (component, service, etc.): * const createToggle = injectCreateToggleState(); // Get the factory * * // Create state for an optional dark mode toggle * const darkModeState = createToggle(false, { label: () => 'Dark Mode' }); * * // Create state for a toggle that must be enabled * const enableAnalyticsState = createToggle(false, { * label: () => 'Enable Analytics', * validation: () => ({ requireTrue: true }) // Use validation option * }); */ declare function injectCreateToggleState(): <TParent = undefined>(value: boolean | DerivedSignal$1<TParent, boolean>, opt?: InjectedToggleStateOptions) => ToggleState<TParent>; /** * Represents the reactive state for a date input form control. * * Extends the base `FormControlSignal<TDate | null>` and adds date-specific * properties like `placeholder` and enhanced `error`/`errorTooltip` signals derived * from the validation result's `.resolve()` method (when using the injected factory). * * @template TParent The type of the parent form group's value, if applicable. Defaults to `undefined`. * @template TDate The type used for date values within the control (e.g., `Date`, Luxon `DateTime`, Moment). Defaults to `Date`. * @see FormControlSignal */ type DateState<TParent = undefined, TDate = Date> = FormControlSignal<TDate | null, // Value can be the specific date type or null TParent> & { /** Signal holding the input placeholder text (e.g., "YYYY-MM-DD"). */ placeholder: Signal<string>; /** * Signal holding the formatted error message suitable for tooltips or detailed display. * When multiple validation errors occur, this may contain all messages, while `error()` might show a summary. * (Generated by `injectCreateDateState` using the validator's `.resolve()` method, or shortened by provided maxErrorHintLength). */ errorTooltip: Signal<string>; /** signal for hint tooltip, default is shortened when hint is longer than 40 chars */ hintTooltip: Signal<string>; /** * Signal holding the minimum selectable date (inclusive), derived from options. * Returns `null` if no minimum date is set. The value is always a `Date` object internally * for reliable comparison, regardless of the input option format (`string` or `Date`). * Useful for binding to date picker component properties (e.g., `[min]`). */ min: Signal<Date | null>; /** * Signal holding the maximum selectable date (inclusive), derived from options. * Returns `null` if no maximum date is set. The value is always a `Date` object internally. * Useful for binding to date picker component properties (e.g., `[max]`). */ max: Signal<Date | null>; /** Type discriminator for date controls. */ type: 'date'; }; /** * Configuration options for the `createDateState` function (the non-DI version). * Extends base form control options for a `TDate | null` value. * * @template TDate The type used for date values. Defaults to `Date`. * @see CreateFormControlOptions * @see createDateState */ type DateStateOptions<TDate = Date> = CreateFormControlOptions<TDate | null, 'control'> & { /** * The locale string (e.g., 'en-US', 'de-DE'). While required by this type, * it's primarily intended to be passed down internally when using the * dependency-injected factory (`injectCreateDateState`) which obtains it from `LOCALE_ID`. * If using `createDateState` directly, you must provide it manually, but its primary * use is within the validation message formatting handled by the injected system. */ locale: string; /** Optional function returning the placeholder text for the date input. */ placeholder?: () => string; /** * Optional function returning the minimum selectable date (inclusive). * Accepts a string (parsed as `new Date(string)`), a `Date` object, or `null`. * Populates the `min` signal on the `DateState`. * Note: If using `injectCreateDateState`, setting `min` via the `validation` * options is generally preferred as it enables validation messages. */ min?: () => string | Date | null; /** * Optional function returning the maximum selectable date (inclusive). * Accepts a string (parsed as `new Date(string)`), a `Date` object, or `null`. * Populates the `max` signal on the `DateState`. * Note: If using `injectCreateDateState`, setting `max` via the `validation` * options is generally preferred as it enables validation messages. */ max?: () => string | Date | null; maxErrorHintLength?: () => number; }; /** * Configuration options specifically for the factory function returned by * `injectCreateDateState`. * * This type omits base properties handled internally by the factory (like `validator`, `required`, `locale`) * and requires validation rules to be provided via the `validation` property using `DateValidatorOptions` * from `@mmstack/form-validation`. * * @template TDate The type used for date values. Defaults to `Date`. * @see injectCreateDateState * @see DateStateOptions * @see DateValidatorOptions */ type InjectedDateStateOptions<TDate = Date> = Omit<DateStateOptions<TDate>, 'required' | 'validator' | 'locale' | 'min' | 'max'> & { /** * Optional function returning a `DateValidatorOptions` object defining the validation rules. * The `min`, `max` & `required` properties set here will be used for both validation *and* to populate * the `min`, `max` & `required` signals on the resulting `DateState`. * The factory function uses this configuration with the injected `validators.date.all()` method. * * @example validation: () => ({ required: true, min: new Date(), max: '2099-12-31' }) */ validation?: () => DateValidatorOptions; }; /** * Creates the reactive state object (`DateState`) for a date form control * without relying on Angular's dependency injection for validation or locale. * Includes computed signals for `min` and `max` date constraints based directly on the provided options. * * Use this function directly only if creating state outside an injection context * or providing a fully custom `validator`, `locale`, `min`, and `max` manually via `opt`. * Prefer `injectCreateDateState` for standard usage within Angular applications. * * Note: The `errorTooltip` signal returned by this function will initially be empty. * Enhanced tooltip generation based on multiple errors is handled by `injectCreateDateState`. * * @template TParent The type of the parent form group's value, if applicable. Defaults to `undefined`. * @template TDate The type used for date values. Defaults to `Date`. * @param value The initial date value (`TDate | null`), or a `DerivedSignal` linking it to a parent state. * @param opt Configuration options (`DateStateOptions`), requires `locale`, optionally `validator`, `placeholder`, `min`, `max`. * @returns A `DateState` instance managing the control's reactive state, including `min` and `max` signals. * @see injectCreateDateState */ declare function createDateState<TParent = undefined, TDate = Date>(value: TDate | null | DerivedSignal<TParent, TDate | null>, opt: DateStateOptions<TDate>): DateState<TParent, TDate>; /** * Creates and returns a factory function for generating `DateState` instances. * * This factory utilizes Angular's dependency injection (`injectValidators`, `LOCALE_ID`) * to automatically handle: * - Validation configuration via `DateValidatorOptions` (passed to the `validation` option). * - Localization for default validation error messages. * - Enhanced error message formatting (splitting merged errors into `error` and `errorTooltip` signals). * - Populating the `min` and `max` signals on `DateState` based on the constraints specified * within the `validation` options object. * - Configuration of date handling based on `provideValidatorConfig`. * * This is the **recommended** way to create `DateState` within an Angular application. * * @returns A factory function: `(value: TDate | null | DerivedSignal<TParent, TDate | null>, opt?: InjectedDateStateOptions<TDate>) => DateState<TParent, TDate>`. * @template TDate The type used for date values passed to the factory (e.g., `Date`, Luxon `DateTime`). * Must match the `TDate` used during `provideValidatorConfig` if custom date handling is required. Defaults to `Date`. * * @example * // Within an injection context: * const createDate = injectCreateDateState(); * // If using Luxon: const createDate = injectCreateDateState<DateTime>(); * * const eventDateState = createDate(null, { * label: () => 'Event Date', * placeholder: () => 'Select event date', * validation: () => ({ // Provide DateValidatorOptions here * required: true, * min: new Date(), // Sets min validation AND state.min() signal * max: '2099-12-31' // Sets max validation AND state.max() signal * }) * }); * * // Template can use min/max signals for datepicker limits: * // <mat-datepicker-toggle [for]="picker" [disabled]="eventDateState.disabled()"></mat-datepicker-toggle> * // <input matInput [matDatepicker]="picker" * // [min]="eventDateState.min()" * // [max]="eventDateState.max()" * // [(ngModel)]="eventDateState.value" ... > * // <mat-datepicker #picker></mat-datepicker> * // <mat-error><span [matTooltip]="eventDateState.errorTooltip()">{{ eventDateState.error() }}</span></mat-error> */ declare function injectCreateDateState(): <TDate = Date, TParent = undefined>(value: TDate | null | DerivedSignal<TParent, TDate | null>, opt?: InjectedDateStateOptions<TDate>) => { error: Signal<string>; errorTooltip: Signal<string>; id: string; value: _angular_core.WritableSignal<TDate | null>; dirty: Signal<boolean>; touched: Signal<boolean>; pending: Signal<boolean>; valid: Signal<boolean>; disabled: Signal<boolean>; readonly: Signal<boolean>; required: Signal<boolean>; label: Signal<string>; hint: Signal<string>; markAsTouched: () => void; markAllAsTouched: () => void; markAsPristine: () => void; markAllAsPristine: () => void; reconcile: (newValue: TDate | null) => void; forceReconcile: (newValue: TDate | null) => void; reset: () => void; resetWithInitial: (initial: TDate | null) => void; from?: ((v: TParent) => TDate | null) | undefined; equal: (a: TDate | null, b: TDate | null) => boolean; controlType: "control"; partialValue: Signal<TDate | null | undefined>; /** Signal holding the input placeholder text (e.g., "YYYY-MM-DD"). */ placeholder: Signal<string>; /** signal for hint tooltip, default is shortened when hint is longer than 40 chars */ hintTooltip: Signal<string>; /** * Signal holding the minimum selectable date (inclusive), derived from options. * Returns `null` if no minimum date is set. The value is always a `Date` object internally * for reliable comparison, regardless of the input option format (`string` or `Date`). * Useful for binding to date picker component properties (e.g., `[min]`). */ min: Signal<Date | null>; /** * Signal holding the maximum selectable date (inclusive), derived from options. * Returns `null` if no maximum date is set. The value is always a `Date` object internally. * Useful for binding to date picker component properties (e.g., `[max]`). */ max: Signal<Date | null>; /** Type discriminator for date controls. */ type: "date"; }; type DateRangeStateChildren<TDate = Date> = { start: DateState<DateRange<TDate>, TDate>; end: DateState<DateRange<TDate>, TDate>; }; /** * Represents the reactive state for a date range input form group. * * Extends the base `FormGroupSignal<DateRange<TDate>>` and adds date-specific * properties like `placeholder` and enhanced `error`/`errorTooltip` signals derived * from the validation result's `.resolve()` method (when using the injected factory). * * @template TParent The type of the parent form group's value, if applicable. Defaults to `undefined`. * @template TDate The type used for date values within the control (e.g., `Date`, Luxon `DateTime`, Moment). Defaults to `Date`. * @see FormGroupSignal * @see DateState */ type DateRangeState<TParent = undefined, TDate = Date> = FormGroupSignal<DateRange<TDate>, DateRangeStateChildren<TDate>, TParent> & { /** * Signal holding the formatted error message suitable for tooltips or detailed display. * When multiple validation errors occur, this may contain all messages, while `error()` might show a summary. * (Generated by `injectCreateDateRangeState` using the validator's `.resolve()` method, or shortened by provided maxErrorHintLength). */ errorTooltip: Signal<string>; /** signal for hint tooltip, default is shortened when hint is longer than 40 chars */ hintTooltip: Signal<string>; /** * Signal holding the minimum selectable date (inclusive), derived from options. * Returns `null` if no minimum date is set. The value is always a `Date` object internally * for reliable comparison, regardless of the input option format (`string` or `Date`). * Useful for binding to date picker component properties (e.g., `[min]`). */ min: Signal<Date | null>; /** * Signal holding the maximum selectable date (inclusive), derived from options. * Returns `null` if no maximum date is set. The value is always a `Date` object internally. * Useful for binding to date picker component properties (e.g., `[max]`). */ max: Signal<Date | null>; /** Type discriminator for date-range controls. */ type: 'date-range'; }; /** * Optional configuration for the `from/to` date state. * This allows you to customize the behavior of the `from` date input. * you can provide specific options such as placeholder. */ type ChildDateStateOptions<TDate = Date> = Omit<DateStateOptions<TDate>, 'locale' | 'min' | 'max' | 'label' | 'disable' | 'readonly' | 'maxErrorHintLength'>; /** * Configuration options for the `createDateRangeState` function (the non-DI version). * Extends base form group options for a `DateRange<TDate>` value. * * @template TDate The type used for date values. Defaults to `Date`. * @see CreateFormGroupOptions * @see createDateRangeState */ type DateRangeStateOptions<TDate = Date> = CreateFormGroupOptions<DateRange<TDate>, DateRangeStateChildren<TDate>> & { /** * The locale string (e.g., 'en-US', 'de-DE'). While required by this type, * it's primarily intended to be passed down internally when using the * dependency-injected factory (`injectCreateDateRangeState`) which obtains it from `LOCALE_ID`. * If using `createDateRangeState` directly, you must provide it manually, but its primary * use is within the validation message formatting handled by the injected system. */ locale: string; /** * Optional function returning the minimum selectable date (inclusive). * Accepts a string (parsed as `new Date(string)`), a `Date` object, or `null`. * Populates the `min` signal on the `DateRangeState`. * Note: If using `injectCreateDateRangeState`, setting `min` via the `validation` * options is generally preferred as it enables validation messages. */ min?: () => string | Date | null; /** * Optional function returning the maximum selectable date (inclusive). * Accepts a string (parsed as `new Date(string)`), a `Date` object, or `null`. * Populates the `max` signal on the `DateRangeState`. * Note: If using `injectCreateDateRangeState`, setting `max` via the `validation` * options is generally preferred as it enables validation messages. */ max?: () => string | Date | null; maxErrorHintLength?: () => number; /** Optional configuration applied specifically to the 'start' date input control (e.g., setting a placeholder). */ start?: ChildDateStateOptions<TDate>; /** Optional configuration applied specifically to the 'end' date input control (e.g., setting a placeholder). */ end?: ChildDateStateOptions<TDate>; }; /** * Creates the reactive state object (`DateRangeState`) for a date range form control * without relying on Angular's dependency injection for validation or locale. * * Internally creates a `formGroup` with `start` and `end` `DateState` children * using the non-DI `createDateState` function. It computes overall `min`/`max` signals * based directly on the provided `opt.min` and `opt.max` options. * * Prefer `injectCreateDateRangeState` for standard usage within Angular applications to leverage * automatic validation integration, localization, and enhanced error display. * * @template TParent The type of the parent form group's value, if applicable. Defaults to `undefined`. * @template TDate The type used for date values. Defaults to `Date`. * @param value The initial date range value (`DateRange<TDate>`, e.g., `{ start: TDate|null, end: TDate|null }`), * or a `DerivedSignal` linking it to a parent state. * @param opt Configuration options (`DateRangeStateOptions`). Requires `locale`. Allows specifying options * for the child `start`/`end` inputs via `opt.start`/`opt.end`. * @returns A `DateRangeState` instance managing the control's reactive state. * @see injectCreateDateRangeState * @see DateRangeStateOptions * @see formGroup * @see createDateState */ declare function createDateRangeState<TParent = undefined, TDate = Date>(value: DateRange<TDate> | DerivedSignal<TParent, DateRange<TDate>>, opt: DateRangeStateOptions<TDate>): DateRangeState<TParent, TDate>; /** * Configuration options specifically for the factory function returned by * `injectCreateDateRangeState`. * * Extends `DateRangeStateOptions` but omits properties handled internally by the factory * (`locale`, `required`, `validator`, `min`, `max`). Requires validation rules for the * *date range itself* (including overall `min`/`max` constraints which also drive the state's signals) * via the `validation` property using `DateValidatorOptions`. * * **Assumption:** It's expected that `@mmstack/form-validation` provides range-specific validation logic * (like ensuring start <= end) accessible via `validators.dateRange.all(...)` when interpreting * the provided `DateValidatorOptions`. * * @template TDate The type used for date values. Defaults to `Date`. * @see injectCreateDateRangeState * @see DateRangeStateOptions * @see DateValidatorOptions */ type InjectedDateRangeStateOptions<TDate = Date> = Omit<DateRangeStateOptions<TDate>, 'locale' | 'required' | 'validator' | 'min' | 'max'> & { /** * Optional function returning `DateValidatorOptions`. Defines validation rules for the * *entire date range* object (e.g., required start/end, overall min/max constraints, * potentially range validity like start <= end if supported by `validators.dateRange.all`). * The `min` and `max` specified here also populate the `DateRangeState`'s `min`/`max` signals. * @example validation: () => ({ required: true, min: new Date(), range: true }) // Assuming 'range' rule exists */ validation?: () => DateValidatorOptions; }; /** * Creates and returns a factory function for generating `DateRangeState` instances. * * This factory utilizes Angular's dependency injection (`injectValidators`, `LOCALE_ID`) * to automatically handle validation configuration (expecting range-specific rules like start <= end * via `validators.dateRange.all` interpreting `DateValidatorOptions`), localization, and enhanced * error message formatting (`error`/`errorTooltip`). The overall `min`/`max` signals on the state * are also automatically derived from the `min`/`max` constraints provided within the `validation` options. * * This is the **recommended** way to create `DateRangeState` within an Angular application. * * @returns A factory function: `(value: DateRange<TDate> | DerivedSignal<TParent, DateRange<TDate>>, opt?: InjectedDateRangeStateOptions<TDate>) => DateRangeState<TParent, TDate>`. * @template TDate The type used for date values. Defaults to `Date`. Must match type used in `provideValidatorConfig`. * @template TParent The type of the parent form group's value, if applicable. Defaults to `undefined`. * * @example * // Within an injection context: * const createDateRange = injectCreateDateRangeState(); * // Assuming DateRange = { start: Date | null, end: Date | null } * * const vacationDatesState = createDateRange({ start: null, end: null }, { * label: () => 'Vacation Dates', * start: { placeholder: () => 'Departure Date' }, // Child control options * end: { placeholder: () => 'Return Date' }, * validation: () => ({ // Validation for the range * required: true, // Requires both start and end * min: new Date(), // Overall minimum date for picker & validation * // Assumes validation library has a rule triggered by DateValidatorOptions * // that checks if start <= end, potentially enabled by default or specific flag * }) * }); * * // Template binds to child states for inputs: * // <mat-date-range-input [formGroup]="vacationDatesFormGroup"> * // <input matStartDate [(ngModel)]="vacationDatesState.children().start.value" [placeholder]="vacationDatesState.children().start.placeholder()"> * // <input matEndDate [(ngModel)]="vacationDatesState.children().end.value" [placeholder]="vacationDatesState.children().end.placeholder()"> * // </mat-date-range-input> * // <mat-date-range-picker [min]="vacationDatesState.min()" [max]="vacationDatesState.max()"></mat-date-range-picker> */ declare function injectCreateDateRangeState(): <TDate = Date, TParent = undefined>(value: DateRange<TDate> | DerivedSignal<TParent, DateRange<TDate>>, opt?: InjectedDateRangeStateOptions<TDate>) => DateRangeState<TParent, TDate>; /** * Represents the reactive state for a time input form control. * * Extends the base `DateState` angular defaults to todays date, but varies the time if no date is provided * min and max values adapt automatically to the dates day * * @template TParent The type of the parent form group's value, if applicable. Defaults to `undefined`. * @template TDate The type used for date values within the control (e.g., `Date`, Luxon `DateTime`, Moment). Defaults to `Date`. * @see DateState */ type TimeState<TParent = undefined, TDate = Date> = Omit<DateState<TParent, TDate>, 'type'> & { type: 'time'; }; /** * @see DateStateOptions */ type TimeStateOptions<TDate = Date> = DateStateOptions<TDate> & { /** * A function to convert the date value to a standard `Date` object. * Defaults to `defaultToDate`, which converts `TDate` to a `Date`. */ toDate?: (date: TDate | null) => Date | null; }; /** * @see InjectedDateStateOptions */ type InjectedTimeStateOptions<TDate = Date> = InjectedDateStateOptions<TDate>; /** * Creates the reactive state object (`TimeState`) for a time form control * without relying on Angular's dependency injection for validation or locale. * Includes computed signals for `min` and `max` date constraints based directly on the provided options. * If provided the day will shift to the current values date, in order to only validate the time part. * Angular defaults to today's date, but varies the time if no date is provided. * * Use this function directly only if creating state outside an injection context * or providing a fully custom `validator`, `locale`, `min`, and `max` manually via `opt`. * Prefer `injectCreateTimeState` for standard usage within Angular applications. * * Note: The `errorTooltip` signal returned by this function will initially be empty. * Enhanced tooltip generation based on multiple errors is handled by `injectCreateTimeState`. * * @template TParent The type of the parent form group's value, if applicable. Defaults to `undefined`. * @template TDate The type used for date values. Defaults to `Date`. * @param value The initial date value (`TDate | null`), or a `DerivedSignal` linking it to a parent state. * @param opt Configuration options (`TimeStateOptions`), requires `locale`, optionally `validator`, `placeholder`, `min`, `max`. * @returns A `TimeState` instance managing the control's reactive state, including `min` and `max` signals. * @see injectCreateTimeState * @see createDateState */ declare function createTimeState<TParent = undefined, TDate = Date>(value: TDate | null | DerivedSignal$1<TParent, TDate | null>, opt: TimeStateOptions<TDate>): TimeState<TParent, TDate>; /** * Creates and returns a factory function for generating `TimeState` instances. * * This factory utilizes Angular's dependency injection (`injectValidators`, `LOCALE_ID`) * to automatically handle: * - Validation configuration via `DateValidatorOptions` (passed to the `validation` option). * - Localization for default validation error messages. * - Enhanced error message formatting (splitting merged errors into `error` and `errorTooltip` signals). * - Populating the `min` and `max` signals on `TimeState` based on the constraints specified * within the `validation` options object. * - Configuration of date handling based on `provideValidatorConfig`. * * This is the **recommended** way to create `TimeState` within an Angular application. * * @returns A factory function: `(value: TDate | null | DerivedSignal<TParent, TDate | null>, opt?: InjectedTimeStateOptions<TDate>) => TimeState<TParent, TDate>`. * @template TDate The type used for date values passed to the factory (e.g., `Date`, Luxon `DateTime`). * Must match the `TDate` used during `provideValidatorConfig` if custom date handling is required. Defaults to `Date`. * * @example * // Within an injection context: * const createTime = injectCreateTimeState(); * // If using Luxon: const createTime = injectCreateTimeState<DateTime>(); * * const eventTimeState = createTime(null, { * label: () => 'Event Time', * placeholder: () => 'Select event time', * validation: () => ({ // Provide DateValidatorOptions here * required: true, * min: new Date(), // Sets min validation AND state.min() signal * }) * }); * * // Template can use min/max signals for datepicker limits: * // <mat-timepicker-toggle [for]="picker" [disabled]="eventTimeState.disabled()"></mat-datepicker-toggle> * // <input matInput [matTimepicker]="picker" * // [min]="eventTimeState.min()" * // [max]="eventTimeState.max()" * // [(ngModel)]="eventTimeState.value" ... > * // <mat-timepicker #picker></mat-datepicker> * // <mat-error><span [matTooltip]="eventTimeState.errorTooltip()">{{ eventTimeState.error() }}</span></mat-error> */ declare function injectCreateTimeState(): <TDate = Date, TParent = undefined>(value: TDate | null | DerivedSignal$1<TParent, TDate | null>, opt?: InjectedTimeStateOptions<TDate>) => { error: _angular_core.Signal<string>; errorTooltip: _angular_core.Signal<string>; required: _angular_core.Signal<boolean>; equal: (a: TDate | null, b: TDate | null) => boolean; readonly: _angular_core.Signal<boolean>; label: _angular_core.Signal<string>; id: string; hint: _angular_core.Signal<string>; controlType: "control"; pending: _angular_core.Signal<boolean>; hintTooltip: _angular_core.Signal<string>; from?: ((v: TParent) => TDate | null) | undefined; value: _angular_core.WritableSignal<TDate | null>; dirty: _angular_core.Signal<boolean>; touched: _angular_core.Signal<boolean>; valid: _angular_core.Signal<boolean>; disabled: _angular_core.Signal<boolean>; markAsTouched: () => void; markAllAsTouched: () => void; markAsPristine: () => void; markAllAsPristine: () => void; reconcile: (newValue: TDate | null) => void; forceReconcile: (newValue: TDate | null) => void; reset: () => void; resetWithInitial: (initial: TDate | null) => void; partialValue: _angular_core.Signal<TDate | null | undefined>; min: _angular_core.Signal<Date | null>; max: _angular_core.Signal<Date | null>; placeholder: _angular_core.Signal<string>; type: "time"; }; /** * Represents the reactive state for a time input form control. * * Extends the base `DateState` to include both date and time components, exposes them as separate controls. * The base controls uses the date control's min/max & other values * * @template TParent The type of the parent form group's value, if applicable. Defaults to `undefined`. * @template TDate The type used for date values within the control (e.g., `Date`, Luxon `DateTime`, Moment). Defaults to `Date`. * @see DateState * @see TimeState */ type DateTimeState<TParent = undefined, TDate = Date> = Omit<DateState<TParent, TDate>, 'type'> & { type: 'datetime'; /** * The date control managing the date part of the datetime input. * It uses the same `min` and `max` constraints as the time control. */ dateControl: DateState<TParent, TDate>; /** * The time control managing the time part of the datetime input. * It uses the same `min` and `max` constraints as the date control. But only the time part is validatied */ timeControl: TimeState<TParent, TDate>; }; /** * @see TimeStateOptions * @see DateStateOptions */ type DateTimeStateOptions<TDate = Date> = TimeStateOptions<TDate> & { timeLabel?: () => string; timeHint?: () => string; timePlaceholder?: () => string; }; /** * @see InjectedTimeStateOptions * @see InjectedDateStateOptions */ type InjectedDateTimeStateOptions<TDate = Date> = InjectedTimeStateOptions<TDate> & { timeLabel?: () => string; timeHint?: () => string; timePlaceholder?: () => string; }; /** * Creates the reactive state object (`DateTimeState`) for a time form control * without relying on Angular's dependency injection for validation or locale. * Includes computed signals for `min` and `max` date constraints based directly on the provided options. * If provided the day will shift to the current values date, in order to only validate the time part. * Angular defaults to today's date, but varies the time if no date is provided. * * Use this function directly only if creating state outside an injection context * or providing a fully custom `validator`, `locale`, `min`, and `max` manually via `opt`. * Prefer `injectCreateDateTimeState` for standard usage within Angular applications. * * Note: The `errorTooltip` signal returned by this function will initially be empty. * Enhanced tooltip generation based on multiple errors is handled by `injectCreateDateTimeState`. * * @template TParent The type of the parent form group's value, if applicable. Defaults to `undefined`. * @template TDate The type used for date values. Defaults to `Date`. * @param value The initial date value (`TDate | null`), or a `DerivedSignal` linking it to a parent state. * @param opt Configuration options (`DateTimeStateOptions`), requires `locale`, optionally `validator`, `placeholder`, `min`, `max`. * @returns A `DateTimeState` instance managing the control's reactive state, including `min` and `max` signals. * @see injectCreateDateTimeState * @see createDateState */ declare function createDateTimeState<TParent = undefined, TDate = Date>(initial: TDate | null | DerivedSignal$1<TParent, TDate | null>, opt: DateTimeStateOptions<TDate>): DateTimeState<TParent, TDate>; /** * Creates and returns a factory function for generating `DateTimeState` instances. * * This factory utilizes Angular's dependency injection (`injectValidators`, `LOCALE_ID`) * to automatically handle: * - Validation configuration via `DateValidatorOptions` (passed to the `validation` option). * - Localization for default validation error messages. * - Enhanced error message formatting (splitting merged errors into `error` and `errorTooltip` signals). * - Populating the `min` and `max` signals on `DateTimeState` based on the constraints specified * within the `validation` options object. * - Configuration of date handling based on `provideValidatorConfig`. * * This is the **recommended** way to create `DateTimeState` within an Angular application. * * @returns A factory function: `(value: TDate | null | DerivedSignal<TParent, TDate | null>, opt?: InjectedDateTimeStateOptions<TDate>) => DateTimeState<TParent, TDate>`. * @template TDate The type used for date values passed to the factory (e.g., `Date`, Luxon `DateTime`). * Must match the `TDate` used during `provideValidatorConfig` if custom date handling is required. Defaults to `Date`. * */ declare function injectCreateDateTimeState(): <TDate = Date, TParent = undefined>(initial: TDate | null | DerivedSignal$1<TParent, TDate | null>, opt?: InjectedDateTimeStateOptions<TDate>) => DateTimeState<TParent, TDate>; /** * Represents the reactive state for a number input form control. * * Extends `FormControlSignal<number | null>` with properties and helpers * for handling placeholders, step increments/decrements, localized number formatting * (decimal separators), keyboard input filtering/handling for non-standard separators, * and enhanced error display (error vs tooltip). * * @template TParent The type of the parent form group's value, if applicable. Defaults to `undefined`. * @see FormControlSignal */ type NumberState<TParent = undefined> = FormControlSignal<number | null, TParent> & { /** Signal holding the input placeholder text (e.g., "Enter quantity", "0"). */ placeholder: Signal<string>; /** * Signal holding the step value used for incrementing/decrementing the number, * typically via spinner buttons or the ArrowUp/ArrowDown keys handled by `keydownHandler`. * Defaults to `1`. */ step: Signal<number>; /** * Signal holding the formatted error message suitable for tooltips or detailed display. * When multiple validation errors occur, this may contain all messages, while `error()` might show a summary. * (Generated by `injectCreateNumberState` using the validator's `.resolve()` method, or shortened by provided maxErrorHintLength). */ errorTooltip: Signal<string>; /** signal for hint tooltip, default is shortened when hint is longer than 40 chars */ hintTooltip: Signal<string>; /** * Signal holding the current numeric value formatted for display. * If the configured decimal separator is the standard '.', this returns the raw `number | null`. * Otherwise, it returns a `string | null` with the decimal point replaced by the configured separator. * Useful for binding directly to the `value` of an `<input [type]="state.inputType()">`. */ localizedValue: Signal<string | number | null>; /** * Function to update the control's underlying numeric value from user input, * which might be a string containing a localized decimal separator (e.g., ','). * Parses the input string (replacing the localized separator with '.') back into a number. * Handles `null`, empty string, and non-numeric input gracefully (sets value to `null`). * Intended for use with `(input)` or `(change)` events, especially when `inputType` is 'string'. * No-op if the control is disabled or readonly. * @param value The string, number, or null value received from the input element. */ setLocalizedValue: (value: string | number | null) => void; /** * Signal indicating the appropriate HTML `input` element `type` attribute ('number' or 'string'). * Returns `'number'` if the configured decimal separator is '.', otherwise returns `'string'`. * Using `<input type="string">` is necessary to allow users to type non-standard decimal separators (like ','). * Bind using `[type]="state.inputType()"`. */ inputType: Signal<'string' | 'number'>; /** * Signal returning a keydown event handler function: `(e?: KeyboardEvent) => void`. * Attach this to the `(keydown)` event of the input element, particularly when `inputType` might be 'string'. * When active (not disabled/readonly and using non-'.' separator), it: * - Prevents input of disallowed characters (allows digits, configured separator, minus, editing keys, standard shortcuts). * - Handles ArrowUp/ArrowDown keys to increment/decrement the value by `step()`. * It's a no-op if `inputType` is 'number' or the control is disabled/readonly. */ keydownHandler: Signal<(e?: KeyboardEvent) => void>; /** Type discriminator for number controls. */ type: 'number'; }; /** * Configuration options for the `createNumberState` function (the non-DI version). * Extends base form control options for a `number | null` value. * * @see CreateFormControlOptions * @see createNumberState */ type NumberStateOptions = CreateFormControlOptions<number | null, 'control'> & { /** Optional function returning the step value for number increments/decrements. Defaults to `() => 1`. */ step?: () => number; /** Optional function returning the placeholder text for the number input. */ placeholder?: () => string; /** * Optional function returning the desired decimal separator character (e.g., ',', '.'). * If not provided, defaults to '.' (ISO standard). This affects the behavior of * `localizedValue`, `setLocalizedValue`, `inputType`, and `keydownHandler`. * If using `injectCreateNumberState`, prefer the `localizeDecimal` option instead. */ decimalSeparator?: () => string; maxErrorHintLength?: () => number; }; /** * Configuration options specifically for the factory function returned by * `injectCreateNumberState`. * * This type omits base properties handled internally by the factory (like `validator`, `required`, `decimalSeparator`) * and requires validation rules to be provided via the `validation` property using `NumberValidatorOptions`. * It adds the `localizeDecimal` option for streamlined locale-based or manual separator configuration. * * @see injectCreateNumberState * @see NumberStateOptions * @see NumberValidatorOptions */ type InjectedNumberStateOptions = Omit<NumberStateOptions, 'required' | 'validator' | 'decimalSeparator'> & { /** * Optional function returning a `NumberValidatorOptions` object defining the validation rules. * The factory uses this configuration with the injected `validators.number.all()` method. * @example validation: () => ({ required: true, min: 0, integer: true }) */ validation?: () => NumberValidatorOptions; /** * Configures if and how the decimal separator should be localized, affecting input type, * formatting (`localizedValue`), parsing (`setLocalizedValue`), and keyboard handling (`keydownHandler`). * Options: * - `() => true`: Use the decimal separator determined from the injected `LOCALE_ID`. * - `() => string`: Use the provided string literal as the decimal separator (e.g., `() => ','`). * - `() => false` or `undefined` (or omit): Use the default '.' separator (results in `<input type="number">`). * @example localizeDecimal: () => true // Use locale's separator (e.g., ',' for 'de-DE') -> input type="string" * @example localizeDecimal: () => ',' // Force comma separator -> input type="string" * @example // No option provided -> uses '.' separator -> input type="number" */ localizeDecimal?: () => boolean | string; }; /** * Creates the reactive state object (`NumberState`) for a number form control * without relying on Angular's dependency injection for validation or localization. * * Use this function directly only if creating state outside an injection context, providing * a fully custom `validator`, or needing to manually specify the `decimalSeparator`. * Prefer `injectCreateNumberState` for standard usage within Angular applications, as it * integrates validation, locale-based formatting, and enhanced error display. * * Note: The `errorTooltip` signal returned by this function will initially be empty. * * @template TParent The type of the parent form group's value, if applicable. Defaults to `undefined`. * @param value The initial number value (`number | null`), or a `DerivedSignal` linking it to a parent state. * @param opt Optional configuration options (`NumberStateOptions`), potentially including `validator`, `decimalSeparator`, `step`, `placeholder`. * @returns A `NumberState` instance managing the control's reactive state. * @see injectCreateNumberState */ declare function createNumberState<TParent = undefined>(value: number | null | DerivedSignal<TParent, number | null>, opt?: NumberStateOptions): NumberState<TParent>; /** * Creates and returns a factory function for generating `NumberState` instances. * * This factory leverages Angular's dependency injection (`injectValidators`, `LOCALE_ID`) * to seamlessly integrate: * - Validation configuration via `NumberValidatorOptions`. * - Optional localization for decimal separators using the `localizeDecimal` option. * - Enhanced error message formatting (splitting merged errors into `error` and `errorTooltip`). * * This is the **recommended** way to create `NumberState` within an Angular application. * * @returns A factory function: `(value: number | null | DerivedSignal<TParent, number | null>, opt?: InjectedNumberStateOptions) => NumberState<TParent>`. * @template TParent The type of the parent form group's value, if applicable. Defaults to `undefined`. * * @example * // Within an injection context: * const createNumber = injectCreateNumberState(); * * const quantityState = createNumber(1, { * label: () => 'Qty', * step: () => 1, * validation: () => ({ required: true, min: 1, integer: true }) * }); * * const localPriceState = createNumber(null, { * label: () => 'Price', * placeholder: () => '0,00', // Example for comma locale * localizeDecimal: () => true, // Use locale separator (e.g., ',') * validation: () => ({ required: true, min: 0, multipleOf: 0.01 }) * }); * * // Template usage requires handling localized input if localizeDecimal is not false/undefined: * // <input * // [type]="localPriceState.inputType()" // Will be 'string' if locale uses ',' * // [value]="localPriceState.localizedValue()" // Formats number with ',' * // (input)="localPriceState.setLocalizedValue($any($event).target.value)" // Parses input with ',' * // (keydown)="localPriceState.keydow