Files
papercrate/frontend/src/viewer/PreviewContext.tsx
T

64 lines
2.0 KiB
TypeScript

import React, { useState, useCallback, useMemo, useRef } from 'react';
import PreviewZoomOverlay from './components/PreviewZoomOverlay';
import type { Document } from '../types/documents';
import type { Identifier } from '../types/identifiers';
import { createSafeContext } from '../utils/createSafeContext';
interface PreviewContextType {
openPreview: (doc: Document) => void;
closePreview: () => void;
}
const [PreviewContext, usePreviewContext] = createSafeContext<PreviewContextType>('Preview');
interface PreviewProviderProps {
children: React.ReactNode;
onNavigate?: (documentId: Identifier) => void;
}
export const PreviewProvider: React.FC<PreviewProviderProps> = ({ children, onNavigate }) => {
const [previewDoc, setPreviewDoc] = useState<Document | null>(null);
const lastFocusedElement = useRef<HTMLElement | null>(null);
const openPreview = useCallback((doc: Document) => {
if (!lastFocusedElement.current) {
lastFocusedElement.current = document.activeElement as HTMLElement;
}
setPreviewDoc(doc);
}, []);
const closePreview = useCallback(() => {
setPreviewDoc(null);
if (lastFocusedElement.current) {
lastFocusedElement.current.focus();
lastFocusedElement.current = null;
}
}, []);
const handleMaximize = useCallback(() => {
if (previewDoc && onNavigate) {
onNavigate(previewDoc.id);
closePreview();
}
}, [previewDoc, onNavigate, closePreview]);
const value = useMemo(() => ({
openPreview,
closePreview,
}), [openPreview, closePreview]);
return (
<PreviewContext.Provider value={value}>
{children}
<PreviewZoomOverlay
open={Boolean(previewDoc)}
onClose={closePreview}
onMaximize={onNavigate ? handleMaximize : undefined}
document={previewDoc}
/>
</PreviewContext.Provider>
);
};
export { usePreviewContext };