diff --git a/src/formio/base.ts b/src/formio/base.ts index ba8e8cd..317e8e7 100644 --- a/src/formio/base.ts +++ b/src/formio/base.ts @@ -82,12 +82,15 @@ export interface PrefillConfig { /** * @group Open Forms schema extensions + * + * The `Extra` type variable allows specifying additional, component-specific, + * extensions namespaced under the `openForms` key. */ -export interface OFExtensions { +export interface OFExtensions { isSensitiveData?: boolean; openForms?: { translations: ComponentTranslations; - }; + } & Extra; registration?: { attribute: string; }; @@ -173,12 +176,19 @@ export type MultipleCapable = S extends {defaultValue?: infer DV} /** * @group Schema primitives + * + * The `ExtraExtensions` type variable allows specifying additional, component-specific, + * extensions namespaced under the `openForms` key. */ export type InputComponentSchema< T = unknown, VN extends CuratedValidatorNames = CuratedValidatorNames, - TK extends string = string -> = StrictComponentSchema & DisplayConfig & OFExtensions & HasValidation; + TK extends string = string, + ExtraExtensions = {} +> = StrictComponentSchema & + DisplayConfig & + OFExtensions & + HasValidation; /** * @group Schema primitives diff --git a/src/formio/components/addressNL.ts b/src/formio/components/addressNL.ts index b1598a1..3c5a049 100644 --- a/src/formio/components/addressNL.ts +++ b/src/formio/components/addressNL.ts @@ -1,5 +1,4 @@ import {HasValidation, InputComponentSchema} from '..'; -import {ComponentTranslations} from '../i18n'; type Validator = 'required'; type TranslatableKeys = 'label' | 'description' | 'tooltip'; @@ -19,22 +18,24 @@ export interface AddressComponents { city?: HasValidation<'pattern', false>; } -export type AddressNLInputSchema = InputComponentSchema; +export interface AddressNLExtensions { + components?: AddressComponents; +} + +export type AddressNLInputSchema = InputComponentSchema< + AddressData, + Validator, + TranslatableKeys, + AddressNLExtensions +>; /** * @group Form.io components * @category Concrete types */ export interface AddressNLComponentSchema - extends Omit< - AddressNLInputSchema, - 'hideLabel' | 'placeholder' | 'disabled' | 'validateOn' | 'openForms' - > { + extends Omit { type: 'addressNL'; deriveAddress: boolean; layout: 'singleColumn' | 'doubleColumn'; - openForms?: { - components?: AddressComponents; - translations?: ComponentTranslations; - }; } diff --git a/src/formio/components/date.ts b/src/formio/components/date.ts index 915374b..413faa4 100644 --- a/src/formio/components/date.ts +++ b/src/formio/components/date.ts @@ -1,5 +1,4 @@ import {InputComponentSchema, MultipleCapable, PrefillConfig} from '..'; -import {OFExtensions} from '../base'; import { FutureDateConstraint as BaseFutureDateConstraint, PastDateConstraint as BasePastDateConstraint, @@ -11,8 +10,6 @@ import { type Validator = 'required' | 'minDate' | 'maxDate'; type TranslatableKeys = 'label' | 'description' | 'tooltip'; -export type DateInputSchema = InputComponentSchema; - export interface IncludeToday { includeToday: boolean | null; } @@ -21,18 +18,24 @@ type FutureOrPastDateConstraint = BaseFutureDateConstraint | BasePastDateConstra type FutureDateConstraint = BaseFutureDateConstraint & IncludeToday; type PastDateConstraint = BasePastDateConstraint & IncludeToday; +export interface DateExtensions { + minDate?: Exclude | FutureDateConstraint; + maxDate?: Exclude | PastDateConstraint; +} + +export type DateInputSchema = InputComponentSchema< + string, + Validator, + TranslatableKeys, + DateExtensions +>; + /** * @group Form.io components * @category Base types */ export interface BaseDateComponentSchema extends Omit, PrefillConfig { type: 'date'; - openForms?: OFExtensions['openForms'] & { - minDate?: - | Exclude - | FutureDateConstraint; - maxDate?: Exclude | PastDateConstraint; - }; datePicker?: DatePickerConfig; customOptions?: PickerCustomOptions; } diff --git a/src/formio/components/datetime.ts b/src/formio/components/datetime.ts index d1adf1f..35e9853 100644 --- a/src/formio/components/datetime.ts +++ b/src/formio/components/datetime.ts @@ -1,5 +1,4 @@ import {InputComponentSchema, MultipleCapable, PrefillConfig} from '..'; -import {OFExtensions} from '../base'; import { DateConstraintConfiguration, DatePickerConfig, @@ -11,7 +10,17 @@ import { type Validator = 'required' | 'minDate' | 'maxDate'; type TranslatableKeys = 'label' | 'description' | 'tooltip'; -export type DateTimeInputSchema = InputComponentSchema; +export interface DateTimeExtensions { + minDate?: Exclude; + maxDate?: Exclude; +} + +export type DateTimeInputSchema = InputComponentSchema< + string, + Validator, + TranslatableKeys, + DateTimeExtensions +>; /** * @group Form.io components @@ -21,10 +30,6 @@ export interface BaseDateTimeComponentSchema extends Omit, PrefillConfig { type: 'datetime'; - openForms?: OFExtensions['openForms'] & { - minDate?: Exclude; - maxDate?: Exclude; - }; datePicker?: DatePickerConfig; customOptions?: PickerCustomOptions; } diff --git a/src/formio/components/email.ts b/src/formio/components/email.ts index 1d00500..f51f7d1 100644 --- a/src/formio/components/email.ts +++ b/src/formio/components/email.ts @@ -3,7 +3,16 @@ import {InputComponentSchema, MultipleCapable} from '..'; type Validator = 'required'; type TranslatableKeys = 'label' | 'description' | 'tooltip'; -export type EmailInputSchema = InputComponentSchema; +export interface EmailExtensions { + requireVerification?: boolean; +} + +export type EmailInputSchema = InputComponentSchema< + string, + Validator, + TranslatableKeys, + EmailExtensions +>; /** * @group Form.io components diff --git a/src/formio/components/radio.ts b/src/formio/components/radio.ts index 5cfe308..7ff4cc2 100644 --- a/src/formio/components/radio.ts +++ b/src/formio/components/radio.ts @@ -1,11 +1,16 @@ import {InputComponentSchema} from '..'; -import {OFExtensions} from '../base'; import {ManualValues, Option, VariableValues} from '../common'; +import {Require} from '../util'; type Validator = 'required'; type TranslatableKeys = 'label' | 'description' | 'tooltip'; -export type RadioInputSchema = InputComponentSchema; +export type RadioInputSchema = InputComponentSchema< + string | null, + Validator, + TranslatableKeys, + Extensions +>; /** * @group Form.io components @@ -20,9 +25,8 @@ interface BaseRadioSchema { * @group Form.io components * @category Base types */ -type RadioManualValuesSchema = Omit & +type RadioManualValuesSchema = Omit, 'hideLabel' | 'disabled'> & BaseRadioSchema & { - openForms: OFExtensions['openForms'] & ManualValues; values: Option[]; }; @@ -30,13 +34,14 @@ type RadioManualValuesSchema = Omit * @group Form.io components * @category Base types */ -type RadioVariableValuesSchema = Omit & - BaseRadioSchema & { - openForms: OFExtensions['openForms'] & VariableValues; - }; +type RadioVariableValuesSchema = Omit, 'hideLabel' | 'disabled'> & + BaseRadioSchema; /** * @group Form.io components * @category Concrete types */ -export type RadioComponentSchema = RadioManualValuesSchema | RadioVariableValuesSchema; +export type RadioComponentSchema = Require< + RadioManualValuesSchema | RadioVariableValuesSchema, + 'openForms' +>; diff --git a/src/formio/components/select.ts b/src/formio/components/select.ts index fd84a6c..18a0314 100644 --- a/src/formio/components/select.ts +++ b/src/formio/components/select.ts @@ -1,11 +1,17 @@ import {InputComponentSchema} from '..'; -import {MultipleCapable, OFExtensions} from '../base'; +import {MultipleCapable} from '../base'; import {ManualValues, Option, VariableValues} from '../common'; +import {Require} from '../util'; type Validator = 'required'; type TranslatableKeys = 'label' | 'description' | 'tooltip'; -export type SelectInputSchema = InputComponentSchema; +export type SelectInputSchema = InputComponentSchema< + string, + Validator, + TranslatableKeys, + Extensions +>; export type SelectUnsupported = 'hideLabel' | 'disabled' | 'placeholder'; @@ -26,9 +32,8 @@ interface BaseSelectSchema { * @group Form.io components * @category Base types */ -type SelectManualValuesSchema = Omit & +type SelectManualValuesSchema = Omit, SelectUnsupported> & BaseSelectSchema & { - openForms: OFExtensions['openForms'] & ManualValues; data: { values: Option[]; }; @@ -38,15 +43,13 @@ type SelectManualValuesSchema = Omit & * @group Form.io components * @category Base types */ -type SelectVariableValuesSchema = Omit & - BaseSelectSchema & { - openForms: OFExtensions['openForms'] & VariableValues; - }; +type SelectVariableValuesSchema = Omit, SelectUnsupported> & + BaseSelectSchema; /** * @group Form.io components * @category Concrete types */ export type SelectComponentSchema = MultipleCapable< - SelectManualValuesSchema | SelectVariableValuesSchema + Require >; diff --git a/src/formio/components/selectboxes.ts b/src/formio/components/selectboxes.ts index 342fd2f..d44a1c8 100644 --- a/src/formio/components/selectboxes.ts +++ b/src/formio/components/selectboxes.ts @@ -1,14 +1,15 @@ import {InputComponentSchema} from '..'; -import {OFExtensions} from '../base'; import {ManualValues, Option, VariableValues} from '../common'; +import {Require} from '../util'; type Validator = 'required' | 'minSelectedCount' | 'maxSelectedCount'; type TranslatableKeys = 'label' | 'description' | 'tooltip'; -export type SelectboxesInputSchema = InputComponentSchema< +export type SelectboxesInputSchema = InputComponentSchema< Record, Validator, - TranslatableKeys + TranslatableKeys, + Extensions >; /** @@ -24,9 +25,11 @@ interface BaseSelectboxesSchema { * @group Form.io components * @category Base types */ -type SelectboxesManualValuesSchema = Omit & +type SelectboxesManualValuesSchema = Omit< + SelectboxesInputSchema, + 'hideLabel' | 'disabled' +> & BaseSelectboxesSchema & { - openForms: OFExtensions['openForms'] & ManualValues; values: Option[]; }; @@ -34,15 +37,17 @@ type SelectboxesManualValuesSchema = Omit & - BaseSelectboxesSchema & { - openForms: OFExtensions['openForms'] & VariableValues; - }; +type SelectboxesVariableValuesSchema = Omit< + SelectboxesInputSchema, + 'hideLabel' | 'disabled' +> & + BaseSelectboxesSchema; /** * @group Form.io components * @category Concrete types */ -export type SelectboxesComponentSchema = - | SelectboxesManualValuesSchema - | SelectboxesVariableValuesSchema; +export type SelectboxesComponentSchema = Require< + SelectboxesManualValuesSchema | SelectboxesVariableValuesSchema, + 'openForms' +>; diff --git a/src/formio/util.ts b/src/formio/util.ts new file mode 100644 index 0000000..9608692 --- /dev/null +++ b/src/formio/util.ts @@ -0,0 +1,8 @@ +/** + * Given a type `T` with optional key(s) `K`, make the key(s) `K` required. + * + * The ternary is to force distribution over unions in `T`. + */ +export type Require = T extends any + ? Omit & Required> + : never; diff --git a/test-d/formio/components/email.test-d.ts b/test-d/formio/components/email.test-d.ts index fe177b3..128c214 100644 --- a/test-d/formio/components/email.test-d.ts +++ b/test-d/formio/components/email.test-d.ts @@ -85,6 +85,7 @@ expectAssignable({ translations: { nl: {label: 'foo'}, }, + requireVerification: true, }, // fixed but not editable validateOn: 'blur',