diff --git a/src/shared/lib/helpers/createPerspectiveManager/createPerspectiveManager.svelte.ts b/src/shared/lib/helpers/createPerspectiveManager/createPerspectiveManager.svelte.ts new file mode 100644 index 0000000..4a98ca8 --- /dev/null +++ b/src/shared/lib/helpers/createPerspectiveManager/createPerspectiveManager.svelte.ts @@ -0,0 +1,130 @@ +import { Spring } from 'svelte/motion'; + +export interface PerspectiveConfig { + /** + * How many px to move back per level + */ + depthStep?: number; + /** + * Scale reduction per level + */ + scaleStep?: number; + /** + * Blur amount per level + */ + blurStep?: number; + /** + * Opacity reduction per level + */ + opacityStep?: number; + /** + * Parallax intensity per level + */ + parallaxIntensity?: number; + /** + * Horizontal offset for each plan (x-axis positioning) + * Positive = right, Negative = left + */ + horizontalOffset?: number; + /** + * Layout mode: 'center' (default) or 'split' for Swiss-style side-by-side + */ + layoutMode?: 'center' | 'split'; +} + +/** + * Manages perspective state with a simple boolean flag. + * + * Drastically simplified from the complex camera/index system. + * Just manages whether content is in "back" or "front" state. + * + * @example + * ```typescript + * const perspective = createPerspectiveManager({ + * depthStep: 100, + * scaleStep: 0.5, + * blurStep: 4, + * }); + * + * // Toggle back/front + * perspective.toggle(); + * + * // Check state + * const isBack = perspective.isBack; // reactive boolean + * ``` + */ +export class PerspectiveManager { + /** + * Spring for smooth back/front transitions + */ + spring = new Spring(0, { + stiffness: 0.2, + damping: 0.8, + }); + + /** + * Reactive boolean: true when in back position (blurred, scaled down) + */ + isBack = $derived(this.spring.current > 0.5); + + /** + * Reactive boolean: true when in front position (fully visible, interactive) + */ + isFront = $derived(this.spring.current < 0.5); + + /** + * Configuration values for style computation + */ + private config: Required; + + constructor(config: PerspectiveConfig = {}) { + this.config = { + depthStep: config.depthStep ?? 100, + scaleStep: config.scaleStep ?? 0.5, + blurStep: config.blurStep ?? 4, + opacityStep: config.opacityStep ?? 0.5, + parallaxIntensity: config.parallaxIntensity ?? 0, + horizontalOffset: config.horizontalOffset ?? 0, + layoutMode: config.layoutMode ?? 'center', + }; + } + + /** + * Toggle between front (0) and back (1) positions. + * Smooth spring animation handles the transition. + */ + toggle = () => { + const target = this.spring.current < 0.5 ? 1 : 0; + this.spring.target = target; + }; + + /** + * Force to back position + */ + setBack = () => { + this.spring.target = 1; + }; + + /** + * Force to front position + */ + setFront = () => { + this.spring.target = 0; + }; + + /** + * Get configuration for style computation + * @internal + */ + getConfig = () => this.config; +} + +/** + * Factory function to create a PerspectiveManager instance. + * + * @param config - Configuration options + * @returns Configured PerspectiveManager instance + */ +export function createPerspectiveManager(config: PerspectiveConfig = {}) { + return new PerspectiveManager(config); +}