diff --git a/i18n/messages/en.json b/i18n/messages/en.json index 7a644ba8..2802a651 100644 --- a/i18n/messages/en.json +++ b/i18n/messages/en.json @@ -84,6 +84,11 @@ "description": "Tooltip for 'validate.min' builder field", "originalDefault": "The minimum value this field can have before the form can be submitted." }, + "205QX5": { + "defaultMessage": "When email address verification is enabled, the user must verify their email address before they can submit the form. This proves the email address exists and that they have access to the account.", + "description": "Tooltip for email 'openForms.requireVerification' builder field", + "originalDefault": "When email address verification is enabled, the user must verify their email address before they can submit the form. This proves the email address exists and that they have access to the account." + }, "2Lg8Vc": { "defaultMessage": "Hide fieldset header", "description": "Label for 'hideHeader' builder field", @@ -344,6 +349,11 @@ "description": "Character count remaining", "originalDefault": "{length} {length, plural, one {character remaining} other {characters remaining}}" }, + "Cf5zSF": { + "defaultMessage": "Verify", + "description": "Email verification button text", + "originalDefault": "Verify" + }, "D0hDzV": { "defaultMessage": "{componentType} component", "description": "Formio builder: component configuration form title", @@ -754,6 +764,11 @@ "description": "Date constraint mode 'past' label", "originalDefault": "In the past" }, + "Wb+QGm": { + "defaultMessage": "Require verification", + "description": "Label for email 'openForms.requireVerification' builder field", + "originalDefault": "Require verification" + }, "WkBjB5": { "defaultMessage": "In case that multiple identifiers are returned (in the case of eHerkenning bewindvoering and DigiD Machtigen), should the prefill data related to the main identifier be used, or that related to the authorised person?", "description": "Tooltip for 'prefill.identifierRole' builder field", @@ -1404,6 +1419,11 @@ "description": "Label for 'validate.maxLength' builder field", "originalDefault": "Maximum length" }, + "yGAl1a": { + "defaultMessage": "Close", + "description": "Modal close button label", + "originalDefault": "Close" + }, "yL9Ql7": { "defaultMessage": "Translations", "description": "Translations: translation column header", diff --git a/i18n/messages/nl.json b/i18n/messages/nl.json index 8367cd31..6e6bbaa1 100644 --- a/i18n/messages/nl.json +++ b/i18n/messages/nl.json @@ -85,6 +85,11 @@ "description": "Tooltip for 'validate.min' builder field", "originalDefault": "The minimum value this field can have before the form can be submitted." }, + "205QX5": { + "defaultMessage": "When email address verification is enabled, the user must verify their email address before they can submit the form. This proves the email address exists and that they have access to the account.", + "description": "Tooltip for email 'openForms.requireVerification' builder field", + "originalDefault": "When email address verification is enabled, the user must verify their email address before they can submit the form. This proves the email address exists and that they have access to the account." + }, "2Lg8Vc": { "defaultMessage": "Verberg veldengroepheader", "description": "Label for 'hideHeader' builder field", @@ -348,6 +353,11 @@ "description": "Character count remaining", "originalDefault": "{length} {length, plural, one {character remaining} other {characters remaining}}" }, + "Cf5zSF": { + "defaultMessage": "Verify", + "description": "Email verification button text", + "originalDefault": "Verify" + }, "D0hDzV": { "defaultMessage": "{componentType}-component", "description": "Formio builder: component configuration form title", @@ -764,6 +774,11 @@ "description": "Date constraint mode 'past' label", "originalDefault": "In the past" }, + "Wb+QGm": { + "defaultMessage": "Require verification", + "description": "Label for email 'openForms.requireVerification' builder field", + "originalDefault": "Require verification" + }, "WkBjB5": { "defaultMessage": "Indien meerdere unieke identificaties beschikbaar zijn (bijvoorbeeld bij eHerkenning Bewindvoering en DigiD Machtigen), welke prefill-gegevens moeten dan opgehaald worden? Deze voor de machtiger of de gemachtigde?", "description": "Tooltip for 'prefill.identifierRole' builder field", @@ -1423,6 +1438,11 @@ "description": "Label for 'validate.maxLength' builder field", "originalDefault": "Maximum length" }, + "yGAl1a": { + "defaultMessage": "Close", + "description": "Modal close button label", + "originalDefault": "Close" + }, "yL9Ql7": { "defaultMessage": "Vertalingen", "description": "Translations: translation column header", diff --git a/package-lock.json b/package-lock.json index 38a67938..a98c15d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,7 +39,7 @@ "@formatjs/cli": "^6.1.1", "@formatjs/ts-transformer": "^3.12.0", "@fortawesome/fontawesome-free": "^6.4.0", - "@open-formulieren/types": "^0.26.0", + "@open-formulieren/types": "^0.29.0", "@storybook/addon-actions": "^8.2.6", "@storybook/addon-essentials": "^8.2.6", "@storybook/addon-interactions": "^8.2.6", @@ -5262,9 +5262,9 @@ } }, "node_modules/@open-formulieren/types": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/@open-formulieren/types/-/types-0.26.0.tgz", - "integrity": "sha512-3FHn/HiEE5CIjQxpUXaf3CzDFKHX0Bs0eVYgBmfUvrOqC/IwmkNyWj31x54gRmwXDsaSewWyRzywnlNimO3o0A==", + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/@open-formulieren/types/-/types-0.29.0.tgz", + "integrity": "sha512-nsgXep2x1P6/QU7tGb8cWM5ukVgm/TL2AoDZtywAbKfPDiGtUZuBS78C8YCzTJQsd+JIgUe6pw4kdUIYphLdcQ==", "dev": true }, "node_modules/@pkgjs/parseargs": { @@ -26396,9 +26396,9 @@ } }, "@open-formulieren/types": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/@open-formulieren/types/-/types-0.26.0.tgz", - "integrity": "sha512-3FHn/HiEE5CIjQxpUXaf3CzDFKHX0Bs0eVYgBmfUvrOqC/IwmkNyWj31x54gRmwXDsaSewWyRzywnlNimO3o0A==", + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/@open-formulieren/types/-/types-0.29.0.tgz", + "integrity": "sha512-nsgXep2x1P6/QU7tGb8cWM5ukVgm/TL2AoDZtywAbKfPDiGtUZuBS78C8YCzTJQsd+JIgUe6pw4kdUIYphLdcQ==", "dev": true }, "@pkgjs/parseargs": { diff --git a/package.json b/package.json index b7da06f5..3e09a155 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "@formatjs/cli": "^6.1.1", "@formatjs/ts-transformer": "^3.12.0", "@fortawesome/fontawesome-free": "^6.4.0", - "@open-formulieren/types": "^0.26.0", + "@open-formulieren/types": "^0.29.0", "@storybook/addon-actions": "^8.2.6", "@storybook/addon-essentials": "^8.2.6", "@storybook/addon-interactions": "^8.2.6", diff --git a/src/components/ComponentPreview.stories.tsx b/src/components/ComponentPreview.stories.tsx index 3663e9dc..14562c98 100644 --- a/src/components/ComponentPreview.stories.tsx +++ b/src/components/ComponentPreview.stories.tsx @@ -1,3 +1,4 @@ +import {EmailComponentSchema} from '@open-formulieren/types'; import {Meta, StoryFn, StoryObj} from '@storybook/react'; import {expect, fireEvent, fn, userEvent, waitFor, within} from '@storybook/test'; @@ -131,6 +132,25 @@ export const Email: Story = { }, }; +export const EmailWithVerification: Story = { + render: Template, + args: { + component: { + type: 'email', + id: 'email', + key: 'emailPreview', + label: 'Email preview', + description: 'A preview of the email Formio component', + hidden: true, // must be ignored + validateOn: 'blur', + openForms: { + translations: {}, + requireVerification: true, + }, + }, + }, +}; + export const EmailMultiple: Story = { render: Template, diff --git a/src/components/ComponentPreview.tsx b/src/components/ComponentPreview.tsx index 5d55e08e..fa2a1b5e 100644 --- a/src/components/ComponentPreview.tsx +++ b/src/components/ComponentPreview.tsx @@ -1,4 +1,5 @@ import {JSONEditor} from '@open-formulieren/monaco-json-editor'; +import clsx from 'clsx'; import {Formik} from 'formik'; import React, {useContext, useState} from 'react'; import {FormattedMessage} from 'react-intl'; @@ -55,7 +56,10 @@ const ComponentPreviewWrapper: React.FC = ({ throw new Error("Can't submit preview form"); }} > -
+
{children}
diff --git a/src/components/formio/textfield.tsx b/src/components/formio/textfield.tsx index 3fc85cf7..082a2103 100644 --- a/src/components/formio/textfield.tsx +++ b/src/components/formio/textfield.tsx @@ -20,6 +20,7 @@ export interface TextFieldProps { showCharCount?: boolean; inputMask?: string; onChange?: (event: React.ChangeEvent) => void; + childrenAfterField?: React.ReactNode; } export const TextField: React.FC = ({ @@ -31,6 +32,7 @@ export const TextField: React.FC { const {getFieldProps, getFieldMeta} = useFormikContext(); @@ -57,20 +59,23 @@ export const TextField: React.FC) => { - formikOnChange(event); - onChange?.(event); - }} - {...props} - /> + <> + ) => { + formikOnChange(event); + onChange?.(event); + }} + {...props} + /> + {childrenAfterField} + ); const hasFocus = inputRef.current === document.activeElement; diff --git a/src/registry/email/edit.tsx b/src/registry/email/edit.tsx index 0dd40358..1277591c 100644 --- a/src/registry/email/edit.tsx +++ b/src/registry/email/edit.tsx @@ -87,6 +87,7 @@ const EditForm: EditFormDefinition = () => { {/* Validation tab */} + @@ -140,9 +141,13 @@ EditForm.defaultValues = { registration: { attribute: '', }, + // openForms extensions + openForms: { + translations: {}, + requireVerification: false, + }, // fixed but not editable validateOn: 'blur', - // inputType: 'email', }; interface DefaultValueProps { @@ -186,4 +191,26 @@ const IsConfirmationRecipient: React.FC = () => { ); }; +const RequireVerification = () => { + const intl = useIntl(); + const tooltip = intl.formatMessage({ + description: "Tooltip for email 'openForms.requireVerification' builder field", + defaultMessage: `When email address verification is enabled, the user must verify + their email address before they can submit the form. This proves the email address + exists and that they have access to the account.`, + }); + return ( + + } + tooltip={tooltip} + /> + ); +}; + export default EditForm; diff --git a/src/registry/email/preview.tsx b/src/registry/email/preview.tsx index 310a4e19..796a8f99 100644 --- a/src/registry/email/preview.tsx +++ b/src/registry/email/preview.tsx @@ -1,8 +1,10 @@ import {EmailComponentSchema} from '@open-formulieren/types'; +import {FormattedMessage} from 'react-intl'; import {TextField} from '@/components/formio'; import {ComponentPreviewProps} from '../types'; +import './previews.scss'; /** * Show a formio email component preview. @@ -12,19 +14,38 @@ import {ComponentPreviewProps} from '../types'; * @open-formulieren/formio-renderer instead for a more accurate preview. */ const Preview: React.FC> = ({component}) => { - const {key, label, description, tooltip, validate = {}, autocomplete, multiple} = component; + const { + key, + label, + description, + tooltip, + validate = {}, + autocomplete, + multiple, + openForms, + } = component; const {required = false} = validate; + const requireVerification = openForms?.requireVerification ?? false; + + const verificationButton = requireVerification ? ( + + ) : null; return ( - + <> + + ); }; diff --git a/src/registry/email/previews.scss b/src/registry/email/previews.scss new file mode 100644 index 00000000..154453f5 --- /dev/null +++ b/src/registry/email/previews.scss @@ -0,0 +1,13 @@ +.component-preview.component-preview--email { + // single value preview + .form-group > div:has(input + button) { + display: flex; + gap: 15px; + } + + // multiple value preview + td:has(input + button) { + display: flex; + gap: 15px; + } +}