From 384b62187ed757ed1d5da4f502fc39e4fc8c2ca7 Mon Sep 17 00:00:00 2001 From: Sergei Maertens Date: Tue, 5 Dec 2023 11:08:14 +0100 Subject: [PATCH] :sparkles: [#2] Implement signature component schema type definition --- src/formio/components/index.ts | 1 + src/formio/components/signature.ts | 61 +++++++++++ src/formio/index.ts | 2 + test-d/formio/components/signature.test-d.ts | 105 +++++++++++++++++++ 4 files changed, 169 insertions(+) create mode 100644 src/formio/components/signature.ts create mode 100644 test-d/formio/components/signature.test-d.ts diff --git a/src/formio/components/index.ts b/src/formio/components/index.ts index 42f3770..e8c0802 100644 --- a/src/formio/components/index.ts +++ b/src/formio/components/index.ts @@ -21,6 +21,7 @@ export * from './radio'; export * from './addressNL'; export * from './map'; export * from './editgrid'; +export * from './signature'; // Layout components export * from './content'; diff --git a/src/formio/components/signature.ts b/src/formio/components/signature.ts new file mode 100644 index 0000000..0e86402 --- /dev/null +++ b/src/formio/components/signature.ts @@ -0,0 +1,61 @@ +import {InputComponentSchema} from '..'; + +type Validator = 'required'; +type TranslatableKeys = 'label' | 'description' | 'tooltip' | 'footer'; + +/** + * The value is base64 encoded binary (image) data, or unset and then it's a string. + * + * When a non-empty value is set, enforce that it is serialized as a data URI. + */ +export type SignatureValue = `data:image/png;base64,${string}`; + +export type SignatureInputSchema = InputComponentSchema< + SignatureValue | '', + Validator, + TranslatableKeys +>; + +/** + * The built-in Formio.js signature component type. + * + * Source code this is based on: + * https://github.com/formio/formio.js/blob/4.13.x/src/components/signature/Signature.js + * + * Note that we don't offer support for many properties through our form builder, like: + * + * - width + * - height + * - penColor + * - backgroundColor + * - minWidth + * - maxWidth + * + * Because of that, they are also not added to the type definitions (yet). That may + * change once we implement our own renderer. + * + * @group Form.io components + * @category Concrete types + */ +export interface SignatureComponentSchema + extends Omit< + SignatureInputSchema, + 'hideLabel' | 'disabled' | 'placeholder' | 'validateOn' | 'multiple' + > { + type: 'signature'; + /** + * The footer is a text displayed below the drawing canvas which may hint the user on + * what is expected of them. + * + * I'm not sure what the difference is with the 'description' field. + */ + footer?: string; // translatable instruction + + /** + * The value type of the component. We don't support `multiple: true` in this component. + * + * Note that we use the `defaultValue` property to infer the value type, we do not + * support actually setting a component default value. + */ + defaultValue?: SignatureValue | ''; +} diff --git a/src/formio/index.ts b/src/formio/index.ts index 1a22fb5..b77d613 100644 --- a/src/formio/index.ts +++ b/src/formio/index.ts @@ -21,6 +21,7 @@ import { RadioComponentSchema, SelectComponentSchema, SelectboxesComponentSchema, + SignatureComponentSchema, TextFieldComponentSchema, TextareaComponentSchema, TimeComponentSchema, @@ -72,6 +73,7 @@ export type AnyComponentSchema = | BsnComponentSchema | AddressNLComponentSchema | NpFamilyMembersComponentSchema + | SignatureComponentSchema | MapComponentSchema | EditGridComponentSchema // layout diff --git a/test-d/formio/components/signature.test-d.ts b/test-d/formio/components/signature.test-d.ts new file mode 100644 index 0000000..457b35a --- /dev/null +++ b/test-d/formio/components/signature.test-d.ts @@ -0,0 +1,105 @@ +import {expectAssignable, expectNotAssignable} from 'tsd'; + +import {SignatureComponentSchema} from '../../../lib/'; + +// minimal signature component schema +expectAssignable({ + id: 'yejak', + type: 'signature', + key: 'someSignature', + label: 'Some signature', +}); + +// with additional, signature-component specific properties +expectAssignable({ + id: 'yejak', + type: 'signature', + key: 'someSignature', + label: 'Some signature', + defaultValue: 'data:image/png;base64,dGhlIGdhbWU=', + footer: 'Please do not draw inappropriate images', +}); + +// full, correct schema +expectAssignable({ + id: 'yejak', + type: 'signature', + // basic tab in builder form + label: 'Some signature', + key: 'someSignature', + description: 'A description', + tooltip: 'A tooltip', + showInSummary: true, + showInEmail: false, + showInPDF: true, + hidden: false, + clearOnHide: true, + isSensitiveData: false, + defaultValue: '', + // advanced tab in builder form + conditional: { + show: undefined, + when: undefined, + eq: undefined, + }, + // validation tab in builder form + validate: { + required: false, + plugins: undefined, + }, + translatedErrors: { + nl: { + required: 'Je moet een waarde opgeven!!!', + }, + }, + errors: { + // translatedErrors is converted into errors by the backend + required: 'Je moet een waarde opgeven!!!', + }, + // registration tab in builder form + registration: { + attribute: '', + }, + // translations tab in builder form + openForms: { + translations: { + nl: { + label: 'foo', + description: 'bar', + }, + }, + }, +}); + +// different component type +expectNotAssignable({ + type: 'fieldset' as const, +}); + +// using unsupported properties +expectNotAssignable({ + id: 'yejak', + type: 'signature' as const, + key: 'someSignature', + label: 'Some signature', + hideLabel: true, +}); + +// bad value format +expectNotAssignable({ + id: 'yejak', + type: 'signature' as const, + key: 'someSignature', + label: 'Some signature', + defaultValue: 'random string', +}); + +// multiple is not supported +expectNotAssignable({ + id: 'yejak', + type: 'signature' as const, + key: 'someSignature', + label: 'Some signature', + multiple: true, + defaultValue: [], +});