diff --git a/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/Form/SubmitConfirmation.mdx b/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/Form/SubmitConfirmation.mdx new file mode 100644 index 00000000000..ed7703ba9a6 --- /dev/null +++ b/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/Form/SubmitConfirmation.mdx @@ -0,0 +1,25 @@ +--- +title: 'SubmitConfirmation' +description: '`Form.SubmitConfirmation` can be used to prevent the `Form.Handler` from submitting, and makes it possible to show a confirmation dialog in different scenarios.' +showTabs: true +tabs: + - title: Info + key: '/info' + - title: Demos + key: '/demos' + - title: Properties + key: '/properties' +breadcrumb: + - text: Forms + href: /uilib/extensions/forms/ + - text: Form + href: /uilib/extensions/forms/Form + - text: SubmitConfirmation + href: /uilib/extensions/forms/Form/SubmitConfirmation/ +--- + +import Info from 'Docs/uilib/extensions/forms/Form/SubmitConfirmation/info' +import Demos from 'Docs/uilib/extensions/forms/Form/SubmitConfirmation/demos' + + + diff --git a/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/Form/SubmitConfirmation/Examples.tsx b/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/Form/SubmitConfirmation/Examples.tsx new file mode 100644 index 00000000000..fe9ea87d6eb --- /dev/null +++ b/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/Form/SubmitConfirmation/Examples.tsx @@ -0,0 +1,152 @@ +import { Dialog, Flex, Section } from '@dnb/eufemia/src' +import ComponentBox from '../../../../../../shared/tags/ComponentBox' +import { Field, Form } from '@dnb/eufemia/src/extensions/forms' + +export const WithDialog = () => { + return ( + + { + await new Promise((resolve) => setTimeout(resolve, 2000)) + }} + > + + + + + + true} + renderWithState={({ connectWithDialog }) => { + return ( + + ) + }} + /> + + + ) +} + +export const WithStateContent = () => { + return ( + + { + await new Promise((resolve) => setTimeout(resolve, 2000)) + }} + > + true} + onStateChange={({ confirmationState }) => { + console.log('onStateChange', confirmationState) + }} + renderWithState={({ confirmationState, connectWithDialog }) => { + let content = null + + switch (confirmationState) { + case 'readyToBeSubmitted': + content = <>Is waiting ... + break + case 'submitInProgress': + content = <>Submitting... + break + case 'submissionComplete': + content = <>Complete! + break + default: + content = ( + + + + + ) + break + } + + return ( + <> + {content} + + + ) + }} + /> + + + ) +} + +export const WithCustomReturnStatus = () => { + return ( + + { + await new Promise((resolve) => setTimeout(resolve, 2000)) + return { + customStatus: 'My custom status', + } + }} + > + + + + + + { + if (submitState && submitState.customStatus) { + setConfirmationState('readyToBeSubmitted') + } + }} + renderWithState={({ connectWithDialog, submitState }) => { + return ( + +
+ + + + + + +
+
+ ) + }} + /> +
+
+ ) +} diff --git a/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/Form/SubmitConfirmation/demos.mdx b/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/Form/SubmitConfirmation/demos.mdx new file mode 100644 index 00000000000..8bf405a3caa --- /dev/null +++ b/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/Form/SubmitConfirmation/demos.mdx @@ -0,0 +1,21 @@ +--- +showTabs: true +--- + +import * as Examples from './Examples' + +## Demos + +### With confirmation dialog + + + +### Enable and disable the confirmation mechanism + +This example makes first an ordinary submit request. But when the custom status is returned, the dialog component will be shown. + + + +### Render different content based on the submit state + + diff --git a/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/Form/SubmitConfirmation/info.mdx b/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/Form/SubmitConfirmation/info.mdx new file mode 100644 index 00000000000..2447c4b04f4 --- /dev/null +++ b/packages/dnb-design-system-portal/src/docs/uilib/extensions/forms/Form/SubmitConfirmation/info.mdx @@ -0,0 +1,99 @@ +--- +showTabs: true +--- + +## Description + +`Form.SubmitConfirmation` can be used to prevent the [Form.Handler](/uilib/extensions/forms/Form/Handler/) from submitting, and makes it possible to show a confirmation dialog in different scenarios. + +```jsx +import { Dialog } from '@dnb/eufemia' +import { Form } from '@dnb/eufemia/extensions/forms' +render( + { + // Your submit request + }} + > + Content... + + { + // Your preventSubmitWhen logic + }} + onStateChange={(parameters) => { + // Your onStateChange logic + }} + renderWithState={(parameters) => { + return 'Your content' + }} + /> + , +) +``` + +The `renderWithState` function is called whenever the submit confirmation state changes. It receives an object as the first parameter, which contains: + +- `connectWithDialog` lets you connect the submit confirmation with a [Dialog](/uilib/components/dialog). +- `submitHandler` is a function that can be called to submit the form. +- `cancelHandler` is a function that can be called to cancel the form. +- `setConfirmationState` is a function that can be called to update the submit state. +- `confirmationState` is a string that can be used to determine the current state of the submit confirmation: + - `idle` + - `readyToBeSubmitted` + - `submitInProgress` + - `submissionComplete` +- `submitState` is the state of the `onSubmit` form event: + - `error` + - `info` + - `warning` + - `success` + - `customStatus` Your custom status. +- `data` is the data that was submitted. + +## Connect with a Dialog + +You can connect the submit confirmation with a [Dialog](/uilib/components/dialog) by using the `connectWithDialog` property. This property is an object that contains the `openState`, `onConfirm`, `onDecline`, and `onClose` properties, which you can spread to the Dialog component. + +```jsx +import { Dialog } from '@dnb/eufemia' +import { Form } from '@dnb/eufemia/extensions/forms' + +render( + + { + return ( + + ) + }} + /> + , +) +``` + +## Using the submitHandler and cancelHandler + +In addition to `connectWithDialog`, there are the `submitHandler` and `cancelHandler` functions, available to handle the submission and cancellation processes: + +```jsx + { + return ( + <> + + }} + /> + + ) + + expect(document.querySelector('button')).not.toBeDisabled() + }) +}) diff --git a/packages/dnb-eufemia/src/extensions/forms/Form/SubmitConfirmation/index.ts b/packages/dnb-eufemia/src/extensions/forms/Form/SubmitConfirmation/index.ts new file mode 100644 index 00000000000..1d850c27c76 --- /dev/null +++ b/packages/dnb-eufemia/src/extensions/forms/Form/SubmitConfirmation/index.ts @@ -0,0 +1,2 @@ +export { default } from './SubmitConfirmation' +export * from './SubmitConfirmation' diff --git a/packages/dnb-eufemia/src/extensions/forms/Form/SubmitConfirmation/stories/SubmitConfirmation.stories.tsx b/packages/dnb-eufemia/src/extensions/forms/Form/SubmitConfirmation/stories/SubmitConfirmation.stories.tsx new file mode 100644 index 00000000000..a97da46b440 --- /dev/null +++ b/packages/dnb-eufemia/src/extensions/forms/Form/SubmitConfirmation/stories/SubmitConfirmation.stories.tsx @@ -0,0 +1,91 @@ +import React from 'react' +import { Field, Form } from '../../..' +import { Dialog, Flex, Section } from '../../../../../components' + +export default { + title: 'Eufemia/Extensions/Forms/Form/SubmitConfirmation', +} + +export function SubmitConfirmation() { + return ( + { + console.log('Now we are submitting...', data) + await new Promise((resolve) => setTimeout(resolve, 3000)) + return { + // error: new Error('Error message'), + customStatus: 'custom', + } + }} + > + + + + + + { + // if (submitState?.customStatus) { + // setConfirmationState('readyToBeSubmitted') + // return false + // } + // return true + // }} + onSubmitResult={({ submitState, setConfirmationState }) => { + if (submitState?.customStatus) { + setConfirmationState('readyToBeSubmitted') + } + }} + renderWithState={({ + submitState, + confirmationState, + connectWithDialog, + }) => { + let content = null + + switch (confirmationState) { + case 'readyToBeSubmitted': + content = <>Is waiting ... + break + case 'submitInProgress': + content = <>Submitting... + break + } + + return ( + <> + {content} + +
+ + + + + + +
+
+ + ) + }} + /> +
+ ) +} diff --git a/packages/dnb-eufemia/src/extensions/forms/Form/index.ts b/packages/dnb-eufemia/src/extensions/forms/Form/index.ts index ddb4dd9a3bb..ae7fd03bd51 100644 --- a/packages/dnb-eufemia/src/extensions/forms/Form/index.ts +++ b/packages/dnb-eufemia/src/extensions/forms/Form/index.ts @@ -5,6 +5,7 @@ export { default as Element } from './Element' export { default as Appearance } from './Appearance' export { default as SubmitButton } from './SubmitButton' export { default as SubmitIndicator } from './SubmitIndicator' +export { default as SubmitConfirmation } from './SubmitConfirmation' export { default as ButtonRow } from './ButtonRow' export { default as MainHeading } from './MainHeading' export { default as SubHeading } from './SubHeading' diff --git a/packages/dnb-eufemia/src/extensions/forms/types.ts b/packages/dnb-eufemia/src/extensions/forms/types.ts index 9e058eea074..fc1435518d1 100644 --- a/packages/dnb-eufemia/src/extensions/forms/types.ts +++ b/packages/dnb-eufemia/src/extensions/forms/types.ts @@ -530,6 +530,7 @@ export type EventStateObjectOr = { warning?: EventStateObjectWarning info?: EventStateObjectInfo pending?: EventStateObjectStatus + customStatus?: unknown } export type EventStateObjectEitherOr = @@ -537,6 +538,7 @@ export type EventStateObjectEitherOr = | { warning: EventStateObjectWarning } | { info: EventStateObjectInfo } | { status: EventStateObjectStatus } + | { customStatus: unknown } export type EventStateObject = EventStateObjectOr & EventStateObjectEitherOr @@ -574,6 +576,10 @@ export type OnSubmitParams = { clearData: () => void } +export type OnSubmitReturn = + | EventReturnWithStateObject + | void + | Promise export type OnSubmit = ( data: Data, { @@ -582,10 +588,7 @@ export type OnSubmit = ( resetForm, clearData, }: OnSubmitParams -) => - | EventReturnWithStateObject - | void - | Promise +) => OnSubmitReturn export type OnCommit = ( data: Data,