From 150bb91a27d9155b2726d040a882f90bc88fa6b2 Mon Sep 17 00:00:00 2001 From: Hiren Kangad Date: Thu, 12 Mar 2026 23:35:25 +0530 Subject: [PATCH] refactor: centralize font-size clamps in textLimits.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Single source of truth for font-size constraints (text 6–160, sticky 8–96) used by creation defaults, resize-bake, and any future mutation paths. Replaces scattered hardcoded min/max values. --- frontend/src/canvas/textLimits.ts | 23 +++++++++++++++++++++++ frontend/src/canvas/tools.ts | 5 +++-- frontend/src/hooks/useCanvasSetup.ts | 3 ++- 3 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 frontend/src/canvas/textLimits.ts diff --git a/frontend/src/canvas/textLimits.ts b/frontend/src/canvas/textLimits.ts new file mode 100644 index 0000000..319e576 --- /dev/null +++ b/frontend/src/canvas/textLimits.ts @@ -0,0 +1,23 @@ +/** + * textLimits — single source of truth for font-size constraints. + * + * Every path that creates, resizes, or mutates fontSize on text/sticky + * items must go through these helpers. This prevents inconsistent + * clamping when ranges are widened later. + */ + +// Plain text: generous range for direct manipulation +const TEXT_FONT_MIN = 6; +const TEXT_FONT_MAX = 160; + +// Sticky note text: narrower range (card layout breaks at extremes) +const STICKY_FONT_MIN = 8; +const STICKY_FONT_MAX = 96; + +export function clampTextFontSize(size: number): number { + return Math.round(Math.min(TEXT_FONT_MAX, Math.max(TEXT_FONT_MIN, size))); +} + +export function clampStickyFontSize(size: number): number { + return Math.round(Math.min(STICKY_FONT_MAX, Math.max(STICKY_FONT_MIN, size))); +} diff --git a/frontend/src/canvas/tools.ts b/frontend/src/canvas/tools.ts index 904030d..a4ddb47 100644 --- a/frontend/src/canvas/tools.ts +++ b/frontend/src/canvas/tools.ts @@ -13,6 +13,7 @@ import type { SelectionManager } from './SelectionManager'; import { DrawingSprite } from './sprites/DrawingSprite'; import type { DrawingObject } from './scene-format'; import { TextEditor } from './TextEditor'; +import { clampTextFontSize, clampStickyFontSize } from './textLimits'; export enum ToolType { SELECT = 'SELECT', @@ -117,7 +118,7 @@ export function activateTool( name: '', visible: true, text: ' ', // placeholder — will be replaced by user input - fontSize: screenToWorld(DEFAULT_TEXT_SCREEN_FONT, zoom, 10, 72), + fontSize: clampTextFontSize(screenToWorld(DEFAULT_TEXT_SCREEN_FONT, zoom, 6, 160)), fill: opts.color!, fontFamily: 'sans-serif', }; @@ -344,7 +345,7 @@ export function activateTool( name: '', visible: true, text: '', - fontSize: screenToWorld(DEFAULT_STICKY_SCREEN_FONT, zoom, 10, 48), + fontSize: clampStickyFontSize(screenToWorld(DEFAULT_STICKY_SCREEN_FONT, zoom, 8, 96)), fontFamily: 'Inter, system-ui, sans-serif', fill: '#ffd43b', // default yellow textColor: '#1a1a1a', diff --git a/frontend/src/hooks/useCanvasSetup.ts b/frontend/src/hooks/useCanvasSetup.ts index fbc8ce5..6b5ba8b 100644 --- a/frontend/src/hooks/useCanvasSetup.ts +++ b/frontend/src/hooks/useCanvasSetup.ts @@ -15,6 +15,7 @@ import { PinOverlay } from '../canvas/PinOverlay'; import { CropOverlay } from '../canvas/CropOverlay'; import { TextSprite } from '../canvas/sprites/TextSprite'; import { TextSharpnessManager } from '../canvas/textSharpness'; +import { clampTextFontSize } from '../canvas/textLimits'; // PresenceOverlay removed — remote selection highlighting was too heavy for minimal benefit import { connectSocket, disconnectSocket } from '../socket'; import api from '../api'; @@ -218,7 +219,7 @@ export function useCanvasSetup(deps: CanvasSetupDeps) { // Use average scale as font multiplier const scale = (absSx + absSy) / 2; const d = item.data as any; - d.fontSize = Math.round(d.fontSize * scale); + d.fontSize = clampTextFontSize(d.fontSize * scale); d.sx = item.data.sx > 0 ? 1 : -1; d.sy = item.data.sy > 0 ? 1 : -1; if (item.displayObject instanceof TextSprite) {