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 = {
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]);
36 <SidebarModal open onBackdropClick={onBackdropClick} rootClassName="pass-modal-two--sidebar-content">
37 {(didEnter) => children({ confirm: doConfirm, didEnter })}
41 title={c('Title').t`Discard changes?`}
43 onClose={() => ensureMounted(setConfirm)({ opened: false }) /* view may have been unmounted */}
45 alertText={c('Warning').t`You have unsaved changes.`}
46 submitText={c('Action').t`Discard`}