Phase 1 of the cohesion refactor (behavior-preserving): Single source of truth: - New src/lib/theme.ts: category colors (moved from data.ts, re-exported for back-compat), derived hex strings, nebula palette, UI colors, CSS var map - New src/lib/config.ts: breakpoint, zoom, parallax, node radii, particle counts, animation timings (previously scattered magic numbers) - New src/lib/utils/tree.ts: getNodeById, getNodeRadius, getDistanceFromOrigin, getBeamIntensity (pure helpers lifted out of onMount) - New src/lib/utils/stats.ts: branch ids/labels, proficiency order, and the stats-panel aggregation helpers (deduped from inline copies) - SkillTree.svelte now imports all of the above; removed the duplicated getCategoryColorHex, stats helpers, branch id/label lists, and inline magic numbers - Populated src/lib/index.ts barrel Bug fixes: - data.ts: tmdbAPI pypiUrl pointed at tvdbAPI -> corrected to tmdbAPI - Removed/ gated stray console.log noise (skill-tree-loaded, SW logs) - Removed dead vars (maxAlpha, glowMaxAlpha) and unused catch binding Tooling: ESLint + Prettier now clean; added Vitest unit tests for the new pure utils (14 tests). svelte-check: 0 errors. build: ok. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
63 lines
1.9 KiB
TypeScript
63 lines
1.9 KiB
TypeScript
// ==========================================================================
|
|
// CONFIG — non-colour tunables (colours live in `theme.ts`).
|
|
//
|
|
// Centralises the magic numbers that were previously scattered through
|
|
// SkillTree.svelte so behaviour can be tuned in one place.
|
|
// ==========================================================================
|
|
|
|
/**
|
|
* Viewport width (px) below which the mobile layout/behaviour kicks in.
|
|
* NOTE: JS treats `< 768` as mobile; CSS media queries use `max-width: 767px`.
|
|
* Both make 768px the first desktop width — keep that pairing if you change this.
|
|
*/
|
|
export const MOBILE_BREAKPOINT = 768;
|
|
|
|
/** Pan/zoom limits and step sizes. */
|
|
export const ZOOM = {
|
|
min: 0.3,
|
|
max: 2.5,
|
|
keyStep: 0.1,
|
|
wheelIn: 1.1,
|
|
wheelOut: 0.9
|
|
} as const;
|
|
|
|
/** Background parallax lag factors (fraction of tree movement). */
|
|
export const PARALLAX = {
|
|
star: 0.1,
|
|
nebula: 0.07,
|
|
gradient: 0.05
|
|
} as const;
|
|
|
|
/** Node radii by size (desktop px); mobile multiplies by MOBILE_RADIUS_FACTOR. */
|
|
export const NODE_RADII: Record<string, number> = {
|
|
'x-large': 75,
|
|
large: 30,
|
|
medium: 25,
|
|
small: 20,
|
|
default: 14
|
|
};
|
|
export const MOBILE_RADIUS_FACTOR = 0.8;
|
|
|
|
/** Keyboard pan distance per arrow-key press (px). */
|
|
export const PAN_SPEED = 50;
|
|
|
|
/** Background particle counts (desktop / mobile). */
|
|
export const PARTICLE_COUNTS = {
|
|
distantStars: { desktop: 200, mobile: 100 },
|
|
mediumStars: { desktop: 60, mobile: 30 },
|
|
brightStars: { desktop: 15, mobile: 8 },
|
|
dust: { desktop: 30, mobile: 15 }
|
|
} as const;
|
|
|
|
/** Entrance-animation timings (seconds), split by device. */
|
|
export const TIMINGS = {
|
|
titleDuration: { desktop: 2.5, mobile: 1.5 },
|
|
zoomDuration: { desktop: 4.5, mobile: 2.5 },
|
|
nodeStagger: { desktop: 0.08, mobile: 0.05 }
|
|
} as const;
|
|
|
|
/** Helper: pick a desktop/mobile value. */
|
|
export function byDevice<T>(pair: { desktop: T; mobile: T }, isMobile: boolean): T {
|
|
return isMobile ? pair.mobile : pair.desktop;
|
|
}
|