import Button from '@atlaskit/button/new'; import type { KeyboardOrMouseEvent } from '@atlaskit/modal-dialog'; import ModalDialog, { ModalBody, ModalFooter, ModalHeader, ModalTitle, ModalTransition } from '@atlaskit/modal-dialog'; import { ModalExtension } from '@atlassian/clientside-extensions'; import type { FunctionComponent, ReactNode } from 'react'; import React, { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { ButtonHandler } from './ButtonHandler'; import type { OnClickHandler } from './types'; const ModalInnerBody: FunctionComponent<{ modalApi: ModalExtension.Api }> = ({ modalApi }) => { const ref = useRef(null); useEffect(() => { const node = ref.current; if (node) { modalApi.getRenderCallback()(node); } return () => { if (node) { modalApi.getCleanupCallback()(node); } }; }, [modalApi]); return
; }; export interface ModalHandlerProps { render: ModalExtension.ModalRenderExtension; isOpen: boolean; onClose: () => void; __withoutTransition?: boolean; __disableFocusLock?: boolean; } export const ModalHandler: FunctionComponent = ({ render, isOpen, onClose, __withoutTransition = false, __disableFocusLock = false, }) => { const [actions, setActions] = useState([]); const modalApi = useMemo(() => { const api = new ModalExtension.Api(onClose, setActions); render(api); return api; }, [render, onClose]); const Wrapper = __withoutTransition ? Fragment : ModalTransition; // Here will be dragons. That's a fishy solution for programmatically disabling the focus lock of the Atlaskit Modal component. // When the stackIndex > 0 this will disable the focus lock of the Modal. That's quite naive implementation since we are abusing // the Atlaskit stacking mechanism. const stackIndex = __disableFocusLock ? 1 : 0; const onCloseHandler = useCallback( (e: KeyboardOrMouseEvent) => { const closeResult = modalApi.getOnCloseCallback()(e); // prevent closing of modal if "closeRequest" is "false" if (closeResult !== false) { onClose(); } }, [modalApi, onClose], ); const actionsAsButtons: JSX.Element[] = useMemo( () => actions.map(({ testId, isLoading, text, onClick, isDisabled }, index) => ( // eslint-disable-next-line react/no-array-index-key )), [actions], ); return ( {isOpen && ( {modalApi.getTitle()} {actionsAsButtons} )} ); }; export interface ModalWithActionHandlerProps extends Omit { children?: ReactNode; render: ModalExtension.ModalRenderExtension; __withoutTransition?: boolean; __disableFocusLock?: boolean; } export const ModalWithActionHandler: FunctionComponent = ({ // Action Handler Properties appearance, children, disabled, hidden, iconAfter, iconBefore, spacing, // Modal Handler Properties render, __withoutTransition, __disableFocusLock, }) => { const [isOpen, setIsOpen] = useState(false); const openModal = useCallback(() => { setIsOpen(true); }, []); const closeModal = useCallback(() => { setIsOpen(false); }, []); if (hidden) { return null; } return ( <> ); };