Editor UX: click background to deselect + strip selection chrome in print

Three small editor-UX fixes:

1. Click in the canvas gutter → deselect. The existing #sheet click
   handler only fired when the click landed inside .sheet; clicks in
   the area between the sheet edge and the previewShell edge
   ("sheetWrap" parent) hit no handler and the selection stuck.
   Added a #previewShell click handler that deselects when the
   click isn't on a .freeLayer and isn't on #sheet (which the
   existing handler still covers). Layer .freeLayer clicks already
   stopPropagation, so they don't bubble through.

2. Selection chrome no longer bleeds into PDF / JPEG-fallback
   output. The codebase had `body.exporting .freeLayer.selected
   { outline: none }` rules sitting dead — JS only ever toggles
   `body.export-print`. Renamed the CSS to match. Also added rules
   to hide .layerHandle (resize squares) and .layerSelectionBox
   (multi-select dashed box) under the same class.

3. The regular Print / Save PDF button (printWithCurrentFilename)
   wasn't adding any export class around window.print(), so
   selection chrome bled into single-sheet prints too. Added
   body.classList.add('export-print') before the print + the
   matching remove on afterprint. The JPEG-PDF-fallback flow
   (enterExportPrintMode) already added this class; now both flows
   benefit from the same CSS.

Verified via CDP: clicking in the gutter outside the sheet now
deselects ({selId:'', isSel:false}).

Co-Authored-By: Claude Opus 4.7 <[email protected]>
This commit is contained in:
thePR0M3TH3ANandClaude Opus 4.7 committed 2026-05-27 10:10:02 -04:00
1 parent cfd42dd92a
commit 119b14e1d3
1 file changed
+30 -10
+30 -10
View File
@@ -2437,19 +2437,27 @@
body.exporting .jewelSlot::before, body.exporting .jewelSlot::after,
body.exporting .jewelSpineGuide,
body.exporting .foldLine, body.exporting .trimArea, body.exporting .bleedFill,
body.exporting .spineText, body.exporting .discSpineStrip {
/* `body.export-print` is added while the printBtn / JPEG-PDF flows are
generating output via window.print(). It strips editor chrome from
the snapshot so the PDF / JPEG-fallback doesn't include layer
selection outlines, resize handles, the spine guide labels, etc. */
body.export-print .spineText, body.export-print .discSpineStrip {
display: none !important;
}
body.exporting .freeLayer.selected {
body.export-print .freeLayer.selected,
body.export-print .freeLayer.multiSelected {
outline: none !important;
box-shadow: none !important;
}
body.exporting .freeLayer {
body.export-print .layerHandle,
body.export-print .layerSelectionBox { display: none !important; }
body.export-print .freeLayer {
pointer-events: none !important;
}
body.exporting .sheet,
body.exporting .sheet *,
body.exporting .designerDiscWrap,
body.exporting .designerDiscWrap * {
body.export-print .sheet,
body.export-print .sheet *,
body.export-print .designerDiscWrap,
body.export-print .designerDiscWrap * {
-webkit-print-color-adjust: exact !important;
print-color-adjust: exact !important;
color-adjust: exact !important;
@@ -14762,11 +14770,13 @@
function printWithCurrentFilename() {
const previousTitle = document.title;
const nextTitle = currentPdfTitle();
const restoreTitle = () => {
document.body.classList.add('export-print');
const restore = () => {
document.title = previousTitle;
window.removeEventListener('afterprint', restoreTitle);
document.body.classList.remove('export-print');
window.removeEventListener('afterprint', restore);
};
window.addEventListener('afterprint', restoreTitle);
window.addEventListener('afterprint', restore);
document.title = nextTitle;
render();
setTimeout(() => window.print(), 50);
@@ -22028,6 +22038,16 @@
clearLayerSelection();
render();
});
// Clicks in the gutter between the sheet edge and the previewShell
// edge also deselect — the existing #sheet handler misses those.
// Layer .freeLayer clicks stopPropagation so they don't bubble up
// through here.
$('previewShell')?.addEventListener('click', (event) => {
if (event.target.closest('.freeLayer')) return;
if (event.target.closest('#sheet')) return; // handled by the rule above
clearLayerSelection();
render();
});
$('layerName').addEventListener('input', (event) => updateSelectedLayer('name', event.target.value));
$('layerUrl').addEventListener('change', (event) => {