From dad9370c691ec27152c023f824c4608288d6db31 Mon Sep 17 00:00:00 2001 From: Sergei Maertens Date: Thu, 30 Nov 2023 11:57:27 +0100 Subject: [PATCH] :sparkles: [#2] Implement columns component schema type --- src/formio/components/columns.ts | 59 ++++++++++++++++++++ src/formio/components/index.ts | 1 + src/formio/index.ts | 4 +- test-d/formio/components/columns.test-d.ts | 62 ++++++++++++++++++++++ 4 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 src/formio/components/columns.ts create mode 100644 test-d/formio/components/columns.test-d.ts diff --git a/src/formio/components/columns.ts b/src/formio/components/columns.ts new file mode 100644 index 0000000..a98762f --- /dev/null +++ b/src/formio/components/columns.ts @@ -0,0 +1,59 @@ +import {AnyComponentSchema, LayoutComponentSchema} from '..'; + +/** + * Configuration of a single column. + * + * Note that this deviates from Formio.js' own schema, as they are tightly coupled with + * Bootstrap properties/class names, which we deliberately avoid. + */ +export interface Column { + /** + * Size on non-mobile viewports. + * + * The size specifies the number of columns spanned in a 12-column grid. If no mobile + * size is specified, a 100% width is assumed. + */ + size: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; + /** + * Size on mobile viewports. + * + * The mobile size specifies the numbers of columns spanned in a 4-column grid. + * + * @todo Add backend migration to ensure this attribute is set everywhere. + */ + sizeMobile: 1 | 2 | 3 | 4; + /** + * Nested components inside a single column. + */ + components: AnyComponentSchema[]; +} + +/** + * The columns component schema. + * + * Columns are used to manage layout on desktop and mobile viewports by grouping nested + * components inside into columns. + * + * @group Form.io components + * @category Concrete types + */ +export interface ColumnsComponentSchema + extends Omit< + LayoutComponentSchema, + | 'label' + | 'placeholder' + | 'multiple' + | 'defaultValue' + | 'conditional' + | 'errors' + | 'description' + | 'tooltip' + | 'hideLabel' + | 'disabled' + | 'validateOn' + > { + id: string; + key: string; + type: 'columns'; + columns: Column[]; +} diff --git a/src/formio/components/index.ts b/src/formio/components/index.ts index 9597ef6..9f2618b 100644 --- a/src/formio/components/index.ts +++ b/src/formio/components/index.ts @@ -21,3 +21,4 @@ export * from './radio'; // Layout components export * from './content'; +export * from './columns'; diff --git a/src/formio/index.ts b/src/formio/index.ts index abc6acc..912ac65 100644 --- a/src/formio/index.ts +++ b/src/formio/index.ts @@ -1,6 +1,7 @@ import { BsnComponentSchema, CheckboxComponentSchema, + ColumnsComponentSchema, ContentComponentSchema, CurrencyComponentSchema, DateComponentSchema, @@ -67,7 +68,8 @@ export type AnyComponentSchema = | BsnComponentSchema | NpFamilyMembersComponentSchema // layout - | ContentComponentSchema; + | ContentComponentSchema + | ColumnsComponentSchema; /** * Convenience type alias for all supported concrete component schema types. diff --git a/test-d/formio/components/columns.test-d.ts b/test-d/formio/components/columns.test-d.ts new file mode 100644 index 0000000..28a9745 --- /dev/null +++ b/test-d/formio/components/columns.test-d.ts @@ -0,0 +1,62 @@ +import {expectAssignable, expectNotAssignable} from 'tsd'; + +import {Column, ColumnsComponentSchema} from '../../../lib'; + +// Minimal schema +expectAssignable({ + id: 'eqegfc', + type: 'columns', + key: 'columns', + columns: [], +}); + +// Full schema +expectAssignable({ + id: 'eqegfc', + type: 'columns', + key: 'columns', + columns: [ + { + size: 6, + sizeMobile: 4, + components: [ + { + id: 'wien53il', + type: 'textfield', + key: 'nestedTextField', + label: 'Nested text field', + }, + ], + }, + { + size: 3, + sizeMobile: 4, + components: [ + { + id: 'abcdefgh', + type: 'textfield', + key: 'nested2', + label: 'Second text field', + }, + ], + }, + ], +}); + +expectNotAssignable({ + size: 0 as const, + sizeMobile: 4 as const, + components: [], +}); + +expectNotAssignable({ + size: 13 as const, + sizeMobile: 4 as const, + components: [], +}); + +expectNotAssignable({ + size: 3.14 as number, + sizeMobile: 4 as const, + components: [], +});