UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

140 lines (139 loc) 4.56 kB
"use client"; import React, { useCallback, useContext, useMemo, useReducer, useRef } from 'react'; import DataContext from "../../DataContext/Context.js"; import useEventListener from "../../DataContext/Provider/useEventListener.js"; import SharedProvider from "../../../../shared/Provider.js"; import { HeightAnimation } from "../../../../components/index.js"; import { removeUndefinedProps } from "../../../../shared/component-helper.js"; function SubmitConfirmation(props) { const [, forceUpdate] = useReducer(() => ({}), {}); const { preventSubmitWhen, onStateChange, onSubmitResult, renderWithState, children } = props; const { setFormState, handleSubmit: handleFinalSubmit, submitState, formElementRef, internalDataRef } = useContext(DataContext); const confirmationStateRef = useRef('idle'); const submitStateRef = useRef(); const preventSubmitRef = useRef(undefined); const validatePreventSubmit = useCallback(() => { return preventSubmitRef.current = preventSubmitWhen?.(getParamsRef.current()); }, [preventSubmitWhen]); const setConfirmationState = useCallback(async state => { confirmationStateRef.current = state; await onStateChange?.(getParamsRef.current()); const setBuffered = (target, keepPending) => { if (target === 'complete') { if (typeof window !== 'undefined') { window.requestAnimationFrame(() => setFormState(target, { keepPending })); return; } } setFormState(target, { keepPending }); }; switch (state) { case 'idle': setBuffered('complete', false); break; case 'readyToBeSubmitted': setBuffered('pending', true); break; case 'submitInProgress': setBuffered('pending', true); break; case 'submissionComplete': setBuffered('complete', false); break; default: forceUpdate(); } }, [onStateChange, setFormState]); const getParamsRef = useRef(() => { const confirmationState = confirmationStateRef.current; const connectWithDialog = { openState: confirmationState === 'readyToBeSubmitted', onConfirm: submitHandler, onDecline: cancelHandler, onClose: ({ triggeredBy }) => { if (triggeredBy === 'keyboard') { cancelHandler(); } } }; return { data: internalDataRef?.current, confirmationState, setConfirmationState, submitHandler, cancelHandler, connectWithDialog, submitState: submitStateRef.current }; }); useMemo(() => { if (Object.keys(removeUndefinedProps(submitState) || {}).length > 0) { submitStateRef.current = { ...submitState }; onSubmitResult?.(getParamsRef.current()); } }, [submitState, onSubmitResult]); const setFocusOnButton = useCallback(() => { try { const form = formElementRef.current; const element = form.querySelector('.dnb-forms-submit-button') || form; element.focus(); } catch (e) {} }, [formElementRef]); const cancelHandler = useCallback(async () => { await setConfirmationState('idle'); setFocusOnButton(); }, [setFocusOnButton, setConfirmationState]); const handleSubmit = useCallback(async ({ preventSubmit }) => { if (confirmationStateRef.current === 'submitInProgress') { return; } if (validatePreventSubmit() !== true) { await setConfirmationState('submitInProgress'); return; } submitStateRef.current = undefined; preventSubmit(); await setConfirmationState('readyToBeSubmitted'); }, [setConfirmationState, validatePreventSubmit]); const { removeEvent } = useEventListener('onSubmit', handleSubmit); const submitHandler = useCallback(async () => { removeEvent(); await setConfirmationState('submitInProgress'); await handleFinalSubmit(); await setConfirmationState('submissionComplete'); setFocusOnButton(); }, [removeEvent, setConfirmationState, handleFinalSubmit, setFocusOnButton]); const sharedProviderParams = { formElement: { disabled: false } }; return React.createElement(React.Fragment, null, children, React.createElement(SharedProvider, sharedProviderParams, React.createElement(HeightAnimation, null, renderWithState?.(getParamsRef.current())))); } SubmitConfirmation._supportsSpacingProps = 'children'; export default SubmitConfirmation; //# sourceMappingURL=SubmitConfirmation.js.map