From a97f5e5257623977568424ff90ae1ee957d734ca Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Fri, 14 Nov 2025 01:20:02 +0000 Subject: [PATCH] text editor cool stuff v2 --- .../tools/pdfTextEditor/PdfTextEditorView.tsx | 173 +++++++++++------- 1 file changed, 111 insertions(+), 62 deletions(-) diff --git a/frontend/src/proprietary/components/tools/pdfTextEditor/PdfTextEditorView.tsx b/frontend/src/proprietary/components/tools/pdfTextEditor/PdfTextEditorView.tsx index 0f11f6210..ff560b89b 100644 --- a/frontend/src/proprietary/components/tools/pdfTextEditor/PdfTextEditorView.tsx +++ b/frontend/src/proprietary/components/tools/pdfTextEditor/PdfTextEditorView.tsx @@ -9,6 +9,7 @@ import { Card, Divider, Group, + Menu, Modal, Pagination, Progress, @@ -18,6 +19,7 @@ import { Switch, Text, Title, + Tooltip, } from '@mantine/core'; import { useTranslation } from 'react-i18next'; import DescriptionIcon from '@mui/icons-material/DescriptionOutlined'; @@ -27,6 +29,9 @@ import AutorenewIcon from '@mui/icons-material/Autorenew'; import WarningAmberIcon from '@mui/icons-material/WarningAmber'; import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined'; import CloseIcon from '@mui/icons-material/Close'; +import MergeTypeIcon from '@mui/icons-material/MergeType'; +import CallSplitIcon from '@mui/icons-material/CallSplit'; +import MoreVertIcon from '@mui/icons-material/MoreVert'; import { Rnd } from 'react-rnd'; import { @@ -937,16 +942,29 @@ const PdfTextEditorView = ({ data }: PdfTextEditorViewProps) => { [editingGroupId, pageGroups], ); - const orderedImages = useMemo( - () => - [...pageImages].sort( - (first, second) => (first?.zOrder ?? -1_000_000) - (second?.zOrder ?? -1_000_000), - ), - [pageImages], - ); - const scale = useMemo(() => Math.min(MAX_RENDER_WIDTH / pageWidth, 2.5), [pageWidth]); - const scaledWidth = pageWidth * scale; - const scaledHeight = pageHeight * scale; +const orderedImages = useMemo( + () => + [...pageImages].sort( + (first, second) => (first?.zOrder ?? -1_000_000) - (second?.zOrder ?? -1_000_000), + ), + [pageImages], +); +const scale = useMemo(() => Math.min(MAX_RENDER_WIDTH / pageWidth, 2.5), [pageWidth]); +const scaledWidth = pageWidth * scale; +const scaledHeight = pageHeight * scale; +const selectionToolbarPosition = useMemo(() => { + if (!hasSelection) { + return null; + } + const firstSelected = pageGroups.find((group) => selectedGroupIds.has(group.id)); + if (!firstSelected) { + return null; + } + const bounds = toCssBounds(currentPage, pageHeight, scale, firstSelected.bounds); + const top = Math.max(bounds.top - 40, 8); + const left = Math.min(Math.max(bounds.left, 8), Math.max(scaledWidth - 220, 8)); + return { left, top }; +}, [hasSelection, pageGroups, selectedGroupIds, currentPage, pageHeight, scale, scaledWidth]); useEffect(() => { if (!hasDocument || !hasVectorPreview) { @@ -1494,58 +1512,12 @@ const PdfTextEditorView = ({ data }: PdfTextEditorViewProps) => { /> - - - - {t('pdfTextEditor.options.manualGrouping.title', 'Manual Text Grouping')} - - - {t('pdfTextEditor.badges.beta', 'Beta')} - - - - {t( - 'pdfTextEditor.options.manualGrouping.description', - 'Hold Ctrl (Cmd) or Shift while clicking to multi-select text boxes, then merge or ungroup them manually.', - )} - - - - - - - - - - + + {t( + 'pdfTextEditor.options.manualGrouping.descriptionInline', + 'Tip: Hold Ctrl (Cmd) or Shift to multi-select text boxes. A floating toolbar will appear above the selection so you can merge, ungroup, or adjust widths.', + )} +
@@ -1756,6 +1728,83 @@ const PdfTextEditorView = ({ data }: PdfTextEditorViewProps) => { }} /> )} + {selectionToolbarPosition && ( + { + event.stopPropagation(); + }} + onClick={(event) => { + event.stopPropagation(); + }} + > + {canMergeSelection && ( + + + + + + )} + {canUngroupSelection && ( + + + + + + )} + + + event.stopPropagation()} + onClick={(event) => event.stopPropagation()} + > + + + + + handleWidthAdjustment('expand')} + > + {t('pdfTextEditor.manual.expandWidth', 'Expand to page edge')} + + handleWidthAdjustment('reset')} + > + {t('pdfTextEditor.manual.resetWidth', 'Reset width')} + + + + + )} {orderedImages.map((image, imageIndex) => { if (!image?.imageData) { return null;