Add drag-and-drop support for PDF field repositioning

Introduced drag-and-drop functionality for fields in the PDF editor:
- Added `SenderPdfFieldMoveRequest` record to encapsulate field movement data.
- Enhanced `SenderPdfImageEditor.razor` with drag-and-drop event handlers (`OnFieldDragStart`, `OnPageDropAsync`) and updated field structure.
- Updated `SenderEditorPage.razor` to handle field movement via the `OnMoveFieldAsync` method.
- Improved CSS styles for draggable fields and added a delete button with hover effects.
- Added `getDropCoordsOnPage` function in `envelope-editor.js` to calculate normalized drop coordinates.

These changes improve the user experience by enabling intuitive field placement and management in the PDF editor.
This commit is contained in:
2026-09-30 09:08:17 +02:00
parent 696cd1b623
commit 0c81d79a9b
5 changed files with 153 additions and 11 deletions

View File

@@ -134,13 +134,47 @@
padding: 0.2rem 0.3rem;
text-align: left;
line-height: 1.1;
cursor: pointer;
cursor: grab;
display: flex;
align-items: flex-start;
justify-content: flex-start;
justify-content: space-between;
gap: 0.35rem;
overflow: hidden;
}
.sender-image-editor__field:active {
cursor: grabbing;
}
.sender-image-editor__field-label {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.sender-image-editor__field-remove {
border: none;
background: rgba(15, 23, 42, 0.78);
color: #ffffff;
width: 1.1rem;
height: 1.1rem;
min-width: 1.1rem;
border-radius: 999px;
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0;
cursor: pointer;
line-height: 1;
margin-left: auto;
flex-shrink: 0;
}
.sender-image-editor__field-remove:hover {
background: rgba(220, 38, 38, 0.9);
}
.sender-image-editor__field:hover {
filter: brightness(0.96);
}

View File

@@ -92,5 +92,31 @@ window.envelopeEditor = {
normY: normY,
pageIndex: targetIndex
};
},
getDropCoordsOnPage: function (viewerCssClass, pageNumber, clientX, clientY) {
const viewer = document.querySelector('.' + viewerCssClass);
if (!viewer) {
console.warn('[envelopeEditor] viewer not found for class:', viewerCssClass);
return null;
}
const page = viewer.querySelector('[data-editor-page="' + pageNumber + '"]');
if (!page) {
console.warn('[envelopeEditor] page not found:', pageNumber);
return null;
}
const rect = page.getBoundingClientRect();
const clampedX = Math.max(rect.left, Math.min(clientX, rect.right));
const clampedY = Math.max(rect.top, Math.min(clientY, rect.bottom));
const normX = (clampedX - rect.left) / rect.width;
const normY = (clampedY - rect.top) / rect.height;
return {
normX: normX,
normY: normY
};
}
};