Merge branch 'feat/inda-383-daily-stat' into 'main'
[ProtonMail-WebClient.git] / packages / pass / components / Layout / Panel / DiscardableModalPanel.tsx
blobb635336550c5a5279e4c3baa2cee3213f2957243
1 import { type ReactNode, useCallback, useState } from 'react';
3 import { c } from 'ttag';
5 import { ConfirmationModal } from '@proton/pass/components/Confirmation/ConfirmationModal';
6 import type { Callback } from '@proton/pass/types';
8 import { useEnsureMounted } from '../../../hooks/useEnsureMounted';
9 import { SidebarModal } from '../Modal/SidebarModal';
11 export type DiscardableModalRenderProps = { confirm: (effect?: Callback) => void; didEnter: boolean };
12 export type DiscardableModalProps = {
13     discardable: boolean;
14     onDiscard: () => void;
15     children: (props: DiscardableModalRenderProps) => ReactNode;
18 /* The didMount state is passed as a render prop to the children so
19  * that they are informed when the modal has appeared on the screen
20  * and completed its reveal animation. This is particularly useful
21  * when the children contain input elements that need to be autofocused
22  * after the modal has finished appearing. By doing this, we can avoid
23  * animation glitches related to the "flickering caret" problem that
24  * can occur with CSS animations. The "flickering caret" problem refers
25  * to the flickering effect that can happen when the input's text cursor
26  * rapidly gains and loses focus, leading to visual inconsistencies. */
27 export const DiscardableModalPanel = ({ discardable, onDiscard, children }: DiscardableModalProps) => {
28     const ensureMounted = useEnsureMounted();
29     const [confirm, setConfirm] = useState<{ opened: boolean }>({ opened: false });
31     const doConfirm = useCallback(() => setConfirm({ opened: true }), []);
32     const onBackdropClick = useCallback(discardable ? onDiscard : () => setConfirm({ opened: true }), [discardable]);
34     return (
35         <div>
36             <SidebarModal open onBackdropClick={onBackdropClick} rootClassName="pass-modal-two--sidebar-content">
37                 {(didEnter) => children({ confirm: doConfirm, didEnter })}
38             </SidebarModal>
40             <ConfirmationModal
41                 title={c('Title').t`Discard changes?`}
42                 open={confirm.opened}
43                 onClose={() => ensureMounted(setConfirm)({ opened: false }) /* view may have been unmounted */}
44                 onSubmit={onDiscard}
45                 alertText={c('Warning').t`You have unsaved changes.`}
46                 submitText={c('Action').t`Discard`}
47             />
48         </div>
49     );