ohif-viewer/platform/ui-next/src/contextProviders/ModalProvider.tsx
Dan Rukas a3b51aa8db
ui(components): New Dialog and Modal components for ui-next (#4772)
Co-authored-by: sedghi <ar.sedghi@gmail.com>
2025-02-28 15:17:55 -05:00

103 lines
2.4 KiB
TypeScript

import React, { useState, createContext, useContext, useCallback, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
interface ModalOptions {
title?: string;
shouldCloseOnEsc?: boolean;
content?: React.ComponentType;
contentProps?: Record<string, unknown>;
containerClassName?: string;
}
interface ModalContextType {
show: (options: Partial<ModalOptions>) => void;
hide: () => void;
containerClassName?: string;
}
interface ModalComponentProps {
isOpen: boolean;
onClose: () => void;
title?: string;
children: React.ReactNode;
}
const ModalContext = createContext<ModalContextType | null>(null);
export const useModal = () => {
const ctx = useContext(ModalContext);
if (!ctx) {
throw new Error('useModal must be used within a ModalProvider');
}
return ctx;
};
const DEFAULT_OPTIONS: ModalOptions = {
title: '',
shouldCloseOnEsc: true,
};
interface ModalService {
setServiceImplementation: (implementation: ModalContextType) => void;
getCustomComponent: () => React.ComponentType<ModalComponentProps> | null;
}
interface ModalProviderProps {
children: React.ReactNode;
modal: React.ComponentType<ModalComponentProps>;
service?: ModalService | null;
}
const ModalProvider: React.FC<ModalProviderProps> = ({
children,
modal: ModalComponent,
service = null,
}) => {
const { t } = useTranslation('Modals');
const [options, setOptions] = useState<ModalOptions>(DEFAULT_OPTIONS);
const ModalContent = options.content;
const show = useCallback((props: Partial<ModalOptions>) => {
setOptions(prev => ({ ...prev, ...props }));
}, []);
const hide = useCallback(() => {
setOptions(DEFAULT_OPTIONS);
}, []);
useEffect(() => {
if (service) {
service.setServiceImplementation({ show, hide });
}
}, [hide, service, show]);
const { title } = options;
const CustomModal = service?.getCustomComponent();
const RenderedModal = CustomModal || ModalComponent;
return (
<ModalContext.Provider value={{ show, hide }}>
{ModalContent && (
<RenderedModal
isOpen={true}
onClose={hide}
title={t(title)}
{...options}
>
<ModalContent
{...options.contentProps}
show={show}
hide={hide}
/>
</RenderedModal>
)}
{children}
</ModalContext.Provider>
);
};
export { ModalProvider };
export const ModalConsumer = ModalContext.Consumer;