From 821593dd8f4e6933159fecfa2c10c4c5085ba73b Mon Sep 17 00:00:00 2001 From: Mark Rapson Date: Mon, 19 Oct 2026 17:55:56 +0100 Subject: [PATCH] Allow one-pixel template regions --- CHANGELOG.md | 6 +++ build/package.player.json | 2 +- build/package.web.json | 2 +- package-lock.json | 4 +- package.json | 2 +- .../js/templates/template-designer-utils.js | 10 ++--- .../public/js/templates/template-designer.js | 44 +++++++++---------- src/web/views/signage/templates/form.hbs | 4 +- test/templates.test.js | 2 +- 9 files changed, 41 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 199603e..f77f7b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ All notable changes to this project will be documented in this file. +## 2.15.7 - 2026-10-19 + +### Fixed + +- Template regions can now be sized down to one canvas pixel. + ## 2.15.6 - 2026-10-18 ### Changed diff --git a/build/package.player.json b/build/package.player.json index 52eab05..fb9fffb 100644 --- a/build/package.player.json +++ b/build/package.player.json @@ -1,6 +1,6 @@ { "name": "pulse-signage-player", - "version": "2.15.6", + "version": "2.15.7", "private": false, "description": "Pulse Signage player application bundle", "engines": { diff --git a/build/package.web.json b/build/package.web.json index b265ec4..ba3c116 100644 --- a/build/package.web.json +++ b/build/package.web.json @@ -1,6 +1,6 @@ { "name": "pulse-signage-web", - "version": "2.15.6", + "version": "2.15.7", "private": false, "description": "Pulse Signage web and bridge application bundle", "engines": { diff --git a/package-lock.json b/package-lock.json index 8fcab28..8a61216 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "pulse-signage", - "version": "2.15.6", + "version": "2.15.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "pulse-signage", - "version": "2.15.6", + "version": "2.15.7", "dependencies": { "@sparticuz/chromium": "^149.0.0", "animate.css": "^4.1.1", diff --git a/package.json b/package.json index 31024dc..98f9115 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pulse-signage", - "version": "2.15.6", + "version": "2.15.7", "private": false, "description": "Pulse Signage application with MySQL and media storage", "engines": { diff --git a/src/web/public/js/templates/template-designer-utils.js b/src/web/public/js/templates/template-designer-utils.js index 73691fc..15a2005 100644 --- a/src/web/public/js/templates/template-designer-utils.js +++ b/src/web/public/js/templates/template-designer-utils.js @@ -56,15 +56,15 @@ if (ratio.ratio >= 1) { var baseWidth = locked ? 420 : 300; return { - width: Math.max(12, Math.round(baseWidth)), - height: Math.max(12, Math.round(baseWidth / ratio.ratio)) + width: Math.max(1, Math.round(baseWidth)), + height: Math.max(1, Math.round(baseWidth / ratio.ratio)) }; } var baseHeight = locked ? 300 : 240; return { - width: Math.max(12, Math.round(baseHeight * ratio.ratio)), - height: Math.max(12, Math.round(baseHeight)) + width: Math.max(1, Math.round(baseHeight * ratio.ratio)), + height: Math.max(1, Math.round(baseHeight)) }; } @@ -297,7 +297,7 @@ function clampRegion(region, size, minSize) { var bounds = size || { width: 1920, height: 1080 }; - var minimum = minSize || 12; + var minimum = minSize || 1; var x = clamp(region.x, 0, bounds.width - minimum); var y = clamp(region.y, 0, bounds.height - minimum); var width = Math.max(minimum, region.width); diff --git a/src/web/public/js/templates/template-designer.js b/src/web/public/js/templates/template-designer.js index 2100c7c..b3a72ff 100644 --- a/src/web/public/js/templates/template-designer.js +++ b/src/web/public/js/templates/template-designer.js @@ -140,10 +140,10 @@ if (ratio) { if (ratio.ratio >= 1) { var baseWidth = locked ? 420 : 300; - return { width: Math.max(12, Math.round(baseWidth)), height: Math.max(12, Math.round(baseWidth / ratio.ratio)) }; + return { width: Math.max(1, Math.round(baseWidth)), height: Math.max(1, Math.round(baseWidth / ratio.ratio)) }; } var baseHeight = locked ? 300 : 240; - return { width: Math.max(12, Math.round(baseHeight * ratio.ratio)), height: Math.max(12, Math.round(baseHeight)) }; + return { width: Math.max(1, Math.round(baseHeight * ratio.ratio)), height: Math.max(1, Math.round(baseHeight)) }; } return { width: locked ? 420 : 300, height: locked ? 240 : 120 }; } @@ -1015,7 +1015,7 @@ function fitRegionToCanvas(region, aspect) { var size = getCanvasSize(); - var minSize = 12; + var minSize = 1; var next = { x: Math.round(Number(region && region.x !== undefined ? region.x : 0)), y: Math.round(Number(region && region.y !== undefined ? region.y : 0)), @@ -1075,8 +1075,8 @@ var next = { x: current.x, y: current.y, - width: Math.max(12, Math.round(current.width || 0)), - height: Math.max(12, Math.round(current.height || 0)) + width: Math.max(1, Math.round(current.width || 0)), + height: Math.max(1, Math.round(current.height || 0)) }; var lockRatio = normalizeLockRatio(current.lock_ratio); var aspect = lockRatio ? parseLockRatio(lockRatio) : null; @@ -1084,20 +1084,20 @@ if (aspect) { if (changedField === 'height') { - next.width = Math.max(12, Math.round(next.height * aspect.ratio)); + next.width = Math.max(1, Math.round(next.height * aspect.ratio)); } else { - next.height = Math.max(12, Math.round(next.width / aspect.ratio)); + next.height = Math.max(1, Math.round(next.width / aspect.ratio)); } if (next.width > size.width || next.height > size.height) { var scale = Math.min(size.width / Math.max(1, next.width), size.height / Math.max(1, next.height), 1); if (scale < 1) { - next.width = Math.max(12, Math.round(next.width * scale)); - next.height = Math.max(12, Math.round(next.height * scale)); + next.width = Math.max(1, Math.round(next.width * scale)); + next.height = Math.max(1, Math.round(next.height * scale)); if (changedField === 'height') { - next.width = Math.max(12, Math.round(next.height * aspect.ratio)); + next.width = Math.max(1, Math.round(next.height * aspect.ratio)); } else { - next.height = Math.max(12, Math.round(next.width / aspect.ratio)); + next.height = Math.max(1, Math.round(next.width / aspect.ratio)); } } } @@ -1237,9 +1237,9 @@ var current = readCard(card); var aspect = parseLockRatio(current.lock_ratio); if (aspect && changedField === 'width' && current.width > 0) { - writeCard(card, { height: Math.max(12, Math.round(current.width / aspect.ratio)) }); + writeCard(card, { height: Math.max(1, Math.round(current.width / aspect.ratio)) }); } else if (aspect && changedField === 'height' && current.height > 0) { - writeCard(card, { width: Math.max(12, Math.round(current.height * aspect.ratio)) }); + writeCard(card, { width: Math.max(1, Math.round(current.height * aspect.ratio)) }); } } else { normalizeRegionCard(card, changedField); @@ -1589,7 +1589,7 @@ function clampRegion(region) { var size = getCanvasSize(); - var minSize = 12; + var minSize = 1; var x = clamp(region.x, 0, size.width - minSize); var y = clamp(region.y, 0, size.height - minSize); var width = Math.max(minSize, region.width); @@ -1619,7 +1619,7 @@ draft.end = toCanvasPoint(upEvent); var width = Math.abs(draft.end.x - draft.start.x); var height = Math.abs(draft.end.y - draft.start.y); - if (width >= 8 && height >= 8) { + if (width >= 1 && height >= 1) { var region = fitRegionToCanvas({ x: Math.min(draft.start.x, draft.end.x), y: Math.min(draft.start.y, draft.end.y), width: width, height: height }); var name = getNextDefaultRegionName('text'); addRegion({ region_key: name, label: name, region_type: 'text', x: region.x, y: region.y, width: region.width, height: region.height, z_index: 1 }); @@ -1671,7 +1671,7 @@ var lockRatio = normalizeLockRatio(startRegion.lock_ratio); var aspect = lockRatio ? parseLockRatio(lockRatio) : null; var canvasSize = getCanvasSize(); - var minSize = 12; + var minSize = 1; function clampResizeDelta(dx, dy) { if (dir.indexOf('w') !== -1) { @@ -1690,17 +1690,17 @@ } function fitFromWidth(width) { - var nextWidth = Math.max(12, Math.round(width)); + var nextWidth = Math.max(1, Math.round(width)); return { width: nextWidth, - height: aspect ? Math.max(12, Math.round(nextWidth / aspect.ratio)) : startRegion.height + height: aspect ? Math.max(1, Math.round(nextWidth / aspect.ratio)) : startRegion.height }; } function fitFromHeight(height) { - var nextHeight = Math.max(12, Math.round(height)); + var nextHeight = Math.max(1, Math.round(height)); return { - width: aspect ? Math.max(12, Math.round(nextHeight * aspect.ratio)) : startRegion.width, + width: aspect ? Math.max(1, Math.round(nextHeight * aspect.ratio)) : startRegion.width, height: nextHeight }; } @@ -1752,8 +1752,8 @@ if (dir.indexOf('n') !== -1) { next.y = startRegion.y + dy; next.height = startRegion.height - dy; } if (dir.indexOf('s') !== -1) { next.height = startRegion.height + dy; } } - if (next.width < 12) { if (dir.indexOf('w') !== -1) { next.x -= 12 - next.width; } next.width = 12; } - if (next.height < 12) { if (dir.indexOf('n') !== -1) { next.y -= 12 - next.height; } next.height = 12; } + if (next.width < 1) { if (dir.indexOf('w') !== -1) { next.x -= 1 - next.width; } next.width = 1; } + if (next.height < 1) { if (dir.indexOf('n') !== -1) { next.y -= 1 - next.height; } next.height = 1; } next = fitRegionToCanvas(next, aspect); writeCard(cardAt(index), { x: next.x, y: next.y, width: next.width, height: next.height }); markTemplateFormDirty(); diff --git a/src/web/views/signage/templates/form.hbs b/src/web/views/signage/templates/form.hbs index 96829e7..3a2c938 100644 --- a/src/web/views/signage/templates/form.hbs +++ b/src/web/views/signage/templates/form.hbs @@ -174,8 +174,8 @@
- - + +
diff --git a/test/templates.test.js b/test/templates.test.js index f5edcaf..688eb58 100644 --- a/test/templates.test.js +++ b/test/templates.test.js @@ -443,7 +443,7 @@ test('region dimensions allow clearing and typing below the minimum until commit assert.equal(harness.rawValue(field), value); } harness.edit(field, '1', 'change'); - assert.equal(harness.value(field), 12); + assert.equal(harness.value(field), 1); harness.edit(field, '9999', 'change'); assert.equal(harness.value(field), field === 'width' ? 1920 : 1080); }