added about modal for the pdf
This commit is contained in:
@@ -5,6 +5,7 @@ import { Toolbar } from './components/Toolbar';
|
||||
import { InspectorPanel } from './components/InspectorPanel';
|
||||
import type { InspectorTab } from './components/InspectorPanel';
|
||||
import { SignatureModal } from './components/SignatureModal';
|
||||
import { AboutModal } from './components/AboutModal';
|
||||
import { ToastViewport } from './components/ui';
|
||||
import { CustomConfirmationModal } from './components/custom/CustomConfirmationModal';
|
||||
import type { CustomConfirmationOptions } from './components/custom/CustomConfirmationModal';
|
||||
@@ -55,6 +56,7 @@ function App() {
|
||||
// Tool aux state
|
||||
const [pendingSignature, setPendingSignature] = useState<{ url: string; aspect: number } | null>(null);
|
||||
const [signatureModalOpen, setSignatureModalOpen] = useState(false);
|
||||
const [aboutModalOpen, setAboutModalOpen] = useState(false);
|
||||
const [activeStamp, setActiveStamp] = useState<{ label: string; color: string } | null>(null);
|
||||
const [confirmState, setConfirmState] = useState<(CustomConfirmationOptions & { onConfirm: () => void }) | null>(null);
|
||||
|
||||
@@ -439,6 +441,7 @@ function App() {
|
||||
onToolChange={setActiveTool}
|
||||
hasSignature={!!pendingSignature}
|
||||
onOpenSignature={() => setSignatureModalOpen(true)}
|
||||
onOpenAbout={() => setAboutModalOpen(true)}
|
||||
/>
|
||||
|
||||
<div className="flex min-w-0 flex-1 flex-col">
|
||||
@@ -542,6 +545,11 @@ function App() {
|
||||
toast('Signature ready — click on the page to place it', 'info');
|
||||
}}
|
||||
/>
|
||||
|
||||
<AboutModal
|
||||
open={aboutModalOpen}
|
||||
onClose={() => setAboutModalOpen(false)}
|
||||
/>
|
||||
|
||||
<CustomConfirmationModal state={confirmState} onClose={() => setConfirmState(null)} />
|
||||
<ToastViewport />
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import { XIcon } from './icons';
|
||||
|
||||
interface AboutModalProps {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export const AboutModal: React.FC<AboutModalProps> = ({ open, onClose }) => {
|
||||
const modalRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
if (e.key === 'Escape' && open) onClose();
|
||||
};
|
||||
window.addEventListener('keydown', handleKeyDown);
|
||||
return () => window.removeEventListener('keydown', handleKeyDown);
|
||||
}, [open, onClose]);
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
modalRef.current?.focus();
|
||||
}
|
||||
}, [open]);
|
||||
|
||||
if (!open) return null;
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm">
|
||||
<div
|
||||
ref={modalRef}
|
||||
tabIndex={-1}
|
||||
className="relative flex w-[480px] max-w-[90vw] flex-col items-center overflow-hidden rounded-[8px] bg-[#222222] p-8 text-center text-white shadow-2xl outline-none"
|
||||
>
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="absolute right-4 top-4 rounded-[4px] p-1 text-white/50 transition-colors hover:bg-white/10 hover:text-white"
|
||||
>
|
||||
<XIcon size={20} />
|
||||
</button>
|
||||
|
||||
<div className="mb-6 flex flex-col items-center">
|
||||
<div className="flex items-center justify-center gap-3">
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-[9px] bg-[#2563eb] text-white shadow-sm">
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round">
|
||||
<path d="M7 3h7l5 5v13H7a2 2 0 01-2-2V5a2 2 0 012-2z" /><path d="M14 3v5h5" />
|
||||
</svg>
|
||||
</div>
|
||||
<span className="text-[26px] font-bold tracking-tight">MASKAN PDF</span>
|
||||
</div>
|
||||
<div className="mt-4 text-[14px] text-white/80">
|
||||
PDF EDITOR
|
||||
</div>
|
||||
<div className="text-[14px] text-white/60">
|
||||
Version 1.0.0
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex w-full flex-col gap-2 border-t border-white/10 pt-6">
|
||||
<div className="text-[18px] font-bold">
|
||||
Maskan Technologies
|
||||
</div>
|
||||
|
||||
<div className="mt-2 text-[14px] leading-relaxed text-white/80">
|
||||
<p>address: Bangalore, Karnataka, India</p>
|
||||
<p>email: contact@maskantechnologies.com</p>
|
||||
<p>tel.: +91 000-000-0000</p>
|
||||
</div>
|
||||
|
||||
<div className="mt-4 text-[14px] font-medium text-white/80">
|
||||
www.maskantechnologies.com
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -4,7 +4,7 @@ import type { ToolId } from '../lib/tools';
|
||||
import { Popover } from './ui';
|
||||
import {
|
||||
SelectIcon, PanIcon, HighlightIcon, DrawIcon, CommentIcon, TextBoxIcon,
|
||||
SignatureIcon, StampIcon, RedactIcon, InfoIcon,
|
||||
SignatureIcon, StampIcon, RedactIcon, InfoIcon, HelpIcon,
|
||||
} from './icons';
|
||||
|
||||
interface ToolDef { id: ToolId; label: string; shortcut: string; icon: React.ReactNode; danger?: boolean }
|
||||
@@ -28,6 +28,7 @@ interface ToolRailProps {
|
||||
onToolChange: (t: ToolId) => void;
|
||||
hasSignature: boolean;
|
||||
onOpenSignature: () => void;
|
||||
onOpenAbout: () => void;
|
||||
}
|
||||
|
||||
const RailButton: React.FC<{ t: ToolDef; active: boolean; onClick: () => void }> = ({ t, active, onClick }) => (
|
||||
@@ -48,7 +49,7 @@ const RailButton: React.FC<{ t: ToolDef; active: boolean; onClick: () => void }>
|
||||
</CustomButton>
|
||||
);
|
||||
|
||||
export const ToolRail: React.FC<ToolRailProps> = ({ activeTool, onToolChange, hasSignature, onOpenSignature }) => {
|
||||
export const ToolRail: React.FC<ToolRailProps> = ({ activeTool, onToolChange, hasSignature, onOpenSignature, onOpenAbout }) => {
|
||||
const pickTool = (id: ToolId) => {
|
||||
onToolChange(id);
|
||||
if (id === 'signature' && !hasSignature) onOpenSignature();
|
||||
@@ -64,12 +65,16 @@ export const ToolRail: React.FC<ToolRailProps> = ({ activeTool, onToolChange, ha
|
||||
|
||||
<div className="flex-1" />
|
||||
|
||||
<CustomButton variant="unstyled" title="About Maskan PDF Editor" onClick={onOpenAbout} className="flex h-9 w-9 items-center justify-center rounded-[10px] text-[#98a1ad] transition-colors hover:bg-[#edeff2] hover:text-[#18212e]">
|
||||
<InfoIcon size={19} />
|
||||
</CustomButton>
|
||||
|
||||
<Popover
|
||||
align="left"
|
||||
width={210}
|
||||
trigger={(open) => (
|
||||
<CustomButton variant="unstyled" title="Keyboard shortcuts" className={`flex h-9 w-9 items-center justify-center rounded-[10px] transition-colors ${open ? 'bg-[#edeff2] text-[#18212e]' : 'text-[#98a1ad] hover:bg-[#edeff2] hover:text-[#18212e]'}`}>
|
||||
<InfoIcon size={19} />
|
||||
<HelpIcon size={19} />
|
||||
</CustomButton>
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -75,5 +75,6 @@ export const CopyIcon: IC = mk(<><rect x="9" y="9" width="11" height="11" rx="2"
|
||||
export const PlusIcon: IC = mk(<path d="M12 5v14M5 12h14" />);
|
||||
export const UploadIcon: IC = mk(<path d="M12 16V4m0 0L8 8m4-4l4 4M4 17v2a2 2 0 002 2h12a2 2 0 002-2v-2" />);
|
||||
export const InfoIcon: IC = mk(<><circle cx="12" cy="12" r="9" /><path d="M12 11v5M12 8h.01" /></>);
|
||||
export const HelpIcon: IC = mk(<><circle cx="12" cy="12" r="9" /><path d="M9 10a3 3 0 116 0c0 1.5-2 2-2 3M12 17h.01" /></>);
|
||||
export const SpinnerIcon: IC = ({ size = 18, className }) =>
|
||||
base(size, `${className ?? ''} animate-spin`, 2, <><path d="M12 3a9 9 0 109 9" opacity="0.85" /><path d="M21 12a9 9 0 00-9-9" opacity="0.25" /></>);
|
||||
|
||||
Reference in New Issue
Block a user