Refactor/reacrhitecture to fsd+ #49
@@ -1,5 +1,8 @@
|
|||||||
export {
|
export {
|
||||||
createTypographySettingsStore,
|
createTypographySettingsStore,
|
||||||
|
MULTIPLIER_L,
|
||||||
|
MULTIPLIER_M,
|
||||||
|
MULTIPLIER_S,
|
||||||
type TypographySettingsStore,
|
type TypographySettingsStore,
|
||||||
typographySettingsStore,
|
typographySettingsStore,
|
||||||
} from './model';
|
} from './model';
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
import {
|
||||||
|
DEFAULT_FONT_SIZE,
|
||||||
|
DEFAULT_FONT_WEIGHT,
|
||||||
|
DEFAULT_LETTER_SPACING,
|
||||||
|
DEFAULT_LINE_HEIGHT,
|
||||||
|
FONT_SIZE_STEP,
|
||||||
|
FONT_WEIGHT_STEP,
|
||||||
|
LETTER_SPACING_STEP,
|
||||||
|
LINE_HEIGHT_STEP,
|
||||||
|
MAX_FONT_SIZE,
|
||||||
|
MAX_FONT_WEIGHT,
|
||||||
|
MAX_LETTER_SPACING,
|
||||||
|
MAX_LINE_HEIGHT,
|
||||||
|
MIN_FONT_SIZE,
|
||||||
|
MIN_FONT_WEIGHT,
|
||||||
|
MIN_LETTER_SPACING,
|
||||||
|
MIN_LINE_HEIGHT,
|
||||||
|
} from '$entities/Font';
|
||||||
|
import type {
|
||||||
|
ControlId,
|
||||||
|
ControlModel,
|
||||||
|
} from '../types/typography';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Responsive font-size scaling factors applied by typographySettingsStore.
|
||||||
|
*/
|
||||||
|
export const MULTIPLIER_S = 0.5;
|
||||||
|
export const MULTIPLIER_M = 0.75;
|
||||||
|
export const MULTIPLIER_L = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default control definitions seeding the typography settings store.
|
||||||
|
* Composed from the font-render ranges/defaults owned by the Font entity.
|
||||||
|
*/
|
||||||
|
export const DEFAULT_TYPOGRAPHY_CONTROLS_DATA: ControlModel<ControlId>[] = [
|
||||||
|
{
|
||||||
|
id: 'font_size',
|
||||||
|
value: DEFAULT_FONT_SIZE,
|
||||||
|
max: MAX_FONT_SIZE,
|
||||||
|
min: MIN_FONT_SIZE,
|
||||||
|
step: FONT_SIZE_STEP,
|
||||||
|
increaseLabel: 'Increase Font Size',
|
||||||
|
decreaseLabel: 'Decrease Font Size',
|
||||||
|
controlLabel: 'Size',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'font_weight',
|
||||||
|
value: DEFAULT_FONT_WEIGHT,
|
||||||
|
max: MAX_FONT_WEIGHT,
|
||||||
|
min: MIN_FONT_WEIGHT,
|
||||||
|
step: FONT_WEIGHT_STEP,
|
||||||
|
increaseLabel: 'Increase Font Weight',
|
||||||
|
decreaseLabel: 'Decrease Font Weight',
|
||||||
|
controlLabel: 'Weight',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'line_height',
|
||||||
|
value: DEFAULT_LINE_HEIGHT,
|
||||||
|
max: MAX_LINE_HEIGHT,
|
||||||
|
min: MIN_LINE_HEIGHT,
|
||||||
|
step: LINE_HEIGHT_STEP,
|
||||||
|
increaseLabel: 'Increase Line Height',
|
||||||
|
decreaseLabel: 'Decrease Line Height',
|
||||||
|
controlLabel: 'Leading',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'letter_spacing',
|
||||||
|
value: DEFAULT_LETTER_SPACING,
|
||||||
|
max: MAX_LETTER_SPACING,
|
||||||
|
min: MIN_LETTER_SPACING,
|
||||||
|
step: LETTER_SPACING_STEP,
|
||||||
|
increaseLabel: 'Increase Letter Spacing',
|
||||||
|
decreaseLabel: 'Decrease Letter Spacing',
|
||||||
|
controlLabel: 'Tracking',
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -1,3 +1,8 @@
|
|||||||
|
export {
|
||||||
|
MULTIPLIER_L,
|
||||||
|
MULTIPLIER_M,
|
||||||
|
MULTIPLIER_S,
|
||||||
|
} from './const/const';
|
||||||
export {
|
export {
|
||||||
createTypographySettingsStore,
|
createTypographySettingsStore,
|
||||||
type TypographySettingsStore,
|
type TypographySettingsStore,
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import type {
|
||||||
|
ControlLabels,
|
||||||
|
NumericControl,
|
||||||
|
} from '$shared/ui';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifiers for the adjustable typography axes
|
||||||
|
*/
|
||||||
|
export type ControlId = 'font_size' | 'font_weight' | 'line_height' | 'letter_spacing';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static configuration for one typography control.
|
||||||
|
*
|
||||||
|
* Derived from the SSOT contract types — declares no fields of its own beyond
|
||||||
|
* the domain `id`. Bounds come from NumericControl, labels from ControlLabels.
|
||||||
|
*
|
||||||
|
* @template T - Control identifier type
|
||||||
|
*/
|
||||||
|
export type ControlModel<T extends string = string> =
|
||||||
|
& Pick<NumericControl, 'value' | 'min' | 'max' | 'step'>
|
||||||
|
& ControlLabels
|
||||||
|
& {
|
||||||
|
/**
|
||||||
|
* Unique identifier for the control
|
||||||
|
*/
|
||||||
|
id: T;
|
||||||
|
};
|
||||||
+67
@@ -0,0 +1,67 @@
|
|||||||
|
/**
|
||||||
|
* Bounded numeric control for typography settings.
|
||||||
|
*
|
||||||
|
* Produces a reactive control that clamps to [min, max] and rounds to step.
|
||||||
|
* Implements the NumericControl contract that ComboControl renders.
|
||||||
|
*/
|
||||||
|
import {
|
||||||
|
clampNumber,
|
||||||
|
roundToStepPrecision,
|
||||||
|
} from '$shared/lib/utils';
|
||||||
|
import type { NumericControl } from '$shared/ui';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bounds + initial value seed for a control
|
||||||
|
*/
|
||||||
|
type ControlSeed = Pick<NumericControl, 'value' | 'min' | 'max' | 'step'>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a reactive bounded numeric control.
|
||||||
|
*
|
||||||
|
* @param initialState - Initial value and bounds
|
||||||
|
* @returns A NumericControl whose value is always clamped and step-rounded
|
||||||
|
*/
|
||||||
|
export function createTypographyControl(initialState: ControlSeed): NumericControl {
|
||||||
|
let value = $state(initialState.value);
|
||||||
|
let max = $state(initialState.max);
|
||||||
|
let min = $state(initialState.min);
|
||||||
|
let step = $state(initialState.step);
|
||||||
|
|
||||||
|
const { isAtMax, isAtMin } = $derived({
|
||||||
|
isAtMax: value >= max,
|
||||||
|
isAtMin: value <= min,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
get value() {
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
set value(newValue) {
|
||||||
|
const rounded = roundToStepPrecision(clampNumber(newValue, min, max), step);
|
||||||
|
if (value !== rounded) {
|
||||||
|
value = rounded;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
get max() {
|
||||||
|
return max;
|
||||||
|
},
|
||||||
|
get min() {
|
||||||
|
return min;
|
||||||
|
},
|
||||||
|
get step() {
|
||||||
|
return step;
|
||||||
|
},
|
||||||
|
get isAtMax() {
|
||||||
|
return isAtMax;
|
||||||
|
},
|
||||||
|
get isAtMin() {
|
||||||
|
return isAtMin;
|
||||||
|
},
|
||||||
|
increase() {
|
||||||
|
value = roundToStepPrecision(clampNumber(value + step, min, max), step);
|
||||||
|
},
|
||||||
|
decrease() {
|
||||||
|
value = roundToStepPrecision(clampNumber(value - step, min, max), step);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
+3
-5
@@ -1,12 +1,10 @@
|
|||||||
import {
|
import type { NumericControl } from '$shared/ui';
|
||||||
type TypographyControl,
|
|
||||||
createTypographyControl,
|
|
||||||
} from '$shared/lib';
|
|
||||||
import {
|
import {
|
||||||
describe,
|
describe,
|
||||||
expect,
|
expect,
|
||||||
it,
|
it,
|
||||||
} from 'vitest';
|
} from 'vitest';
|
||||||
|
import { createTypographyControl } from './createTypographyControl.svelte';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test Strategy for createTypographyControl Helper
|
* Test Strategy for createTypographyControl Helper
|
||||||
@@ -34,7 +32,7 @@ describe('createTypographyControl - Unit Tests', () => {
|
|||||||
min?: number;
|
min?: number;
|
||||||
max?: number;
|
max?: number;
|
||||||
step?: number;
|
step?: number;
|
||||||
}): TypographyControl {
|
}): NumericControl {
|
||||||
return createTypographyControl({
|
return createTypographyControl({
|
||||||
value: initialValue,
|
value: initialValue,
|
||||||
min: options?.min ?? 0,
|
min: options?.min ?? 0,
|
||||||
Reference in New Issue
Block a user