diff --git a/src/lib/PdfEditor.svelte b/src/lib/PdfEditor.svelte index ba9cf7f..97ba33d 100644 --- a/src/lib/PdfEditor.svelte +++ b/src/lib/PdfEditor.svelte @@ -3039,6 +3039,26 @@ }; } + /** + * Anchors the delete affordance above the top-right corner of a selection — + * for linear shapes that lands just past the end of the line. + * @param {AnnotationShape} shape @param {{ width: number; height: number }} pageSize + */ + function shapeDeleteButtonBox(shape, pageSize) { + const size = 24 / zoomLevel; + const gap = 8 / zoomLevel; + const above = shape.y - gap - size; + return { + size, + icon: 14 / zoomLevel, + radius: 7 / zoomLevel, + // The page clips its overflow, so fall back to the inner corner when the + // shape sits too close to the top edge. + x: clamp(shape.x + shape.width - size, 0, Math.max(0, pageSize.width - size)), + y: clamp(above >= 0 ? above : shape.y + gap, 0, Math.max(0, pageSize.height - size)) + }; + } + /** @param {AnnotationShape} shape */ function shapeVisualPoints(shape) { if (isLinearShape(shape)) return Object.values(linearEndpoints(shape)); @@ -4375,6 +4395,12 @@ if (!viewer) return; const pointerTarget = event.target; if (pointerTarget instanceof Element && pointerTarget.closest('[data-text-editor]')) return; + if (event.button === 0 && pointerTarget instanceof Element && pointerTarget.closest('[data-shape-delete]')) { + event.preventDefault(); + event.stopPropagation(); + deleteSelectedShapes(); + return; + } const shapeHit = shapeTarget(event); const hitShape = shapeHit ? findShape(shapeHit.pageIndex, shapeHit.id) : null; @@ -6758,6 +6784,35 @@ >{badgeLabel} {/if} + {#if activeTool === 'select'} + {@const deleteButton = shapeDeleteButtonBox(currentSelection, pageSizes[index] ?? { width: 1, height: 1 })} + + + + + {/if} {/if} @@ -10182,6 +10237,25 @@ pointer-events: all; } + .shape-delete-button { + cursor: pointer; + } + + .shape-delete-button rect { + fill: #fff; + stroke: rgba(13, 24, 40, 0.14); + pointer-events: all; + } + + .shape-delete-button image { + pointer-events: none; + } + + .shape-delete-button:hover rect { + fill: #ffe9ea; + stroke: #ff383c; + } + .shape-size-badge { pointer-events: none; }