refactor(SetupFont): reorganize TypographyMenu and add control tests

This commit is contained in:
Ilia Mashkov
2026-03-02 22:20:29 +03:00
parent efe1b4f9df
commit 0fa3437661
6 changed files with 979 additions and 117 deletions
@@ -1,3 +1,15 @@
/**
* Typography control manager
*
* Manages a collection of typography controls (font size, weight, line height,
* letter spacing) with persistent storage. Supports responsive scaling
* through a multiplier system.
*
* The font size control uses a multiplier system to allow responsive scaling
* while preserving the user's base size preference. The multiplier is applied
* when displaying/editing, but the base size is what's stored.
*/
import {
type ControlDataModel,
type ControlModel,
@@ -17,14 +29,37 @@ import {
type ControlOnlyFields<T extends string = string> = Omit<ControlModel<T>, keyof ControlDataModel>;
/**
* A control with its instance
*/
export interface Control extends ControlOnlyFields<ControlId> {
instance: TypographyControl;
}
/**
* Storage schema for typography settings
*/
export interface TypographySettings {
fontSize: number;
fontWeight: number;
lineHeight: number;
letterSpacing: number;
}
/**
* Typography control manager class
*
* Manages multiple typography controls with persistent storage and
* responsive scaling support for font size.
*/
export class TypographyControlManager {
/** Map of controls keyed by ID */
#controls = new SvelteMap<string, Control>();
/** Responsive multiplier for font size display */
#multiplier = $state(1);
/** Persistent storage for settings */
#storage: PersistentStore<TypographySettings>;
/** Base font size (user preference, unscaled) */
#baseSize = $state(DEFAULT_FONT_SIZE);
constructor(configs: ControlModel<ControlId>[], storage: PersistentStore<TypographySettings>) {
@@ -85,6 +120,9 @@ export class TypographyControlManager {
});
}
/**
* Gets initial value for a control from storage or defaults
*/
#getInitialValue(id: string, saved: TypographySettings): number {
if (id === 'font_size') return saved.fontSize * this.#multiplier;
if (id === 'font_weight') return saved.fontWeight;
@@ -93,11 +131,17 @@ export class TypographyControlManager {
return 0;
}
// --- Getters / Setters ---
/** Current multiplier for responsive scaling */
get multiplier() {
return this.#multiplier;
}
/**
* Set the multiplier and update font size display
*
* When multiplier changes, the font size control's display value
* is updated to reflect the new scale while preserving base size.
*/
set multiplier(value: number) {
if (this.#multiplier === value) return;
this.#multiplier = value;
@@ -109,7 +153,10 @@ export class TypographyControlManager {
}
}
/** The scaled size for CSS usage */
/**
* The scaled size for CSS usage
* Returns baseSize * multiplier for actual rendering
*/
get renderedSize() {
return this.#baseSize * this.#multiplier;
}
@@ -118,6 +165,7 @@ export class TypographyControlManager {
get baseSize() {
return this.#baseSize;
}
set baseSize(val: number) {
this.#baseSize = val;
const ctrl = this.#controls.get('font_size')?.instance;
@@ -162,6 +210,9 @@ export class TypographyControlManager {
return this.#controls.get('letter_spacing')?.instance.value ?? DEFAULT_LETTER_SPACING;
}
/**
* Reset all controls to default values
*/
reset() {
this.#storage.clear();
const defaults = this.#storage.value;
@@ -185,21 +236,11 @@ export class TypographyControlManager {
}
/**
* Storage schema for typography settings
*/
export interface TypographySettings {
fontSize: number;
fontWeight: number;
lineHeight: number;
letterSpacing: number;
}
/**
* Creates a typography control manager that handles a collection of typography controls.
* Creates a typography control manager
*
* @param configs - Array of control configurations.
* @param storageId - Persistent storage identifier.
* @returns - Typography control manager instance.
* @param configs - Array of control configurations
* @param storageId - Persistent storage identifier
* @returns Typography control manager instance
*/
export function createTypographyControlManager(
configs: ControlModel<ControlId>[],