From fa1c3fcff188afde8a92d3b4ff4017f8efca10e4 Mon Sep 17 00:00:00 2001 From: Viicos <65306057+Viicos@users.noreply.github.com> Date: Fri, 10 Nov 2023 16:12:33 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20[#2]=20Implement=20types=20for=20`s?= =?UTF-8?q?elect`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/formio/components/index.ts | 1 + src/formio/components/select.ts | 52 +++++ src/formio/index.ts | 2 + test-d/formio/components/select.test-d.ts | 232 ++++++++++++++++++++++ 4 files changed, 287 insertions(+) create mode 100644 src/formio/components/select.ts create mode 100644 test-d/formio/components/select.test-d.ts diff --git a/src/formio/components/index.ts b/src/formio/components/index.ts index 66c243e..b8eda7a 100644 --- a/src/formio/components/index.ts +++ b/src/formio/components/index.ts @@ -11,6 +11,7 @@ export * from './iban'; export * from './licenseplate'; export * from './bsn'; export * from './number'; +export * from './select'; export * from './checkbox'; export * from './selectboxes'; export * from './file'; diff --git a/src/formio/components/select.ts b/src/formio/components/select.ts new file mode 100644 index 0000000..fd84a6c --- /dev/null +++ b/src/formio/components/select.ts @@ -0,0 +1,52 @@ +import {InputComponentSchema} from '..'; +import {MultipleCapable, OFExtensions} from '../base'; +import {ManualValues, Option, VariableValues} from '../common'; + +type Validator = 'required'; +type TranslatableKeys = 'label' | 'description' | 'tooltip'; + +export type SelectInputSchema = InputComponentSchema; + +export type SelectUnsupported = 'hideLabel' | 'disabled' | 'placeholder'; + +/** + * @group Form.io components + * @category Base types + */ +interface BaseSelectSchema { + type: 'select'; + // not to be confused with openforms.dataSrc. Formio itself supports dynamic sources + // like json/url/resource/custom but we don't use any of that, our backend resolves + // dynamic values into data.values already. + // So our openForms.dataSrc == itemsExpression results in dataSrc == values. + dataSrc: 'values'; +} + +/** + * @group Form.io components + * @category Base types + */ +type SelectManualValuesSchema = Omit & + BaseSelectSchema & { + openForms: OFExtensions['openForms'] & ManualValues; + data: { + values: Option[]; + }; + }; + +/** + * @group Form.io components + * @category Base types + */ +type SelectVariableValuesSchema = Omit & + BaseSelectSchema & { + openForms: OFExtensions['openForms'] & VariableValues; + }; + +/** + * @group Form.io components + * @category Concrete types + */ +export type SelectComponentSchema = MultipleCapable< + SelectManualValuesSchema | SelectVariableValuesSchema +>; diff --git a/src/formio/index.ts b/src/formio/index.ts index 0088779..adce960 100644 --- a/src/formio/index.ts +++ b/src/formio/index.ts @@ -13,6 +13,7 @@ import { PhoneNumberComponentSchema, PostcodeComponentSchema, RadioComponentSchema, + SelectComponentSchema, SelectboxesComponentSchema, TextFieldComponentSchema, TimeComponentSchema, @@ -52,6 +53,7 @@ export type AnyComponentSchema = | PostcodeComponentSchema | FileComponentSchema | NumberComponentSchema + | SelectComponentSchema | CheckboxComponentSchema | SelectboxesComponentSchema | CurrencyComponentSchema diff --git a/test-d/formio/components/select.test-d.ts b/test-d/formio/components/select.test-d.ts new file mode 100644 index 0000000..6802564 --- /dev/null +++ b/test-d/formio/components/select.test-d.ts @@ -0,0 +1,232 @@ +import {expectAssignable, expectNotAssignable} from 'tsd'; + +import {SelectComponentSchema} from '../../../lib'; + +// minimal component schema, manual: +expectAssignable({ + id: 'yejak', + type: 'select', + dataSrc: 'values', + key: 'someSelect', + label: 'Some select', + openForms: { + dataSrc: 'manual', + translations: {}, + }, + data: { + values: [ + { + value: 'dummy', + label: 'dummy', + }, + ], + }, +}); + +// minimal component schema, variable: +expectAssignable({ + id: 'yejak', + type: 'select', + dataSrc: 'values', + key: 'someSelect', + label: 'Some select', + openForms: { + dataSrc: 'variable', + itemsExpression: 'dummy', + translations: {}, + }, +}); + +// minimal component schema, multiple false: +expectAssignable({ + id: 'yejak', + type: 'select', + dataSrc: 'values', + key: 'someSelect', + label: 'Some select', + multiple: false, + defaultValue: 'dummy', + openForms: { + dataSrc: 'variable', + itemsExpression: 'dummy', + translations: {}, + }, +}); + +// minimal component schema, multiple true: +expectAssignable({ + id: 'yejak', + type: 'select', + dataSrc: 'values', + key: 'someSelect', + label: 'Some select', + multiple: true, + defaultValue: ['dummy'], + openForms: { + dataSrc: 'variable', + itemsExpression: 'dummy', + translations: {}, + }, +}); + +// minimal component schema, multiple true and empty defaults: +expectAssignable({ + id: 'yejak', + type: 'select', + dataSrc: 'values', + key: 'someSelect', + label: 'Some select', + multiple: true, + defaultValue: [], + openForms: { + dataSrc: 'variable', + itemsExpression: 'dummy', + translations: {}, + }, +}); + +// values translations +expectAssignable({ + id: 'yejak', + type: 'select', + dataSrc: 'values', + key: 'someSelect', + label: 'Some select', + defaultValue: 'dummy', + openForms: { + dataSrc: 'manual', + translations: {}, + }, + data: { + values: [ + { + value: 'dummy', + label: 'dummy', + openForms: { + translations: { + en: { + label: 'dummy_en', + }, + nl: { + label: 'dummy_nl', + }, + }, + }, + }, + ], + }, +}); + +// full, correct schema +expectAssignable({ + id: 'yejak', + type: 'select', + dataSrc: 'values', + // basic tab + label: 'Some select', + key: 'someSelect', + description: '', + tooltip: 'A tooltip', + showInSummary: true, + showInEmail: false, + showInPDF: true, + hidden: false, + clearOnHide: true, + isSensitiveData: true, + defaultValue: 'dummy', + // Advanced tab + conditional: { + show: undefined, + when: '', + eq: '', + }, + // Validation tab + validate: { + required: false, + plugins: [], + }, + translatedErrors: {nl: {required: 'Geef checkbox.'}}, + errors: {required: 'Geef checkbox.'}, + // registration tab + registration: { + attribute: '', + }, + // translations tab in builder form + openForms: { + translations: { + nl: {label: 'foo'}, + }, + dataSrc: 'variable', + itemsExpression: 'dummy', + }, + // fixed but not editable + validateOn: 'blur', +}); + +// Missing openForms +expectNotAssignable({ + id: 'yejak', + type: 'select', + dataSrc: 'values', + key: 'someSelect', + label: 'Some select', +}); + +// multiple true, wrong default value +expectNotAssignable({ + id: 'yejak', + type: 'select', + dataSrc: 'values', + key: 'someSelect', + label: 'Some select', + multiple: true, + defaultValue: 'dummy', + openForms: { + dataSrc: 'variable', + itemsExpression: 'dummy', + translations: {}, + }, +}); + +// multiple false, wrong default value +expectNotAssignable({ + id: 'yejak', + type: 'select', + dataSrc: 'values', + key: 'someSelect', + label: 'Some select', + multiple: false, + defaultValue: ['dummy'], + openForms: { + dataSrc: 'variable', + itemsExpression: 'dummy', + translations: {}, + }, +}); + +// manual without values +expectNotAssignable({ + id: 'yejak', + type: 'select', + dataSrc: 'values', + key: 'someSelect', + label: 'Some select', + openForms: { + dataSrc: 'manual', + translations: {}, + }, + data: {}, +}); + +// variable without itemsExpressions +expectNotAssignable({ + id: 'yejak', + type: 'select', + dataSrc: 'values', + key: 'someSelect', + label: 'Some select', + openForms: { + dataSrc: 'variable', + translations: {}, + }, +});