fix(sticky): make size presets absolute again

This commit is contained in:
Hiren Kangad
2026-03-13 00:50:21 +05:30
parent 9f69eae308
commit f77ac59e6c
3 changed files with 13 additions and 56 deletions
+2 -37
View File
@@ -1,9 +1,8 @@
/**
* stickyPresets — sticky note size presets (shared domain module).
*
* Presets are defined in screen-space so they preserve the same visual intent
* regardless of viewport zoom. Scene data still stores world-space width and
* fontSize; callers convert through the helpers below.
* Presets are absolute semantic sizes. Zoom changes the camera/view only; it
* must not change what S/M/L/XL/XXL mean for an existing sticky.
*/
export type StickyTextSize = 'S' | 'M' | 'L' | 'XL' | 'XXL';
@@ -36,37 +35,3 @@ export function nearestStickySize(fontSize: number): StickyTextSize {
export function getStickyWidthForSize(fontSize: number): number {
return STICKY_WIDTH_MAP[nearestStickySize(fontSize)];
}
/**
* Convert a preset's screen-space target to world-space sticky metrics.
* objectScale is included so old non-1 scaled stickies still respond
* predictably when a preset is applied.
*/
export function getStickyWorldMetricsForPreset(
preset: StickyTextSize,
zoom: number,
objectScale: number = 1,
): { fontSize: number; width: number } {
const safeZoom = Math.max(zoom, 0.001);
const safeScale = Math.max(Math.abs(objectScale), 0.001);
return {
fontSize: STICKY_FONT_MAP[preset] / (safeZoom * safeScale),
width: STICKY_WIDTH_MAP[preset] / (safeZoom * safeScale),
};
}
/**
* Convert a desired on-screen font size into world-space sticky metrics by
* snapping to the nearest preset first.
*/
export function getStickyWorldMetricsForScreenFont(
screenFontSize: number,
zoom: number,
objectScale: number = 1,
): { fontSize: number; width: number; preset: StickyTextSize } {
const preset = nearestStickySize(screenFontSize);
return {
...getStickyWorldMetricsForPreset(preset, zoom, objectScale),
preset,
};
}
+4 -6
View File
@@ -13,7 +13,7 @@ import { DrawingSprite } from './sprites/DrawingSprite';
import type { DrawingObject } from './scene-format';
import { TextEditor } from './TextEditor';
import { clampTextFontSize } from './textLimits';
import { DEFAULT_STICKY_PRESET, getStickyWorldMetricsForPreset } from './stickyPresets';
import { DEFAULT_STICKY_PRESET, STICKY_FONT_MAP, STICKY_WIDTH_MAP } from './stickyPresets';
export enum ToolType {
SELECT = 'SELECT',
@@ -323,10 +323,8 @@ export function activateTool(
const rect = container.getBoundingClientRect();
const world = viewport.toWorld(e.clientX - rect.left, e.clientY - rect.top);
const zoom = viewport.scale.x;
const presetMetrics = getStickyWorldMetricsForPreset(DEFAULT_STICKY_PRESET, zoom);
const cardW = presetMetrics.width;
const cardH = screenToWorld(60, zoom, 40, 200);
const cardW = STICKY_WIDTH_MAP[DEFAULT_STICKY_PRESET];
const cardH = 60; // auto-computed by StickySprite
const stickyData = {
id: crypto.randomUUID(),
type: 'sticky' as const,
@@ -343,7 +341,7 @@ export function activateTool(
name: '',
visible: true,
text: '',
fontSize: presetMetrics.fontSize,
fontSize: STICKY_FONT_MAP[DEFAULT_STICKY_PRESET],
fontFamily: 'Inter, system-ui, sans-serif',
fill: '#ffd43b', // default yellow
textColor: '#1a1a1a',