diff --git a/frontend/public/locales/en-US/translation.json b/frontend/public/locales/en-US/translation.json index 944a1df22..00cfe7265 100644 --- a/frontend/public/locales/en-US/translation.json +++ b/frontend/public/locales/en-US/translation.json @@ -1737,5 +1737,48 @@ "text": "To make these permissions unchangeable, use the Add Password tool to set an owner password." } } + }, + "watermark": { + "completed": "Watermark added", + "submit": "Add Watermark", + "filenamePrefix": "watermarked", + "error": { + "failed": "An error occurred while adding watermark to the PDF." + }, + "watermarkType": { + "text": "Text", + "image": "Image" + }, + "settings": { + "type": "Watermark Type", + "text": { + "label": "Watermark Text", + "placeholder": "Enter watermark text" + }, + "image": { + "label": "Watermark Image", + "choose": "Choose Image", + "selected": "Selected: {{filename}}" + }, + "fontSize": "Font Size", + "position": "Position", + "rotation": "Rotation (degrees)", + "opacity": "Opacity (%)", + "spacing": { + "width": "Width Spacing", + "height": "Height Spacing" + } + }, + "positions": { + "topLeft": "Top Left", + "topCenter": "Top Center", + "topRight": "Top Right", + "centerLeft": "Center Left", + "center": "Center", + "centerRight": "Center Right", + "bottomLeft": "Bottom Left", + "bottomCenter": "Bottom Center", + "bottomRight": "Bottom Right" + } } } diff --git a/frontend/src/components/tools/addWatermark/AddWatermarkSettings.tsx b/frontend/src/components/tools/addWatermark/AddWatermarkSettings.tsx new file mode 100644 index 000000000..3dcc63bfe --- /dev/null +++ b/frontend/src/components/tools/addWatermark/AddWatermarkSettings.tsx @@ -0,0 +1,174 @@ +import React, { useRef } from "react"; +import { Button, Stack, Text, NumberInput, Select, TextInput, FileButton } from "@mantine/core"; +import { useTranslation } from "react-i18next"; + +interface AddWatermarkParameters { + watermarkType: 'text' | 'image'; + watermarkText: string; + watermarkImage?: File; + fontSize: number; + rotation: number; + opacity: number; + widthSpacer: number; + heightSpacer: number; + position: string; + overrideX?: number; + overrideY?: number; +} + +interface AddWatermarkSettingsProps { + parameters: AddWatermarkParameters; + onParameterChange: (key: keyof AddWatermarkParameters, value: any) => void; + disabled?: boolean; +} + +const AddWatermarkSettings = ({ parameters, onParameterChange, disabled = false }: AddWatermarkSettingsProps) => { + const { t } = useTranslation(); + const resetRef = useRef<() => void>(null); + + const positionOptions = [ + { value: 'topLeft', label: 'Top Left' }, + { value: 'topCenter', label: 'Top Center' }, + { value: 'topRight', label: 'Top Right' }, + { value: 'centerLeft', label: 'Center Left' }, + { value: 'center', label: 'Center' }, + { value: 'centerRight', label: 'Center Right' }, + { value: 'bottomLeft', label: 'Bottom Left' }, + { value: 'bottomCenter', label: 'Bottom Center' }, + { value: 'bottomRight', label: 'Bottom Right' } + ]; + + return ( + + {/* Watermark Type Selection */} + + Watermark Type +
+ + +
+
+ + {/* Text Watermark Settings */} + {parameters.watermarkType === 'text' && ( + + Watermark Text + onParameterChange('watermarkText', e.target.value)} + disabled={disabled} + /> + + Font Size + onParameterChange('fontSize', value || 12)} + min={8} + max={72} + disabled={disabled} + /> + + )} + + {/* Image Watermark Settings */} + {parameters.watermarkType === 'image' && ( + + Watermark Image + onParameterChange('watermarkImage', file)} + accept="image/*" + disabled={disabled} + > + {(props) => ( + + )} + + {parameters.watermarkImage && ( + + Selected: {parameters.watermarkImage.name} + + )} + + )} + + {/* Position Settings */} + + Position +