diff --git a/frontend/src/components/tools/sign/SignSettings.tsx b/frontend/src/components/tools/sign/SignSettings.tsx index b767ab764..51ec08ec5 100644 --- a/frontend/src/components/tools/sign/SignSettings.tsx +++ b/frontend/src/components/tools/sign/SignSettings.tsx @@ -1,6 +1,6 @@ import React, { useRef, useState } from 'react'; import { useTranslation } from "react-i18next"; -import { Stack, TextInput, FileInput, Paper, Group, Button, Text, Alert, Modal, ColorSwatch, Menu, ActionIcon, Slider, Select, Combobox, useCombobox } from '@mantine/core'; +import { Stack, TextInput, FileInput, Paper, Group, Button, Text, Alert, Modal, ColorSwatch, Menu, ActionIcon, Slider, Select, Combobox, useCombobox, ColorPicker } from '@mantine/core'; import ButtonSelector from "../../shared/ButtonSelector"; import { SignParameters } from "../../../hooks/tools/sign/useSignParameters"; @@ -22,6 +22,7 @@ const SignSettings = ({ parameters, onParameterChange, disabled = false, onActiv const [canvasSignatureData, setCanvasSignatureData] = useState(null); const [imageSignatureData, setImageSignatureData] = useState(null); const [isModalOpen, setIsModalOpen] = useState(false); + const [isColorPickerOpen, setIsColorPickerOpen] = useState(false); const modalCanvasRef = useRef(null); const visibleModalCanvasRef = useRef(null); const [isModalDrawing, setIsModalDrawing] = useState(false); @@ -31,6 +32,7 @@ const SignSettings = ({ parameters, onParameterChange, disabled = false, onActiv const [fontSizeInput, setFontSizeInput] = useState((parameters.fontSize || 16).toString()); const fontSizeCombobox = useCombobox(); const penSizeCombobox = useCombobox(); + const modalPenSizeCombobox = useCombobox(); // Drawing functions for signature canvas const startDrawing = (e: React.MouseEvent) => { @@ -260,7 +262,7 @@ const SignSettings = ({ parameters, onParameterChange, disabled = false, onActiv // Set the new image as the active signature setImageSignatureData(e.target.result as string); - onParameterChange('signatureData', e.target.result as string); + // Don't call onParameterChange here - let the useEffect handle it // Auto-activate placement mode after image upload setTimeout(() => { @@ -275,12 +277,10 @@ const SignSettings = ({ parameters, onParameterChange, disabled = false, onActiv } else if (!file) { // Clear image signature when no file is selected setImageSignatureData(null); - if (parameters.signatureType === 'image') { - onParameterChange('signatureData', undefined); - // Deactivate signature placement when image is removed - if (onDeactivateSignature) { - onDeactivateSignature(); - } + // Don't call onParameterChange here - let the useEffect handle it + // Deactivate signature placement when image is removed + if (onDeactivateSignature) { + onDeactivateSignature(); } } }; @@ -460,140 +460,105 @@ const SignSettings = ({ parameters, onParameterChange, disabled = false, onActiv {/* Signature Creation based on type */} {parameters.signatureType === 'canvas' && ( - - { - setIsModalOpen(true); - // Copy content to modal canvas after a brief delay - setTimeout(() => { - if (visibleModalCanvasRef.current && modalCanvasRef.current) { - const visibleCtx = visibleModalCanvasRef.current.getContext('2d'); - if (visibleCtx) { - visibleCtx.strokeStyle = selectedColor; - visibleCtx.lineWidth = penSize; - visibleCtx.lineCap = 'round'; - visibleCtx.lineJoin = 'round'; - visibleCtx.clearRect(0, 0, visibleModalCanvasRef.current.width, visibleModalCanvasRef.current.height); - visibleCtx.drawImage(modalCanvasRef.current, 0, 0, visibleModalCanvasRef.current.width, visibleModalCanvasRef.current.height); - } - } - }, 300); - }} - disabled={disabled} - title="Expand Canvas" - > - + - + {t('sign.draw.title', 'Draw your signature')} - - - - - - - Select Color - - {['#000000', '#0066cc', '#cc0000', '#cc6600', '#009900', '#6600cc'].map((color) => ( - setSelectedColor(color)} - /> - ))} - - - - { - const size = parseInt(optionValue); - if (!isNaN(size)) { - setPenSize(size); - setPenSizeInput(optionValue); - } - penSizeCombobox.closeDropdown(); - }} - store={penSizeCombobox} - withinPortal={false} - > - - { - const value = event.currentTarget.value; - setPenSizeInput(value); - - const size = parseInt(value); - if (!isNaN(size) && size >= 1 && size <= 200) { - setPenSize(size); - } - - penSizeCombobox.openDropdown(); - penSizeCombobox.updateSelectedOptionIndex(); - }} - onClick={() => penSizeCombobox.openDropdown()} - onFocus={() => penSizeCombobox.openDropdown()} - onBlur={() => { - penSizeCombobox.closeDropdown(); - const size = parseInt(penSizeInput); - if (isNaN(size) || size < 1 || size > 200) { - setPenSizeInput(penSize.toString()); - } - }} - disabled={disabled} - style={{ width: '80px' }} + +
+ Color + + setIsColorPickerOpen(true)} /> - + +
+
+ Pen Size + { + const size = parseInt(optionValue); + if (!isNaN(size)) { + setPenSize(size); + setPenSizeInput(optionValue); + } + penSizeCombobox.closeDropdown(); + }} + store={penSizeCombobox} + withinPortal={false} + > + + { + const value = event.currentTarget.value; + setPenSizeInput(value); - - - {['1', '2', '3', '4', '5', '8', '10', '12', '15', '20', '25', '30', '40', '50'].map((size) => ( - - {size}px - - ))} - - - + const size = parseInt(value); + if (!isNaN(size) && size >= 1 && size <= 200) { + setPenSize(size); + } -
+
+ +
+ + +
)} @@ -733,23 +709,13 @@ const SignSettings = ({ parameters, onParameterChange, disabled = false, onActiv {/* Drawing Controls */} {/* Color Picker */} -
- Color - - {['#000000', '#0066cc', '#cc0000', '#cc6600', '#009900', '#6600cc'].map((color) => ( - setSelectedColor(color)} - /> - ))} - -
+ setIsColorPickerOpen(true)} + /> {/* Pen Size */}
@@ -844,22 +810,17 @@ const SignSettings = ({ parameters, onParameterChange, disabled = false, onActiv
- Color: - - {['#000000', '#0066cc', '#cc0000', '#cc6600', '#009900', '#6600cc'].map((color) => ( - setSelectedColor(color)} - /> - ))} - + Color + setIsColorPickerOpen(true)} + />
-
- Pen Size: + Pen Size { const size = parseInt(optionValue); @@ -867,15 +828,15 @@ const SignSettings = ({ parameters, onParameterChange, disabled = false, onActiv setPenSize(size); setPenSizeInput(optionValue); } - penSizeCombobox.closeDropdown(); + modalPenSizeCombobox.closeDropdown(); }} - store={penSizeCombobox} + store={modalPenSizeCombobox} withinPortal={false} > { const value = event.currentTarget.value; @@ -886,19 +847,19 @@ const SignSettings = ({ parameters, onParameterChange, disabled = false, onActiv setPenSize(size); } - penSizeCombobox.openDropdown(); - penSizeCombobox.updateSelectedOptionIndex(); + modalPenSizeCombobox.openDropdown(); + modalPenSizeCombobox.updateSelectedOptionIndex(); }} - onClick={() => penSizeCombobox.openDropdown()} - onFocus={() => penSizeCombobox.openDropdown()} + onClick={() => modalPenSizeCombobox.openDropdown()} + onFocus={() => modalPenSizeCombobox.openDropdown()} onBlur={() => { - penSizeCombobox.closeDropdown(); + modalPenSizeCombobox.closeDropdown(); const size = parseInt(penSizeInput); if (isNaN(size) || size < 1 || size > 200) { setPenSizeInput(penSize.toString()); } }} - style={{ width: '100px' }} + style={{ width: '60px' }} /> @@ -961,6 +922,32 @@ const SignSettings = ({ parameters, onParameterChange, disabled = false, onActiv + + {/* Color Picker Modal */} + setIsColorPickerOpen(false)} + title="Choose Color" + size="sm" + centered + > + + + + + + + ); }; diff --git a/frontend/src/components/viewer/ThumbnailSidebar.tsx b/frontend/src/components/viewer/ThumbnailSidebar.tsx index 3accbe042..b78e13774 100644 --- a/frontend/src/components/viewer/ThumbnailSidebar.tsx +++ b/frontend/src/components/viewer/ThumbnailSidebar.tsx @@ -25,7 +25,7 @@ export function ThumbnailSidebar({ visible, onToggle: _onToggle }: ThumbnailSide }); setThumbnails({}); } - }, [visible, thumbnails]); + }, [visible]); // Remove thumbnails from dependency to prevent infinite loop // Generate thumbnails when sidebar becomes visible useEffect(() => {