{"version":3,"sources":["../src/index.ts","../src/core/controllers/CursorController.ts","../src/core/managers/EventManager.ts","../src/core/managers/ModuleManager.ts","../src/objects/StringObject.ts","../src/core/managers/ObjectManager.ts","../src/core/controllers/ScrollController.ts","../src/core/controllers/StringScrollDefault.ts","../src/core/controllers/StringScrollDisable.ts","../src/core/controllers/StringScrollSmooth.ts","../src/core/managers/ScrollManager.ts","../src/states/CursorState.ts","../src/states/RenderState.ts","../src/states/ScrollState.ts","../src/states/TimeState.ts","../src/states/ViewportState.ts","../src/core/StringData.ts","../src/core/StringModule.ts","../src/tools/BoundingClientRectTool.ts","../src/tools/DOMAttributeTool.ts","../src/tools/RecordAttributeTool.ts","../src/tools/TransformNullifyTool.ts","../src/tools/RelativePositionTool.ts","../src/tools/LerpTool.ts","../src/tools/UnitParserTool.ts","../src/tools/AdaptiveLerpTool.ts","../src/tools/OriginParserTool.ts","../src/tools/ColorParserTool.ts","../src/tools/ValidationTool.ts","../src/tools/EasingFunctionTool.ts","../src/tools/MagneticPullTool.ts","../src/tools/LerpColorTool.ts","../src/tools/LerpVector2Tool.ts","../src/tools/TransformScaleParserTool.ts","../src/tools/CharIndexerTool.ts","../src/tools/LayoutLineSplitterTool.ts","../src/tools/SplitDomBuilderTool.ts","../src/tools/WordIndexerTool.ts","../src/tools/SplitOptionsParserTool.ts","../src/core/StringToolsContainer.ts","../src/modules/cursor/StringCursor.ts","../src/modules/cursor/StringMagnetic.ts","../src/modules/loading/StringLazy.ts","../src/modules/loading/StringLoading.ts","../src/modules/screen/StringInview.ts","../src/modules/screen/StringResponsive.ts","../src/modules/scroll/StringAnchor.ts","../src/modules/scroll/StringGlide.ts","../src/modules/scroll/StringLerp.ts","../src/modules/scroll/StringProgress.ts","../src/modules/scroll/StringParallax.ts","../src/modules/scrollbar/StringScrollbarHorizontal.ts","../src/modules/scrollbar/StringScrollbarVertical.ts","../src/modules/scrollbar/StringScrollbar.ts","../src/modules/text/StringSplit.ts","../src/modules/tracker/StringDelayLerpTracker.ts","../src/modules/tracker/StringFPSTracker.ts","../src/modules/tracker/StringLerpTracker.ts","../src/modules/tracker/StringPositionTracker.ts","../src/utils/Debounce.ts","../src/utils/StringFPS.ts","../src/modules/loading/StringVideoAutoplay.ts"],"sourcesContent":["import { CursorController } from \"./core/controllers/CursorController\";\r\nimport { IStringModule } from \"./core/IStringModule\";\r\nimport { EventManager } from \"./core/managers/EventManager\";\r\nimport { ModuleManager } from \"./core/managers/ModuleManager\";\r\nimport { ObjectManager } from \"./core/managers/ObjectManager\";\r\nimport { ScrollManager } from \"./core/managers/ScrollManager\";\r\nimport { StringContext } from \"./core/StringContext\";\r\nimport { StringData } from \"./core/StringData\";\r\nimport { StringModule } from \"./core/StringModule\";\r\nimport { DefaultToolsContainer } from \"./core/StringToolsContainer\";\r\nimport { StringCursor } from \"./modules/cursor/StringCursor\";\r\nimport { StringMagnetic } from \"./modules/cursor/StringMagnetic\";\r\nimport { StringLazy } from \"./modules/loading/StringLazy\";\r\nimport { StringLoading } from \"./modules/loading/StringLoading\";\r\nimport { StringInview } from \"./modules/screen/StringInview\";\r\nimport { StringResponsive } from \"./modules/screen/StringResponsive\";\r\nimport { StringAnchor } from \"./modules/scroll/StringAnchor\";\r\nimport { StringGlide } from \"./modules/scroll/StringGlide\";\r\nimport { StringLerp } from \"./modules/scroll/StringLerp\";\r\nimport { StringParallax } from \"./modules/scroll/StringParallax\";\r\nimport { StringProgress } from \"./modules/scroll/StringProgress\";\r\nimport { StringScrollbar } from \"./modules/scrollbar/StringScrollbar\";\r\nimport { StringSplit } from \"./modules/text/StringSplit\";\r\nimport { StringDelayLerpTracker } from \"./modules/tracker/StringDelayLerpTracker\";\r\nimport { StringFPSTracker } from \"./modules/tracker/StringFPSTracker\";\r\nimport { StringLerpTracker } from \"./modules/tracker/StringLerpTracker\";\r\nimport { StringPositionTracker } from \"./modules/tracker/StringPositionTracker\";\r\nimport { StringObject } from \"./objects/StringObject\";\r\nimport { ScrollMode } from \"./states/ScrollState\";\r\nimport { Debounce } from \"./utils/Debounce\";\r\nimport { EventCallback } from \"./models/event/EventCallback\";\r\nimport { StringFPS } from \"./utils/StringFPS\";\r\nimport { StringSettings } from \"./utils/StringSettings\";\r\nimport { StringVideoAutoplay } from \"./modules/loading/StringVideoAutoplay\";\r\n\r\nfunction isTouchDevice() {\r\n  return \"ontouchstart\" in window || navigator.maxTouchPoints > 0;\r\n}\r\nfunction isSafari(): boolean {\r\n  let ua = navigator.userAgent.toLowerCase();\r\n  if (ua.indexOf(\"safari\") != -1) {\r\n    if (ua.indexOf(\"chrome\") > -1) {\r\n      return false;\r\n    } else {\r\n      return true;\r\n    }\r\n  } else {\r\n    return false;\r\n  }\r\n}\r\n\r\nclass StringTune {\r\n  /** Bound handler for the scroll start event */\r\n  private onScrollStartBind: any;\r\n\r\n  /** Bound handler for the scroll stop event */\r\n  private onScrollStopBind: any;\r\n\r\n  /** Bound handler for the scroll direction change event */\r\n  private onDirectionChangeBind: any;\r\n\r\n  /** Bound wheel event handler */\r\n  private onWheelBind: any;\r\n\r\n  /** Bound scroll event handler */\r\n  private onScrollBind: any;\r\n\r\n  /** Bound resize event handler */\r\n  private onResizeBind: any;\r\n\r\n  /** Bound mouse move handler */\r\n  private onMouseMoveBind: any;\r\n\r\n  /** Singleton instance of StringTune */\r\n  private static i: StringTune;\r\n\r\n  /** Root scrollable element (typically <body>) */\r\n  private root: any;\r\n\r\n  /** Window object (used for event bindings and dimensions) */\r\n  private window: any;\r\n\r\n  /** Previous window width for resize diff check */\r\n  private prevWidth: number = 0;\r\n\r\n  /** Previous window height for resize diff check */\r\n  private prevHeight: number = 0;\r\n\r\n  /** Manages all modules registered in the system */\r\n  private moduleManager: ModuleManager;\r\n\r\n  /** Manages scroll modes and active scroll engine */\r\n  private scrollManager: ScrollManager;\r\n\r\n  /** Manages all interactive objects (elements with `string-*` attributes) */\r\n  private objectManager: ObjectManager;\r\n\r\n  /** Central event manager for internal pub-sub logic */\r\n  private eventManager: EventManager;\r\n\r\n  /** Handles custom cursor logic (if enabled) */\r\n  private cursorController: CursorController;\r\n\r\n  /** Provides default utility tools (parsers, interpolation, etc.) */\r\n  private tools: DefaultToolsContainer;\r\n\r\n  /** Main loop used for frame updates (with fixed FPS) */\r\n  private loop: StringFPS = new StringFPS();\r\n\r\n  /** Global reactive data store (scroll, viewport, etc.) */\r\n  private data: StringData;\r\n\r\n  /** Context shared across all modules (events, data, tools, settings) */\r\n  private context: StringContext;\r\n\r\n  /**\r\n   * Sets the scroll position manually.\r\n   * This overrides all internal scroll states including target and lerped values.\r\n   * Useful for programmatic jumps or syncing scroll externally.\r\n   *\r\n   * @param value The new scroll position in pixels.\r\n   */\r\n  public set scrollPosition(value: number) {\r\n    this.data.scroll.current = value;\r\n    this.data.scroll.target = value;\r\n    this.data.scroll.delta = 0;\r\n    this.data.scroll.lerped = 0;\r\n    this.scrollManager.updatePosition();\r\n  }\r\n\r\n  /**\r\n   * Configures the container element(s) used for scroll tracking.\r\n   * Accepts either the `Window` object or an `HTMLElement`.\r\n   * Determines the appropriate internal element references based on the input type\r\n   * and triggers a resize calculation.\r\n   *\r\n   * @param {Window | HTMLElement | any} container The target window or HTML element to associate with scrolling.\r\n   * Handles `Window`, `HTMLElement`, and potentially other types via fallback.\r\n   */\r\n  public set scrollContainer(container: any) {\r\n    if (container instanceof Window) {\r\n      this.data.scroll.container = document.body;\r\n      this.data.scroll.elementContainer = document.documentElement;\r\n      this.data.scroll.scrollContainer = container;\r\n    } else if (container instanceof HTMLElement) {\r\n      this.data.scroll.container = container;\r\n      this.data.scroll.elementContainer = container;\r\n      this.data.scroll.scrollContainer = container;\r\n    } else {\r\n      // Fallback case\r\n      this.data.scroll.container = document.body;\r\n      this.data.scroll.elementContainer = document.documentElement;\r\n      this.data.scroll.scrollContainer = container; // Assigns the original (potentially non-standard) container\r\n    }\r\n    this.debouncedResize();\r\n  }\r\n\r\n  /**\r\n   * Gets the current scroll position in pixels.\r\n   * This is typically updated every frame.\r\n   */\r\n  public get speed() {\r\n    return this.data.scroll.current;\r\n  }\r\n\r\n  /**\r\n   * Sets the base scroll speed for smooth scrolling.\r\n   * Typically a value between 0 and 1.\r\n   */\r\n  public set speed(value: number) {\r\n    this.data.scroll.speed = value;\r\n  }\r\n\r\n  /**\r\n   * Sets the scroll acceleration using a normalized value from 0 to 1.\r\n   * Internally maps it to a real acceleration value between 0.1 and 0.5.\r\n   *\r\n   * @param speed A normalized acceleration factor (0 to 1).\r\n   */\r\n  public set speedAccelerate(speed: number) {\r\n    const min = 0.1;\r\n    const max = 0.5;\r\n    this.data.scroll.speedAccelerate = min + (max - min) * speed;\r\n  }\r\n\r\n  /**\r\n   * Sets the scroll mode for desktop devices.\r\n   * Can be 'smooth', 'default', or 'disable'.\r\n   */\r\n  public set scrollDesktopMode(mode: ScrollMode) {\r\n    this.scrollManager.setDesktopMode(mode);\r\n  }\r\n\r\n  /**\r\n   * Sets the scroll mode for mobile devices.\r\n   * Can be 'smooth', 'default', or 'disable'.\r\n   */\r\n  public set scrollMobileMode(mode: ScrollMode) {\r\n    this.scrollManager.setMobileMode(mode);\r\n  }\r\n\r\n  private debouncedResize = Debounce(this.onResize, 30);\r\n\r\n  private constructor() {\r\n    this.root = document.body;\r\n    this.window = window;\r\n\r\n    this.tools = new DefaultToolsContainer();\r\n    this.data = new StringData();\r\n    this.eventManager = new EventManager();\r\n    this.moduleManager = new ModuleManager(this.data);\r\n    this.objectManager = new ObjectManager(\r\n      this.data,\r\n      this.moduleManager,\r\n      this.eventManager\r\n    );\r\n\r\n    this.context = {\r\n      events: this.eventManager,\r\n      data: this.data,\r\n      tools: this.tools,\r\n      settings: {},\r\n    };\r\n\r\n    this.cursorController = new CursorController(1, this.context);\r\n    this.scrollManager = new ScrollManager(this.context);\r\n\r\n    this.setupSettings({\r\n      \"offset-top\": \"0%\",\r\n      \"offset-bottom\": \"0%\",\r\n      key: \"--progress\",\r\n      \"inview-top\": \"0%\",\r\n      \"inview-bottom\": \"0%\",\r\n      \"enter-el\": \"top\",\r\n      \"enter-vp\": \"bottom\",\r\n      \"exit-el\": \"bottom\",\r\n      \"exit-vp\": \"top\",\r\n      \"parallax-bias\": \"0.0\",\r\n      parallax: \"0.2\",\r\n      lerp: \"0.2\",\r\n      radius: \"150\",\r\n      strength: \"0.3\",\r\n      glide: \"1\",\r\n      anchor: \"center center\",\r\n      timeout: 900,\r\n      alignment: \"center\",\r\n      \"target-disable\": \"false\",\r\n      \"target-style-disable\": \"false\",\r\n      \"target-class\": \"\",\r\n      active: \"false\",\r\n      fixed: \"false\",\r\n      repeat: \"false\",\r\n      \"self-disable\": \"false\",\r\n      abs: \"false\",\r\n      easing: \"cubic-bezier(0.25, 0.25, 0.25, 0.25)\",\r\n      \"glide-base-velocity\": 0.00125,\r\n      \"glide-reduce-velocity\": 0.0000625,\r\n      \"glide-negative-velocity\": -0.0001,\r\n    });\r\n\r\n    this.onWheelBind = this.onWheelEvent.bind(this);\r\n    this.onScrollBind = this.onScrollEvent.bind(this);\r\n    this.onResizeBind = this.onResize.bind(this);\r\n    this.onMouseMoveBind = this.onMouseMoveEvent.bind(this);\r\n\r\n    this.onScrollStartBind = this.onScrollStart.bind(this);\r\n    this.onScrollStopBind = this.onScrollStop.bind(this);\r\n    this.onDirectionChangeBind = this.onDirectionChange.bind(this);\r\n\r\n    this.scrollManager.bindEvents({\r\n      onScrollStart: this.onScrollStartBind,\r\n      onScrollStop: this.onScrollStopBind,\r\n      onDirectionChange: this.onDirectionChangeBind,\r\n    });\r\n\r\n    this.loop.setOnFrame((time: number) => {\r\n      this.data.time.delta = time - this.data.time.now;\r\n      this.data.time.previous = this.data.time.now;\r\n      this.data.time.now = time;\r\n      this.data.time.elapsed += this.data.time.delta;\r\n      this.onUpdateEvent();\r\n    });\r\n    this.on(\"image:load:all\", () => {\r\n      this.onResize();\r\n    });\r\n\r\n    this.scrollContainer = window;\r\n  }\r\n\r\n  /**\r\n   * Returns the singleton instance of StringTune.\r\n   * If not already created, initializes it.\r\n   */\r\n  public static getInstance(): StringTune {\r\n    if (!StringTune.i) {\r\n      StringTune.i = new StringTune();\r\n    }\r\n    return StringTune.i;\r\n  }\r\n\r\n  /**\r\n   * Finds and returns an existing module by its class.\r\n   * Useful for reusing a module instance without re-registering.\r\n   *\r\n   * @template T The type of the module to retrieve.\r\n   * @param type The module class constructor.\r\n   * @returns The module instance if found, otherwise undefined.\r\n   */\r\n  public reuse<T>(type: new (...args: any[]) => T): T | undefined {\r\n    return this.moduleManager.find(type);\r\n  }\r\n\r\n  /**\r\n   * Instantiates and registers a new module.\r\n   * Accepts optional per-instance settings that override global settings.\r\n   *\r\n   * @param objectClass The module class to instantiate.\r\n   * @param settings Optional settings specific to this module.\r\n   */\r\n  public use(objectClass: typeof StringModule, settings: any = null) {\r\n    const effectiveSettings = {\r\n      ...this.context.settings,\r\n      ...settings,\r\n    };\r\n    const module = new objectClass({\r\n      events: this.eventManager,\r\n      data: this.data,\r\n      tools: this.tools,\r\n      settings: effectiveSettings,\r\n    });\r\n    this.moduleManager.register(module);\r\n  }\r\n\r\n  /**\r\n   * Subscribes to a global event within the system.\r\n   *\r\n   * @param eventName The name of the event to listen for.\r\n   * @param callback The function to call when the event is triggered.\r\n   * @param id Optional subscription ID (for easier management).\r\n   */\r\n  public on(eventName: string, callback: EventCallback<any>, id: string = \"\") {\r\n    this.eventManager.on(eventName, callback, id);\r\n  }\r\n\r\n  /**\r\n   * Unsubscribes from a global event.\r\n   *\r\n   * @param eventName The name of the event.\r\n   * @param callback The previously registered callback.\r\n   * @param id Optional ID used during subscription.\r\n   */\r\n  public off(eventName: string, callback: EventCallback<any>, id: string = \"\") {\r\n    this.eventManager.off(eventName, callback, id);\r\n  }\r\n\r\n  /**\r\n   * Starts the scroll engine and initializes all listeners, observers, and modules.\r\n   *\r\n   * @param fps Desired frames per second for the update loop.\r\n   */\r\n  public start(fps: number) {\r\n    // window.addEventListener('scroll', this.onScrollBind);\r\n    // this.root.addEventListener('wheel', this.onWheelBind, { passive: false });\r\n\r\n    this.data.scroll.scrollContainer?.addEventListener(\r\n      \"scroll\",\r\n      this.onScrollBind\r\n    );\r\n    this.data.scroll.container?.addEventListener(\"wheel\", this.onWheelBind, {\r\n      passive: false,\r\n    });\r\n\r\n    window.addEventListener(\"resize\", this.onResizeBind);\r\n    this.root.addEventListener(\"mousemove\", this.onMouseMoveBind);\r\n\r\n    const observerContainerResize = new ResizeObserver(() => {\r\n      this.debouncedResize();\r\n    });\r\n    observerContainerResize.observe(this.context.data.scroll.container);\r\n\r\n    const observerContainerMutation = new MutationObserver(\r\n      (mutationsList: MutationRecord[], observer: MutationObserver) => {\r\n        for (const mutation of mutationsList) {\r\n          if (\r\n            mutation.type === \"attributes\" &&\r\n            (mutation.attributeName === \"style\" ||\r\n              mutation.attributeName === \"class\")\r\n          ) {\r\n            this.onResize();\r\n          }\r\n        }\r\n      }\r\n    );\r\n    const config: MutationObserverInit = {\r\n      attributes: true,\r\n      attributeFilter: [\"style\", \"class\"],\r\n    };\r\n    observerContainerMutation.observe(\r\n      this.context.data.scroll.container,\r\n      config\r\n    );\r\n\r\n    this.use(StringInview);\r\n\r\n    const htmlFontSize = window.getComputedStyle(\r\n      document.documentElement\r\n    ).fontSize;\r\n    const fontSizeNumber = parseFloat(htmlFontSize);\r\n    this.context.data.viewport.baseRem = fontSizeNumber;\r\n\r\n    document.documentElement.classList.add(\"-string\");\r\n    this.moduleManager.onInit();\r\n    this.onResize();\r\n    this.initObjects();\r\n    this.objectManager.observeDOM();\r\n\r\n    this.loop.start(fps);\r\n    this.eventManager.emit(`start`, null);\r\n  }\r\n\r\n  /**\r\n   * Initializes all DOM elements with `string` or `string-copy-from` attributes.\r\n   * Registers them with the object manager and triggers resize/scroll/frame hooks.\r\n   */\r\n  private initObjects() {\r\n    document.querySelectorAll(\"[string],[data-string]\").forEach((element) => {\r\n      this.objectManager.add(element as HTMLElement);\r\n    });\r\n    document\r\n      .querySelectorAll(\"[string-copy-from],[data-string-copy-from]\")\r\n      .forEach((element) => {\r\n        let connectTargetId = this.tools.domAttribute.process({\r\n          element: element as HTMLElement,\r\n          key: \"copy-from\",\r\n          fallback: \"\",\r\n        });\r\n        if (connectTargetId && connectTargetId.length > 0) {\r\n          this.objectManager.enqueueConnection(\r\n            connectTargetId,\r\n            element as HTMLElement\r\n          );\r\n        }\r\n      });\r\n    this.moduleManager.onResize();\r\n    this.moduleManager.onScroll();\r\n    this.moduleManager.onFrame();\r\n  }\r\n\r\n  /**\r\n   * Sets global fallback settings for all modules.\r\n   * These can be overridden by module-specific settings during `use(...)`.\r\n   *\r\n   * @param settings A key-value map of default settings (e.g. 'offset-top': '-10%').\r\n   */\r\n  public setupSettings(settings: StringSettings): void {\r\n    this.context.settings = {\r\n      ...this.context.settings,\r\n      ...settings,\r\n    };\r\n    this.onSettingsChange();\r\n  }\r\n\r\n  /**\r\n   * Handles mouse move event and dispatches it to cursor and modules.\r\n   * @param e Native mouse move event.\r\n   */\r\n  private onMouseMoveEvent(e: MouseEvent) {\r\n    this.cursorController.onMouseMove(e);\r\n    this.moduleManager.onMouseMove(e);\r\n  }\r\n\r\n  /**\r\n   * Handles wheel scroll event and passes it to the scroll engine and modules.\r\n   * @param e Native wheel event.\r\n   */\r\n  private onWheelEvent(e: WheelEvent) {\r\n    this.scrollManager.get().onWheel(e);\r\n    this.moduleManager.onWheel(e);\r\n  }\r\n\r\n  /**\r\n   * Called when scrolling begins.\r\n   * Triggers module scroll start lifecycle hook.\r\n   */\r\n  private onScrollStart() {\r\n    this.moduleManager.onScrollStart();\r\n  }\r\n\r\n  /**\r\n   * Called when scrolling ends.\r\n   * Triggers module scroll stop lifecycle hook.\r\n   */\r\n  private onScrollStop() {\r\n    this.moduleManager.onScrollStop();\r\n  }\r\n\r\n  /**\r\n   * Called when scrolling ends.\r\n   * Triggers module scroll stop lifecycle hook.\r\n   */\r\n  private onDirectionChange() {\r\n    this.moduleManager.onDirectionChange();\r\n  }\r\n\r\n  /**\r\n   * Called when global or module settings are updated.\r\n   * Notifies all managers and modules to re-read new settings.\r\n   */\r\n  private onSettingsChange() {\r\n    this.cursorController.onSettingsChange();\r\n    this.objectManager.onSettingsChange();\r\n    this.moduleManager.onSettingsChange();\r\n  }\r\n\r\n  /**\r\n   * Handles native scroll event.\r\n   * Prevents default behavior and triggers internal scroll logic and event emissions.\r\n   *\r\n   * @param e The native scroll event.\r\n   */\r\n  private onScrollEvent(e: Event) {\r\n    e.preventDefault();\r\n    this.scrollManager.get().onScroll(e);\r\n    this.moduleManager.onScroll();\r\n    this.eventManager.emit(`lerp`, this.data.scroll.lerped);\r\n    this.eventManager.emit(`scroll`, this.data.scroll.current);\r\n    return false;\r\n  }\r\n\r\n  /**\r\n   * Called every frame by the update loop.\r\n   * Triggers scroll engine, modules, and global `update` event.\r\n   */\r\n  private onUpdateEvent() {\r\n    this.cursorController.onFrame();\r\n    this.scrollManager.get().onFrame();\r\n    this.moduleManager.onFrame();\r\n    this.eventManager.emit(`update`, null);\r\n  }\r\n\r\n  /**\r\n   * Handles resize events from scroll container or window.\r\n   * Ignores height-only changes on mobile to prevent layout jumps.\r\n   * Rebuilds layout and triggers module resize if size really changed.\r\n   */\r\n  public onResize(): void {\r\n    const container = this.data.scroll.container;\r\n    const scroll = this.context.data.scroll;\r\n    let width = 0;\r\n    let height = 0;\r\n    var newScrollHeight;\r\n    var newContainerTopPosition = 0;\r\n    const rect = container.getBoundingClientRect();\r\n\r\n    if (container.tagName == \"BODY\") {\r\n      width = window.innerWidth;\r\n      height = window.innerHeight;\r\n    } else {\r\n      width = rect.width;\r\n      height = rect.height;\r\n    }\r\n\r\n    newContainerTopPosition = rect.top;\r\n    newScrollHeight = scroll.container.scrollHeight;\r\n    const transformScale = this.tools.transformScaleParser.process({\r\n      value: window.getComputedStyle(container).transform,\r\n    });\r\n    this.context.data.viewport.transformScale = transformScale;\r\n\r\n    const isDesktop = width > 1080;\r\n\r\n    const widthChanged = this.prevWidth !== width;\r\n    const heightChanged = this.prevHeight !== height;\r\n    const scrollHeightChanged =\r\n      this.context.data.viewport.contentHeight !== newScrollHeight;\r\n\r\n    const shouldRebuild =\r\n      widthChanged || (isDesktop && heightChanged) || scrollHeightChanged;\r\n\r\n    this.context.data.scroll.topPosition = newContainerTopPosition;\r\n    this.context.data.viewport.contentWidth = width;\r\n    this.context.data.viewport.contentHeight = newScrollHeight;\r\n\r\n    this.prevWidth = width;\r\n    this.prevHeight = height;\r\n\r\n    this.context.data.viewport.windowWidth = width;\r\n    this.context.data.viewport.windowHeight = height;\r\n\r\n    const htmlFontSize = window.getComputedStyle(\r\n      document.documentElement\r\n    ).fontSize;\r\n    const fontSizeNumber = parseFloat(htmlFontSize);\r\n    this.context.data.viewport.baseRem = fontSizeNumber * transformScale;\r\n\r\n    scroll.bottomPosition = this.context.data.viewport.contentHeight - height;\r\n\r\n    if (shouldRebuild) {\r\n      this.context.data.scroll.current =\r\n        this.context.data.scroll.container.scrollTop;\r\n      this.context.data.scroll.target =\r\n        this.context.data.scroll.container.scrollTop;\r\n      this.context.data.scroll.transformedCurrent =\r\n        this.context.data.scroll.current *\r\n        this.context.data.viewport.transformScale;\r\n      this.scrollManager.updateResponsiveMode();\r\n      this.moduleManager.onResize();\r\n      this.onSettingsChange();\r\n      this.moduleManager.onScroll();\r\n      this.moduleManager.onFrame();\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Cleans up the system, removes all event listeners, stops the loop,\r\n   * and destroys modules and event subscriptions.\r\n   */\r\n  public destroy() {\r\n    this.data.scroll.scrollContainer?.removeEventListener(\r\n      \"scroll\",\r\n      this.onScrollBind\r\n    );\r\n    this.data.scroll.container?.removeEventListener(\"wheel\", this.onScrollBind);\r\n\r\n    this.window.removeEventListener(\"resize\", this.onResizeBind);\r\n    this.root.removeEventListener(\"mousemove\", this.onMouseMoveBind);\r\n    this.loop.stop();\r\n    this.moduleManager.destroy();\r\n    this.eventManager.clearAll();\r\n  }\r\n}\r\n\r\nexport {\r\n  StringTune as default,\r\n  StringCursor,\r\n  StringDelayLerpTracker,\r\n  StringFPSTracker,\r\n  StringGlide,\r\n  StringLazy,\r\n  StringLerp,\r\n  StringLerpTracker,\r\n  StringLoading,\r\n  StringMagnetic,\r\n  StringParallax,\r\n  StringPositionTracker,\r\n  StringProgress,\r\n  StringResponsive,\r\n  StringScrollbar,\r\n  StringSplit,\r\n  StringAnchor,\r\n  StringTune as StringTune,\r\n  StringVideoAutoplay,\r\n  StringModule,\r\n  StringObject,\r\n  StringData,\r\n  type StringContext,\r\n};\r\n","import { CursorState } from \"../../states/CursorState\"\r\nimport { EventManager } from \"../managers/EventManager\"\r\nimport { StringContext } from \"../StringContext\"\r\nimport { StringData } from \"../StringData\"\r\nimport { StringToolsContainer } from \"../StringToolsContainer\"\r\n\r\n/**\r\n * Manages virtual cursor logic: smoothing, updating, and syncing with mouse events.\r\n * \r\n * This controller handles cursor position tracking with smoothing (lerp) logic.\r\n * Useful for animated cursor effects and interaction modules.\r\n */\r\nexport class CursorController {\r\n  /** Context providing access to shared data, tools, and settings. */\r\n  protected context: StringContext\r\n\r\n  /** Threshold below which cursor is considered settled (no movement). */\r\n  private readonly SETTLE_THRESHOLD = 0.1\r\n\r\n  /** Smoothing factor used to interpolate cursor movement. */\r\n  private smoothingFactor: number\r\n\r\n  /**\r\n   * Constructs a new `CursorController` instance.\r\n   * @param smoothing The initial lerp smoothing factor (0 to 1).\r\n   * @param context The shared context containing state and tools.\r\n   */\r\n  constructor(smoothing: number = 0.1, context: StringContext) {\r\n    this.smoothingFactor = smoothing\r\n    this.context = context\r\n    this.onSettingsChange()\r\n  }\r\n\r\n  /**\r\n   * Updates the target cursor position from a mouse event.\r\n   * This is the raw position that smoothing will interpolate toward.\r\n   * @param e MouseEvent with current cursor position.\r\n   */\r\n  public onMouseMove(e: MouseEvent): void {\r\n    this.context.data.cursor.targetX = e.clientX\r\n    this.context.data.cursor.targetY = e.clientY\r\n  }\r\n\r\n  /**\r\n   * Updates smoothed cursor position using linear interpolation (lerp).\r\n   * Should be called on every animation frame.\r\n   * Handles snapping when movement is below threshold.\r\n   */\r\n  public onFrame(): void {\r\n    const { targetX, targetY, smoothedX, smoothedY } = this.context.data.cursor\r\n\r\n    const stepX = this.context.tools.lerp.process({ from: smoothedX, to: targetX, progress: this.smoothingFactor })\r\n    const stepY = this.context.tools.lerp.process({ from: smoothedY, to: targetY, progress: this.smoothingFactor })\r\n\r\n    const distance = this.getStepDistance(stepX, stepY)\r\n\r\n    if (this.isSettled(distance)) {\r\n      this.snapToTarget()\r\n    } else {\r\n      this.applyStep(stepX, stepY)\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Called when global settings change.\r\n   * Updates the internal lerp factor from context settings.\r\n   */\r\n  public onSettingsChange(): void {\r\n    let lerp = Number(this.context.settings['lerp'])\r\n    this.setLerpFactor(lerp)\r\n  }\r\n\r\n  /**\r\n   * Dynamically adjusts the smoothing factor using adaptive mapping.\r\n   * @param t The raw input lerp value (usually from 0 to 1).\r\n   */\r\n  public setLerpFactor(t: number): void {\r\n    this.smoothingFactor = this.context.tools.adaptiveLerp.process({  \r\n      value: t,\r\n      inMin: 0.1,\r\n      inMax: 1.0,\r\n      outMin: 0.05,\r\n      outMax: 0.65\r\n    })\r\n  }\r\n\r\n  /**\r\n   * Calculates the Euclidean distance from the cursor step.\r\n   * @param x Step in X direction.\r\n   * @param y Step in Y direction.\r\n   * @returns The length of the movement vector.\r\n   */\r\n  private getStepDistance(x: number, y: number): number {\r\n    return Math.hypot(x, y)\r\n  }\r\n\r\n  /**\r\n   * Determines whether the movement is below the settle threshold.\r\n   * @param distance Distance between smoothed and target positions.\r\n   * @returns Whether the cursor should snap to target.\r\n   */\r\n  private isSettled(distance: number): boolean {\r\n    return distance < this.SETTLE_THRESHOLD\r\n  }\r\n\r\n  /**\r\n   * Immediately sets smoothed position to the target and zeroes deltas.\r\n   */\r\n  private snapToTarget(): void {\r\n    this.context.data.cursor.smoothedX = this.context.data.cursor.targetX\r\n    this.context.data.cursor.smoothedY = this.context.data.cursor.targetY\r\n    this.context.data.cursor.stepX = 0\r\n    this.context.data.cursor.stepY = 0\r\n  }\r\n\r\n  /**\r\n   * Applies lerped movement step to smoothed position and stores delta.\r\n   * @param x Step in X direction.\r\n   * @param y Step in Y direction.\r\n   */\r\n  private applyStep(x: number, y: number): void {\r\n    this.context.data.cursor.smoothedX += x\r\n    this.context.data.cursor.smoothedY += y\r\n    this.context.data.cursor.stepX = x\r\n    this.context.data.cursor.stepY = y\r\n  }\r\n}\r\n","import { EventCallback } from \"../../models/event/EventCallback\";\r\n\r\n/**\r\n * Manages custom event subscriptions and dispatching.\r\n * Allows multiple listeners per event and supports optional `id` suffixing.\r\n */\r\nexport class EventManager {\r\n  private listeners: Record<string, Set<EventCallback<any>>> = {};\r\n\r\n  /**\r\n   * Subscribes to an event.\r\n   * Optionally appends an `id` to the event name for namespacing.\r\n   *\r\n   * @param eventName The base event name (e.g. \"scroll\", \"update\").\r\n   * @param callback The function to call when the event is emitted.\r\n   * @param id Optional unique identifier to scope the event (e.g. element ID).\r\n   */\r\n  on<T = any>(\r\n    eventName: string,\r\n    callback: EventCallback<T>,\r\n    id?: string\r\n  ): void {\r\n    const fullEvent = id ? `${eventName}_${id}` : eventName;\r\n\r\n    if (!this.listeners[fullEvent]) {\r\n      this.listeners[fullEvent] = new Set();\r\n    }\r\n    this.listeners[fullEvent].add(callback);\r\n  }\r\n\r\n  /**\r\n   * Unsubscribes from a specific event listener.\r\n   * Must match the original `eventName`, `callback`, and optional `id`.\r\n   *\r\n   * @param eventName The base event name to unsubscribe from.\r\n   * @param callback The callback function to remove.\r\n   * @param id Optional identifier used when subscribing.\r\n   */\r\n  off<T = any>(\r\n    eventName: string,\r\n    callback: EventCallback<T>,\r\n    id?: string\r\n  ): void {\r\n    const fullEvent = id ? `${eventName}_${id}` : eventName;\r\n\r\n    if (this.listeners[fullEvent]) {\r\n      this.listeners[fullEvent].delete(callback);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Emits an event with an optional payload.\r\n   * All matching listeners will be called.\r\n   *\r\n   * @param eventName The full event name (must include `id` if used).\r\n   * @param payload Optional data passed to event listeners.\r\n   */\r\n  emit<T = any>(eventName: string, payload?: T): void {\r\n    const set = this.listeners[eventName];\r\n    if (!set) return;\r\n\r\n    for (const callback of set) {\r\n      callback(payload as T);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Subscribes to a per-object progress event.\r\n   * @param id The object ID.\r\n   * @param callback The callback to handle progress value.\r\n   */\r\n  onProgress(id: string, callback: EventCallback<number>): void {\r\n    this.on(`progress:${id}`, callback);\r\n  }\r\n\r\n  /**\r\n   * Emits a per-object progress event.\r\n   * @param id The object ID.\r\n   * @param value The progress value.\r\n   */\r\n  emitProgress(id: string, value: number): void {\r\n    this.emit(`progress:${id}`, value);\r\n  }\r\n\r\n  /**\r\n   * Subscribes to a per-object in-view event.\r\n   * @param id The object ID.\r\n   * @param callback The callback to handle visibility.\r\n   */\r\n  onInview(id: string, callback: EventCallback<boolean>): void {\r\n    this.on(`object:inview:${id}`, callback);\r\n  }\r\n\r\n  /**\r\n   * Emits a per-object in-view event.\r\n   * @param id The object ID.\r\n   * @param visible Whether the object is visible.\r\n   */\r\n  emitInview(id: string, visible: boolean): void {\r\n    this.emit(`object:inview${id}`, visible);\r\n  }\r\n\r\n  /**\r\n   * Subscribes to the global scroll event.\r\n   * @param callback The callback to handle scroll value.\r\n   */\r\n  onScroll(callback: EventCallback<number>): void {\r\n    this.on(`scroll`, callback);\r\n  }\r\n\r\n  /**\r\n   * Emits the global scroll event.\r\n   * @param value The scroll value.\r\n   */\r\n  emitScroll(value: number): void {\r\n    this.emit(`scroll`, value);\r\n  }\r\n\r\n  /**\r\n   * Subscribes to the global update event.\r\n   * @param callback The callback to handle update.\r\n   */\r\n  onUpdate(callback: EventCallback<void>): void {\r\n    this.on(`update`, callback);\r\n  }\r\n\r\n  /**\r\n   * Emits the global update event.\r\n   */\r\n  emitUpdate(): void {\r\n    this.emit(`update`);\r\n  }\r\n\r\n  /**\r\n   * Clears all listeners for a specific event.\r\n   *\r\n   * @param eventName The full event name (including optional `id`).\r\n   */\r\n  clear(eventName: string): void {\r\n    delete this.listeners[eventName];\r\n  }\r\n\r\n  /**\r\n   * Clears all registered events.\r\n   */\r\n  clearAll(): void {\r\n    this.listeners = {};\r\n  }\r\n}\r\n","import { StringData } from \"../..\";\r\nimport { IStringModule } from \"../IStringModule\";\r\nimport { StringModule } from \"../StringModule\";\r\n\r\n/**\r\n * Central manager for registering, tracking and delegating lifecycle events \r\n * to core and UI modules in the system.\r\n * \r\n * Handles scroll, resize, animation frame updates and DOM events.\r\n */\r\nexport class ModuleManager {\r\n  /** All core logic modules (e.g., scroll, in-view, parallax). */\r\n  private modules: StringModule[] = [];\r\n\r\n  /** All UI or visual/interaction-based modules (e.g., cursor, split text). */\r\n  private uiModules: StringModule[] = [];\r\n\r\n  /**\r\n   * @param data Shared state container for scroll, viewport, etc.\r\n   */\r\n  constructor(private data: StringData) {}\r\n\r\n  /**\r\n   * Registers a module into the appropriate group based on its type.\r\n   * @param module The module instance to register.\r\n   */\r\n  register(module: StringModule): void {\r\n    if (module.type === 1) this.modules.push(module);\r\n    if (module.type === 2) this.uiModules.push(module);\r\n  }\r\n\r\n  /**\r\n   * Finds the first registered module of the given class/type.\r\n   * @param type The module class constructor.\r\n   * @returns The instance, if found.\r\n   */\r\n  find<T>(type: new (...args: any[]) => T): T | undefined {\r\n    return this.modules.find(m => m instanceof type) as T | undefined;\r\n  }\r\n\r\n  /** Invokes `onInit` on all modules. */\r\n  onInit(): void {\r\n    [...this.modules, ...this.uiModules].forEach(m => m.onInit());\r\n  }\r\n\r\n  /** Invokes `onFrame` on all modules, passing shared state. */\r\n  onFrame(): void {\r\n    [...this.modules, ...this.uiModules].forEach(m => m.onFrame(this.data));\r\n  }\r\n\r\n  /** Invokes `onScroll` on all modules with current scroll state. */\r\n  onScroll(): void {\r\n    [...this.modules, ...this.uiModules].forEach(m => m.onScroll(this.data));\r\n  }\r\n\r\n  /** Invokes `onResize` on all modules. */\r\n  onResize(): void {\r\n    [...this.modules, ...this.uiModules].forEach(m => m.onResize());\r\n  }\r\n\r\n  /**\r\n   * Delegates mouse movement events to modules.\r\n   * @param e The mousemove event.\r\n   */\r\n  onMouseMove(e: MouseEvent): void {\r\n    [...this.modules, ...this.uiModules].forEach(m => m.onMouseMove(e));\r\n  }\r\n\r\n  /**\r\n   * Delegates wheel events to modules.\r\n   * @param e The wheel event.\r\n   */\r\n  onWheel(e: WheelEvent): void {\r\n    [...this.modules, ...this.uiModules].forEach(m => m.onWheel(e));\r\n  }\r\n\r\n  /** Notifies all modules that scroll has changed diraction. */\r\n  onDirectionChange(): void {\r\n    [...this.modules, ...this.uiModules].forEach(m => m.onDirectionChange());\r\n  }\r\n\r\n  /** Notifies all modules that scroll has started. */\r\n  onScrollStart(): void {\r\n    [...this.modules, ...this.uiModules].forEach(m => m.onScrollStart());\r\n  }\r\n\r\n  /** Notifies all modules that scroll has stopped. */\r\n  onScrollStop(): void {\r\n    [...this.modules, ...this.uiModules].forEach(m => m.onScrollStop());\r\n  }\r\n\r\n  /** Notifies all modules that scroll axis (horizontal/vertical) has changed. */\r\n  onAxisChange(): void {\r\n    [...this.modules, ...this.uiModules].forEach(m => m.onAxisChange());\r\n  }\r\n\r\n  /** Notifies all modules that device type (desktop/mobile) has changed. */\r\n  onDeviceChange(): void {\r\n    [...this.modules, ...this.uiModules].forEach(m => m.onDeviceChange());\r\n  }\r\n\r\n  /** Notifies modules of updates to scroll-related configuration. */\r\n  onScrollConfigChange(): void {\r\n    [...this.modules, ...this.uiModules].forEach(m => m.onScrollConfigChange());\r\n  }\r\n\r\n  /** Notifies modules of updated global or module-specific settings. */\r\n  onSettingsChange(): void {\r\n    [...this.modules, ...this.uiModules].forEach(m => m.onSettingsChange());\r\n  }\r\n\r\n  /**\r\n   * Called when DOM is mutated — e.g. new elements added/removed.\r\n   * @param added Newly added DOM nodes.\r\n   * @param removed Removed DOM nodes.\r\n   */\r\n  onDOMMutate(added: NodeList, removed: NodeList): void {\r\n    [...this.modules, ...this.uiModules].forEach(m => m.onDOMMutate(added, removed));\r\n  }\r\n\r\n  /** Cleans up all modules and clears internal lists. */\r\n  destroy(): void {\r\n    [...this.modules, ...this.uiModules].forEach(m => m.destroy());\r\n    this.modules = [];\r\n    this.uiModules = [];\r\n  }\r\n\r\n  /**\r\n   * Returns all modules (core + UI) as a flat array.\r\n   */\r\n  get all(): IStringModule[] {\r\n    return [...this.modules, ...this.uiModules];\r\n  }\r\n\r\n  /**\r\n   * Returns only core modules (type === 1).\r\n   */\r\n  get core(): IStringModule[] {\r\n    return this.modules;\r\n  }\r\n\r\n  /**\r\n   * Returns only UI modules (type === 2).\r\n   */\r\n  get ui(): IStringModule[] {\r\n    return this.uiModules;\r\n  }\r\n}\r\n","import { IStringModule } from \"../core/IStringModule\";\r\nimport { EventManager } from \"../core/managers/EventManager\";\r\n\r\n/**\r\n * Internal class representing a DOM-bound interactive object.\r\n * Connected to modules and holds its own internal state.\r\n */\r\nexport class StringObject {\r\n  /**\r\n   * The DOM element this object wraps.\r\n   */\r\n  public htmlElement: HTMLElement;\r\n\r\n  /**\r\n   * Unique global ID assigned by the system.\r\n   */\r\n  public id: string = \"\";\r\n\r\n  /**\r\n   * Space-separated list of all attribute keys associated with this object.\r\n   */\r\n  public keys: string[] = [];\r\n\r\n  /**\r\n   * A list of elements that should be affected in sync with this one.\r\n   */\r\n  public connects: HTMLElement[] = [];\r\n\r\n  /**\r\n   * Internal key-value store of dynamic object properties (like offsets, progress, etc.).\r\n   */\r\n  private properties: Map<string, any> = new Map();\r\n\r\n  /**\r\n   * Modules currently connected to this object.\r\n   */\r\n  private modules: IStringModule[] = [];\r\n\r\n  /**\r\n   * Manages and handles events for the object.\r\n   * Provides functionality to register, trigger, and manage event listeners.\r\n   */\r\n  events: EventManager = new EventManager();\r\n\r\n  constructor(id: string, element: HTMLElement) {\r\n    this.htmlElement = element;\r\n    this.id = id;\r\n  }\r\n\r\n  /**\r\n   * Stores a property value for this object.\r\n   * @param key - Property name\r\n   * @param value - Value to store\r\n   */\r\n  public setProperty<T>(key: string, value: T): void {\r\n    this.properties.set(key, value);\r\n  }\r\n\r\n  /**\r\n   * Retrieves a previously stored property value.\r\n   * @param key - Property name\r\n   * @returns The value or null if not set\r\n   */\r\n  public getProperty<T>(key: string): T {\r\n    return this.properties.get(key) ?? null;\r\n  }\r\n\r\n  /**\r\n   * Marks this object as \"active\" (usually on intersection/scroll enter).\r\n   */\r\n  public enter(): void {\r\n    this.events.emit(\"enter\", this);\r\n    this.setProperty(\"active\", true);\r\n    this.modules.forEach((module) => {\r\n      module.enterObject(this.id, this);\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Marks this object as \"inactive\" (usually on intersection/scroll leave).\r\n   */\r\n  public leave(): void {\r\n    this.events.emit(\"leave\", this);\r\n    this.setProperty(\"active\", false);\r\n    this.modules.forEach((module) => {\r\n      module.exitObject(this.id);\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Shows the object, applies visual class and notifies connected modules.\r\n   */\r\n  public show(): void {\r\n    this.htmlElement.classList.add(\"-inview\");\r\n  }\r\n\r\n  /**\r\n   * Hides the object, removes visual class (if repeat is enabled), and notifies modules.\r\n   */\r\n  public hide(): void {\r\n    const shouldRepeat = this.getProperty<boolean>(\"repeat\");\r\n    if (shouldRepeat) {\r\n      this.htmlElement.classList.remove(\"-inview\");\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Connects a module to this object if not already connected.\r\n   * @param module - The module to connect\r\n   */\r\n  public connect(module: IStringModule): void {\r\n    if (!this.modules.includes(module)) {\r\n      this.modules.push(module);\r\n    }\r\n  }\r\n}\r\n","import { ModuleManager } from \"./ModuleManager\";\r\nimport { StringData } from \"../StringData\";\r\nimport { StringObject } from \"../../objects/StringObject\";\r\nimport { EventManager } from \"./EventManager\";\r\n\r\nexport class ObjectManager {\r\n  private objects = new Map<string, StringObject>();\r\n  private connectQueue: { id: string; element: HTMLElement }[] = [];\r\n  private globalId = 1;\r\n\r\n  constructor(\r\n    private data: StringData,\r\n    private modules: ModuleManager,\r\n    private events: EventManager\r\n  ) {}\r\n\r\n  /**\r\n   * Returns the object map (read-only).\r\n   */\r\n  get all(): ReadonlyMap<string, StringObject> {\r\n    return this.objects;\r\n  }\r\n\r\n  /**\r\n   * Adds a new object from an element.\r\n   */\r\n  public add(el: HTMLElement) {\r\n    const idAttr = el.getAttribute(\"string-id\") ?? `string-${this.globalId++}`;\r\n\r\n    const object =\r\n      idAttr && this.objects.has(idAttr)\r\n        ? this.objects.get(idAttr)!\r\n        : new StringObject(idAttr, el);\r\n\r\n    el.setAttribute(\"string-id\", object.id);\r\n\r\n    const keysAttr =\r\n      el.getAttribute(\"string\") ?? el.getAttribute(\"data-string\");\r\n\r\n    if (keysAttr) {\r\n      object.keys = (keysAttr ?? \"\").split(\"|\");\r\n    }\r\n\r\n    el.setAttribute(\"string-inited\", \"\");\r\n    this.objects.set(object.id, object);\r\n\r\n    const attributes = this.getAllAttributes(el);\r\n\r\n    // Delegate core setup (dimensions, offsets, key, start/end, etc.)\r\n    this.modules.core.forEach((m) => {\r\n      if (\r\n        \"setupCoreProperties\" in m &&\r\n        typeof m[\"setupCoreProperties\"] === \"function\"\r\n      ) {\r\n        (m as any).setupCoreProperties(object, el, attributes);\r\n      }\r\n    });\r\n\r\n    // Try connecting to modules\r\n    this.modules.core.forEach((m) => {\r\n      if (m.canConnect(object)) {\r\n        m.initializeObject(this.globalId, object, el, attributes);\r\n        m.calculatePositions(object, this.data.viewport.windowHeight);\r\n        m.connectObject(object);\r\n      }\r\n    });\r\n\r\n    // Restore connect-from\r\n    const queueItems = this.connectQueue.filter((q) => q.id === object.id);\r\n    queueItems.forEach((item) => object.connects.push(item.element));\r\n    this.connectQueue = this.connectQueue.filter((q) => q.id !== object.id);\r\n\r\n    // Set up observers\r\n    this.initObservers(object, el);\r\n  }\r\n\r\n  /**\r\n   * Removes an object by its id.\r\n   */\r\n  public remove(id: string) {\r\n    const obj = this.objects.get(id);\r\n    if (!obj) return;\r\n\r\n    obj.events.clearAll();\r\n    obj.getProperty<IntersectionObserver>(\"observer-progress\")?.disconnect();\r\n    obj.getProperty<IntersectionObserver>(\"observer-inview\")?.disconnect();\r\n\r\n    obj.htmlElement.removeAttribute(\"string-inited\");\r\n    obj.leave();\r\n\r\n    this.objects.delete(id);\r\n  }\r\n\r\n  /**\r\n   * Add an element that will connect later.\r\n   */\r\n  public enqueueConnection(id: string, element: HTMLElement) {\r\n    this.connectQueue.push({ id, element });\r\n  }\r\n\r\n  private getAllAttributes(el: HTMLElement): Record<string, any> {\r\n    const attributes: Record<string, any> = {};\r\n    Array.from(el.attributes).forEach((attr) => {\r\n      attributes[attr.name] = attr.value;\r\n    });\r\n    return attributes;\r\n  }\r\n\r\n  private initObservers(obj: StringObject, el: HTMLElement) {\r\n    const start = obj.getProperty<number>(\"offset-top\") ?? 0;\r\n    const end = obj.getProperty<number>(\"offset-bottom\") ?? 0;\r\n    const inviewTop = obj.getProperty<number>(\"inview-top\") ?? 0;\r\n    const inviewBottom = obj.getProperty<number>(\"inview-bottom\") ?? 0;\r\n\r\n    obj.getProperty<IntersectionObserver>(\"observer-progress\")?.disconnect();\r\n    obj.getProperty<IntersectionObserver>(\"observer-inview\")?.disconnect();\r\n\r\n    const progressCallback = (entries: IntersectionObserverEntry[]) => {\r\n      entries.forEach((e) => {\r\n        this.events.emit(`object:activate:${obj.id}`, e.isIntersecting);\r\n        e.isIntersecting ? obj.enter() : obj.leave();\r\n      });\r\n    };\r\n\r\n    const inviewCallback = (entries: IntersectionObserverEntry[]) => {\r\n      entries.forEach((e) => {\r\n        this.events.emit(`object:inview:${obj.id}`, e.isIntersecting);\r\n        e.isIntersecting ? obj.show() : obj.hide();\r\n      });\r\n    };\r\n\r\n    const progressObserver = new IntersectionObserver(progressCallback, {\r\n      root: null,\r\n      rootMargin: `${end + this.data.viewport.windowHeight}px 0px ${\r\n        start + this.data.viewport.windowHeight\r\n      }px 0px`,\r\n      threshold: 0.001,\r\n    });\r\n\r\n    const inviewObserver = new IntersectionObserver(inviewCallback, {\r\n      root: null,\r\n      rootMargin: `${end + inviewTop}px 0px ${start + inviewBottom}px 0px`,\r\n      threshold: 0.001,\r\n    });\r\n\r\n    progressObserver.observe(el);\r\n    inviewObserver.observe(el);\r\n\r\n    obj.setProperty(\"observer-progress\", progressObserver);\r\n    obj.setProperty(\"observer-inview\", inviewObserver);\r\n  }\r\n\r\n  /**\r\n   * Observes DOM mutations to auto-add/remove elements with [string] attribute.\r\n   * Should be called once after DOM is ready.\r\n   */\r\n  public observeDOM(): void {\r\n    const observer = new MutationObserver((mutations) => {\r\n      mutations.forEach((mutation) => {\r\n        if (mutation.type === \"childList\") {\r\n          // Removed elements\r\n          mutation.removedNodes.forEach((node) => {\r\n            if (node.nodeType !== Node.ELEMENT_NODE) return;\r\n\r\n            const element = node as HTMLElement;\r\n\r\n            if (this.isFixed(element)) return;\r\n\r\n            if (element.hasAttribute(\"string\")) {\r\n              this.handleRemoved(element);\r\n            }\r\n\r\n            element\r\n              .querySelectorAll(\"[string],[data-string]\")\r\n              .forEach((child) => {\r\n                if (this.isFixed(child as HTMLElement)) return;\r\n                this.handleRemoved(child as HTMLElement);\r\n              });\r\n          });\r\n\r\n          // Added elements\r\n          mutation.addedNodes.forEach((node) => {\r\n            if (node.nodeType !== Node.ELEMENT_NODE) return;\r\n\r\n            const element = node as HTMLElement;\r\n\r\n            if (this.isFixed(element)) return;\r\n\r\n            if (\r\n              element.hasAttribute(\"string\") &&\r\n              !element.hasAttribute(\"string-inited\")\r\n            ) {\r\n              this.add(element);\r\n            }\r\n\r\n            element\r\n              .querySelectorAll(\r\n                \"[string]:not([string-inited]),[data-string]:not([string-inited])\"\r\n              )\r\n              .forEach((child) => this.add(child as HTMLElement));\r\n\r\n            // Check for connect-from logic\r\n            const copyFrom =\r\n              element.getAttribute(\"string-copy-from\") ??\r\n              element.getAttribute(\"data-string-copy-from\");\r\n            if (copyFrom) {\r\n              if (this.objects.has(copyFrom)) {\r\n                this.objects.get(copyFrom)!.connects.push(element);\r\n              } else {\r\n                this.enqueueConnection(copyFrom, element);\r\n              }\r\n            }\r\n          });\r\n\r\n          // Let modules know about DOM rebuild\r\n          this.modules.all.forEach((m) => m.onDOMRebuild());\r\n        }\r\n      });\r\n    });\r\n\r\n    observer.observe(document.body, {\r\n      childList: true,\r\n      subtree: true,\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Removes an object and its observers.\r\n   */\r\n  private handleRemoved(el: HTMLElement): void {\r\n    const id = el.getAttribute(\"string-id\");\r\n    if (!id) return;\r\n\r\n    const copyFrom =\r\n      el.getAttribute(\"string-copy-from\") ??\r\n      el.getAttribute(\"data-string-copy-from\");\r\n    if (copyFrom) {\r\n      this.connectQueue = this.connectQueue.filter((q) => q.id !== copyFrom);\r\n    }\r\n\r\n    this.remove(id);\r\n  }\r\n\r\n  /**\r\n   * Re-applies module initialization logic to all managed objects after settings change.\r\n   *\r\n   * This method should be called when `StringSettings` are updated at runtime,\r\n   * especially if the new settings affect how modules calculate offsets,\r\n   * easing, origins, or custom configuration.\r\n   *\r\n   * Internally, it re-runs `initializeObject`, `calculatePositions`, and `connectObject`\r\n   * for each core module that can connect to the object.\r\n   *\r\n   * This is useful for supporting dynamic configuration updates without requiring\r\n   * a full DOM rebuild or reinitialization.\r\n   */\r\n  public onSettingsChange() {\r\n    this.objects.forEach((object) => {\r\n      this.modules.core.forEach((m) => {\r\n        if (m.canConnect(object)) {\r\n          const attributes = this.getAllAttributes(object.htmlElement);\r\n          m.initializeObject(\r\n            this.globalId,\r\n            object,\r\n            object.htmlElement,\r\n            attributes\r\n          );\r\n          m.calculatePositions(object, this.data.viewport.windowHeight);\r\n          m.connectObject(object);\r\n        }\r\n      });\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Checks whether the element is marked as fixed (not managed).\r\n   */\r\n  private isFixed(el: HTMLElement): boolean {\r\n    return el.hasAttribute(\"string-fixed\");\r\n  }\r\n}\r\n","import { StringContext } from \"../StringContext\";\r\n\r\n/**\r\n * Base class for managing scroll behavior in the system.\r\n * Handles abstract scroll state and updates, intended for extension.\r\n */\r\nexport class ScrollController {\r\n  /** Shared context containing data and tools */\r\n  protected context: StringContext;\r\n\r\n  /** Reference to the document object */\r\n  protected document: Document;\r\n\r\n  /** Name of the scroll mode (e.g. 'default', 'smooth', etc.) */\r\n  public name: string = \"\";\r\n\r\n  /** Whether the system is in programmatic scroll mode */\r\n  public isProg: boolean = false;\r\n\r\n  /** Whether parallax-related logic should be active */\r\n  public isParallaxEnabled: boolean = false;\r\n\r\n  /** Scroll direction: vertical or horizontal */\r\n  protected _scrollDirection: \"vertical\" | \"horizontal\" = \"vertical\";\r\n\r\n  /**\r\n   * Sets scroll direction and updates internal scroll logic.\r\n   * @param scrollDirection Either 'vertical' or 'horizontal'.\r\n   */\r\n  public set scrollDirection(scrollDirection: \"vertical\" | \"horizontal\") {\r\n    this._scrollDirection = scrollDirection;\r\n\r\n    if (this._scrollDirection === \"vertical\") {\r\n      this.onCalcUpdate = () => {\r\n        this.context.data.scroll.scrollContainer?.scrollTo(\r\n          0,\r\n          this.context.data.scroll.current\r\n        );\r\n        // this.scrollContainer.scrollTo(0, this.context.data.scroll.current);\r\n      };\r\n    } else if (this._scrollDirection === \"horizontal\") {\r\n      this.onCalcUpdate = () => {\r\n        this.context.data.scroll.scrollContainer?.scrollTo(\r\n          this.context.data.scroll.current,\r\n          0\r\n        );\r\n        // this.scrollContainer.scrollTo(this.context.data.scroll.current, 0);\r\n      };\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Creates a new ScrollController instance.\r\n   * @param context Shared context containing data and settings.\r\n   */\r\n  constructor(context: StringContext) {\r\n    this.document = document;\r\n    this.context = context;\r\n  }\r\n\r\n  /**\r\n   * Called when scroll direction changes (up ↔ down).\r\n   * Override this callback in subclasses or instances.\r\n   */\r\n  public onChangeDirection = () => {};\r\n\r\n  /**\r\n   * Called when scroll starts (user input).\r\n   * Override this callback in subclasses or instances.\r\n   */\r\n  public onScrollStart = () => {};\r\n\r\n  /**\r\n   * Called when scroll ends.\r\n   * Override this callback in subclasses or instances.\r\n   */\r\n  public onScrollStop = () => {};\r\n\r\n  /**\r\n   * Scroll-to function called on each frame.\r\n   * This will be reassigned depending on scroll direction.\r\n   */\r\n  public onCalcUpdate: () => void = () => {\r\n    this.context.data.scroll.scrollContainer?.scrollTo(\r\n      0,\r\n      this.context.data.scroll.current\r\n    );\r\n  };\r\n\r\n  /**\r\n   * Called every animation frame.\r\n   * Intended to be overridden in subclasses.\r\n   */\r\n  public onFrame(): void {}\r\n\r\n  /**\r\n   * Called when wheel event is fired.\r\n   * Override to implement custom scroll interaction.\r\n   * @param e Wheel event.\r\n   */\r\n  public onWheel(e: any): void {}\r\n\r\n  /**\r\n   * Called when native scroll event is fired.\r\n   * Override to track native scroll position.\r\n   * @param e Scroll event.\r\n   */\r\n  public onScroll(e: any): void {}\r\n\r\n  public disableScrollEvents(): void {}\r\n\r\n  public enableScrollEvents(): void {}\r\n}\r\n","import { StringContext } from \"../StringContext\";\r\nimport { ScrollController } from \"./ScrollController\";\r\n\r\n/**\r\n * Default scroll controller using native browser scrolling behavior.\r\n * Handles `scrollTop`, easing delta over time for smooth lerped animations.\r\n */\r\nexport class StringScrollDefault extends ScrollController {\r\n  /** Unique name identifier for this scroll mode. */\r\n  public readonly name: string = 'default';\r\n\r\n  /**\r\n   * Constructs a new instance of the default scroll controller.\r\n   * @param context Shared string system context.\r\n   */\r\n  constructor(context: StringContext) {\r\n    super(context);\r\n  }\r\n\r\n  /**\r\n   * Called every animation frame.\r\n   * Applies easing to scroll delta and updates lerped value.\r\n   * Fires `onScrollStop` once movement has settled.\r\n   */\r\n  public onFrame(): void {\r\n    if (this.context.data.scroll.delta !== 0) {\r\n      const delta = this.context.data.scroll.delta * this.context.data.scroll.speedAccelerate;\r\n      this.context.data.scroll.delta -= delta;\r\n      this.context.data.scroll.lerped = delta;\r\n\r\n      if (Math.abs(this.context.data.scroll.lerped) < 0.1) {\r\n        this.context.data.scroll.delta = 0;\r\n        this.context.data.scroll.lerped = 0;\r\n        this.onScrollStop();\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Called on native scroll event.\r\n   * Syncs the internal scroll state with the current page scroll.\r\n   * @param e Scroll event object (unused).\r\n   */\r\n  public onScroll(e: any): void {\r\n    const scrollTop = this.context.data.scroll.elementContainer.scrollTop;\r\n    this.context.data.scroll.current = scrollTop;\r\n    this.context.data.scroll.target = scrollTop;\r\n    this.context.data.scroll.transformedCurrent = scrollTop\r\n  }\r\n\r\n  /**\r\n   * Handles wheel input by updating scroll delta for easing.\r\n   * Triggers `onScrollStart` if delta begins from zero.\r\n   * @param e Wheel event.\r\n   */\r\n  public onWheel(e: any): void {\r\n    if (e.deltaY !== 0) {\r\n      if (this.context.data.scroll.delta === 0) {\r\n        this.onScrollStart();\r\n      }\r\n\r\n      const plusDelta = e.deltaY;\r\n\r\n      // Prevent negative delta from triggering at top of scroll\r\n      if (this.context.data.scroll.target === 0) {\r\n        this.context.data.scroll.delta += Math.max(0, e.deltaY);\r\n      }\r\n\r\n      this.context.data.scroll.delta += plusDelta;\r\n    }\r\n  }\r\n}\r\n","import { StringContext } from \"../StringContext\";\r\nimport { ScrollController } from \"./ScrollController\";\r\n\r\n/**\r\n * Scroll controller that disables all user-initiated scrolling.\r\n * Prevents native scroll and wheel behavior, effectively locking the page.\r\n */\r\nexport class StringScrollDisable extends ScrollController {\r\n  /** Unique name identifier for this scroll mode. */\r\n  public readonly name: string = \"disable\";\r\n\r\n  /**\r\n   * Constructs the scroll disabling controller.\r\n   * @param context The shared string system context.\r\n   */\r\n\r\n  private preventScroll = (e: Event) => {\r\n    e.preventDefault();\r\n  };\r\n\r\n  private preventKeyScroll = (e: KeyboardEvent) => {\r\n    const keysThatScroll = [\r\n      \"ArrowUp\",\r\n      \"ArrowDown\",\r\n      \"PageUp\",\r\n      \"PageDown\",\r\n      \" \",\r\n      \"Home\",\r\n      \"End\",\r\n    ];\r\n    if (keysThatScroll.includes(e.key)) {\r\n      e.preventDefault();\r\n    }\r\n  };\r\n\r\n  private onPreventScroll = this.preventScroll.bind(this);\r\n  private onPreventKeyScroll = this.preventKeyScroll.bind(this);\r\n\r\n  constructor(context: StringContext) {\r\n    super(context);\r\n  }\r\n\r\n  disableScrollEvents() {\r\n    window.addEventListener(\"touchmove\", this.onPreventScroll, {\r\n      passive: false,\r\n    });\r\n    window.addEventListener(\"keydown\", this.onPreventKeyScroll);\r\n  }\r\n\r\n  enableScrollEvents() {\r\n    window.removeEventListener(\"touchmove\", this.onPreventScroll);\r\n    window.removeEventListener(\"keydown\", this.onPreventKeyScroll);\r\n  }\r\n\r\n  /**\r\n   * Called on each animation frame.\r\n   * Not used in this controller since scrolling is disabled.\r\n   */\r\n  public onFrame(): void {}\r\n\r\n  /**\r\n   * Prevents scroll via mouse wheel.\r\n   * @param e Wheel event.\r\n   */\r\n  public onWheel(e: any): void {\r\n    e.preventDefault();\r\n  }\r\n\r\n  /**\r\n   * Prevents scroll via native scroll interaction (e.g. touch).\r\n   * @param e Scroll event.\r\n   */\r\n  public onScroll(e: any): void {\r\n    e.preventDefault();\r\n  }\r\n}\r\n","import { StringContext } from \"../StringContext\";\r\nimport { ScrollController } from \"./ScrollController\";\r\n\r\n/**\r\n * CSS class names applied to `<html>` element based on scroll direction.\r\n */\r\nconst CLASS_NAMES = {\r\n  SCROLL_FORWARD: '-scroll-forward',\r\n  SCROLL_BACK: '-scroll-back',\r\n} as const;\r\n\r\n/**\r\n * Smooth scroll controller with delta-based acceleration and direction tracking.\r\n * Handles wheel events and scroll position updates with smooth interpolation.\r\n */\r\nexport class StringScrollSmooth extends ScrollController {\r\n  /** \r\n * Unique identifier for this scroll controller type.\r\n * Used for selection and debug purposes.\r\n */\r\npublic readonly name: string = 'smooth';\r\n\r\n/** \r\n * Whether the user has manually scrolled using the native scrollbar.\r\n * When true, the scroll position is directly synced from DOM on next frame.\r\n */\r\nprivate isScrollbarManipulation = false;\r\n\r\n/** \r\n * Current internal force applied to the scroll target.\r\n * Calculated from accumulated scroll impulse and acceleration.\r\n */\r\nprivate scrollForce: number = 0;\r\n\r\n/** \r\n * Latest raw scroll impulse received from the wheel event (`deltaY`).\r\n * Temporarily stored for direction and boundary checks.\r\n */\r\nprivate wheelImpulse: number = 0;\r\n\r\n/** \r\n * Scroll position from the previous frame.\r\n * Used to detect actual movement and trigger updates only when needed.\r\n */\r\nprivate previousCurrent: number = 0;\r\n\r\n/** \r\n * Current scroll direction.\r\n * - `true` — scrolling down\r\n * - `false` — scrolling up\r\n * - `null` — unknown (initial state)\r\n */\r\nprivate isBottomScrollDirection: boolean | null = null;\r\n\r\n/** \r\n * Minimum velocity threshold below which scrolling is considered stopped.\r\n * Prevents micro-movements from continuing infinite smooth scroll.\r\n */\r\nprivate readonly velocityThreshold = 0.1;\r\n\r\n\r\n  constructor(context: StringContext) {\r\n    super(context);\r\n  }\r\n\r\n  /**\r\n   * Handles scroll direction changes and toggles CSS classes accordingly.\r\n   * @param newDirection `true` if scrolling down, `false` if up.\r\n   */\r\n  private updateScrollDirection(newDirection: boolean) {\r\n    if (this.isBottomScrollDirection === null) {\r\n      this.isBottomScrollDirection = newDirection;\r\n      return;\r\n    }\r\n    this.context.data.scroll.isScrollingDown = newDirection;\r\n    this.onChangeDirection();\r\n\r\n    document.documentElement.classList.toggle(CLASS_NAMES.SCROLL_FORWARD, newDirection);\r\n    document.documentElement.classList.toggle(CLASS_NAMES.SCROLL_BACK, !newDirection);\r\n  }\r\n\r\n  /**\r\n   * Immediately stops scrolling and resets all deltas and directions.\r\n   */\r\n  public stopScroll(): void {\r\n    this.context.data.scroll.lerped = 0;\r\n    this.context.data.scroll.delta = 0;\r\n    this.context.data.scroll.target = this.context.data.scroll.current;\r\n    this.isProg = false;\r\n    this.onCalcUpdate();\r\n    document.documentElement.classList.remove(CLASS_NAMES.SCROLL_BACK, CLASS_NAMES.SCROLL_FORWARD);\r\n    this.isBottomScrollDirection = null;\r\n  }\r\n\r\n  /**\r\n   * Called on each animation frame to apply lerped scroll logic.\r\n   */\r\n  public onFrame(): void {\r\n    if (this.isScrollbarManipulation) {\r\n      this.isScrollbarManipulation = false;\r\n      this.context.data.scroll.current = this.context.data.scroll.elementContainer.scrollTop\r\n      this.context.data.scroll.target = this.context.data.scroll.elementContainer.scrollTop\r\n      this.context.data.scroll.transformedCurrent = this.context.data.scroll.current * this.context.data.viewport.transformScale\r\n      return;\r\n    }\r\n\r\n    \r\n    if (this.context.data.scroll.delta !== 0) {\r\n      this.scrollForce = this.context.data.scroll.delta * this.context.data.scroll.speedAccelerate;\r\n\r\n      this.context.data.scroll.target = Math.min(\r\n        Math.max(0, this.context.data.scroll.target + this.scrollForce),\r\n        this.context.data.scroll.bottomPosition\r\n      );\r\n      this.context.data.scroll.delta -= this.scrollForce;\r\n\r\n      this.context.data.scroll.lerped = \r\n        (this.context.data.scroll.target - this.context.data.scroll.current) * \r\n        this.context.data.scroll.speed;\r\n\r\n      const absVelocity = Math.abs(this.context.data.scroll.lerped);\r\n      if (this.context.data.scroll.lerped > 0) {\r\n        this.context.data.scroll.current = Math.ceil(this.context.data.scroll.current + this.context.data.scroll.lerped);\r\n      } else {\r\n        this.context.data.scroll.current = Math.floor(this.context.data.scroll.current + this.context.data.scroll.lerped);\r\n      }\r\n      \r\n      this.context.data.scroll.transformedCurrent = this.context.data.scroll.current * this.context.data.viewport.transformScale\r\n      this.updateScrollDirection(this.context.data.scroll.lerped > 0);\r\n\r\n      if (absVelocity < this.velocityThreshold) {\r\n        this.stopScroll();\r\n        this.onScrollStop();\r\n      } else {\r\n        this.isProg = true;\r\n        if (this.previousCurrent !== this.context.data.scroll.current) {\r\n          this.previousCurrent = this.context.data.scroll.current;\r\n          this.onCalcUpdate();\r\n        }\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Handles user wheel input to accumulate scroll delta.\r\n   * @param e The WheelEvent from the browser.\r\n   */\r\n  public onWheel(e: WheelEvent): void {\r\n    if (e.deltaY !== 0) {\r\n      e.preventDefault();\r\n    }\r\n\r\n    this.wheelImpulse = e.deltaY;\r\n    if (this.wheelImpulse === 0) return;\r\n\r\n    if (this.context.data.scroll.delta === 0) {\r\n      this.onScrollStart();\r\n    }\r\n    \r\n    const scrollDirection = Math.sign(this.wheelImpulse);\r\n    const atTop = this.context.data.scroll.target === 0 && scrollDirection < 0;\r\n    const atBottom = this.context.data.scroll.target === this.context.data.scroll.bottomPosition && scrollDirection > 0;\r\n    if (atTop || atBottom) return;\r\n    this.context.data.scroll.delta += this.wheelImpulse;\r\n  }\r\n\r\n  /**\r\n   * Detects native scrollbar manipulation when smooth scroll is idle.\r\n   * @param e Scroll event.\r\n   */\r\n  public onScroll(e: Event): void {\r\n    if (!this.isProg) {\r\n      this.isScrollbarManipulation = true;\r\n    }\r\n  }\r\n}\r\n","import { ScrollMode } from \"../../states/ScrollState\";\r\nimport { ScrollController } from \"../controllers/ScrollController\";\r\nimport { StringScrollDefault } from \"../controllers/StringScrollDefault\";\r\nimport { StringScrollDisable } from \"../controllers/StringScrollDisable\";\r\nimport { StringScrollSmooth } from \"../controllers/StringScrollSmooth\";\r\nimport { StringContext } from \"../StringContext\";\r\n\r\n/**\r\n * Handles scroll engine setup and switching logic.\r\n * Synchronizes scroll modes with the centralized ScrollState inside StringContext.\r\n */\r\nexport class ScrollManager {\r\n  private modes: Map<ScrollMode, ScrollController> = new Map();\r\n\r\n  constructor(private context: StringContext) {\r\n    this.modes.set(\"smooth\", new StringScrollSmooth(context));\r\n    this.modes.set(\"default\", new StringScrollDefault(context));\r\n    this.modes.set(\"disable\", new StringScrollDisable(context));\r\n\r\n    // Initial mode based on screen width\r\n    this.updateResponsiveMode();\r\n  }\r\n\r\n  /**\r\n   * Manually sets the scroll mode for mobile devices.\r\n   * @param mode The scroll mode: 'smooth', 'default', or 'disable'.\r\n   */\r\n  public setMobileMode(mode: ScrollMode): void {\r\n    this.context.data.scroll.modeMobile = mode;\r\n    this.updateResponsiveMode();\r\n  }\r\n\r\n  /**\r\n   * Manually sets the scroll mode for desktop devices.\r\n   * @param mode The scroll mode: 'smooth', 'default', or 'disable'.\r\n   */\r\n  public setDesktopMode(mode: ScrollMode): void {\r\n    this.context.data.scroll.modeDesktop = mode;\r\n    this.updateResponsiveMode();\r\n  }\r\n\r\n  /**\r\n   * Automatically switches scroll mode based on screen width.\r\n   * Call this inside your resize handler.\r\n   */\r\n  public updateResponsiveMode(): void {\r\n    const isMobile = window.innerWidth < 1080;\r\n    const newMode = isMobile\r\n      ? this.context.data.scroll.modeMobile\r\n      : this.context.data.scroll.modeDesktop;\r\n\r\n    this.setMode(newMode);\r\n  }\r\n\r\n  public updatePosition(): void {\r\n    this.modes.forEach((engine) => {\r\n      engine.onCalcUpdate();\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Sets the current scroll mode and updates the active scroll engine.\r\n   * @param mode The scroll mode to activate.\r\n   */\r\n  public setMode(mode: ScrollMode): void {\r\n    if (!this.modes.has(mode)) {\r\n      console.warn(`[ScrollManager] Unknown scroll mode: ${mode}`);\r\n      return;\r\n    }\r\n    this.get().enableScrollEvents();\r\n    this.context.data.scroll.mode = mode;\r\n    this.get().disableScrollEvents();\r\n  }\r\n\r\n  /**\r\n   * Returns the currently active scroll engine based on state.\r\n   */\r\n  public get(): ScrollController {\r\n    return this.modes.get(this.context.data.scroll.mode)!;\r\n  }\r\n\r\n  /**\r\n   * Returns all available scroll engine instances.\r\n   */\r\n  public getEngines(): Map<ScrollMode, ScrollController> {\r\n    return this.modes;\r\n  }\r\n\r\n  /**\r\n   * Calls `onFrame()` on the current scroll engine.\r\n   */\r\n  public onFrame(): void {\r\n    this.get().onFrame();\r\n  }\r\n\r\n  /**\r\n   * Forwards native scroll event to the current scroll engine.\r\n   * @param e The scroll event.\r\n   */\r\n  public onScroll(e: Event): void {\r\n    this.get().onScroll(e);\r\n  }\r\n\r\n  /**\r\n   * Forwards wheel event to the current scroll engine.\r\n   * @param e The wheel event.\r\n   */\r\n  public onWheel(e: WheelEvent): void {\r\n    this.get().onWheel(e);\r\n  }\r\n\r\n  /**\r\n   * Subscribes lifecycle event handlers to all scroll engines.\r\n   * @param events Scroll lifecycle callbacks.\r\n   */\r\n  public bindEvents(events: {\r\n    onScrollStart: () => void;\r\n    onScrollStop: () => void;\r\n    onDirectionChange: () => void;\r\n  }) {\r\n    this.modes.forEach((engine) => {\r\n      engine.onScrollStart = events.onScrollStart;\r\n      engine.onScrollStop = events.onScrollStop;\r\n      engine.onChangeDirection = events.onDirectionChange;\r\n    });\r\n  }\r\n}\r\n","/**\r\n * Reactive cursor data for raw, target, smoothed and step deltas.\r\n */\r\nexport class CursorState {\r\n  /**\r\n   * Target X position of the cursor (e.g., from `mousemove`)\r\n   */\r\n  targetX: number = 0\r\n\r\n  /**\r\n   * Target Y position of the cursor.\r\n   */\r\n  targetY: number = 0\r\n\r\n  /**\r\n   * Smoothed X position after applying lerp.\r\n   */\r\n  smoothedX: number = 0\r\n\r\n  /**\r\n   * Smoothed Y position after applying lerp.\r\n   */\r\n  smoothedY: number = 0\r\n\r\n  /**\r\n   * Delta step between current and target X (used internally for lerp).\r\n   */\r\n  stepX: number = 0\r\n\r\n  /**\r\n   * Delta step between current and target Y.\r\n   */\r\n  stepY: number = 0\r\n}\r\n","/**\r\n * Global Three.js or rendering context reference.\r\n */\r\nexport class RenderState {\r\n  /** Instance of Three.js or another render context */\r\n  threeInstance: any = null\r\n}\r\n","export type ScrollDirection = 'vertical' | 'horizontal'\r\nexport type ScrollMode = 'smooth' | 'disable' | 'default'\r\n\r\n/**\r\n * Describes current scroll-related state for all calculations and modules.\r\n */\r\nexport class ScrollState {\r\n  /** Target scroll value — where we want to scroll to (used in smooth scroll) */\r\n  target: number = 0\r\n\r\n  /** Current scroll value (actual scroll position) */\r\n  current: number = 0\r\n\r\n  /** Transformed current scroll value (with transform by scroll container) */\r\n  transformedCurrent: number = 0\r\n\r\n  /** Delta between frames (used for animation / velocity) */\r\n  delta: number = 0\r\n\r\n  /** Interpolated scroll value for smooth transitions */\r\n  lerped: number = 0\r\n\r\n  /** Displacement value (similar to lerped, but used for other animations) */\r\n  displacement: number = 0\r\n\r\n  /** Whether scroll direction is downward */\r\n  isScrollingDown: boolean = false\r\n\r\n  /** Top screen scroll position */\r\n  topPosition: number = 0\r\n\r\n  /** Bottom screen scroll position */\r\n  bottomPosition: number = 0\r\n\r\n  /** Scroll direction (vertical / horizontal) */\r\n  direction: ScrollDirection = 'vertical'\r\n\r\n  /** Scroll container element */\r\n  elementContainer: HTMLElement = document.documentElement\r\n\r\n  /** Scroll container element */\r\n  scrollContainer: HTMLElement | Window = window\r\n\r\n  /** Scroll container element */\r\n  container: HTMLElement = document.body\r\n\r\n  /**\r\n   * Currently active scroll mode.\r\n   * Can be 'smooth', 'default', or 'disable'.\r\n   */\r\n  mode: ScrollMode = 'smooth'\r\n\r\n  /**\r\n   * Scroll mode to use on mobile devices.\r\n   * Can be 'smooth', 'default', or 'disable'.\r\n   */\r\n  modeMobile: ScrollMode = 'smooth'\r\n\r\n  /**\r\n   * Scroll mode to use on desktop devices.\r\n   * Can be 'smooth', 'default', or 'disable'.\r\n   */\r\n  modeDesktop: ScrollMode = 'smooth'\r\n\r\n  /**\r\n   * Base scroll speed used for calculating smooth scrolling.\r\n   * Typically a small value between 0 and 1.\r\n   */\r\n  speed: number = 0.1\r\n\r\n  /**\r\n   * Acceleration factor used for scroll easing or velocity-based animations.\r\n   * Also typically a value between 0 and 1.\r\n   */\r\n  speedAccelerate: number = 0.25\r\n}\r\n","/**\r\n * Represents the time-related state of the current and previous animation frames.\r\n * \r\n * Useful for calculating delta time, total elapsed time, and implementing\r\n * time-based animations or physics.\r\n */\r\nexport class TimeState {\r\n  /**\r\n   * Timestamp of the current animation frame in milliseconds.\r\n   * This value is typically obtained via `performance.now()`.\r\n   */\r\n  now: number = 0;\r\n\r\n  /**\r\n   * Timestamp of the previous animation frame in milliseconds.\r\n   */\r\n  previous: number = 0;\r\n\r\n  /**\r\n   * Time difference between the current and previous frames in milliseconds.\r\n   * Commonly used to calculate animation progress.\r\n   */\r\n  delta: number = 0;\r\n\r\n  /**\r\n   * Total time elapsed since the start of the animation or system in milliseconds.\r\n   */\r\n  elapsed: number = 0;\r\n}\r\n","/**\r\n * Describes current viewport size and scaling.\r\n */\r\nexport class ViewportState {\r\n  /** Width of the visible window */\r\n  windowWidth: number = 0\r\n\r\n  /** Height of the visible window */\r\n  windowHeight: number = 0\r\n\r\n  /** Full scroll width (content width inside scroll container) */\r\n  contentWidth: number = 0\r\n\r\n  /** Full scroll height (content height inside scroll container) */\r\n  contentHeight: number = 0\r\n\r\n  /** Screen scale ratio for width (e.g. device pixel ratio or zoom level) */\r\n  scaleWidth: number = 1\r\n\r\n  /** Screen scale ratio for height */\r\n  scaleHeight: number = 1\r\n\r\n  transformScale: number = 1\r\n\r\n  baseRem: number = 16\r\n}\r\n","import { CursorState } from \"../states/CursorState\"\r\nimport { RenderState } from \"../states/RenderState\"\r\nimport { ScrollState } from \"../states/ScrollState\"\r\nimport { TimeState } from \"../states/TimeState\"\r\nimport { ViewportState } from \"../states/ViewportState\"\r\n\r\n/**\r\n * Container for global dynamic state used throughout the string-tune system.\r\n * Provides access to live scroll, viewport, cursor, and render states,\r\n * which are updated each frame and shared across modules and tools.\r\n */\r\nexport class StringData {\r\n  /**\r\n   * Scroll-related state object.\r\n   * Contains live values like `target`, `current`, `delta`, `direction`, and more.\r\n   * Used for scroll-based animations, transitions, and effects.\r\n   */\r\n  scroll = new ScrollState()\r\n\r\n  /**\r\n   * Viewport-related state object.\r\n   * Holds dimensions like window size, content size, aspect ratios, and more.\r\n   * Useful for layout calculations, unit parsing, and element positioning.\r\n   */\r\n  viewport = new ViewportState()\r\n\r\n  /**\r\n   * Cursor-related state object.\r\n   * Tracks cursor position, velocity, movement, and derived values.\r\n   * Can be used for pointer interactions, proximity effects, and hover states.\r\n   */\r\n  cursor = new CursorState()\r\n\r\n  /**\r\n   * Render-related state object.\r\n   * Stores data related to rendering context (e.g. WebGL, Three.js),\r\n   * such as shared materials, textures, or active render frame data.\r\n   */\r\n  render = new RenderState()\r\n\r\n   /**\r\n   * Time-related state object.\r\n   * Tracks frame timings, including current timestamp, delta between frames,\r\n   * and total elapsed time since animation start.\r\n   * Useful for time-based animations, easing, frame consistency, and syncing logic.\r\n   */\r\n  time = new TimeState()\r\n}\r\n","import { IStringModule } from './IStringModule'\r\nimport { StringObject } from '../objects/StringObject'\r\nimport { StringToolsContainer } from './StringToolsContainer'\r\nimport { StringData } from './StringData'\r\nimport { AttributeType } from '../models/attribute/AttributeType'\r\nimport { StringContext } from './StringContext'\r\nimport { EventManager } from './managers/EventManager'\r\nimport { AttributeMapping } from '../models/attribute/AttributeMapping'\r\n\r\n\r\n\r\n\r\n/**\r\n * Base class for a module used in the string-tune system.\r\n * Extend this class to create custom modules that respond to scroll, resize, input, etc.\r\n */\r\nexport class StringModule implements IStringModule {\r\n  \r\n  /**\r\n   * List of attribute names this module should automatically read\r\n   * from the DOM element and assign to the object properties.\r\n   * Example: [\"offset-top\", \"offset-bottom\"]\r\n   */\r\n  protected attributesToMap: AttributeMapping[]\r\n\r\n  /**\r\n   * A map of all entered objects by their unique ID.\r\n   */\r\n  protected objectMap: Map<string, StringObject> = new Map()\r\n\r\n  /**\r\n   * A flat array of all connected objects.\r\n   */\r\n  protected objects: StringObject[] = []\r\n\r\n  /**\r\n   * The HTML attribute key that identifies objects this module is responsible for.\r\n   */\r\n  protected htmlKey: string = ''\r\n\r\n  /**\r\n   * Module type ID used internally to categorize module behavior.\r\n   */\r\n  protected _type: number = 1\r\n\r\n  /**\r\n   * Returns the type of the module.\r\n   * Type 1 = core module, type 2 = UI module.\r\n   */\r\n  public get type(): number {\r\n    return this._type\r\n  }\r\n\r\n  /**\r\n   * Tools container providing utilities for attribute parsing, unit conversion, etc.\r\n   * Acts as a dependency injection hub for core IStringTool implementations.\r\n   */\r\n  protected tools: StringToolsContainer\r\n\r\n  /**\r\n   * Shared global data object containing scroll state, viewport info, cursor position, etc.\r\n   * Used for calculations within lifecycle hooks like `onScroll`, `onFrame`, and `onResize`.\r\n   */\r\n  protected data: StringData\r\n\r\n  /**\r\n   * Configuration object specific to the current module.\r\n   * Passed in during module registration or initialization.\r\n   */\r\n  protected settings: Record<string, any>\r\n\r\n  /**\r\n   * Event hub for communication between modules or systems.\r\n   * Supports custom event emitting, listening, and unsubscription.\r\n   */\r\n  protected events: EventManager\r\n\r\n\r\n\r\n  constructor(context: StringContext) {\r\n    this.tools = context.tools\r\n    this.data = context.data\r\n    this.settings = context.settings\r\n    this.events = context.events\r\n\r\n\r\n\r\n    this.attributesToMap = [\r\n      { key: 'active', type: \"boolean\", fallback: this.settings['active'] },\r\n      { key: 'fixed', type: \"boolean\", fallback: this.settings['fixed'] },\r\n      { key: 'repeat', type: \"boolean\", fallback: this.settings['repeat'] },\r\n      { key: 'self-disable', type: \"boolean\", fallback: this.settings['self-disable'] },\r\n      { key: 'abs', type: \"boolean\", fallback: this.settings['abs'] },\r\n      { key: 'key', type: \"string\", fallback: this.settings['key'] },\r\n      { key: 'offset-top', type: \"dimension\", fallback: this.settings['offset-top'] },\r\n      { key: 'offset-bottom', type: \"dimension\", fallback: this.settings['offset-bottom'] },\r\n      { key: 'inview-top', type: \"dimension\", fallback: this.settings['inview-top'] },\r\n      { key: 'inview-bottom', type: \"dimension\", fallback: this.settings['inview-bottom'] },\r\n      {\r\n        key: 'start', type: \"number\", fallback: (element: HTMLElement, object: StringObject, boundingRect: DOMRect) => {\r\n          const top = boundingRect.top\r\n          return Math.floor(top) + this.data.scroll.container.scrollTop * this.data.viewport.transformScale\r\n        }\r\n      },\r\n      {\r\n        key: 'end', type: \"number\", fallback: (element: HTMLElement, object: StringObject, boundingRect: DOMRect) => {\r\n          const top = boundingRect.top\r\n          const height = boundingRect.height\r\n          return top + height - this.data.scroll.transformedCurrent\r\n        }\r\n      },\r\n      {\r\n        key: 'size', type: \"number\", fallback: (element: HTMLElement, object: StringObject, boundingRect: DOMRect) => {\r\n          return boundingRect.height\r\n        }\r\n      },\r\n      {\r\n        key: 'half-width', type: \"number\", fallback: (element: HTMLElement, object: StringObject, boundingRect: DOMRect) => {\r\n          return boundingRect.width / 2\r\n        }\r\n      },\r\n      {\r\n        key: 'half-height', type: \"number\", fallback: (element: HTMLElement, object: StringObject, boundingRect: DOMRect) => {\r\n          return boundingRect.height / 2\r\n        }\r\n      },\r\n    ]\r\n  }\r\n\r\n  /**\r\n   * Called when a DOM element is detected as a potential interactive object.\r\n   */\r\n  initializeObject(\r\n    globalId: number,\r\n    object: StringObject,\r\n    element: HTMLElement,\r\n    attributes: Record<string, any>\r\n  ): void {\r\n    let boundingRect = this.tools.boundingClientRect.process({ element })\r\n    for (const { key, type, fallback, transform } of this.attributesToMap) {\r\n      const resolvedFallback =\r\n        typeof fallback === 'function' ? fallback(element, object, boundingRect) : fallback\r\n      const raw = this.tools.domAttribute.process({\r\n        element,\r\n        key,\r\n        fallback: attributes[key] ?? this.settings[key] ?? resolvedFallback\r\n      })\r\n\r\n      let parsed = this.parseAttribute(raw, type, {\r\n        element,\r\n        viewportHeight: this.data.viewport.windowHeight,\r\n        baseRem: this.data.viewport.baseRem\r\n      })\r\n\r\n      if (transform) {\r\n        parsed = transform(parsed)\r\n      }\r\n      object.setProperty(key, parsed)\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Calculates object-specific positions or metrics based on the current layout or scroll state.\r\n   * This method is intended to be overridden in subclasses if the module needs to precompute\r\n   * layout-dependent values (e.g. parallax offsets, trigger zones, distances).\r\n   *\r\n   * @param object The `StringObject` instance whose positions are being calculated.\r\n   * @param windowSize The current window height or width (depending on scroll axis).\r\n   */\r\n  calculatePositions(object: StringObject, windowSize: number) {\r\n  }\r\n\r\n  /**\r\n   * Parses a raw DOM attribute value into the correct type based on mapping.\r\n   * Handles fallback resolution, transformation, and special units.\r\n   *\r\n   * @param value Raw attribute string from DOM.\r\n   * @param type The expected attribute type (e.g. number, boolean, dimension).\r\n   * @param context Optional helper values like element or viewport size.\r\n   * @returns The parsed and transformed value.\r\n   */\r\n  protected parseAttribute(\r\n    value: string | null,\r\n    type: AttributeType,\r\n    context: {\r\n      element?: HTMLElement\r\n      viewportHeight?: number\r\n      baseRem?: number\r\n    } = {}\r\n  ): any {\r\n    if (value == null) return null\r\n\r\n    if (typeof type === 'object' && type.type === 'enum') {\r\n      return type.values.includes(value) ? value : type.values[0]\r\n    }\r\n\r\n    switch (type) {\r\n      case \"number\":\r\n        return parseFloat(value)\r\n\r\n      case \"boolean\":\r\n        return value === \"\" || value === \"true\";\r\n\r\n      case \"json\":\r\n        try {\r\n          return JSON.parse(value)\r\n        } catch {\r\n          return null\r\n        }\r\n\r\n      case \"tuple\":\r\n        return value.trim().split(/\\s+/)\r\n      \r\n      case \"easing\":\r\n        return this.tools.easingFunction.process({ easing: value })\r\n      \r\n      case \"color\":\r\n        return this.tools.colorParser.process({ value: value })\r\n      \r\n      case \"dimension\":\r\n        if (value == \"0\") return 0;\r\n        if (context.element != null && context.viewportHeight != null && context.baseRem != null) {\r\n          return this.tools.unitParser.process({\r\n            value,\r\n            element: context.element,\r\n            viewportHeight: context.viewportHeight,\r\n            baseRem: context.baseRem\r\n          })\r\n        } else {\r\n          return 0\r\n        }\r\n        \r\n      default:\r\n        return value\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Determines whether the module should attach to a given object,\r\n   * based on the presence of the module's `htmlKey` in the object keys.\r\n   *\r\n   * @param object The target object to test.\r\n   * @returns `true` if the module can connect, `false` otherwise.\r\n   */\r\n  canConnect(object: StringObject): boolean {\r\n    return object.keys.includes(this.htmlKey)\r\n  }\r\n\r\n  /**\r\n   * Registers the module on a given object, adds the object to internal list,\r\n   * and triggers connection logic.\r\n   *\r\n   * @param object The object to connect to.\r\n   */\r\n  connectObject(object: StringObject): void {\r\n    object.connect(this)\r\n    this.onObjectConnected(object)\r\n  }\r\n\r\n  /**\r\n   * Registers the object internally when it enters the module’s scope.\r\n   */\r\n  enterObject(id: string, object: StringObject): void {\r\n    if (!this.objectMap.has(id)) {\r\n      this.objectMap.set(id, object)\r\n      this.objects.push(object)\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Unregisters the object when it leaves the module’s scope.\r\n   */\r\n  exitObject(id: string): void {\r\n    const object = this.objectMap.get(id)\r\n    if (!object) return\r\n\r\n    this.objectMap.delete(id)\r\n\r\n    const index = this.objects.indexOf(object)\r\n    if (index !== -1) {\r\n      this.objects.splice(index, 1)\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Called when an object is connected. Can be overridden to apply initial styles or logic.\r\n   * @param object The connected object.\r\n   */\r\n  onObjectConnected(object: StringObject): void { }\r\n  \r\n  /**\r\n   * Applies a style or callback to both the main element and all its connected elements.\r\n   * \r\n   * @param object The object whose elements to update.\r\n   * @param applyFn The function that receives an HTMLElement and performs any update.\r\n   */\r\n  protected applyToElementAndConnects(object: StringObject, applyFn: (el: HTMLElement) => void) {\r\n    applyFn(object.htmlElement)\r\n    object.connects.forEach(applyFn)\r\n  }\r\n\r\n  /**\r\n   * Cleans up internal state and detaches the module from the system.\r\n   */\r\n  destroy(): void {\r\n    this.objects = []\r\n    this.objectMap = new Map()\r\n  }\r\n\r\n  // ───────────────────────────────\r\n  // Lifecycle Hooks\r\n  // ───────────────────────────────\r\n\r\n  /** Called once when the module is initialized. */\r\n  onInit(): void {}\r\n\r\n  /** Called on each frame with current scroll and state data. */\r\n  onFrame(data: StringData): void {}\r\n\r\n  /** Called when the window or layout is resized. */\r\n  onResize(): void {}\r\n\r\n  /** Called when scroll position changes. */\r\n  onScroll(data: StringData): void {}\r\n\r\n  /** Called when user changed scroll diraction. */\r\n  onDirectionChange(): void {}\r\n\r\n  /** Called when user starts scrolling. */\r\n  onScrollStart(): void {}\r\n\r\n  /** Called when user stops scrolling. */\r\n  onScrollStop(): void {}\r\n\r\n  /** Called when scroll direction changes (e.g., up ↔ down). */\r\n  onScrollDirectionChange(): void {}\r\n\r\n  /** Called when scroll axis changes (vertical ↔ horizontal). */\r\n  onAxisChange(): void {}\r\n\r\n  /** Called when device type changes (e.g., desktop ↔ mobile). */\r\n  onDeviceChange(): void {}\r\n\r\n  /** Called when scroll-related system settings or parameters change. */\r\n  onScrollConfigChange(): void {}\r\n\r\n  /** Called when scroll-related system settings or parameters change. */\r\n  onSettingsChange(): void {}\r\n\r\n  /** Called when the DOM is rebuilt, such as after a major mutation. */\r\n  onDOMRebuild(): void {}\r\n\r\n  /** Called on every mouse movement. */\r\n  onMouseMove(event: MouseEvent): void {}\r\n\r\n  /** Called on wheel input (independent of scroll). */\r\n  onWheel(event: WheelEvent): void {}\r\n\r\n  /**\r\n   * Called when DOM elements are added or removed.\r\n   */\r\n  onDOMMutate(added: NodeList, removed: NodeList): void {}\r\n}\r\n","import { IStringTool } from \"../core/IStringTool\"\r\n\r\n/**\r\n * Input for `BoundingClientRectTool`.\r\n */\r\ninterface BoundingClientRectInput {\r\n  /** The DOM element to retrieve bounding rect from. */\r\n  element: HTMLElement\r\n}\r\n\r\n/**\r\n * Tool for accessing `getBoundingClientRect()` in a consistent, testable way.\r\n */\r\nexport default class BoundingClientRectTool\r\n  implements IStringTool<BoundingClientRectInput, DOMRect>\r\n{\r\n  /**\r\n   * @returns The bounding client rect of the provided element.\r\n   */\r\n  process({ element }: BoundingClientRectInput): DOMRect {\r\n    return element.getBoundingClientRect()\r\n  }\r\n}\r\n","import { IStringTool } from \"../core/IStringTool\"\r\n\r\ninterface DOMAttributeInput {\r\n  element: HTMLElement\r\n  key: string // for example: \"offset-tom\"\r\n  fallback?: string | null\r\n}\r\n\r\nexport default class DOMAttributeTool implements IStringTool<DOMAttributeInput, string | null> {\r\n  /**\r\n   * Retrieves the value of either `string-${key}` or `data-string-${key}` attribute.\r\n   *\r\n   * @example key = \"offset-tom\" → tries:\r\n   *   - element.getAttribute(\"string-offset-tom\")\r\n   *   - element.getAttribute(\"data-string-offset-tom\")\r\n   */\r\n  process({ element, key, fallback = null }: DOMAttributeInput): string | null {\r\n    return (\r\n      element.getAttribute(`string-${key}`) ??\r\n      element.getAttribute(`data-string-${key}`) ??\r\n      fallback\r\n    )\r\n  }\r\n}\r\n","import { IStringTool } from \"../core/IStringTool\"\r\n\r\n/**\r\n * Input for retrieving a value from a key-value object or dataset-like structure.\r\n */\r\ninterface RecordAttributeInput {\r\n  /** Source object to read from (e.g. dataset or plain record). */\r\n  record: Record<string, any>\r\n\r\n  /** Key to look up (without `\"data-\"` prefix). */\r\n  name: string\r\n\r\n  /** Fallback value if both keys are missing. */\r\n  fallback?: any\r\n}\r\n\r\n/**\r\n * Retrieves a value from an object or dataset-like structure.\r\n * Tries `record[name]` first, then `record[\"data-\" + name]`, or returns fallback.\r\n */\r\nexport default class RecordAttributeTool implements IStringTool<RecordAttributeInput, any> {\r\n  /**\r\n   * @returns Value from the record or fallback.\r\n   */\r\n  process({ record, name, fallback = null }: RecordAttributeInput): any {\r\n    return (\r\n      record[name] ??\r\n      record[`data-${name}`] ??\r\n      fallback\r\n    )\r\n  }\r\n}\r\n","import { IStringTool } from \"../core/IStringTool\"\r\n\r\n/**\r\n * Input for removing transform effects from an element's bounding box.\r\n */\r\ninterface TransformNullifyInput {\r\n  /** The DOM element whose CSS transform should be nullified. */\r\n  element: HTMLElement\r\n}\r\n\r\n/**\r\n * Output with corrected bounding box values.\r\n */\r\ninterface TransformNullifyOutput {\r\n  /** Top position without transform effects. */\r\n  top: number\r\n\r\n  /** Left position without transform effects. */\r\n  left: number\r\n\r\n  /** Width without transform scaling. */\r\n  width: number\r\n\r\n  /** Height without transform scaling. */\r\n  height: number\r\n}\r\n\r\n/**\r\n * Computes the true bounding box of a DOM element,\r\n * nullifying CSS `transform: matrix(...)` effects.\r\n */\r\nexport default class TransformNullifyTool\r\n  implements IStringTool<TransformNullifyInput, TransformNullifyOutput>\r\n{\r\n  /**\r\n   * @returns Element position and size without transform influence.\r\n   */\r\n  process({ element }: TransformNullifyInput): TransformNullifyOutput {\r\n    const rect = element.getBoundingClientRect()\r\n    const matrix = getComputedStyle(element).transform\r\n\r\n    const values = matrix\r\n      .match(/-?[\\d.]+/g)\r\n      ?.map(parseFloat) ?? []\r\n\r\n    if (values.length === 6) {\r\n      const [a, b, c, d, e, f] = values\r\n      const det = a * d - b * c\r\n\r\n      return {\r\n        width: rect.width / (a || 1),\r\n        height: rect.height / (d || 1),\r\n        left: (rect.left * d - rect.top * c + c * f - e * d) / det,\r\n        top: (-rect.left * b + rect.top * a + e * b - a * f) / det,\r\n      }\r\n    }\r\n\r\n    return rect\r\n  }\r\n}\r\n","import { IStringTool } from \"../core/IStringTool\"\r\nimport TransformNullifyTool from \"./TransformNullifyTool\"\r\n\r\n/**\r\n * Input for calculating the position of an element relative to a container.\r\n */\r\ninterface RelativePositionInput {\r\n  /** The DOM element whose position should be calculated. */\r\n  element: HTMLElement\r\n\r\n  /** Optional container to measure against. Defaults to `document.body`. */\r\n  container?: HTMLElement\r\n}\r\n\r\n/**\r\n * Output: relative position in pixels.\r\n */\r\ninterface RelativePositionOutput {\r\n  /** Distance from the top of the container. */\r\n  top: number\r\n\r\n  /** Distance from the left of the container. */\r\n  left: number\r\n}\r\n\r\n/**\r\n * Calculates an element's position relative to a container.\r\n * Uses `TransformNullifyTool` to account for CSS transforms.\r\n */\r\nexport default class RelativePositionTool\r\n  implements IStringTool<RelativePositionInput, RelativePositionOutput>\r\n{\r\n  constructor(\r\n    /** Optional tool for CSS transform-neutral measurements. */\r\n    private transformTool = new TransformNullifyTool()\r\n  ) {}\r\n\r\n  /**\r\n   * @returns Relative top/left position of element within container.\r\n   */\r\n  process({ element, container = document.body }: RelativePositionInput): RelativePositionOutput {\r\n    let containerRect: DOMRect\r\n    try {\r\n      containerRect = container.getBoundingClientRect()\r\n    } catch {\r\n      containerRect = document.body.getBoundingClientRect()\r\n    }\r\n\r\n    const elRect = this.transformTool.process({ element })\r\n\r\n    return {\r\n      top: elRect.top - containerRect.top,\r\n      left: elRect.left - containerRect.left,\r\n    }\r\n  }\r\n}\r\n","import { IStringTool } from \"../core/IStringTool\"\r\n\r\ninterface LerpInput {\r\n  /** Starting value of the interpolation. */\r\n  from: number\r\n\r\n  /** Target value to interpolate towards. */\r\n  to: number\r\n\r\n  /** Interpolation progress between 0 (start) and 1 (end). */\r\n  progress: number\r\n}\r\n\r\nexport default class LerpTool implements IStringTool<LerpInput, number> {\r\n  /**\r\n   * Calculates the linear interpolation between two values.\r\n   * @returns Interpolated value.\r\n   */\r\n  process({ from, to, progress }: LerpInput): number {\r\n    return (to - from) * progress\r\n  }\r\n}\r\n\r\n","import { IStringTool } from \"../core/IStringTool\"\r\n\r\n/**\r\n * Input for parsing unit-based strings into numeric pixel values.\r\n */\r\ninterface UnitParserInput {\r\n  /** Unit string, e.g. `\"20px\"`, `\"50%\"`, `\"1.5rem\"`, or `\"selfHeight\"` */\r\n  value: string\r\n\r\n  /** DOM element used for `\"selfHeight\"` calculation */\r\n  element: HTMLElement\r\n\r\n  /** Viewport height in pixels (for percentage conversion) */\r\n  viewportHeight: number\r\n\r\n  /** Root font size in pixels (for rem conversion) */\r\n  baseRem: number\r\n}\r\n\r\n/**\r\n * Converts unit-based strings to numeric pixel values.\r\n * Supports `px`, `%`, `rem`, and `\"selfHeight\"` keyword. Handles negatives.\r\n */\r\nexport default class UnitParserTool implements IStringTool<UnitParserInput, number> {\r\n  /**\r\n   * @returns Numeric value in pixels (positive or negative).\r\n   */\r\n  process({ value, element, viewportHeight, baseRem }: UnitParserInput): number {\r\n    const isNegative = value.startsWith(\"-\")\r\n    if (isNegative) value = value.slice(1)\r\n\r\n    let result = 0\r\n\r\n    if (value === \"selfHeight\") {\r\n      result = element.offsetHeight\r\n    } else if (value.endsWith(\"px\")) {\r\n      result = parseFloat(value)\r\n    } else if (value.endsWith(\"%\")) {\r\n      result = (parseFloat(value) / 100) * viewportHeight\r\n    } else if (value.endsWith(\"rem\")) {\r\n      result = parseFloat(value) * baseRem\r\n    }\r\n\r\n    return isNegative ? -result : result\r\n  }\r\n}\r\n","import { IStringTool } from \"../core/IStringTool\"\r\n\r\n/**\r\n * Input for adaptive lerp factor calculation.\r\n * Maps a speed-like value to a lerp factor, where:\r\n * - lower speed ⇒ slower smoothing (higher lerp factor)\r\n * - higher speed ⇒ faster response (lower lerp factor)\r\n */\r\ninterface AdaptiveLerpInput {\r\n  /** Current value (e.g., speed or delta). */\r\n  value: number\r\n\r\n  /** Minimum input threshold (default: 0.1) */\r\n  inMin?: number\r\n\r\n  /** Maximum input threshold (default: 1.0) */\r\n  inMax?: number\r\n\r\n  /** Output when input is at minimum (default: 0.65) */\r\n  outMax?: number\r\n\r\n  /** Output when input is at maximum (default: 0.05) */\r\n  outMin?: number\r\n}\r\n\r\n/**\r\n * Converts a numeric input (like velocity) into an adaptive lerp factor.\r\n * Useful for scroll or speed-based smoothing effects.\r\n */\r\nexport default class AdaptiveLerpTool implements IStringTool<AdaptiveLerpInput, number> {\r\n  /**\r\n   * @returns A remapped lerp factor from `outMax` to `outMin`.\r\n   */\r\n  process({\r\n    value,\r\n    inMin = 0.1,\r\n    inMax = 1.0,\r\n    outMin = 0.05,\r\n    outMax = 0.65\r\n  }: AdaptiveLerpInput): number {\r\n    if (value < inMin) return outMax\r\n    if (value > 1.0) value = 1.0\r\n\r\n    if (value <= inMax) {\r\n      const t = (value - inMin) / (inMax - inMin)\r\n      return outMax - t * (outMax - outMin)\r\n    }\r\n\r\n    return outMin\r\n  }\r\n}\r\n","import { IStringTool } from \"../core/IStringTool\"\r\n\r\n/**\r\n * Input for origin parser.\r\n * Supports static values or `random(...)` expressions.\r\n */\r\ninterface OriginInput {\r\n  /** Raw origin string, e.g. `'center'` or `'random(top, bottom)'`. */\r\n  value: string\r\n}\r\n\r\n/**\r\n * Tool that parses origin strings.\r\n * Allows static values like `'center'`, or expressions like `'random(...)'` to select one randomly.\r\n */\r\nexport default class OriginParserTool implements IStringTool<OriginInput, string> {\r\n  /**\r\n   * @returns Parsed string value (static or randomly chosen).\r\n   */\r\n  process({ value }: OriginInput): string {\r\n    const raw = value.trim()\r\n\r\n    if (raw.startsWith(\"random(\") && raw.endsWith(\")\")) {\r\n      const options = raw\r\n        .slice(7, -1)\r\n        .split(\",\")\r\n        .map((s) => s.trim())\r\n        .filter(Boolean)\r\n\r\n      const index = Math.floor(Math.random() * options.length)\r\n      return options[index]\r\n    }\r\n\r\n    return raw\r\n  }\r\n}\r\n","import { IStringTool } from \"../core/IStringTool\"\r\nimport { StringColor } from \"../models/color/StringColor\"\r\n\r\n/**\r\n * Input for parsing color strings into RGBA format.\r\n */\r\ninterface ColorParserInput {\r\n  /** Color string in hex, rgb[a], or hsl[a] format. */\r\n  value: string\r\n}\r\n\r\n/**\r\n * Parses a CSS color string (`#fff`, `rgb(...)`, `hsl(...)`, etc.)\r\n * into an object with `r`, `g`, `b`, `a` values.\r\n */\r\nexport default class ColorParserTool\r\n  implements IStringTool<ColorParserInput, StringColor>\r\n{\r\n  /**\r\n   * @returns RGBA object parsed from color string.\r\n   */\r\n  process({ value }: ColorParserInput): StringColor {\r\n    const str = value.trim().toLowerCase()\r\n\r\n    // --- HEX ---\r\n    if (str.startsWith(\"#\")) {\r\n      let hex = str.slice(1)\r\n\r\n      if (hex.length === 3) {\r\n        hex = hex.split(\"\").map((ch) => ch + ch).join(\"\")\r\n      }\r\n\r\n      const r = parseInt(hex.slice(0, 2), 16)\r\n      const g = parseInt(hex.slice(2, 4), 16)\r\n      const b = parseInt(hex.slice(4, 6), 16)\r\n      const a = hex.length === 8 ? parseInt(hex.slice(6, 8), 16) / 255 : 1\r\n\r\n      return { r, g, b, a }\r\n    }\r\n\r\n    // --- RGB / RGBA ---\r\n    const rgbMatch = str.match(/rgba?\\(([^)]+)\\)/)\r\n    if (rgbMatch) {\r\n      const [r, g, b, a = 1] = rgbMatch[1]\r\n        .split(\",\")\r\n        .map((v) => parseFloat(v.trim()))\r\n\r\n      return { r, g, b, a }\r\n    }\r\n\r\n    // --- HSL / HSLA ---\r\n    const hslMatch = str.match(/hsla?\\(([^)]+)\\)/)\r\n    if (hslMatch) {\r\n      const [h, s, l, a = \"1\"] = hslMatch[1].split(\",\").map((v) => v.trim())\r\n      const [r, g, b] = this.hslToRgb(parseFloat(h), parseFloat(s), parseFloat(l))\r\n      return { r, g, b, a: parseFloat(a) }\r\n    }\r\n\r\n    // fallback: transparent\r\n    return { r: 0, g: 0, b: 0, a: 0 }\r\n  }\r\n\r\n  private hslToRgb(h: number, s: string | number, l: string | number): [number, number, number] {\r\n    h = h / 360\r\n    s = parseFloat(s.toString()) / 100\r\n    l = parseFloat(l.toString()) / 100\r\n\r\n    const hue2rgb = (p: number, q: number, t: number) => {\r\n      if (t < 0) t += 1\r\n      if (t > 1) t -= 1\r\n      if (t < 1 / 6) return p + (q - p) * 6 * t\r\n      if (t < 1 / 2) return q\r\n      if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6\r\n      return p\r\n    }\r\n\r\n    const q = l < 0.5 ? l * (1 + s) : l + s - l * s\r\n    const p = 2 * l - q\r\n\r\n    const r = Math.round(hue2rgb(p, q, h + 1 / 3) * 255)\r\n    const g = Math.round(hue2rgb(p, q, h) * 255)\r\n    const b = Math.round(hue2rgb(p, q, h - 1 / 3) * 255)\r\n\r\n    return [r, g, b]\r\n  }\r\n}\r\n","import { IStringTool } from \"../core/IStringTool\"\r\n\r\ntype RuleType = \"required\" | \"email\" | \"minLength\" | \"maxLength\"\r\n\r\nexport type ValidationErrorCode =\r\n  | \"required\"\r\n  | \"invalid-email\"\r\n  | \"too-short\"\r\n  | \"too-long\"\r\n\r\nexport type ValidationRule =\r\n  | \"required\"\r\n  | \"email\"\r\n  | { type: \"minLength\"; value: number }\r\n  | { type: \"maxLength\"; value: number }\r\n\r\ninterface ValidationInput {\r\n  /** Value to validate. */\r\n  value: string\r\n\r\n  /** List of rules to apply. */\r\n  rules: ValidationRule[]\r\n\r\n  /**\r\n   * Optional message map: key = errorCode, value = string or function returning a message.\r\n   */\r\n  messages?: Partial<\r\n    Record<\r\n      ValidationErrorCode,\r\n      string | ((args: { value: string; rule: ValidationRule }) => string)\r\n    >\r\n  >\r\n}\r\n\r\nexport interface ValidationOutput {\r\n  /** `true` if valid, `false` if error found. */\r\n  valid: boolean\r\n\r\n  /** One of the known error codes (or null if no error). */\r\n  error: ValidationErrorCode | null\r\n\r\n  /** Final message (either default or user-defined). */\r\n  message: string | null\r\n}\r\n\r\n/**\r\n * Tool for validating strings using rules like `required`, `minLength`, etc.\r\n * Allows custom error messages (as string or generator function).\r\n */\r\nexport default class ValidationTool implements IStringTool<ValidationInput, ValidationOutput> {\r\n  /**\r\n   * Validates input value and returns error code + message.\r\n   */\r\n  process({ value, rules, messages = {} }: ValidationInput): ValidationOutput {\r\n    for (const rule of rules) {\r\n      let code: ValidationErrorCode | null = null\r\n\r\n      if (rule === \"required\" && value.trim() === \"\") {\r\n        code = \"required\"\r\n      } else if (rule === \"email\" && !/^\\S+@\\S+\\.\\S+$/.test(value)) {\r\n        code = \"invalid-email\"\r\n      } else if (typeof rule === \"object\") {\r\n        if (rule.type === \"minLength\" && value.length < rule.value) code = \"too-short\"\r\n        if (rule.type === \"maxLength\" && value.length > rule.value) code = \"too-long\"\r\n      }\r\n\r\n      if (code) {\r\n        const raw = messages[code]\r\n        const message =\r\n          typeof raw === \"function\" ? raw({ value, rule }) : raw ?? this.defaultMessage(code, rule)\r\n        return { valid: false, error: code, message }\r\n      }\r\n    }\r\n\r\n    return { valid: true, error: null, message: null }\r\n  }\r\n\r\n  private defaultMessage(code: ValidationErrorCode, rule?: ValidationRule): string {\r\n    switch (code) {\r\n      case \"required\":\r\n        return \"This field is required.\"\r\n      case \"invalid-email\":\r\n        return \"Please enter a valid email.\"\r\n      case \"too-short\":\r\n        return `Too short${typeof rule === \"object\" && \"value\" in rule ? ` (min ${rule.value})` : \"\"}.`\r\n      case \"too-long\":\r\n        return `Too long${typeof rule === \"object\" && \"value\" in rule ? ` (max ${rule.value})` : \"\"}.`\r\n    }\r\n  }\r\n}\r\n","import { IStringTool } from \"../core/IStringTool\"\r\n\r\n/**\r\n * Input parameters for EasingFunctionTool.\r\n */\r\ninterface EasingFunctionInput {\r\n  /**\r\n   * The easing string.\r\n   * Can be: 'linear', 'ease', 'ease-in', 'ease-out', 'ease-in-out', or 'cubic-bezier(...)'\r\n   */\r\n  easing: string\r\n}\r\n\r\n/**\r\n * Output of the easing function: receives t in [0,1] and returns eased value.\r\n */\r\nexport type EasingFunctionOutput = (t: number) => number\r\n\r\n/**\r\n * Tool for parsing easing strings into easing functions.\r\n * Supports standard keywords (`ease-in`, `ease-out`, etc.) and `cubic-bezier(...)` expressions.\r\n */\r\nexport default class EasingFunctionTool implements IStringTool<EasingFunctionInput, EasingFunctionOutput> {\r\n  private namedCurves: Record<string, [number, number, number, number]> = {\r\n    \"linear\": [0, 0, 1, 1],\r\n    \"ease\": [0.25, 0.1, 0.25, 1],\r\n    \"ease-in\": [0.42, 0, 1, 1],\r\n    \"ease-out\": [0, 0, 0.58, 1],\r\n    \"ease-in-out\": [0.42, 0, 0.58, 1],\r\n  }\r\n\r\n  /**\r\n   * Parses an easing string and returns a corresponding easing function.\r\n   */\r\n  process({ easing }: EasingFunctionInput): EasingFunctionOutput {\r\n    const def = easing.trim()\r\n\r\n    if (this.namedCurves[def]) {\r\n      return this.cubicBezier(...this.namedCurves[def])\r\n    }\r\n\r\n    const match = def.match(/^cubic-bezier\\s*\\(\\s*([-+]?\\d*\\.?\\d+)\\s*,\\s*([-+]?\\d*\\.?\\d+)\\s*,\\s*([-+]?\\d*\\.?\\d+)\\s*,\\s*([-+]?\\d*\\.?\\d+)\\s*\\)$/);\r\n\r\n    if (match) {\r\n      const [x1, y1, x2, y2] = match.slice(1).map(Number)\r\n      return this.cubicBezier(x1, y1, x2, y2)\r\n    }\r\n\r\n    // fallback: linear\r\n    return (t: number) => t\r\n  }\r\n\r\n  /**\r\n   * Generates a cubic-bezier easing function.\r\n   * Ported from https://github.com/gre/bezier-easing (MIT)\r\n   */\r\n  private cubicBezier(x1: number, y1: number, x2: number, y2: number): EasingFunctionOutput {\r\n    const cx = 3 * x1\r\n    const bx = 3 * (x2 - x1) - cx\r\n    const ax = 1 - cx - bx\r\n\r\n    const cy = 3 * y1\r\n    const by = 3 * (y2 - y1) - cy\r\n    const ay = 1 - cy - by\r\n\r\n    function sampleCurveX(t: number) {\r\n      return ((ax * t + bx) * t + cx) * t\r\n    }\r\n\r\n    function sampleCurveY(t: number) {\r\n      return ((ay * t + by) * t + cy) * t\r\n    }\r\n\r\n    function sampleCurveDerivativeX(t: number) {\r\n      return (3 * ax * t + 2 * bx) * t + cx\r\n    }\r\n\r\n    function solveCurveX(x: number, epsilon = 1e-5) {\r\n      let t0, t1, t2 = x, x2, d2, i\r\n\r\n      // Newton-Raphson method\r\n      for (i = 0; i < 8; i++) {\r\n        x2 = sampleCurveX(t2) - x\r\n        if (Math.abs(x2) < epsilon) return t2\r\n        d2 = sampleCurveDerivativeX(t2)\r\n        if (Math.abs(d2) < 1e-6) break\r\n        t2 = t2 - x2 / d2\r\n      }\r\n\r\n      // Bisection fallback\r\n      t0 = 0\r\n      t1 = 1\r\n      t2 = x\r\n\r\n      while (t0 < t1) {\r\n        x2 = sampleCurveX(t2) - x\r\n        if (Math.abs(x2) < epsilon) return t2\r\n        if (x2 > 0) t1 = t2\r\n        else t0 = t2\r\n        t2 = (t1 + t0) / 2\r\n      }\r\n\r\n      return t2\r\n    }\r\n\r\n    return function (x: number) {\r\n      return sampleCurveY(solveCurveX(x))\r\n    }\r\n  }\r\n}\r\n","import { IStringTool } from \"../core/IStringTool\"\r\n\r\n/**\r\n * Input parameters for calculating magnetic pull factor.\r\n */\r\ninterface MagneticPullInput {\r\n  /** Distance between pointer and element center (px). */\r\n  distance: number\r\n\r\n  /** Max distance within which magnetic pull is active. */\r\n  radius: number\r\n\r\n  /** Strength of the magnetic pull (0–1 recommended). */\r\n  strength: number\r\n}\r\n\r\n/**\r\n * Output: factor to multiply by direction vector (dx/dy) to get magnetic offset.\r\n */\r\ntype MagneticPullOutput = number\r\n\r\n/**\r\n * Tool for calculating magnetic attraction based on distance to element.\r\n * Returns a scalar value (0..strength) depending on proximity.\r\n */\r\nexport default class MagneticPullTool implements IStringTool<MagneticPullInput, MagneticPullOutput> {\r\n  /**\r\n   * Returns a pull factor based on distance to target within a radius.\r\n   * @param input - Magnetic pull parameters.\r\n   * @returns A multiplier (typically < 1) to apply to dx/dy.\r\n   */\r\n  process({ distance, radius, strength }: MagneticPullInput): number {\r\n    if (distance >= radius) return 0\r\n    const proximity = (radius - distance) / radius // 1 when close, 0 at edge\r\n    return strength * proximity\r\n  }\r\n}\r\n","import { IStringTool } from \"../core/IStringTool\"\r\nimport { StringColor } from \"../models/color/StringColor\"\r\n\r\n/**\r\n * Input parameters for `LerpColorTool`.\r\n */\r\ninterface LerpColorInput {\r\n  /**\r\n   * Starting color as an object `{ r, g, b, a }` where each value is in the range `0–1`.\r\n   */\r\n  from: StringColor\r\n\r\n  /**\r\n   * Target color as an object `{ r, g, b, a }` where each value is in the range `0–1`.\r\n   */\r\n  to: StringColor\r\n\r\n  /**\r\n   * Interpolation progress from `0` (start) to `1` (end).\r\n   */\r\n  progress: number\r\n}\r\n\r\n/**\r\n * Tool for linearly interpolating between two RGBA colors using `StringColor` format.\r\n * Each channel (`r`, `g`, `b`, `a`) is interpolated independently.\r\n * Returns a new `StringColor` with the interpolated values.\r\n */\r\nexport default class LerpColorTool implements IStringTool<LerpColorInput, StringColor> {\r\n  /**\r\n   * Performs linear interpolation between two `StringColor` values.\r\n   *\r\n   * @param input.from - The starting color `{ r, g, b, a }`.\r\n   * @param input.to - The target color `{ r, g, b, a }`.\r\n   * @param input.progress - A number from `0` to `1` indicating interpolation progress.\r\n   * @returns Interpolated color as a new `StringColor`.\r\n   */\r\n  process({ from, to, progress }: LerpColorInput): StringColor {\r\n    return {\r\n      r: from.r + (to.r - from.r) * progress,\r\n      g: from.g + (to.g - from.g) * progress,\r\n      b: from.b + (to.b - from.b) * progress,\r\n      a: from.a + (to.a - from.a) * progress,\r\n    }\r\n  }\r\n}\r\n","import { IStringTool } from \"../core/IStringTool\"\r\nimport { StringVector } from \"../models/vector/StringVector\"\r\n\r\n/**\r\n * Input parameters for LerpVector2Tool.\r\n */\r\ninterface LerpVector2Input {\r\n  /**\r\n   * Starting vector value `{ x, y }`.\r\n   */\r\n  from: StringVector\r\n\r\n  /**\r\n   * Target vector value `{ x, y }`.\r\n   */\r\n  to: StringVector\r\n\r\n  /**\r\n   * Interpolation progress from `0` (start) to `1` (end).\r\n   */\r\n  progress: number\r\n}\r\n\r\n/**\r\n * Tool for linearly interpolating between two 2D vectors.\r\n * Useful for cursor smoothing, UI element animations, and motion blending.\r\n */\r\nexport default class LerpVector2Tool implements IStringTool<LerpVector2Input, StringVector> {\r\n  /**\r\n   * Calculates the interpolated vector between `from` and `to`.\r\n   *\r\n   * @param input.from - The starting vector `{ x, y }`.\r\n   * @param input.to - The target vector `{ x, y }`.\r\n   * @param input.progress - Interpolation progress from `0` (start) to `1` (end).\r\n   * @returns Interpolated vector `{ x, y }`.\r\n   */\r\n  process({ from, to, progress }: LerpVector2Input): { x: number, y: number } {\r\n    return {\r\n      x: (to.x - from.x) * progress,\r\n      y: (to.y - from.y) * progress,\r\n    }\r\n  }\r\n}\r\n\r\n","import { IStringTool } from \"../core/IStringTool\"; // Переконайтесь, що шлях правильний\r\n\r\n/**\r\n * Input for parsing the transform string to extract scale.\r\n */\r\ninterface TransformParserInput {\r\n  /** CSS transform string (e.g., \"matrix(0.5, 0, 0, 0.5, 10, 20)\", \"scale(0.5)\", \"none\"). */\r\n  value: string;\r\n}\r\n\r\n/**\r\n * Parses a CSS transform string to extract the primary scale factor.\r\n * Assumes uniform scale or extracts the X-axis scale factor from matrix/scale functions.\r\n */\r\nexport default class TransformScaleParserTool\r\n  implements IStringTool<TransformParserInput, number> // Output is a number\r\n{\r\n  /**\r\n   * Processes the transform string and extracts the scale factor.\r\n   * @returns Numeric scale factor (defaults to 1 if no scale transform is found or parsing fails).\r\n   */\r\n  process({ value }: TransformParserInput): number {\r\n    const defaultScale = 1;\r\n    const str = value?.trim();\r\n\r\n    if (!str || str === 'none') {\r\n      return defaultScale;\r\n    }\r\n    try {\r\n      if (str.startsWith('matrix(')) {\r\n        const matrixValues = str.match(/matrix\\(([^)]+)\\)/);\r\n        if (matrixValues && matrixValues[1]) {\r\n          const matrixNumbers = matrixValues[1].split(',').map(s => parseFloat(s.trim()));\r\n          if (matrixNumbers.length >= 1 && !isNaN(matrixNumbers[0])) {\r\n            return matrixNumbers[0];\r\n          }\r\n        }\r\n      }\r\n\r\n      if (str.startsWith('scale(')) {\r\n        const scaleValue = str.match(/scale\\(([^)]+)\\)/);\r\n        if (scaleValue && scaleValue[1]) {\r\n          const scaleNumbers = scaleValue[1].split(',').map(s => parseFloat(s.trim()));\r\n          if (scaleNumbers.length >= 1 && !isNaN(scaleNumbers[0])) {\r\n            return scaleNumbers[0];\r\n          }\r\n        }\r\n      }\r\n\r\n       if (str.startsWith('scaleX(')) {\r\n        const scaleXValue = str.match(/scaleX\\(([^)]+)\\)/);\r\n        if (scaleXValue && scaleXValue[1]) {\r\n          const scaleNumber = parseFloat(scaleXValue[1].trim());\r\n          if (!isNaN(scaleNumber)) {\r\n            return scaleNumber;\r\n          }\r\n        }\r\n      }\r\n\r\n       if (str.startsWith('scale3d(')) {\r\n         const scale3dValue = str.match(/scale3d\\(([^)]+)\\)/);\r\n         if (scale3dValue && scale3dValue[1]) {\r\n             const scaleNumbers = scale3dValue[1].split(',').map(s => parseFloat(s.trim()));\r\n             if (scaleNumbers.length >= 1 && !isNaN(scaleNumbers[0])) {\r\n                 return scaleNumbers[0]; // Повертаємо sx\r\n             }\r\n         }\r\n       }\r\n\r\n       if (str.startsWith('matrix3d(')) {\r\n           const matrix3dValues = str.match(/matrix3d\\(([^)]+)\\)/);\r\n           if (matrix3dValues && matrix3dValues[1]) {\r\n               const matrixNumbers = matrix3dValues[1].split(',').map(s => parseFloat(s.trim()));\r\n               if (matrixNumbers.length >= 1 && !isNaN(matrixNumbers[0])) {\r\n                   return matrixNumbers[0];\r\n               }\r\n           }\r\n       }\r\n\r\n    } catch (error) {\r\n      console.error(`Error parsing transform string \"${str}\":`, error);\r\n      return defaultScale;\r\n    }\r\n\r\n    return defaultScale;\r\n  }\r\n}\r\n","import { IStringTool } from \"../core/IStringTool\";\r\nimport { CalculatedValue } from \"../models/text/CalculatedValue\";\r\nimport { CharIndexerInput } from \"../models/text/CharIndexerInput\";\r\nimport { ISplitOptionItem } from \"../models/text/ISplitOptionItem\";\r\nimport { ProcessedChar } from \"../models/text/ProcessedChar\";\r\n\r\n/**\r\n * Tool to process words split by layout, breaking them into characters\r\n * and assigning relevant indices (global, line, word) for each character.\r\n * Calculates index values based on ISplitOptions for characters ('char', 'charLine', 'charWord').\r\n * Produces an array of ProcessedChar objects.\r\n */\r\nexport class CharIndexerTool implements IStringTool<CharIndexerInput, ProcessedChar[]> {\r\n\r\n  /**\r\n   * Iterates through processed words, splits them into characters, assigns\r\n   * global, line, and word character indices, and calculates index values\r\n   * based on the provided character options ('char', 'charLine', 'charWord').\r\n   *\r\n   * @param input.processedWords - Array of ProcessedWord objects from WordIndexerTool.\r\n   * @param input.lines - Array of LayoutLine objects (needed for calculating total characters per line).\r\n   * @param input.options - The relevant ISplitOptions ('char', 'charLine', 'charWord').\r\n   * @param input.totalChars - Total number of non-whitespace characters in the original text.\r\n   * @returns An array of ProcessedChar objects, ready for DOM building/styling.\r\n   */\r\n  process({ processedWords, lines, options, totalChars }: CharIndexerInput): ProcessedChar[] {\r\n    const processedChars: ProcessedChar[] = [];\r\n    let globalCharIndex = 0; // Global character counter (non-whitespace)\r\n\r\n    // Pre-calculate total characters per line for efficiency\r\n    const totalLineCharsMap = new Map<number, number>();\r\n    lines.forEach((line, lineIndex) => {\r\n        const totalCharsInLine = line.words.reduce((sum, word) => sum + word.text.length, 0);\r\n        totalLineCharsMap.set(lineIndex, totalCharsInLine);\r\n    });\r\n\r\n    let currentLineCharIndex = 0; // Character index within the current line\r\n    let previousLineIndex = -1;   // Tracks when we move to a new line\r\n\r\n    // Iterate through the processed words provided as input\r\n    processedWords.forEach(pWord => {\r\n      const wordText = pWord.text;\r\n      const parentLineIndex = pWord.lineIndex;\r\n      const wordLength = wordText.length; // Number of characters in the current word\r\n      const totalCharsInCurrentLine = totalLineCharsMap.get(parentLineIndex) || 0; // Get pre-calculated total\r\n\r\n      // Reset line character index when moving to a new line\r\n      if (parentLineIndex !== previousLineIndex) {\r\n        currentLineCharIndex = 0;\r\n        previousLineIndex = parentLineIndex;\r\n      }\r\n\r\n      const chars = Array.from(wordText); // Split word into characters (handles Unicode correctly)\r\n\r\n      // Iterate through each character of the word\r\n      chars.forEach((char, wordCharIndex) => {\r\n        const calculatedValues: CalculatedValue[] = []; // Use the unified CalculatedValue\r\n\r\n        // 1. Calculate for 'char' options (global context)\r\n        if (options.char) {\r\n          options.char.forEach(optDef => {\r\n             // Use globalCharIndex as primary, totalChars as parentLength\r\n            const value = this.calculateIndex(optDef, globalCharIndex, wordCharIndex, totalChars);\r\n            // Create CalculatedValue object\r\n            calculatedValues.push({ value, type: 'char', align: optDef.align });\r\n          });\r\n        }\r\n\r\n        // 2. Calculate for 'charLine' options (line context)\r\n        if (options.charLine) {\r\n          options.charLine.forEach(optDef => {\r\n             // Use currentLineCharIndex as primary, totalCharsInCurrentLine as parentLength\r\n            const value = this.calculateIndex(optDef, currentLineCharIndex, wordCharIndex, totalCharsInCurrentLine);\r\n             // Create CalculatedValue object\r\n            calculatedValues.push({ value, type: 'charLine', align: optDef.align });\r\n          });\r\n        }\r\n\r\n        // 3. Calculate for 'charWord' options (word context)\r\n        if (options.charWord) {\r\n          options.charWord.forEach(optDef => {\r\n             // Use wordCharIndex as primary, wordLength as parentLength\r\n            const value = this.calculateIndex(optDef, wordCharIndex, wordCharIndex, wordLength);\r\n             // Create CalculatedValue object\r\n            calculatedValues.push({ value, type: 'charWord', align: optDef.align });\r\n          });\r\n        }\r\n\r\n        // Create the ProcessedChar object\r\n        processedChars.push({\r\n          text: char,\r\n          globalCharIndex: globalCharIndex,\r\n          lineCharIndex: currentLineCharIndex,\r\n          wordCharIndex: wordCharIndex,\r\n          parentGlobalWordIndex: pWord.globalIndex, // Carry over parent info\r\n          parentLineIndex: pWord.lineIndex,\r\n          parentWordIndexInLine: pWord.wordIndexInLine,\r\n          calculatedValues: calculatedValues // Store the array of CalculatedValue\r\n        });\r\n\r\n        // Increment character counters for the next iteration\r\n        globalCharIndex++;\r\n        currentLineCharIndex++;\r\n      }); // end character loop\r\n    }); // end word loop\r\n\r\n    return processedChars;\r\n  }\r\n\r\n  /**\r\n   * Calculates the final numerical index value based on alignment options, context indices, and parent length.\r\n   * (Identical helper function as in WordIndexerTool - could be extracted to a common utility).\r\n   *\r\n   * @param option - The specific option item definition ({ align, random, abs }).\r\n   * @param primaryIndex - The main index used for calculation (global, line, or word char index).\r\n   * @param localIndex - The secondary index (e.g., index within word).\r\n   * @param parentLength - The total count in the relevant context (total chars, line chars, or word chars).\r\n   * @returns The calculated numerical index value.\r\n   */\r\n   private calculateIndex(\r\n     option: ISplitOptionItem,\r\n     primaryIndex: number,\r\n     localIndex: number,\r\n     parentLength: number\r\n   ): number {\r\n      let index = primaryIndex;\r\n\r\n     if (option.align === 'random') {\r\n       const min = option.random?.min ?? 0;\r\n       const max = option.random?.max ?? (parentLength > 0 ? parentLength - 1 : 0);\r\n       const effectiveMin = Math.min(min, max);\r\n       const effectiveMax = Math.max(min, max);\r\n       index = Math.floor(Math.random() * (effectiveMax - effectiveMin + 1)) + effectiveMin;\r\n     } else if (option.align === 'end') {\r\n        index = (parentLength > 0 ? parentLength - 1 : 0) - primaryIndex;\r\n     } else if (option.align === 'center') {\r\n        index = primaryIndex - Math.floor(parentLength / 2);\r\n     }\r\n\r\n     if (option.abs) {\r\n       index = Math.abs(index);\r\n     }\r\n     return index;\r\n   }\r\n}","import { IStringTool } from \"../core/IStringTool\";\r\nimport { LayoutLine } from \"../models/text/LayoutLine\";\r\nimport { LayoutSplitInput } from \"../models/text/LayoutSplitInput\";\r\n\r\n/**\r\n * Tool to split a text string into structured lines and words based on how\r\n * the text would visually wrap within a given target HTML element.\r\n * This simulates browser rendering by measuring word widths.\r\n * Returns an array of LayoutLine objects.\r\n */\r\nexport class LayoutLineSplitterTool\r\n  implements IStringTool<LayoutSplitInput, LayoutLine[]>\r\n{\r\n  /**\r\n   * Processes the input text and splits it into lines containing words,\r\n   * simulating word wrapping within the boundaries of the targetElement.\r\n   *\r\n   * @param input.text - The text content to split.\r\n   * @param input.targetElement - The HTMLElement used as a reference for width and font styles.\r\n   * @returns An array of LayoutLine objects, each containing the line's text and an array of its words.\r\n   * Returns an empty array on error or invalid input.\r\n   */\r\n  process({ text, targetElement }: LayoutSplitInput): LayoutLine[] {\r\n    if (!text || !targetElement || targetElement.offsetWidth <= 0) {\r\n      console.warn(\r\n        \"LayoutLineSplitterTool: Invalid input or target element has zero width.\"\r\n      );\r\n      return [];\r\n    }\r\n\r\n    const cleanedText = this.decodeHtmlEntity(text);\r\n    // Split by whitespace and filter out empty strings that might result from multiple spaces\r\n    const words = cleanedText\r\n      .trim()\r\n      .split(/\\s+/)\r\n      .filter((word) => word.length > 0);\r\n\r\n    if (words.length === 0) {\r\n      return []; // No words to process\r\n    }\r\n\r\n    // Create and configure the temporary span for measurements\r\n    const tempSpan = document.createElement(\"span\");\r\n    const compStyles = window.getComputedStyle(targetElement);\r\n    // Copy relevant styles that affect width\r\n    tempSpan.style.fontFamily = compStyles.fontFamily;\r\n    tempSpan.style.fontSize = compStyles.fontSize;\r\n    tempSpan.style.fontWeight = compStyles.fontWeight;\r\n    tempSpan.style.letterSpacing = compStyles.letterSpacing;\r\n    tempSpan.style.textTransform = compStyles.textTransform;\r\n    tempSpan.style.wordSpacing = compStyles.wordSpacing;\r\n    // Ensure the measurement span itself doesn't wrap and is hidden\r\n    tempSpan.style.whiteSpace = \"nowrap\";\r\n    tempSpan.style.visibility = \"hidden\";\r\n    tempSpan.style.position = \"absolute\"; // Prevent affecting layout\r\n    tempSpan.style.top = \"-9999px\";\r\n    tempSpan.style.left = \"-9999px\";\r\n    document.body.appendChild(tempSpan); // Must be in DOM for offsetWidth\r\n\r\n    const layoutLines: LayoutLine[] = [];\r\n    let currentLineWords: string[] = []; // Accumulates words for the current line\r\n    let currentLineWidth = 0; // Tracks the width of the current line\r\n    const spaceWidth = this.measureWidth(\" \", tempSpan); // Measure space width once\r\n    const containerWidth = targetElement.offsetWidth; // Target width for wrapping\r\n\r\n    try {\r\n      words.forEach((word) => {\r\n        const wordWidth = this.measureWidth(word, tempSpan);\r\n        // Calculate width if this word is added: current width + space (if needed) + word width\r\n        const potentialWidth =\r\n          currentLineWidth +\r\n          (currentLineWords.length > 0 ? spaceWidth : 0) +\r\n          wordWidth;\r\n\r\n        // Check if the word fits on the current line\r\n        if (currentLineWords.length > 0 && potentialWidth > containerWidth) {\r\n          // Word doesn't fit: finalize the current line\r\n          layoutLines.push({\r\n            text: currentLineWords.join(\" \"),\r\n            words: currentLineWords.map((w) => ({ text: w })), // Convert word strings to LayoutWord objects\r\n          });\r\n          // Start a new line with the current word\r\n          currentLineWords = [word];\r\n          currentLineWidth = wordWidth;\r\n        } else {\r\n          // Word fits: add it to the current line\r\n          currentLineWords.push(word);\r\n          // Update the current line width\r\n          currentLineWidth =\r\n            currentLineWords.length === 1 ? wordWidth : potentialWidth;\r\n        }\r\n      });\r\n\r\n      // Add the last remaining line after the loop finishes\r\n      if (currentLineWords.length > 0) {\r\n        layoutLines.push({\r\n          text: currentLineWords.join(\" \"),\r\n          words: currentLineWords.map((w) => ({ text: w })),\r\n        });\r\n      }\r\n    } finally {\r\n      // Ensure the temporary span is removed from the DOM\r\n      if (tempSpan.parentNode === document.body) {\r\n        document.body.removeChild(tempSpan);\r\n      }\r\n    }\r\n\r\n    return layoutLines;\r\n  }\r\n\r\n  /**\r\n   * Measures the width of a given text string using the provided temporary span.\r\n   * @param text - The text to measure.\r\n   * @param tempSpan - The pre-styled temporary span element used for measurement.\r\n   * @returns The width of the text in pixels.\r\n   */\r\n  private measureWidth(text: string, tempSpan: HTMLSpanElement): number {\r\n    tempSpan.textContent = text;\r\n    return tempSpan.offsetWidth;\r\n  }\r\n\r\n  /**\r\n   * Decodes basic HTML entities (currently just &amp;).\r\n   * Can be expanded if more entities need handling.\r\n   * @param str - The string potentially containing HTML entities.\r\n   * @returns The string with '&amp;' decoded to '&'.\r\n   */\r\n  private decodeHtmlEntity(str: string): string {\r\n    // Basic decoding, extend as needed\r\n    return str.replace(/&amp;/g, \"&\");\r\n  }\r\n}\r\n","import { IStringTool } from \"../core/IStringTool\";\r\nimport { CalculatedValue } from \"../models/text/CalculatedValue\";\r\nimport { DomBuilderInput } from \"../models/text/DomBuilderInput\";\r\nimport { ISplitOptions } from \"../models/text/ISplitOptions\";\r\nimport { LayoutLine } from \"../models/text/LayoutLine\"; // Assuming LayoutLine might be needed for line styles\r\nimport { ProcessedChar } from \"../models/text/ProcessedChar\"; // Assuming ProcessedChar structure\r\nimport { ProcessedWord } from \"../models/text/ProcessedWord\"; // Assuming ProcessedWord structure\r\n\r\n/**\r\n * Tool to build the final innerHTML string with nested spans (-s-line, -s-word, -s-char)\r\n * and apply calculated CSS variables based on processed data from indexer tools.\r\n * Implements the IStringTool interface.\r\n */\r\nexport class SplitDomBuilderTool\r\n  implements IStringTool<DomBuilderInput, string>\r\n{\r\n  /**\r\n   * Generates the innerHTML string for the split text by creating nested spans\r\n   * (-s-line, -s-word, -s-char) based on options and applying styles from calculated index values.\r\n   *\r\n   * @param input An object containing layout lines, processed words, processed characters, and the original split options.\r\n   * @returns The generated HTML string representing the split content.\r\n   */\r\n  process({ lines, words, chars, options }: DomBuilderInput): string {\r\n    const rootElement = document.createElement(\"div\");\r\n    let wordCounter = 0;\r\n    let charCounter = 0;\r\n\r\n    const needsLineSpans = this.hasLineOptions(options);\r\n    const needsWordSpans = this.hasWordOptions(options);\r\n    const needsCharSpans = this.hasCharOptions(options);\r\n\r\n    lines.forEach((line, lineIndex) => {\r\n      // Added lineIndex for potential line style application\r\n      const lineContainer = needsLineSpans\r\n        ? document.createElement(\"span\")\r\n        : rootElement;\r\n      if (needsLineSpans) {\r\n        lineContainer.classList.add(\"-s-line\");\r\n        // TODO: Apply 'line' options if available on line object\r\n        // this.applyStyles(lineContainer, line.calculatedValues);\r\n        rootElement.appendChild(lineContainer);\r\n      }\r\n\r\n      const wordsInThisLine = words.slice(\r\n        wordCounter,\r\n        wordCounter + line.words.length\r\n      );\r\n      wordCounter += line.words.length;\r\n\r\n      wordsInThisLine.forEach((pWord, indexInLine) => {\r\n        const currentWordChars = chars.slice(\r\n          charCounter,\r\n          charCounter + pWord.text.length\r\n        );\r\n        // Advance charCounter regardless of how chars are added below\r\n        charCounter += pWord.text.length;\r\n\r\n        if (needsWordSpans) {\r\n          // --- Create Word Span ---\r\n          const wordSpan = document.createElement(\"span\");\r\n          wordSpan.classList.add(\"-s-word\");\r\n          this.applyStyles(wordSpan, pWord.calculatedValues);\r\n\r\n          if (needsCharSpans && pWord.text.length > 0) {\r\n            // Add char spans inside word span\r\n            currentWordChars.forEach((pChar) => {\r\n              const charSpan = this.createCharSpan(pChar);\r\n              wordSpan.appendChild(charSpan);\r\n            });\r\n          } else if (pWord.text.length > 0) {\r\n            // Add word text directly if no char spans needed\r\n            wordSpan.appendChild(document.createTextNode(pWord.text));\r\n          }\r\n          // Append the completed word span to the line container\r\n          lineContainer.appendChild(wordSpan);\r\n        } else {\r\n          // --- No Word Span Needed ---\r\n          if (needsCharSpans && pWord.text.length > 0) {\r\n            // Add char spans directly to line container\r\n            currentWordChars.forEach((pChar) => {\r\n              const charSpan = this.createCharSpan(pChar);\r\n              lineContainer.appendChild(charSpan);\r\n            });\r\n          } else if (pWord.text.length > 0) {\r\n            // Add word text directly to line container\r\n            lineContainer.appendChild(document.createTextNode(pWord.text));\r\n          }\r\n        }\r\n\r\n        // Add spacing after word/chars if not the last word in the line\r\n        if (\r\n          indexInLine < wordsInThisLine.length - 1 ||\r\n          needsLineSpans == false\r\n        ) {\r\n          lineContainer.appendChild(document.createTextNode(\"\\u00a0\")); // Non-breaking space\r\n        }\r\n      }); // End words loop\r\n    }); // End lines loop\r\n\r\n    return rootElement.innerHTML;\r\n  }\r\n\r\n  /**\r\n   * Creates and styles a character span.\r\n   * @param pChar - The processed character data.\r\n   * @returns The styled HTMLSpanElement for the character.\r\n   * @private\r\n   */\r\n  private createCharSpan(pChar: ProcessedChar): HTMLSpanElement {\r\n    const charSpan = document.createElement(\"span\");\r\n    charSpan.classList.add(\"-s-char\");\r\n    // Handle potential whitespace characters if needed, otherwise use textContent\r\n    charSpan.textContent = pChar.text; // Use textContent for safety\r\n    this.applyStyles(charSpan, pChar.calculatedValues);\r\n    return charSpan;\r\n  }\r\n\r\n  /**\r\n   * Checks if any line-level splitting options (line, wordLine, charLine) are present.\r\n   * @param options - The ISplitOptions object.\r\n   * @returns True if any line-level options exist and have definitions, false otherwise.\r\n   * @private\r\n   */\r\n  private hasLineOptions(options: ISplitOptions): boolean {\r\n    return (\r\n      (options.line?.length ?? 0) > 0 ||\r\n      (options.wordLine?.length ?? 0) > 0 ||\r\n      (options.charLine?.length ?? 0) > 0\r\n    );\r\n  }\r\n\r\n  /**\r\n   * Checks if any word-level splitting options (word, wordLine) are present.\r\n   * @param options - The ISplitOptions object.\r\n   * @returns True if any word-level options exist and have definitions, false otherwise.\r\n   * @private\r\n   */\r\n  private hasWordOptions(options: ISplitOptions): boolean {\r\n    return (\r\n      (options.word?.length ?? 0) > 0 || (options.wordLine?.length ?? 0) > 0\r\n    );\r\n  }\r\n\r\n  /**\r\n   * Checks if any character-level splitting options (char, charLine, charWord) are present.\r\n   * @param options - The ISplitOptions object.\r\n   * @returns True if any character-level options exist and have definitions, false otherwise.\r\n   * @private\r\n   */\r\n  private hasCharOptions(options: ISplitOptions): boolean {\r\n    return (\r\n      (options.char?.length ?? 0) > 0 ||\r\n      (options.charLine?.length ?? 0) > 0 ||\r\n      (options.charWord?.length ?? 0) > 0\r\n    );\r\n  }\r\n\r\n  /**\r\n   * Applies the pre-calculated index values as CSS custom properties to the element's style.\r\n   * @param span - The HTMLElement (line, word, or char span) to apply styles to.\r\n   * @param calculatedValues - An array of calculated values from the indexer tool.\r\n   * @private\r\n   */\r\n  private applyStyles(\r\n    span: HTMLElement,\r\n    calculatedValues: CalculatedValue[]\r\n  ): void {\r\n    if (calculatedValues) {\r\n      calculatedValues.forEach((calcValue) => {\r\n        const variableName = this.generateVariableName(\r\n          calcValue.type,\r\n          calcValue.align\r\n        );\r\n        span.style.setProperty(variableName, String(calcValue.value));\r\n      });\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Generates a CSS custom property name based on the split type and alignment.\r\n   * @param type - The type of split element ('line', 'word', 'char', etc.).\r\n   * @param align - The alignment option ('start', 'center', 'end', 'random').\r\n   * @returns The generated CSS variable name string (e.g., '--word-center').\r\n   * @private\r\n   */\r\n  private generateVariableName(type: string, align: string): string {\r\n    // This simplified version assumes one variable per type/align combo.\r\n    // More complex logic might be needed if multiple definitions require distinct variables.\r\n    return `--${type}-${align}`;\r\n  }\r\n}\r\n","import { IStringTool } from \"../core/IStringTool\";\r\nimport { CalculatedValue } from \"../models/text/CalculatedValue\";\r\nimport { ISplitOptionItem } from \"../models/text/ISplitOptionItem\";\r\nimport { ProcessedWord } from \"../models/text/ProcessedWord\";\r\nimport { WordIndexerInput } from \"../models/text/WordIndexerInput\";\r\n\r\n/**\r\n * Tool to process layout lines and words, assigning relevant indices\r\n * and calculating index values based on ISplitOptions ('word', 'wordLine').\r\n * Produces an array of ProcessedWord objects.\r\n */\r\nexport class WordIndexerTool\r\n  implements IStringTool<WordIndexerInput, ProcessedWord[]>\r\n{\r\n  /**\r\n   * Iterates through lines and words, assigning global and local indices,\r\n   * and calculating index values based on the provided options ('word', 'wordLine').\r\n   *\r\n   * @param input.lines - Array of LayoutLine objects from LayoutLineSplitterTool.\r\n   * @param input.options - The relevant ISplitOptions ('word', 'wordLine').\r\n   * @returns An array of ProcessedWord objects, each containing word text, indices,\r\n   * and an array of calculated values based on options.\r\n   */\r\n  process({ lines, options }: WordIndexerInput): ProcessedWord[] {\r\n    const processedWords: ProcessedWord[] = [];\r\n    let globalWordIndex = 0;\r\n    // Calculate total words once if needed by calculateIndex, though current logic uses parentLength dynamically\r\n    const totalWords = lines.reduce((sum, line) => sum + line.words.length, 0);\r\n\r\n    lines.forEach((line, lineIndex) => {\r\n      const wordsInLine = line.words;\r\n      const lineWordCount = wordsInLine.length; // Number of words in the current line\r\n\r\n      wordsInLine.forEach((word, wordIndexInLine) => {\r\n        const calculatedValues: CalculatedValue[] = []; // Use the unified CalculatedValue\r\n\r\n        // 1. Calculate for 'word' options (global context)\r\n        if (options.word && options.word.length > 0) {\r\n          options.word.forEach((optDef) => {\r\n            // Use globalWordIndex as primary, totalWords as parentLength\r\n            const value = this.calculateIndex(\r\n              optDef,\r\n              globalWordIndex,\r\n              wordIndexInLine,\r\n              totalWords\r\n            );\r\n            // Create CalculatedValue object\r\n            calculatedValues.push({ value, type: \"word\", align: optDef.align });\r\n          });\r\n        }\r\n\r\n        // 2. Calculate for 'wordLine' options (line context)\r\n        if (options.wordLine && options.wordLine.length > 0) {\r\n          options.wordLine.forEach((optDef) => {\r\n            // Use wordIndexInLine as primary, lineWordCount as parentLength\r\n            const value = this.calculateIndex(\r\n              optDef,\r\n              wordIndexInLine,\r\n              wordIndexInLine,\r\n              lineWordCount\r\n            );\r\n            // Create CalculatedValue object\r\n            calculatedValues.push({\r\n              value,\r\n              type: \"wordLine\",\r\n              align: optDef.align,\r\n            });\r\n          });\r\n        }\r\n\r\n        // Create the ProcessedWord object with the unified calculatedValues\r\n        processedWords.push({\r\n          text: word.text,\r\n          globalIndex: globalWordIndex,\r\n          lineIndex: lineIndex,\r\n          wordIndexInLine: wordIndexInLine,\r\n          calculatedValues: calculatedValues, // Store the array of CalculatedValue\r\n        });\r\n\r\n        globalWordIndex++; // Increment global index for the next word\r\n      }); // End word loop\r\n    }); // End line loop\r\n\r\n    return processedWords;\r\n  }\r\n\r\n  /**\r\n   * Calculates the final numerical index value based on alignment options, context indices, and parent length.\r\n   * This logic determines the value eventually set as a CSS variable.\r\n   *\r\n   * @param option - The specific option item definition ({ align, random, abs }).\r\n   * @param primaryIndex - The main index used for calculation (global index for 'word', index within line for 'wordLine').\r\n   * @param localIndex - The secondary index (e.g., index within the line), potentially useful for some alignment logic.\r\n   * @param parentLength - The total count in the relevant context (total words for 'word', words in the current line for 'wordLine').\r\n   * @returns The calculated numerical index value.\r\n   */\r\n  private calculateIndex(\r\n    option: ISplitOptionItem,\r\n    primaryIndex: number,\r\n    localIndex: number, // Kept for potential future use, e.g., complex centering\r\n    parentLength: number\r\n  ): number {\r\n    let index = primaryIndex; // Base value is the primary contextual index\r\n\r\n    // Apply alignment logic\r\n    if (option.align === \"random\") {\r\n      const min = option.random?.min ?? 0;\r\n      // Ensure max is valid (length - 1 for zero-based index)\r\n      const max =\r\n        option.random?.max ?? (parentLength > 0 ? parentLength - 1 : 0);\r\n      // Handle cases where min might be > max\r\n      const effectiveMin = Math.min(min, max);\r\n      const effectiveMax = Math.max(min, max);\r\n      // Generate random integer within the effective range\r\n      index =\r\n        Math.floor(Math.random() * (effectiveMax - effectiveMin + 1)) +\r\n        effectiveMin;\r\n    } else if (option.align === \"end\") {\r\n      // Calculate index relative to the end (e.g., 0 -> length-1, 1 -> length-2)\r\n      index = (parentLength > 0 ? parentLength - 1 : 0) - primaryIndex;\r\n    } else if (option.align === \"center\") {\r\n      // Calculate index relative to the center point\r\n      index = primaryIndex - Math.floor(parentLength / 2);\r\n    }\r\n    // 'start' alignment uses the primaryIndex directly, no modification needed here.\r\n\r\n    // Apply absolute value if requested\r\n    if (option.abs) {\r\n      index = Math.abs(index);\r\n    }\r\n    return index;\r\n  }\r\n}\r\n","import { IStringTool } from \"../core/IStringTool\";\r\nimport { ISplitOptionItem } from \"../models/text/ISplitOptionItem\";\r\nimport { ISplitOptions } from \"../models/text/ISplitOptions\";\r\nimport { SplitOptionsParserInput } from \"../models/text/SplitOptionsParserInput\";\r\n\r\n/**\r\n * Tool responsible for parsing the string value of a split attribute\r\n * (e.g., \"line[center]|char[random(0,10)|abs]\") into a structured\r\n * ISplitOptions object.\r\n * Implements the IStringTool interface.\r\n */\r\nexport class SplitOptionsParserTool\r\n  implements IStringTool<SplitOptionsParserInput, ISplitOptions>\r\n{\r\n  /**\r\n   * Parses the attribute string into an ISplitOptions object.\r\n   * Handles splitting by '|', parsing prefixes (word-, char-), main types (line, word, char),\r\n   * and parameters within brackets (align, random, abs).\r\n   *\r\n   * @param input - An object containing the attributeValue string (can be null).\r\n   * @returns An ISplitOptions object representing the parsed rules.\r\n   * Returns an object with empty arrays if the attributeValue is null or empty.\r\n   */\r\n  process({ attributeValue }: SplitOptionsParserInput): ISplitOptions {\r\n    // Initialize with empty arrays for all possible options\r\n    const options: ISplitOptions = {\r\n      line: [],\r\n      word: [],\r\n      char: [],\r\n      charLine: [],\r\n      charWord: [],\r\n      wordLine: [],\r\n    };\r\n\r\n    // Return default empty options if attribute value is null or empty string\r\n    if (!attributeValue) {\r\n      return options;\r\n    }\r\n\r\n    // Split the main attribute value by the pipe '|' separator\r\n    const parts = attributeValue.split(\"|\");\r\n\r\n    parts.forEach((part) => {\r\n      // Trim whitespace from each part\r\n      const trimmedPart = part.trim();\r\n      if (!trimmedPart) return; // Skip empty parts resulting from separators like '||' or trailing '|'\r\n\r\n      // Regex to capture:\r\n      // 1. Optional prefix (word-, char-) - (\\w+-)?\r\n      // 2. Main option type (line, word, char) - (\\w+)\r\n      // 3. Optional parameters section including brackets - (\\[(.*?)\\])?\r\n      // 4. Content within the brackets (params string) - (.*?)\r\n      const match = trimmedPart.match(/^(\\w+-)?(\\w+)(\\[(.*?)\\])?$/);\r\n\r\n      if (match) {\r\n        const prefix = match[1] || \"\"; // e.g., \"word-\" or \"\"\r\n        const optionType = match[2]; // e.g., \"line\", \"word\", \"char\"\r\n        const fullOptionKey = prefix + optionType; // Combined key like \"line\", \"word\", \"charLine\"\r\n        // Extract params string inside brackets, or empty string if no brackets\r\n        const paramsString = match[4] || \"\";\r\n        // Split params by comma and trim each resulting param string\r\n        const params = paramsString\r\n          .split(\";\")\r\n          .map((p) => p.trim())\r\n          .filter((p) => p.length > 0); // Filter out empty params\r\n\r\n        // Parse the parameters within brackets using the helper method\r\n        const parsedParam: ISplitOptionItem = this.parseParamsArray(params);\r\n\r\n        // Add the parsed parameters object to the correct array in the options object\r\n        // Use a type assertion for simplicity. More complex type guards could be used.\r\n        switch (fullOptionKey) {\r\n          case \"line\":\r\n            (options.line as ISplitOptionItem[]).push(parsedParam);\r\n            break;\r\n          case \"word\":\r\n            (options.word as ISplitOptionItem[]).push(parsedParam);\r\n            break;\r\n          case \"char\":\r\n            (options.char as ISplitOptionItem[]).push(parsedParam);\r\n            break;\r\n          case \"charLine\": // e.g., char-line\r\n            (options.charLine as ISplitOptionItem[]).push(parsedParam);\r\n            break;\r\n          case \"charWord\": // e.g., char-word\r\n            (options.charWord as ISplitOptionItem[]).push(parsedParam);\r\n            break;\r\n          case \"wordLine\": // e.g., word-line\r\n            (options.wordLine as ISplitOptionItem[]).push(parsedParam);\r\n            break;\r\n          default:\r\n            // Log a warning for unrecognized option combinations\r\n            console.warn(\r\n              `SplitOptionsParserTool: Unrecognized option type \"${fullOptionKey}\" in part \"${trimmedPart}\"`\r\n            );\r\n            break;\r\n        }\r\n      } else {\r\n        // Log a warning for parts that don't match the expected format \"type[params]\" or \"prefix-type[params]\"\r\n        console.warn(\r\n          `SplitOptionsParserTool: Could not parse part format \"${trimmedPart}\"`\r\n        );\r\n      }\r\n    }); // End forEach part\r\n\r\n    return options; // Return the populated options object\r\n  }\r\n\r\n  /**\r\n   * Parses an array of string parameters (extracted from within brackets `[...]`).\r\n   * Determines alignment, random settings, and absolute flag.\r\n   * Example input: ['center'], ['random(0, 10)', 'abs']\r\n   *\r\n   * @param params - An array of string parameters.\r\n   * @returns An ISplitOptionItem object representing the parsed parameters.\r\n   */\r\n  private parseParamsArray(params: string[]): ISplitOptionItem {\r\n    // Default result with 'start' alignment\r\n    const result: ISplitOptionItem = { align: \"start\" };\r\n\r\n    params.forEach((param) => {\r\n      if (param === \"abs\") {\r\n        // Set the absolute flag\r\n        result.abs = true;\r\n      } else if (param.startsWith(\"random\")) {\r\n        // Handle random alignment\r\n        result.align = \"random\"; // Set alignment type\r\n        // Try to parse min/max values like random(10,50)\r\n        // Allows optional whitespace around numbers and comma\r\n        const randomMatch = param.match(/random\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*\\)/);\r\n        if (randomMatch) {\r\n          // If numbers found, parse and store them\r\n          result.random = {\r\n            min: parseInt(randomMatch[1], 10),\r\n            max: parseInt(randomMatch[2], 10),\r\n          };\r\n          // Optional: Add validation like min <= max here if desired\r\n        }\r\n        // If 'random' specified without valid numbers, result.align is 'random',\r\n        // and result.random remains undefined (defaults will apply later based on context).\r\n      } else if ([\"start\", \"center\", \"end\"].includes(param)) {\r\n        // Handle specific alignment keywords\r\n        result.align = param;\r\n      }\r\n      // Silently ignore any other unrecognized parameters within the brackets\r\n    });\r\n\r\n    return result; // Return the parsed option item definition\r\n  }\r\n}\r\n","import BoundingClientRectTool from \"../tools/BoundingClientRectTool\"\r\nimport DOMAttributeTool from \"../tools/DOMAttributeTool\"\r\nimport RecordAttributeTool from \"../tools/RecordAttributeTool\"\r\nimport RelativePositionTool from \"../tools/RelativePositionTool\"\r\nimport LerpTool from \"../tools/LerpTool\"\r\nimport TransformNullifyTool from \"../tools/TransformNullifyTool\"\r\nimport UnitParserTool from \"../tools/UnitParserTool\"\r\nimport AdaptiveLerpTool from \"../tools/AdaptiveLerpTool\"\r\nimport OriginParserTool from \"../tools/OriginParserTool\"\r\nimport ColorParserTool from \"../tools/ColorParserTool\"\r\nimport ValidationTool from \"../tools/ValidationTool\"\r\nimport EasingFunctionTool from \"../tools/EasingFunctionTool\"\r\nimport MagneticPullTool from \"../tools/MagneticPullTool\"\r\nimport LerpColorTool from \"../tools/LerpColorTool\"\r\nimport LerpVector2Tool from \"../tools/LerpVector2Tool\"\r\nimport TransformScaleParserTool from \"../tools/TransformScaleParserTool\"\r\nimport { CharIndexerTool } from \"../tools/CharIndexerTool\"\r\nimport { LayoutLineSplitterTool } from \"../tools/LayoutLineSplitterTool\"\r\nimport { SplitDomBuilderTool } from \"../tools/SplitDomBuilderTool\"\r\nimport { WordIndexerTool } from \"../tools/WordIndexerTool\"\r\nimport { SplitOptionsParserTool } from \"../tools/SplitOptionsParserTool\"\r\n\r\n/**\r\n * Interface describing all available tools used inside modules.\r\n */\r\nexport interface StringToolsContainer {\r\n  /** Tool for reading DOM attributes (including data-*). */\r\n  domAttribute: DOMAttributeTool\r\n\r\n  /** Tool for reading attributes from a plain JS object or dataset. */\r\n  recordAttribute: RecordAttributeTool\r\n\r\n  /** Tool for calculating the relative position between two elements. */\r\n  relativePosition: RelativePositionTool\r\n\r\n  /** Tool that nullifies the effect of CSS transform matrix. */\r\n  transformNullify: TransformNullifyTool\r\n\r\n  /** Tool that wraps getBoundingClientRect with consistent output. */\r\n  boundingClientRect: BoundingClientRectTool\r\n\r\n  /** Tool for parsing string-based values like '50%', '2rem', 'selfHeight'. */\r\n  unitParser: UnitParserTool\r\n\r\n  /** Tool for performing linear interpolation (lerp). */\r\n  lerp: LerpTool\r\n\r\n  /** \r\n   * Tool for adaptive interpolation based on dynamic input value.\r\n   * Useful when smoothing cursor speed, scroll velocity, etc.\r\n   */\r\n  adaptiveLerp: AdaptiveLerpTool\r\n\r\n  /**\r\n   * Tool for parsing origin strings.\r\n   * Supports values like `'top'`, `'center'`, or random expressions like `'random(top, bottom)'`.\r\n   */\r\n  originParser: OriginParserTool\r\n\r\n  /**\r\n   * Tool for parsing CSS color strings into { r, g, b, a } format.\r\n   * Supports `#hex`, `rgb[a](...)`, `hsl[a](...)` inputs.\r\n   */\r\n  colorParser: ColorParserTool\r\n\r\n  /**\r\n   * Tool for validating strings using rules like `required`, `minLength`, `email`, etc.\r\n   * Returns validation status, error code, and optional message.\r\n   */\r\n  validation: ValidationTool\r\n\r\n  /**\r\n   * Tool for parsing CSS-like easing strings into easing functions.\r\n   * Supports keywords like `'ease'`, `'linear'`, and full `cubic-bezier(...)` expressions.\r\n   */\r\n  easingFunction: EasingFunctionTool\r\n\r\n  /**\r\n   * Tool for calculating magnetic offset strength based on proximity to pointer.\r\n   */\r\n  magneticPull: MagneticPullTool\r\n\r\n  /**\r\n   * Tool for interpolating between two RGBA colors.\r\n   * Accepts `from` and `to` colors as `{ r, g, b, a }`, and a `progress` value from `0` to `1`.\r\n   * Returns an interpolated `StringColor` object.\r\n   */\r\n  lerpColor: LerpColorTool\r\n\r\n  /**\r\n   * Tool for interpolating between two 2D vectors.\r\n   * Accepts `{ x, y }` objects and a `progress` value between `0` and `1`.\r\n   * Returns a new `{ x, y }` vector.\r\n   */\r\n  lerpVector: LerpVector2Tool\r\n\r\n  transformScaleParser: TransformScaleParserTool\r\n\r\n  layoutSplitter: LayoutLineSplitterTool\r\n\r\n  wordIndexer: WordIndexerTool\r\n\r\n  charIndexer: CharIndexerTool\r\n\r\n  domBuilder: SplitDomBuilderTool\r\n\r\n  optionsParser: SplitOptionsParserTool\r\n\r\n}\r\n\r\n/**\r\n * Default implementation of the StringToolContainer,\r\n * which provides ready-to-use instances of all core tools.\r\n */\r\nexport class DefaultToolsContainer implements StringToolsContainer {\r\n  public domAttribute = new DOMAttributeTool()\r\n  public recordAttribute = new RecordAttributeTool()\r\n  public transformNullify = new TransformNullifyTool()\r\n  public boundingClientRect = new BoundingClientRectTool()\r\n  public relativePosition = new RelativePositionTool(this.transformNullify)\r\n  public unitParser = new UnitParserTool()\r\n  public lerp = new LerpTool()\r\n  public adaptiveLerp = new AdaptiveLerpTool()\r\n  public originParser = new OriginParserTool()\r\n  public colorParser = new ColorParserTool()\r\n  public validation = new ValidationTool()\r\n  public easingFunction = new EasingFunctionTool()\r\n  public magneticPull = new MagneticPullTool()\r\n  public lerpColor = new LerpColorTool()\r\n  public lerpVector = new LerpVector2Tool()\r\n  public transformScaleParser = new TransformScaleParserTool()\r\n  public layoutSplitter = new LayoutLineSplitterTool()\r\n  public wordIndexer = new WordIndexerTool()\r\n  public charIndexer = new CharIndexerTool()\r\n  public domBuilder = new SplitDomBuilderTool()\r\n  public optionsParser = new SplitOptionsParserTool()\r\n\r\n}\r\n","import { StringContext } from \"../../core/StringContext\";\r\nimport { StringData } from \"../../core/StringData\";\r\nimport { StringModule } from \"../../core/StringModule\";\r\nimport { StringObject } from \"../../objects/StringObject\";\r\n\r\nexport class StringCursor extends StringModule {\r\n  protected enterObjectsMap: Map<string, StringObject> = new Map<\r\n    string,\r\n    StringObject\r\n  >();\r\n  protected enterObjects: Array<StringObject> = new Array<StringObject>();\r\n  cursor: any;\r\n  cursorContent: any;\r\n  overCount: number = 0;\r\n\r\n  constructor(context: StringContext) {\r\n    super(context);\r\n    this.htmlKey = \"cursor\";\r\n    this.cursor = document.querySelector(\r\n      \"[string-cursor],[data-string-cursor]\"\r\n    ) as HTMLElement;\r\n    this.cursorContent = document.querySelector(\r\n      \"[string-cursor-content],[data-string-cursor-content]\"\r\n    ) as HTMLElement;\r\n\r\n    this.attributesToMap = [\r\n      ...this.attributesToMap,\r\n      {\r\n        key: \"target-disable\",\r\n        type: \"boolean\",\r\n        fallback: this.settings[\"target-disable\"],\r\n      },\r\n      {\r\n        key: \"target-style-disable\",\r\n        type: \"boolean\",\r\n        fallback: this.settings[\"target-style-disable\"],\r\n      },\r\n      {\r\n        key: \"target-class\",\r\n        type: \"string\",\r\n        fallback: this.settings[\"target-class\"],\r\n      },\r\n      {\r\n        key: \"cursor-class\",\r\n        type: \"string\",\r\n        fallback: this.settings[\"cursor-class\"],\r\n      },\r\n      {\r\n        key: \"alignment\",\r\n        type: { type: \"enum\", values: [\"start\", \"center\", \"end\"] },\r\n        fallback: this.settings[\"alignment\"],\r\n      },\r\n      {\r\n        key: \"lerp\",\r\n        type: \"number\",\r\n        fallback: this.settings[\"lerp\"],\r\n        transform: (value: number) => {\r\n          return this.tools.adaptiveLerp.process({\r\n            value,\r\n            inMin: 0.1,\r\n            inMax: 1.0,\r\n            outMin: 0.05,\r\n            outMax: 0.65,\r\n          });\r\n        },\r\n      },\r\n    ];\r\n  }\r\n\r\n  initializeObject(\r\n    globalId: number,\r\n    object: StringObject,\r\n    element: HTMLElement,\r\n    attributes: Record<string, any>\r\n  ): void {\r\n    super.initializeObject(globalId, object, element, attributes);\r\n    object.setProperty(\"mouse-x\", 0);\r\n    object.setProperty(\"mouse-y\", 0);\r\n    object.setProperty(\"mouse-pixel-x\", 0);\r\n    object.setProperty(\"mouse-pixel-y\", 0);\r\n    object.setProperty(\"is-mouse-over\", false);\r\n    object.setProperty(\"is-mouse-move\", false);\r\n  }\r\n\r\n  onFrame(data: StringData): void {\r\n    requestAnimationFrame(() => {\r\n      this.objects.forEach((object) => {\r\n        const isOver = object.getProperty<boolean>(\"is-mouse-over\");\r\n        const isDisabled = object.getProperty<boolean>(\"cursor-target-disable\");\r\n        const lerpFactor = object.getProperty<number>(\"lerp\") ?? 0.15;\r\n\r\n        if (isOver && !isDisabled) {\r\n          const rect = object.htmlElement.getBoundingClientRect();\r\n          const cursorX = this.data.cursor.targetX;\r\n          const cursorY = this.data.cursor.targetY;\r\n          const elementX = cursorX - rect.left;\r\n          const elementY = cursorY - rect.top;\r\n\r\n          let px = object.getProperty<number>(\"mouse-pixel-x\") ?? 0;\r\n          let py = object.getProperty<number>(\"mouse-pixel-y\") ?? 0;\r\n\r\n          const dx = px - elementX;\r\n          const dy = py - elementY;\r\n          const distSquared = dx * dx + dy * dy;\r\n\r\n          if (distSquared > 0.0001) {\r\n            const isMoving =\r\n              object.getProperty<boolean>(\"is-mouse-move\") ?? false;\r\n            if (!isMoving) {\r\n              object.setProperty(\"is-mouse-move\", true);\r\n              object.setProperty(\"mouse-pixel-x\", elementX);\r\n              object.setProperty(\"mouse-pixel-y\", elementY);\r\n              object.setProperty(\"mouse-x\", elementX);\r\n              object.setProperty(\"mouse-y\", elementY);\r\n              px = elementX;\r\n              py = elementY;\r\n              this.events.emit(`cursor:start:${object.id}`, null);\r\n            }\r\n\r\n            const lerpedX = this.tools.lerp.process({\r\n              from: px,\r\n              to: elementX,\r\n              progress: lerpFactor,\r\n            });\r\n            const lerpedY = this.tools.lerp.process({\r\n              from: py,\r\n              to: elementY,\r\n              progress: lerpFactor,\r\n            });\r\n\r\n            const updatedX = px + lerpedX;\r\n            const updatedY = py + lerpedY;\r\n\r\n            object.setProperty(\"mouse-pixel-x\", updatedX);\r\n            object.setProperty(\"mouse-pixel-y\", updatedY);\r\n\r\n            const alignment =\r\n              object.getProperty<string>(\"alignment\") ?? \"center\";\r\n            const offsetX = this.calculateOffset(\r\n              alignment,\r\n              updatedX,\r\n              rect.width\r\n            );\r\n            const offsetY = this.calculateOffset(\r\n              alignment,\r\n              updatedY,\r\n              rect.height\r\n            );\r\n\r\n            object.setProperty(\"mouse-x\", offsetX);\r\n            object.setProperty(\"mouse-y\", offsetY);\r\n\r\n            this.setMouseCoordinates(object, offsetX, offsetY);\r\n\r\n            this.events.emit(`cursor:move:${object.id}`, {\r\n              x: offsetX,\r\n              y: offsetY,\r\n            });\r\n            this.events.emit(`cursor:pixel:${object.id}`, {\r\n              x: updatedX,\r\n              y: updatedY,\r\n            });\r\n          } else {\r\n            object.setProperty(\"mouse-pixel-x\", elementX);\r\n            object.setProperty(\"mouse-pixel-y\", elementY);\r\n            this.events.emit(`cursor:end:${object.id}`, null);\r\n          }\r\n        } else {\r\n          const mouseX = object.getProperty<number>(\"mouse-x\") ?? 0;\r\n          const mouseY = object.getProperty<number>(\"mouse-y\") ?? 0;\r\n          if (mouseX !== 0 || mouseY !== 0) {\r\n            object.setProperty(\"is-mouse-move\", false);\r\n\r\n            const rect = object.htmlElement.getBoundingClientRect();\r\n            const halfWidth =\r\n              object.getProperty<number>(\"half-width\") ?? rect.width / 2;\r\n            const halfHeight =\r\n              object.getProperty<number>(\"half-height\") ?? rect.height / 2;\r\n\r\n            const targetX = this.calculateOffset(\r\n              \"center\",\r\n              halfWidth,\r\n              rect.width\r\n            );\r\n            const targetY = this.calculateOffset(\r\n              \"center\",\r\n              halfHeight,\r\n              rect.height\r\n            );\r\n\r\n            const newMouseX =\r\n              mouseX +\r\n              this.tools.lerp.process({\r\n                from: mouseX,\r\n                to: targetX,\r\n                progress: lerpFactor,\r\n              });\r\n            const newMouseY =\r\n              mouseY +\r\n              this.tools.lerp.process({\r\n                from: mouseY,\r\n                to: targetY,\r\n                progress: lerpFactor,\r\n              });\r\n\r\n            object.setProperty(\"mouse-x\", newMouseX);\r\n            object.setProperty(\"mouse-y\", newMouseY);\r\n\r\n            if (Math.abs(newMouseX) < 0.001 && Math.abs(newMouseY) < 0.001) {\r\n              object.setProperty(\"mouse-x\", 0);\r\n              object.setProperty(\"mouse-y\", 0);\r\n              object.setProperty(\"mouse-pixel-x\", 0);\r\n              object.setProperty(\"mouse-pixel-y\", 0);\r\n            }\r\n\r\n            this.setMouseCoordinates(object, newMouseX, newMouseY);\r\n          }\r\n        }\r\n      });\r\n\r\n      const { stepX, stepY, smoothedX, smoothedY } = this.data.cursor;\r\n      if (stepX !== 0 || stepY !== 0) {\r\n        this.events.emit(\"cursor\", {\r\n          stepX,\r\n          stepY,\r\n          x: smoothedX,\r\n          y: smoothedY,\r\n        });\r\n\r\n        this.cursor.style.setProperty(\"--x\", smoothedX.toString());\r\n        this.cursor.style.setProperty(\"--y\", smoothedY.toString());\r\n        this.cursor.style.setProperty(\"--x-lerp\", stepX.toString());\r\n        this.cursor.style.setProperty(\"--y-lerp\", stepY.toString());\r\n      }\r\n    });\r\n  }\r\n\r\n  onObjectConnected(object: StringObject) {\r\n    const element = object.htmlElement;\r\n    let timeoutId: ReturnType<typeof setTimeout> | null = null;\r\n\r\n    object.setProperty(\"timeoutId\", timeoutId);\r\n\r\n    object.setProperty(\"mouseleave\", () => {\r\n      this.onMouseLeave(object);\r\n    });\r\n    object.setProperty(\"mouseenter\", () => {\r\n      this.onMouseEnter(object);\r\n    });\r\n\r\n    object.setProperty(\"onEnterEvent\", this.onEnterObject.bind(this));\r\n    object.events.on(\r\n      \"enter\",\r\n      object.getProperty<(object: StringObject) => void>(\"onEnterEvent\")\r\n    );\r\n    object.setProperty(\"onLeaveEvent\", this.onLeaveObject.bind(this));\r\n    object.events.on(\r\n      \"leave\",\r\n      object.getProperty<(object: StringObject) => void>(\"onLeaveEvent\")\r\n    );\r\n  }\r\n\r\n  getCursorClass(object: StringObject) {\r\n    const value = object.getProperty<string>(\"cursor-class\");\r\n    return value != null && value.length > 0 ? value : null;\r\n  }\r\n\r\n  onMouseEnter(object: StringObject) {\r\n    this.overCount++;\r\n    object.setProperty(\"is-mouse-over\", true);\r\n\r\n    const cursorClass = this.getCursorClass(object);\r\n    if (cursorClass) {\r\n      this.cursor.classList.add(cursorClass);\r\n    }\r\n\r\n    this.cursor.classList.add(\"-showing\");\r\n\r\n    object.setProperty(\r\n      \"timeoutId\",\r\n      setTimeout(() => {\r\n        this.cursor.classList.remove(\"-showing\");\r\n        this.cursor.classList.add(\"-show\");\r\n      }, 1200)\r\n    );\r\n\r\n    object.htmlElement.addEventListener(\r\n      \"mouseleave\",\r\n      object.getProperty(\"mouseleave\")\r\n    );\r\n  }\r\n\r\n  onMouseLeave(object: StringObject) {\r\n    this.overCount--;\r\n    object.setProperty(\"is-mouse-over\", false);\r\n\r\n    if (object.getProperty(\"timeoutId\")) {\r\n      clearTimeout(object.getProperty(\"timeoutId\"));\r\n      object.setProperty(\"timeoutId\", null);\r\n    }\r\n\r\n    const cursorClass = this.getCursorClass(object);\r\n    if (cursorClass) {\r\n      this.cursor.classList.remove(cursorClass);\r\n    }\r\n\r\n    this.cursor.classList.remove(\"-showing\");\r\n    this.cursor.classList.remove(\"-show\");\r\n\r\n    object.htmlElement.removeEventListener(\r\n      \"mouseleave\",\r\n      object.getProperty(\"mouseleave\")\r\n    );\r\n  }\r\n\r\n  private onEnterObject(object: StringObject) {\r\n    object.htmlElement.addEventListener(\r\n      \"mouseenter\",\r\n      object.getProperty(\"mouseenter\")\r\n    );\r\n  }\r\n  private onLeaveObject(object: StringObject) {\r\n    object.htmlElement.removeEventListener(\r\n      \"mouseenter\",\r\n      object.getProperty(\"mouseenter\")\r\n    );\r\n    object.htmlElement.removeEventListener(\r\n      \"mouseleave\",\r\n      object.getProperty(\"mouseleave\")\r\n    );\r\n  }\r\n\r\n  private setMouseCoordinates(object: StringObject, x: number, y: number) {\r\n    if (!object.getProperty(\"cursor-target-style-disable\")) {\r\n      this.applyToElementAndConnects(object, (el) => {\r\n        el.style.setProperty(\"--x\", x.toFixed(2));\r\n        el.style.setProperty(\"--y\", y.toFixed(2));\r\n      });\r\n    }\r\n  }\r\n\r\n  private calculateOffset(\r\n    alignment: string,\r\n    mousePos: number,\r\n    size: number\r\n  ): number {\r\n    switch (alignment) {\r\n      case \"start\":\r\n        return mousePos / size;\r\n      case \"end\":\r\n        return (mousePos - size) / size;\r\n      case \"center\":\r\n      default:\r\n        return (mousePos - size / 2) / (size / 2);\r\n    }\r\n  }\r\n}\r\n","import { StringContext } from \"../../core/StringContext\";\r\nimport { StringData } from \"../../core/StringData\";\r\nimport { StringModule } from \"../../core/StringModule\";\r\nimport { StringObject } from \"../../objects/StringObject\";\r\n\r\nexport class StringMagnetic extends StringModule {\r\n  constructor(context: StringContext) {\r\n    super(context);\r\n    this.htmlKey = \"magnetic\";\r\n\r\n    this.attributesToMap = [\r\n      ...this.attributesToMap,\r\n      { key: \"strength\", type: \"number\", fallback: this.settings[\"strength\"] },\r\n      { key: \"radius\", type: \"number\", fallback: this.settings[\"radius\"] },\r\n    ];\r\n  }\r\n\r\n  override initializeObject(\r\n    globalId: number,\r\n    object: StringObject,\r\n    element: HTMLElement,\r\n    attributes: Record<string, any>\r\n  ): void {\r\n    super.initializeObject(globalId, object, element, attributes);\r\n    object.setProperty(\"is-magneting\", false);\r\n    object.setProperty(\"magnetic-target-x\", 0);\r\n    object.setProperty(\"magnetic-target-y\", 0);\r\n    object.setProperty(\"magnetic-x\", 0);\r\n    object.setProperty(\"magnetic-y\", 0);\r\n    object.setProperty(\"lerp\", 0.1);\r\n  }\r\n\r\n  onMouseMove(e: MouseEvent): void {\r\n    this.objects.forEach((object) => {\r\n      const element = object.htmlElement as HTMLElement;\r\n      const rect = element.getBoundingClientRect();\r\n      const centerX =\r\n        rect.left + (object.getProperty<number>(\"half-width\") ?? 0);\r\n      const centerY =\r\n        rect.top + (object.getProperty<number>(\"half-height\") ?? 0);\r\n      const dx = e.clientX - centerX;\r\n      const dy = e.clientY - centerY;\r\n      const distance = Math.sqrt(dx ** 2 + dy ** 2);\r\n\r\n      const radius = object.getProperty<number>(\"radius\") ?? 0;\r\n      const strength = object.getProperty<number>(\"strength\") ?? 0;\r\n\r\n      const factor = this.tools.magneticPull.process({\r\n        distance,\r\n        radius,\r\n        strength,\r\n      });\r\n\r\n      object.setProperty(\"magnetic-target-x\", dx * factor);\r\n      object.setProperty(\"magnetic-target-y\", dy * factor);\r\n      if (factor > 0) {\r\n        object.setProperty(\"is-magneting\", true);\r\n      }\r\n    });\r\n  }\r\n\r\n  onFrame(data: StringData): void {\r\n    this.objects.forEach((object) => {\r\n      if (object.getProperty(\"is-magneting\")) {\r\n        let magneticX = object.getProperty<number>(\"magnetic-x\") ?? 0;\r\n        let magneticY = object.getProperty<number>(\"magnetic-y\") ?? 0;\r\n\r\n        let lerp = object.getProperty<number>(\"lerp\") ?? 0;\r\n\r\n        let targetMagneticX =\r\n          object.getProperty<number>(\"magnetic-target-x\") ?? 0;\r\n        let targetMagneticY =\r\n          object.getProperty<number>(\"magnetic-target-y\") ?? 0;\r\n\r\n        let lerpX = this.tools.lerp.process({\r\n          from: magneticX,\r\n          to: targetMagneticX,\r\n          progress: lerp,\r\n        });\r\n        let lerpY = this.tools.lerp.process({\r\n          from: magneticY,\r\n          to: targetMagneticY,\r\n          progress: lerp,\r\n        });\r\n\r\n        if (lerpX > -0.01 && lerpX < 0.01) {\r\n          lerpX = 0;\r\n          object.setProperty(\r\n            \"magnetic-x\",\r\n            object.getProperty(\"magnetic-target-x\")\r\n          );\r\n        }\r\n        if (lerpY > -0.01 && lerpY < 0.01) {\r\n          lerpY = 0;\r\n          object.setProperty(\r\n            \"magnetic-y\",\r\n            object.getProperty(\"magnetic-target-y\")\r\n          );\r\n        }\r\n        magneticX += lerpX;\r\n        magneticY += lerpY;\r\n        object.setProperty<number>(\"magnetic-x\", magneticX);\r\n        object.setProperty<number>(\"magnetic-y\", magneticY);\r\n        this.events.emit(`magnetic:move:${object.id}`, {\r\n          x: magneticX,\r\n          y: magneticY,\r\n        });\r\n\r\n        this.applyToElementAndConnects(object, (el) => {\r\n          el.style.setProperty(\"--magnetic-x\", magneticX.toString());\r\n          el.style.setProperty(\"--magnetic-y\", magneticY.toString());\r\n        });\r\n\r\n        if (\r\n          object.getProperty(\"magnetic-target-x\") == magneticX ||\r\n          object.getProperty(\"magnetic-target-y\") == magneticY\r\n        ) {\r\n          object.setProperty(\"is-magneting\", false);\r\n        }\r\n      }\r\n    });\r\n  }\r\n}\r\n","import { StringContext } from \"../../core/StringContext\";\r\nimport { StringModule } from \"../../core/StringModule\";\r\nimport { StringObject } from \"../../objects/StringObject\";\r\n\r\n/**\r\n * Module that handles lazy-loading of images with `string-lazy` attribute.\r\n * Automatically loads and applies aspect-ratio once image is loaded.\r\n */\r\nexport class StringLazy extends StringModule {\r\n  private isStartLoaded = false;\r\n  private loadingCount = 0;\r\n\r\n  constructor(context: StringContext) {\r\n    super(context);\r\n    this.htmlKey = \"lazy\";\r\n  }\r\n\r\n  /**\r\n   * Called on module start — preloads all <img string-lazy> in DOM.\r\n   */\r\n  onInit(): void {\r\n    const images = document.querySelectorAll(\r\n      \"img[string-lazy], img[data-string-lazy]\"\r\n    );\r\n    images.forEach((img) => this.loadImage(img as HTMLImageElement));\r\n    this.isStartLoaded = true;\r\n  }\r\n\r\n  /**\r\n   * Called when an image becomes a managed object.\r\n   */\r\n  onObjectConnected(object: StringObject): void {\r\n    this.loadingCount++;\r\n\r\n    if (this.isStartLoaded) {\r\n      const img = object.htmlElement as HTMLImageElement;\r\n      this.loadImage(img);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Loads image and sets aspect-ratio based on real dimensions.\r\n   */\r\n  private async loadImage(img: HTMLImageElement): Promise<void> {\r\n    const src = this.tools.domAttribute.process({\r\n      element: img,\r\n      key: this.htmlKey,\r\n      fallback: \"\",\r\n    });\r\n\r\n    if (!src) return;\r\n\r\n    try {\r\n      img.classList.add(\"lazyLoad\");\r\n      img.src = src;\r\n\r\n      img.addEventListener(\"load\", () => {\r\n        img.classList.add(\"-loaded\");\r\n      });\r\n      await this.setAspectRatio(img, src);\r\n    } catch (err) {\r\n      console.warn(\"Failed to load image:\", src);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Loads image data to extract real dimensions and apply aspect-ratio style.\r\n   */\r\n  private setAspectRatio(el: HTMLElement, url: string): Promise<void> {\r\n    return new Promise((resolve, reject) => {\r\n      const xhr = new XMLHttpRequest();\r\n      xhr.open(\"GET\", url, true);\r\n      xhr.responseType = \"arraybuffer\";\r\n      xhr.setRequestHeader(\"Range\", \"bytes=0-\");\r\n      xhr.onload = () => {\r\n        if (xhr.status === 200 || xhr.status === 206) {\r\n          const blob = new Blob([xhr.response]);\r\n          const img = new Image();\r\n          img.onload = () => {\r\n            el.style.aspectRatio = `${img.width} / ${img.height}`;\r\n            URL.revokeObjectURL(img.src);\r\n\r\n            this.loadingCount--;\r\n            if (this.loadingCount <= 0) {\r\n              this.events.emit(\"image:load:all\", null);\r\n              this.loadingCount = 0;\r\n            }\r\n\r\n            resolve();\r\n          };\r\n          img.onerror = () => {\r\n            URL.revokeObjectURL(img.src);\r\n            this.loadingCount--;\r\n            reject(new Error(\"Image failed to decode\"));\r\n          };\r\n          img.src = URL.createObjectURL(blob);\r\n        } else {\r\n          reject(new Error(\"Image request failed\"));\r\n        }\r\n      };\r\n      xhr.onerror = () => reject(new Error(\"XHR error\"));\r\n      xhr.send();\r\n    });\r\n  }\r\n}\r\n","import { StringContext } from \"../../core/StringContext\";\r\nimport { StringModule } from \"../../core/StringModule\";\r\n\r\n\r\nexport class StringLoading extends StringModule{\r\n  loadingTimeout: number = 0\r\n\r\n  constructor(context: StringContext) {\r\n    super(context)\r\n    this._type = 2\r\n    this.loadingTimeout = this.settings['timeout']\r\n  }\r\n  onInit(): void {\r\n    setTimeout(() => {\r\n      const htmlElement = document.documentElement;\r\n      htmlElement.classList.add('-loaded');\r\n    }, this.loadingTimeout);\r\n    \r\n  }\r\n}","import { StringModule } from \"../../core/StringModule\";\r\nimport { StringObject } from \"../../objects/StringObject\";\r\n\r\nexport class StringInview extends StringModule {\r\n  constructor(visitor: any) {\r\n    super(visitor);\r\n    this.htmlKey = '';\r\n  }\r\n  canConnect(object: StringObject): boolean {\r\n    return object.keys[0]==undefined;\r\n  }\r\n}\r\n","import { StringContext } from \"../../core/StringContext\";\r\nimport { StringModule } from \"../../core/StringModule\";\r\n\r\nenum DeviceType {\r\n  Mobile,\r\n  Tablet,\r\n  Laptop,\r\n  Desktop,\r\n}\r\n\r\ninterface DeviceQueryConfig {\r\n  min?: number;\r\n  max?: number;\r\n  enable?: boolean;\r\n}\r\n\r\ninterface QueryConfig {\r\n  mobile?: DeviceQueryConfig;\r\n  tablet?: DeviceQueryConfig;\r\n  laptop?: DeviceQueryConfig;\r\n  desktop?: DeviceQueryConfig;\r\n}\r\n\r\nclass StringResponsiveQueryDevice {\r\n  public min?: number = undefined;\r\n  public max?: number = undefined;\r\n  public enable: boolean = true;\r\n\r\n  constructor(config?: DeviceQueryConfig) {\r\n    this.min = config?.min;\r\n    this.max = config?.max;\r\n    this.enable = config?.enable ?? true;\r\n  }\r\n\r\n  setEnable(enable: boolean = true) {\r\n    this.enable = enable;\r\n  }\r\n  setRange(min?: number, max?: number) {\r\n    this.min = min ?? undefined;\r\n    this.max = max ?? undefined;\r\n  }\r\n\r\n  get mediaQuery(): string {\r\n    let query = \"screen\";\r\n    if (this.min) {\r\n      query += ` and (min-width: ${this.min}px)`;\r\n    }\r\n    if (this.max) {\r\n      query += ` and (max-width: ${this.max}px)`;\r\n    }\r\n    return query;\r\n  }\r\n}\r\n\r\nexport class StringResponsive extends StringModule {\r\n  private queries: { [key in DeviceType]: StringResponsiveQueryDevice } = {\r\n    [DeviceType.Mobile]: new StringResponsiveQueryDevice({ max: 359 }),\r\n    [DeviceType.Tablet]: new StringResponsiveQueryDevice({\r\n      min: 360,\r\n      max: 1079,\r\n    }),\r\n    [DeviceType.Laptop]: new StringResponsiveQueryDevice({\r\n      min: 1080,\r\n      max: 1365,\r\n    }),\r\n    [DeviceType.Desktop]: new StringResponsiveQueryDevice({ min: 1366 }),\r\n  };\r\n\r\n  private matchMedias: { [key in DeviceType]: MediaQueryList } = {\r\n    [DeviceType.Mobile]: window.matchMedia(\r\n      this.queries[DeviceType.Mobile].mediaQuery\r\n    ),\r\n    [DeviceType.Tablet]: window.matchMedia(\r\n      this.queries[DeviceType.Tablet].mediaQuery\r\n    ),\r\n    [DeviceType.Laptop]: window.matchMedia(\r\n      this.queries[DeviceType.Laptop].mediaQuery\r\n    ),\r\n    [DeviceType.Desktop]: window.matchMedia(\r\n      this.queries[DeviceType.Desktop].mediaQuery\r\n    ),\r\n  };\r\n\r\n  constructor(context: StringContext) {\r\n    super(context);\r\n    this._type = 2;\r\n  }\r\n\r\n  onConnect() {}\r\n\r\n  onInit(): void {\r\n    if (this.settings != null) {\r\n      if (this.settings[\"settings\"] != null) {\r\n        let config = this.settings[\"settings\"];\r\n        if (config.mobile) {\r\n          this.queries[DeviceType.Mobile].enable = true;\r\n          this.queries[DeviceType.Mobile].setRange(\r\n            config.mobile.min == undefined ? null : config.mobile.min,\r\n            config.mobile.max ?? null\r\n          );\r\n          this.matchMedias[DeviceType.Mobile] = window.matchMedia(\r\n            this.queries[DeviceType.Mobile].mediaQuery\r\n          );\r\n        } else {\r\n          this.queries[DeviceType.Mobile].enable = false;\r\n        }\r\n\r\n        if (config.tablet) {\r\n          this.queries[DeviceType.Tablet].enable = true;\r\n          this.queries[DeviceType.Tablet].setRange(\r\n            config.mobile.min == undefined ? null : config.mobile.min,\r\n            config.mobile.max ?? null\r\n          );\r\n          this.matchMedias[DeviceType.Tablet] = window.matchMedia(\r\n            this.queries[DeviceType.Mobile].mediaQuery\r\n          );\r\n        } else {\r\n          this.queries[DeviceType.Tablet].enable = false;\r\n        }\r\n\r\n        if (config.laptop) {\r\n          this.queries[DeviceType.Laptop].enable = true;\r\n          this.queries[DeviceType.Laptop].setRange(\r\n            config.mobile.min == undefined ? null : config.mobile.min,\r\n            config.mobile.max ?? null\r\n          );\r\n          this.matchMedias[DeviceType.Laptop] = window.matchMedia(\r\n            this.queries[DeviceType.Mobile].mediaQuery\r\n          );\r\n        } else {\r\n          this.queries[DeviceType.Laptop].enable = false;\r\n        }\r\n\r\n        if (config.desktop) {\r\n          this.queries[DeviceType.Desktop].enable = true;\r\n          this.queries[DeviceType.Desktop].setRange(\r\n            config.mobile.min == undefined ? null : config.mobile.min,\r\n            config.mobile.max ?? null\r\n          );\r\n          this.matchMedias[DeviceType.Desktop] = window.matchMedia(\r\n            this.queries[DeviceType.Mobile].mediaQuery\r\n          );\r\n        } else {\r\n          this.queries[DeviceType.Desktop].enable = false;\r\n        }\r\n      }\r\n    }\r\n    this.updateElements();\r\n  }\r\n\r\n  onResize(): void {\r\n    this.updateElements();\r\n  }\r\n\r\n  private updateElements() {\r\n    const isMobileMedia =\r\n      this.matchMedias[DeviceType.Mobile].matches &&\r\n      this.queries[DeviceType.Mobile].enable;\r\n    const isTabletMedia =\r\n      this.matchMedias[DeviceType.Tablet].matches &&\r\n      this.queries[DeviceType.Tablet].enable;\r\n    const isLaptopMedia =\r\n      this.matchMedias[DeviceType.Laptop].matches &&\r\n      this.queries[DeviceType.Laptop].enable;\r\n    const isDesktopMedia =\r\n      this.matchMedias[DeviceType.Desktop].matches &&\r\n      this.queries[DeviceType.Desktop].enable;\r\n\r\n    const elements = document.querySelectorAll(\r\n      \"[string-mobile], [string-tablet], [string-laptop], [string-desktop]\"\r\n    );\r\n\r\n    elements.forEach((element: any) => {\r\n      let showElement = false;\r\n\r\n      if (element.hasAttribute(\"string-mobile\") && isMobileMedia) {\r\n        showElement = true;\r\n        this.events.emit(\"screen:mobile\", isMobileMedia);\r\n      }\r\n      if (element.hasAttribute(\"string-tablet\") && isTabletMedia) {\r\n        showElement = true;\r\n        this.events.emit(\"screen:tablet\", isTabletMedia);\r\n      }\r\n      if (element.hasAttribute(\"string-laptop\") && isLaptopMedia) {\r\n        showElement = true;\r\n        this.events.emit(\"screen:laptop\", isLaptopMedia);\r\n      }\r\n      if (element.hasAttribute(\"string-desktop\") && isDesktopMedia) {\r\n        showElement = true;\r\n        this.events.emit(\"screen:desktop\", isDesktopMedia);\r\n      }\r\n\r\n      if (showElement) {\r\n        element.style.display = null;\r\n      } else {\r\n        element.style.display = `none`;\r\n      }\r\n    });\r\n  }\r\n}\r\n","import { StringContext } from \"../../core/StringContext\";\r\nimport { StringModule } from \"../../core/StringModule\";\r\nimport { StringObject } from \"../../objects/StringObject\";\r\n\r\nexport class StringAnchor extends StringModule {\r\n  constructor(context: StringContext) {\r\n    super(context);\r\n    this.htmlKey = 'anchor';\r\n    this.attributesToMap = [\r\n      ...this.attributesToMap,\r\n      {\r\n        key: 'anchor',\r\n        type: 'tuple',\r\n        fallback: this.settings['anchor'],\r\n        transform: (tuple: string[]) => {\r\n          const [xRaw, yRaw] = tuple;\r\n          const x = this.tools.originParser.process({value: xRaw});\r\n          const y = this.tools.originParser.process({value: yRaw});\r\n          return { x, y };\r\n        },\r\n      }\r\n    ];\r\n  }\r\n  onObjectConnected(object: StringObject) {\r\n    super.onObjectConnected(object)\r\n    const anchor = object.getProperty<{ x: string, y: string }>('anchor')\r\n    if (anchor) {\r\n      this.applyToElementAndConnects(object, (el) => {\r\n        el.style.transformOrigin = `${anchor.x} ${anchor.y}`;\r\n      })\r\n    }\r\n  }\r\n\r\n}","import { StringContext } from \"../../core/StringContext\";\r\nimport { StringData } from \"../../core/StringData\";\r\nimport { StringModule } from \"../../core/StringModule\";\r\nimport { StringObject } from \"../../objects/StringObject\";\r\n\r\nconst ACCELERATION_STEP: number = 0.05;\r\nconst MIN_DISPLACEMENT: number = 0.01;\r\nconst MAX_DISPLACEMENT: number = 1;\r\nconst MIN_VELOCITY: number = -1;\r\nconst MAX_VELOCITY: number = 1;\r\n\r\nexport class StringGlide extends StringModule {\r\n  private previousLerp: number = 0;\r\n  private displacement: number = 0;\r\n  private acceleration: number = 0;\r\n  private velocityMultiplier: number = 0.00125;\r\n  private isInitialScroll: boolean = true;\r\n\r\n  private baseVelocityMultiplier: number = 0.00125;\r\n  private reducedVelocityMultiplier: number = this.baseVelocityMultiplier / 20;\r\n  private negativeVelocityMultiplier: number = -0.0001;\r\n\r\n  private maxDisplacementValue: number = 0;\r\n\r\n  constructor(context: StringContext) {\r\n    super(context);\r\n    this.htmlKey = \"glide\";\r\n\r\n    this.baseVelocityMultiplier =\r\n      this.settings[\"glide-base-velocity\"] ?? this.baseVelocityMultiplier;\r\n    this.reducedVelocityMultiplier =\r\n      this.settings[\"glide-reduce-velocity\"] ?? this.reducedVelocityMultiplier;\r\n    this.negativeVelocityMultiplier =\r\n      this.settings[\"glide-negative-velocity\"] ??\r\n      this.negativeVelocityMultiplier;\r\n\r\n    this.attributesToMap = [\r\n      ...this.attributesToMap,\r\n      { key: \"glide\", type: \"number\", fallback: this.settings[\"glide\"] },\r\n    ];\r\n  }\r\n\r\n  private setupItem = (object: StringObject) => {\r\n    let glide = object.getProperty<number>(\"glide\") ?? 0;\r\n\r\n    let glideValue =\r\n      -this.data.scroll.displacement * this.maxDisplacementValue * glide;\r\n    this.events.emit(`object:glide:${object.id}`, glideValue);\r\n\r\n    const transformCompute = `translate3d(0, ${glideValue}px, 0)`;\r\n    object.htmlElement.style.transform = transformCompute;\r\n  };\r\n\r\n  private onUpdateDesktopEvent = () => {\r\n    for (let i = 0; i < this.objects.length; i++) {\r\n      let object = this.objects[i];\r\n      this.setupItem(object);\r\n    }\r\n  };\r\n  private onUpdateMobileEvent = () => {};\r\n  private onUpdateEvent = this.onUpdateDesktopEvent;\r\n\r\n  private calcExpanderFactor(isDirectionUp: boolean): void {\r\n    const isConditionMet = isDirectionUp\r\n      ? this.data.scroll.lerped < this.previousLerp\r\n      : this.data.scroll.lerped > this.previousLerp;\r\n\r\n    this.velocityMultiplier = isConditionMet\r\n      ? this.isInitialScroll\r\n        ? this.baseVelocityMultiplier\r\n        : this.reducedVelocityMultiplier\r\n      : this.negativeVelocityMultiplier;\r\n\r\n    if (!isConditionMet) {\r\n      this.isInitialScroll = false;\r\n    }\r\n  }\r\n  onStart(): void {\r\n    this.maxDisplacementValue = this.data.viewport.windowHeight * 0.1;\r\n  }\r\n\r\n  onResize(): void {\r\n    if (window.innerWidth > 1080) {\r\n      this.maxDisplacementValue = this.data.viewport.windowHeight * 0.1;\r\n      this.onUpdateEvent = this.onUpdateDesktopEvent;\r\n    } else {\r\n      this.onUpdateEvent = this.onUpdateMobileEvent;\r\n      this.resetState();\r\n      this.objects.forEach((object) => {\r\n        this.setupItem(object);\r\n      });\r\n    }\r\n  }\r\n\r\n  private resetState(): void {\r\n    this.displacement = 0;\r\n    this.acceleration = 0;\r\n    this.isInitialScroll = true;\r\n    this.velocityMultiplier = this.baseVelocityMultiplier;\r\n  }\r\n\r\n  onScrollStart(): void {\r\n    this.resetState();\r\n  }\r\n\r\n  onScrollStop(): void {\r\n    this.resetState();\r\n    this.previousLerp = 0;\r\n    //document.documentElement.style.setProperty('--glide', '0');\r\n    for (let i = 0; i < this.objects.length; i++) {\r\n      let object = this.objects[i];\r\n      const transformCompute = `translate3d(0, 0px, 0)`;\r\n      object.htmlElement.style.transform = transformCompute;\r\n      object.htmlElement.style.setProperty(\r\n        \"--glide\",\r\n        this.data.scroll.displacement.toString()\r\n      );\r\n    }\r\n  }\r\n\r\n  onFrame(data: StringData): void {\r\n    this.calcExpanderFactor(this.data.scroll.isScrollingDown === false);\r\n    this.acceleration = Math.min(\r\n      MAX_DISPLACEMENT,\r\n      this.acceleration + ACCELERATION_STEP\r\n    );\r\n    this.displacement = Math.max(\r\n      MIN_DISPLACEMENT,\r\n      Math.min(MAX_DISPLACEMENT, this.displacement + this.velocityMultiplier)\r\n    );\r\n    this.data.scroll.displacement = Math.min(\r\n      MAX_VELOCITY,\r\n      Math.max(\r\n        MIN_VELOCITY,\r\n        this.data.scroll.lerped * this.displacement * this.acceleration\r\n      )\r\n    );\r\n    this.objects.forEach((object) => {\r\n      this.applyToElementAndConnects(object, (el) => {\r\n        el.style.setProperty(\r\n          \"--glide\",\r\n          this.data.scroll.displacement.toString()\r\n        );\r\n      });\r\n    });\r\n    this.previousLerp = this.data.scroll.lerped;\r\n    this.onUpdateEvent();\r\n  }\r\n}\r\n","import { StringContext } from \"../../core/StringContext\";\r\nimport { StringData } from \"../../core/StringData\";\r\nimport { StringModule } from \"../../core/StringModule\";\r\nimport { StringToolsContainer } from \"../../core/StringToolsContainer\";\r\nimport { StringObject } from \"../../objects/StringObject\";\r\n\r\n/**\r\n * Module that updates the `--lerp` CSS variable on elements\r\n * based on current scroll velocity.\r\n */\r\nexport class StringLerp extends StringModule {\r\n  constructor(context: StringContext) {\r\n    super(context);\r\n    this.htmlKey = \"lerp\";\r\n  }\r\n\r\n  /**\r\n   * Resets the `--lerp` value to 0 when scroll stops.\r\n   */\r\n  onScrollStop(): void {\r\n    this.objects.forEach((object) => {\r\n      this.setLerpValue(object, 0);\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Updates `--lerp` value for each connected object during scroll.\r\n   */\r\n  onFrame(data: StringData): void {\r\n    const velocity = data.scroll.lerped;\r\n    this.objects.forEach((object) => {\r\n      this.setLerpValue(object, velocity);\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Sets the `--lerp` CSS variable on the object.\r\n   */\r\n  private setLerpValue(object: StringObject, value: number): void {\r\n    this.events.emit(`object:lerp:${object.id}`, value);\r\n    object.htmlElement.style.setProperty(\"--lerp\", value.toString());\r\n  }\r\n}\r\n","import { StringContext } from \"../../core/StringContext\";\r\nimport { StringData } from \"../../core/StringData\";\r\nimport { StringModule } from \"../../core/StringModule\";\r\nimport { StringToolsContainer } from \"../../core/StringToolsContainer\";\r\nimport { StringObject } from \"../../objects/StringObject\";\r\nimport { EasingFunctionOutput } from \"../../tools/EasingFunctionTool\";\r\nimport LerpVector2Tool from \"../../tools/LerpVector2Tool\";\r\n\r\nexport class StringProgress extends StringModule {\r\n  constructor(context: StringContext) {\r\n    super(context);\r\n    this.htmlKey = \"progress\";\r\n\r\n    this.attributesToMap = [\r\n      ...this.attributesToMap,\r\n      { key: \"enter-el\", type: \"string\", fallback: this.settings[\"enter-el\"] },\r\n      { key: \"enter-vp\", type: \"string\", fallback: this.settings[\"enter-vp\"] },\r\n      { key: \"exit-el\", type: \"string\", fallback: this.settings[\"exit-el\"] },\r\n      { key: \"exit-vp\", type: \"string\", fallback: this.settings[\"exit-vp\"] },\r\n      { key: \"easing\", type: \"easing\", fallback: this.settings[\"easing\"] },\r\n    ];\r\n  }\r\n\r\n  /**\r\n   * Called when an object is initialized.\r\n   */\r\n  initializeObject(\r\n    globalId: number,\r\n    object: StringObject,\r\n    element: HTMLElement,\r\n    attributes: Record<string, any>\r\n  ): void {\r\n    super.initializeObject(globalId, object, element, attributes);\r\n  }\r\n\r\n  /**\r\n   * Called on scroll.\r\n   */\r\n  onScroll(data: StringData): void {\r\n    super.onScroll(data);\r\n    this.objects.forEach((object) => {\r\n      this.setUpObject(object);\r\n    });\r\n  }\r\n\r\n  onObjectConnected(object: StringObject) {\r\n    super.onObjectConnected(object);\r\n\r\n    object.setProperty(\"setUpObject\", this.setUpObject.bind(this));\r\n    object.events.on(\r\n      \"enter\",\r\n      object.getProperty<(object: StringObject) => void>(\"setUpObject\")\r\n    );\r\n  }\r\n\r\n  private setUpObject(object: StringObject) {\r\n    const startPosition = object.getProperty<number>(\"start-position\");\r\n    const differencePosition = object.getProperty<number>(\r\n      \"difference-position\"\r\n    );\r\n    const key = object.getProperty<string>(\"key\");\r\n\r\n    const progress = object.getProperty<EasingFunctionOutput>(\"easing\")(\r\n      Math.min(\r\n        1,\r\n        Math.max(\r\n          0,\r\n          (this.data.scroll.transformedCurrent - startPosition) /\r\n            differencePosition\r\n        )\r\n      )\r\n    );\r\n\r\n    if (object.getProperty<number>(\"progress\") !== progress) {\r\n      this.events.emit(`object:progress:${object.id}`, progress);\r\n      object.setProperty<number>(\"progress\", progress);\r\n      const progressStr = progress.toString();\r\n      this.applyToElementAndConnects(object, (el) => {\r\n        el.style.setProperty(key, progressStr);\r\n      });\r\n    }\r\n  }\r\n\r\n  calculatePositions(object: StringObject, windowSize: number) {\r\n    const start = object.getProperty<number>(\"start\");\r\n    const size = object.getProperty<number>(\"size\");\r\n\r\n    const offsetStart = object.getProperty<number>(\"offset-bottom\");\r\n    const offsetEnd = object.getProperty<number>(\"offset-top\");\r\n\r\n    const startElement = object.getProperty(\"enter-el\");\r\n    const startViewport = object.getProperty(\"enter-vp\");\r\n    const endElement = object.getProperty(\"exit-el\");\r\n    const endViewport = object.getProperty(\"exit-vp\");\r\n\r\n    let startPosition = 0;\r\n    let endPosition = 0;\r\n\r\n    if (\r\n      (startElement === \"top\" && startViewport === \"top\") ||\r\n      (startElement === \"left\" && startViewport === \"left\")\r\n    ) {\r\n      startPosition = start - offsetStart;\r\n    } else if (\r\n      (startElement === \"top\" && startViewport === \"bottom\") ||\r\n      (startElement === \"left\" && startViewport === \"right\")\r\n    ) {\r\n      startPosition = start - windowSize - offsetStart;\r\n    } else if (\r\n      (startElement === \"bottom\" && startViewport === \"top\") ||\r\n      (startElement === \"right\" && startViewport === \"left\")\r\n    ) {\r\n      startPosition = start + size - offsetStart;\r\n    } else if (\r\n      (startElement === \"bottom\" && startViewport === \"bottom\") ||\r\n      (startElement === \"right\" && startViewport === \"right\")\r\n    ) {\r\n      startPosition = start - windowSize + size - offsetStart;\r\n    }\r\n\r\n    // End position calculation\r\n    if (\r\n      (endElement === \"top\" && endViewport === \"top\") ||\r\n      (endElement === \"left\" && endViewport === \"left\")\r\n    ) {\r\n      endPosition = start + offsetEnd;\r\n    } else if (\r\n      (endElement === \"top\" && endViewport === \"bottom\") ||\r\n      (endElement === \"left\" && endViewport === \"right\")\r\n    ) {\r\n      endPosition = start - windowSize + offsetEnd;\r\n    } else if (\r\n      (endElement === \"bottom\" && endViewport === \"top\") ||\r\n      (endElement === \"right\" && endViewport === \"left\")\r\n    ) {\r\n      endPosition = start + size + offsetEnd;\r\n    } else if (\r\n      (endElement === \"bottom\" && endViewport === \"bottom\") ||\r\n      (endElement === \"right\" && endViewport === \"right\")\r\n    ) {\r\n      endPosition = start - windowSize + size + offsetEnd;\r\n    }\r\n\r\n    object.setProperty<number>(\r\n      \"start-position\",\r\n      startPosition - this.data.scroll.topPosition\r\n    );\r\n    object.setProperty<number>(\"end-position\", endPosition);\r\n    object.setProperty<number>(\r\n      \"difference-position\",\r\n      endPosition - startPosition\r\n    );\r\n  }\r\n}\r\n","import { StringContext } from \"../../core/StringContext\";\r\nimport { StringData } from \"../../core/StringData\";\r\nimport { StringObject } from \"../../objects/StringObject\";\r\nimport { StringProgress } from \"./StringProgress\";\r\n\r\nexport class StringParallax extends StringProgress {\r\n  constructor(context: StringContext) {\r\n    super(context);\r\n    this.htmlKey = \"parallax\";\r\n\r\n    this.attributesToMap = [\r\n      ...this.attributesToMap,\r\n      { key: \"parallax\", type: \"number\", fallback: this.settings[\"parallax\"] },\r\n      {\r\n        key: \"parallax-bias\",\r\n        type: \"number\",\r\n        fallback: this.settings[\"parallax-bias\"],\r\n      },\r\n    ];\r\n  }\r\n\r\n  /**\r\n   * Called when an object is initialized.\r\n   */\r\n  override initializeObject(\r\n    globalId: number,\r\n    object: StringObject,\r\n    element: HTMLElement,\r\n    attributes: Record<string, any>\r\n  ): void {\r\n    super.initializeObject(globalId, object, element, attributes);\r\n    const bias = object.getProperty<number>(\"parallax-bias\") ?? 0.0;\r\n    const factor = object.getProperty<number>(\"parallax\") ?? 0.2;\r\n\r\n    object.setProperty(\"parallax-position-start\", -0.5 + 0.5 * bias);\r\n    object.setProperty(\"parallax-position-end\", 0.5 + 0.5 * (1 - bias));\r\n\r\n    const screenSize = this.data.viewport.windowHeight;\r\n\r\n    object.setProperty(\"offset-top\", factor * screenSize);\r\n    object.setProperty(\"offset-bottom\", factor * screenSize);\r\n  }\r\n\r\n  /**\r\n   * Called on scroll.\r\n   */\r\n  override onScroll(data: StringData): void {\r\n    super.onScroll(data);\r\n    this.scrollHandler();\r\n  }\r\n\r\n  /**\r\n   * Called on resize.\r\n   */\r\n  override onResize(): void {\r\n    const isDesktop = window.innerWidth > 1080;\r\n    this.scrollHandler = isDesktop\r\n      ? this.handleScrollDesktop\r\n      : this.handleScrollMobile;\r\n\r\n    if (!isDesktop) {\r\n      this.handleScrollDesktop();\r\n    }\r\n  }\r\n\r\n  private handleScrollDesktop = (): void => {\r\n    this.objects.forEach((object) => {\r\n      const progress = object.getProperty<number>(\"progress\") ?? 0;\r\n      const factor = object.getProperty<number>(\"parallax\") ?? 0;\r\n      const start = object.getProperty<number>(\"parallax-position-start\") ?? 0;\r\n      const end = object.getProperty<number>(\"parallax-position-end\") ?? 1;\r\n\r\n      const screenSize = this.data.viewport.windowHeight;\r\n      const translation =\r\n        factor * screenSize * start + progress * factor * screenSize * end;\r\n\r\n      this.events.emit(`object:parallax:${object.id}`, translation);\r\n      const transform = `translate3d(0, ${translation}px, 0)`;\r\n      this.applyToElementAndConnects(object, (el) => {\r\n        el.style.transform = transform;\r\n      });\r\n    });\r\n  };\r\n\r\n  private handleScrollMobile = (): void => {};\r\n\r\n  private scrollHandler = this.handleScrollDesktop;\r\n}\r\n","import { StringData } from \"../../core/StringData\";\r\n\r\nexport class StringScrollbarHorizontal {\r\n  private scrollbar: any;\r\n  private thumb: any;\r\n  private isDragging = false;\r\n  private startY: number = 0;\r\n  private startScrollPosition: number = 0;\r\n  data: StringData;\r\n\r\n  constructor(data: StringData, scrollbar: any, thumb: any) {\r\n    this.data = data;\r\n    this.scrollbar = scrollbar;\r\n    this.thumb = thumb;\r\n  }\r\n\r\n  onResize(): void {\r\n    const contentWidth = this.data.viewport.contentWidth;\r\n    const visibleWidth = this.data.viewport.windowWidth;\r\n\r\n    const thumbSize = (visibleWidth / contentWidth) * visibleWidth;\r\n    this.thumb.style.setProperty('--size', thumbSize + 'px');\r\n\r\n    if (contentWidth <= visibleWidth) {\r\n      this.scrollbar.classList.add('-hide');\r\n    } else {\r\n      this.scrollbar.classList.remove('-hide');\r\n    }\r\n  }\r\n\r\n  updateThumb() {\r\n    const contentWidth = this.data.viewport.contentWidth;\r\n    const visibleWidth = this.data.viewport.windowWidth;\r\n    this.thumb.style.setProperty('--position', `${(this.data.scroll.current / contentWidth) * visibleWidth + 'px'}`);\r\n  }\r\n\r\n  mouseDownEvent(e: MouseEvent) {\r\n    this.startY = e.clientY;\r\n    this.startScrollPosition = this.data.scroll.current;\r\n  }\r\n\r\n  mouseMoveEvent(e: MouseEvent) {\r\n    const deltaY = e.clientY - this.startY;\r\n    const newScrollPosition = this.startScrollPosition + (deltaY / this.data.viewport.windowWidth) * this.data.viewport.contentWidth;\r\n    this.data.scroll.current = newScrollPosition;\r\n    this.data.scroll.target = newScrollPosition;\r\n    window.scrollTo(0, newScrollPosition);\r\n    this.updateThumb();\r\n  }\r\n}\r\n","import { StringData } from \"../../core/StringData\";\r\n\r\nexport class StringScrollbarVertical {\r\n  private scrollbar: any;\r\n  private thumb: any;\r\n  private isDragging = false;\r\n  private startCoordinate: number = 0;\r\n  private startScrollPosition: number = 0;\r\n  data: StringData;\r\n\r\n  constructor(data: StringData, scrollbar: any, thumb: any) {\r\n    this.data = data;\r\n    this.scrollbar = scrollbar;\r\n    this.thumb = thumb;\r\n  }\r\n\r\n  onResize(): void {\r\n    const contentSize = this.data.viewport.contentHeight;\r\n    const visibleSize = this.data.viewport.windowHeight;\r\n    const thumbSize = (visibleSize / contentSize) * visibleSize;\r\n    this.thumb.style.setProperty('--height', thumbSize + 'px');\r\n    if (contentSize <= visibleSize) {\r\n      this.scrollbar.classList.add('-hide');\r\n    } else {\r\n      this.scrollbar.classList.remove('-hide');\r\n    }\r\n  }\r\n\r\n  updateThumb() {\r\n    const contentHeight = this.data.viewport.contentHeight;\r\n    const visibleHeight = this.data.viewport.windowHeight;\r\n    \r\n    this.thumb.style.setProperty('--position', `${(this.data.scroll.current / contentHeight) * visibleHeight + 'px'}`);\r\n  }\r\n\r\n  mouseDownEvent(e: MouseEvent) {\r\n    this.startCoordinate = e.clientY;\r\n    this.startScrollPosition = this.data.scroll.current;\r\n  }\r\n\r\n  mouseMoveEvent(e: MouseEvent) {\r\n    const deltaY = e.clientY - this.startCoordinate;\r\n    const newScrollPosition = this.startScrollPosition + (deltaY / this.data.viewport.windowHeight) * this.data.viewport.contentHeight;\r\n    const maxScroll = this.data.scroll.bottomPosition;\r\n    const clamped = Math.max(0, Math.min(newScrollPosition, maxScroll));\r\n    this.data.scroll.current = clamped;\r\n    this.data.scroll.target = clamped;\r\n    window.scrollTo(0, clamped);\r\n    this.updateThumb();\r\n  }\r\n}\r\n","import { StringContext } from '../../core/StringContext';\r\nimport { StringData } from '../../core/StringData';\r\nimport { StringModule } from '../../core/StringModule';\r\nimport { StringScrollbarHorizontal } from './StringScrollbarHorizontal';\r\nimport { StringScrollbarVertical } from './StringScrollbarVertical';\r\n\r\nexport class StringScrollbar extends StringModule {\r\n  private scrollbar: any;\r\n  private thumb: any;\r\n  private scrollTimeout: any;\r\n\r\n  private isDragging = false;\r\n  private scrollMode: 'smooth' | 'disable' | 'default' = 'smooth';\r\n\r\n  private mouseUpEventBind: any;\r\n  private mouseDownEventBind: any;\r\n  private mouseMoveEventBind: any;\r\n\r\n  private scrollbarState: any;\r\n  private scrollbarStateHorizontal: any;\r\n  private scrollbarStateVertical: any;\r\n\r\n  constructor(context: StringContext) {\r\n    super(context)\r\n\r\n    this.mouseUpEventBind = this.mouseUpEvent.bind(this);\r\n    this.mouseDownEventBind = this.mouseDownEvent.bind(this);\r\n    this.mouseMoveEventBind = this.mouseMoveEvent.bind(this);\r\n  }\r\n  destructor(): void {\r\n    document.removeEventListener('mouseup', this.mouseUpEventBind);\r\n    this.thumb.removeEventListener('mousedown', this.mouseDownEventBind);\r\n    document.removeEventListener('mousemove', this.mouseMoveEventBind);\r\n  }\r\n\r\n  onInit(): void {\r\n    this.createScrollbar();\r\n    this.updateThumb();\r\n    this.addCustomStyles();\r\n    document.addEventListener('mouseup', this.mouseUpEventBind);\r\n    this.thumb.addEventListener('mousedown', this.mouseDownEventBind);\r\n    document.addEventListener('mousemove', this.mouseMoveEventBind);\r\n    document.documentElement.classList.add(`-no-scrollbar`);\r\n  }\r\n\r\n  onScroll(data: StringData): void {\r\n    this.updateThumb();\r\n    this.showScrollbar();\r\n    this.hideScrollbar();\r\n  }\r\n\r\n  onResize(): void {\r\n    this.scrollbarState.onResize();\r\n  }\r\n\r\n  private addCustomStyles() {\r\n    const style = document.createElement('style');\r\n    style.textContent = `\r\n          ::-webkit-scrollbar {\r\n            display: none;\r\n            width: 0;\r\n            height: 0;\r\n            -webkit-appearance: none;\r\n          }\r\n          body {\r\n            -ms-overflow-style: none;  /* IE and Edge */\r\n            scrollbar-width: none;  /* Firefox */\r\n          }\r\n          .-without-scrollbar::-webkit-scrollbar {\r\n            display: none;\r\n          }\r\n          .-without-scrollbar {\r\n              -ms-overflow-style: none; /* IE and Edge */\r\n              scrollbar-width: none; /* Firefox */\r\n          }\r\n      `;\r\n    document.head.appendChild(style);\r\n  }\r\n\r\n  private createScrollbar() {\r\n    this.scrollbar = document.createElement('div');\r\n    this.scrollbar.classList.add('scrollbar');\r\n    this.thumb = document.createElement('div');\r\n    this.thumb.classList.add('thumb');\r\n    this.scrollbar.appendChild(this.thumb);\r\n    document.body.appendChild(this.scrollbar);\r\n\r\n    this.scrollbarStateHorizontal = new StringScrollbarHorizontal(this.data, this.scrollbar, this.thumb);\r\n    this.scrollbarStateVertical = new StringScrollbarVertical(this.data, this.scrollbar, this.thumb);\r\n    this.scrollbarState = this.scrollbarStateVertical;\r\n  }\r\n\r\n  private updateThumb() {\r\n    this.scrollbarState.updateThumb();\r\n  }\r\n\r\n  private mouseDownEvent(e: MouseEvent) {\r\n    this.isDragging = true;\r\n    this.scrollbarState.mouseDownEvent(e);\r\n    document.body.style.userSelect = 'none';\r\n    this.scrollbar.classList.add('-touch');\r\n  }\r\n\r\n  private mouseMoveEvent(e: MouseEvent) {\r\n    if (!this.isDragging) return;\r\n\r\n    this.scrollbarState.mouseMoveEvent(e);\r\n  }\r\n\r\n  private mouseUpEvent() {\r\n    this.isDragging = false;\r\n    document.body.style.userSelect = '';\r\n    this.hideScrollbar();\r\n    this.scrollbar.classList.remove('-touch');\r\n  }\r\n\r\n  private showScrollbar() {\r\n    this.scrollbar.classList.add('-scroll');\r\n  }\r\n\r\n  private hideScrollbar() {\r\n    if (this.scrollTimeout) {\r\n      clearTimeout(this.scrollTimeout);\r\n    }\r\n    this.scrollTimeout = setTimeout(() => {\r\n      this.scrollbar.classList.remove('-scroll');\r\n    }, 1000);\r\n  }\r\n}\r\n","import { StringContext } from \"../../core/StringContext\";\r\nimport { StringModule } from \"../../core/StringModule\";\r\nimport { ISplitOptions } from \"../../models/text/ISplitOptions\";\r\nimport { LayoutLine } from \"../../models/text/LayoutLine\";\r\nimport { ProcessedChar } from \"../../models/text/ProcessedChar\";\r\nimport { ProcessedWord } from \"../../models/text/ProcessedWord\";\r\nimport { StringObject } from \"../../objects/StringObject\";\r\n\r\n/**\r\n * StringModule responsible for splitting text within HTML elements\r\n * into lines, words, and characters based on layout and attributes,\r\n * and applying CSS variables for animation purposes.\r\n * Uses a tool-based approach for modularity.\r\n */\r\nexport class StringSplit extends StringModule {\r\n  /**\r\n   * Initializes the StringSplit module and its tools.\r\n   * @param context - The global StringContext.\r\n   */\r\n  constructor(context: StringContext) {\r\n    super(context);\r\n    this.htmlKey = \"split\";\r\n    // Assuming tools are initialized in the base class or here if needed\r\n  }\r\n\r\n  /**\r\n   * Called when the module initializes.\r\n   * Processes elements already present in the DOM on load.\r\n   */\r\n  onInit(): void {\r\n    document\r\n      .querySelectorAll(`[string=\"${this.htmlKey}\"]`)\r\n      .forEach((element) => {\r\n        if (element instanceof HTMLElement) {\r\n          this.processElement(element);\r\n        }\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Called when the window is resized.\r\n   * Re-processes already split elements as their layout might have changed.\r\n   */\r\n  onResize(): void {\r\n    document\r\n      .querySelectorAll(`[string=\"${this.htmlKey}\"].-splited`)\r\n      .forEach((element) => {\r\n        if (element instanceof HTMLElement) {\r\n          this.processElement(element);\r\n        }\r\n      });\r\n  }\r\n\r\n  /**\r\n   * Called when a new StringObject associated with this module connects.\r\n   * Processes the newly connected element.\r\n   * @param object - The StringObject representing the connected element.\r\n   */\r\n  onObjectConnected(object: StringObject): void {\r\n    this.processElement(object.htmlElement);\r\n  }\r\n\r\n  /**\r\n   * Central method to process splitting for a given HTML element for automatic DOM manipulation.\r\n   * Orchestrates the use of various tools: parsing options, calculating layout,\r\n   * indexing words and characters, building the final HTML, and updating the DOM.\r\n   * Includes error handling.\r\n   * @param element - The HTMLElement to process.\r\n   * @private\r\n   */\r\n  private processElement(element: HTMLElement): void {\r\n    if (!element) return;\r\n\r\n    const isAlreadySplit = element.classList.contains(\"-splited\");\r\n    let originalHtml = element.getAttribute(\"string-split-original\");\r\n\r\n    if (!isAlreadySplit || originalHtml === null) {\r\n      originalHtml = element.innerHTML;\r\n      element.setAttribute(\"string-split-original\", originalHtml);\r\n      element.classList.add(\"-splited\");\r\n    }\r\n\r\n    if (!originalHtml || originalHtml.trim() === \"\") {\r\n      if (element.innerHTML !== \"\") element.innerHTML = \"\";\r\n      return;\r\n    }\r\n\r\n    try {\r\n      // Note: Assumes SplitOptionsParserTool exists on this.tools\r\n      const attributeValue = element.getAttribute(\"string-split\");\r\n      const options: ISplitOptions = this.tools.optionsParser.process({\r\n        attributeValue,\r\n      });\r\n\r\n      const newHtml = this.generateSplitHtml(originalHtml, element, options);\r\n\r\n      // Only update DOM if the generated HTML is different\r\n      if (element.innerHTML !== newHtml) {\r\n        element.innerHTML = newHtml;\r\n      }\r\n    } catch (error) {\r\n      console.error(\"StringSplit: Error processing element:\", element, error);\r\n      // Revert to original HTML as a fallback strategy\r\n      if (originalHtml !== null) {\r\n        try {\r\n          if (element.innerHTML !== originalHtml) {\r\n            element.innerHTML = originalHtml;\r\n          }\r\n        } catch (revertError) {\r\n          console.error(\r\n            \"StringSplit: Error reverting element to original HTML:\",\r\n            element,\r\n            revertError\r\n          );\r\n          // If reverting fails, at least clear it to avoid broken state\r\n          element.innerHTML = \"\";\r\n        }\r\n      } else {\r\n        // If no original HTML was stored, just clear it\r\n        element.innerHTML = \"\";\r\n      }\r\n      // Remove the split marker class as processing failed\r\n      element.classList.remove(\"-splited\");\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Generates an HTML string with split text based on the provided text,\r\n   * a reference element for layout measurement, and options. Does not modify the DOM.\r\n   *\r\n   * @param textToSplit - The text or HTML string to split.\r\n   * @param layoutReferenceElement - The HTMLElement used for layout calculations. Should be in the DOM for accurate results.\r\n   * @param options - The splitting options (ISplitOptions).\r\n   * @returns The generated HTML string with split elements, or an empty string on error.\r\n   * @public\r\n   */\r\n  public generateSplitHtml(\r\n    textToSplit: string,\r\n    layoutReferenceElement: HTMLElement,\r\n    options: ISplitOptions\r\n  ): string {\r\n    // Basic validation for tools and inputs\r\n    if (\r\n      !this.tools?.layoutSplitter ||\r\n      !this.tools?.wordIndexer ||\r\n      !this.tools?.charIndexer ||\r\n      !this.tools?.domBuilder\r\n    ) {\r\n      console.error(\"StringSplit: Required tools are not initialized.\");\r\n      return \"\";\r\n    }\r\n    if (!textToSplit || !layoutReferenceElement) {\r\n      console.error(\"StringSplit.generateSplitHtml: Invalid input provided.\");\r\n      return \"\";\r\n    }\r\n    // Warn if the reference element isn't in the DOM, as measurements might be incorrect\r\n    if (!layoutReferenceElement.isConnected) {\r\n      console.warn(\r\n        \"StringSplit.generateSplitHtml: layoutReferenceElement is not connected to the DOM. Layout calculation might be inaccurate.\"\r\n      );\r\n    }\r\n\r\n    try {\r\n      // Steps analogous to processElement, but without DOM mutation or attribute handling\r\n      const textForLayout = textToSplit; // Assuming input text is ready\r\n\r\n      // Note: Assumes layoutSplitter has 'decodeHtmlEntity' or similar utility\r\n      const textForCharCount =\r\n        this.tools.layoutSplitter[\"decodeHtmlEntity\"](textForLayout);\r\n      const totalChars = textForCharCount.replace(/\\s+/g, \"\").length;\r\n\r\n      // Calculate layout (lines and words) using the reference element\r\n      const layoutLines: LayoutLine[] = this.tools.layoutSplitter.process({\r\n        text: textForLayout,\r\n        targetElement: layoutReferenceElement,\r\n      });\r\n\r\n      // If layout calculation yields no lines (e.g., element is display:none) return empty string.\r\n      if (layoutLines.length === 0 && textForLayout.trim() !== \"\") {\r\n        console.warn(\r\n          \"StringSplit: Layout calculation resulted in no lines for text:\",\r\n          textForLayout,\r\n          \"within element:\",\r\n          layoutReferenceElement\r\n        );\r\n        return \"\";\r\n      }\r\n\r\n      // Index words based on layout and options\r\n      const processedWords: ProcessedWord[] = this.tools.wordIndexer.process({\r\n        lines: layoutLines,\r\n        options: { word: options.word, wordLine: options.wordLine },\r\n      });\r\n\r\n      // Index characters based on words, lines, options, and total count\r\n      const processedChars: ProcessedChar[] = this.tools.charIndexer.process({\r\n        processedWords: processedWords,\r\n        lines: layoutLines,\r\n        options: {\r\n          char: options.char,\r\n          charLine: options.charLine,\r\n          charWord: options.charWord,\r\n        },\r\n        totalChars: totalChars,\r\n      });\r\n\r\n      // Build the final DOM structure as a string\r\n      // Note: Assumes domBuilder tool exists\r\n      const newHtml: string = this.tools.domBuilder.process({\r\n        lines: layoutLines,\r\n        words: processedWords,\r\n        chars: processedChars,\r\n        options: options, // Pass all options for potential checks in builder\r\n      });\r\n\r\n      return newHtml; // Return the generated string\r\n    } catch (error) {\r\n      console.error(\r\n        \"StringSplit.generateSplitHtml: Error processing text:\",\r\n        textToSplit,\r\n        \"within element:\",\r\n        layoutReferenceElement,\r\n        error\r\n      );\r\n      return \"\"; // Return empty string on error\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Example demonstrating how to use generateSplitHtml.\r\n   * @param spanElement - The element to split and use for layout reference.\r\n   * @returns The resulting HTML string.\r\n   * @public\r\n   */\r\n  public exampleUsage(spanElement: HTMLElement): string {\r\n    // Define sample options\r\n    const options: ISplitOptions = {\r\n      word: [{ align: \"center\" }],\r\n      char: [\r\n        {\r\n          align: \"start\",\r\n          random: { min: 0, max: spanElement.textContent?.length || 0 },\r\n          abs: true,\r\n        },\r\n      ],\r\n    };\r\n    // Get the text content to split (use innerHTML if splitting HTML tags is intended)\r\n    const textContent = spanElement.innerHTML;\r\n\r\n    // Generate the split HTML string\r\n    const splitedHTML = this.generateSplitHtml(\r\n      textContent,\r\n      spanElement, // Use the element itself for layout reference\r\n      options\r\n    );\r\n\r\n    return splitedHTML;\r\n  }\r\n}\r\n","import { StringContext } from \"../../core/StringContext\"\r\nimport { StringData } from \"../../core/StringData\"\r\nimport { StringModule } from \"../../core/StringModule\"\r\n\r\n/**\r\n * Visual tracker that plots scroll displacement (velocity) in real time.\r\n * Useful for debugging and tuning smoothing behavior.\r\n */\r\nexport class StringDelayLerpTracker extends StringModule {\r\n  private canvas!: HTMLCanvasElement\r\n  private context!: CanvasRenderingContext2D\r\n  private history: number[] = []\r\n\r\n  private maxPoints = 0\r\n  private height = 0\r\n  private value = 0\r\n  private target = 0\r\n\r\n  constructor(context: StringContext) {\r\n    super(context)\r\n    this._type = 2\r\n  }\r\n\r\n  /**\r\n   * Called when the module starts — sets up canvas.\r\n   */\r\n  onInit(): void {\r\n    this.initCanvas()\r\n    this.maxPoints = this.canvas.width\r\n  }\r\n\r\n  /**\r\n   * Called on scroll — stores current displacement and redraws.\r\n   */\r\n  onScroll(data: StringData): void {\r\n    const d = Math.abs(data.scroll.displacement)\r\n    this.value = d\r\n    this.history.push(d)\r\n\r\n    if (this.history.length > this.maxPoints) {\r\n      this.history.shift()\r\n    }\r\n\r\n    this.draw()\r\n  }\r\n\r\n  /**\r\n   * Draws the displacement graph to canvas.\r\n   */\r\n  private draw(): void {\r\n    const ctx = this.context\r\n    const w = this.canvas.width\r\n    const h = this.canvas.height\r\n\r\n    ctx.clearRect(0, 0, w, h)\r\n\r\n    ctx.strokeStyle = \"red\"\r\n    ctx.lineWidth = 2\r\n    ctx.beginPath()\r\n\r\n    this.history.forEach((val, i) => {\r\n      const x = i\r\n      const y = h - val * this.height\r\n      i === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y)\r\n    })\r\n\r\n    ctx.stroke()\r\n  }\r\n\r\n  /**\r\n   * Creates and styles the tracking canvas.\r\n   */\r\n  private initCanvas(): void {\r\n    const canvas = document.createElement(\"canvas\")\r\n    const width = window.innerWidth * 0.5\r\n    this.height = window.innerHeight / 15 - 20\r\n\r\n    canvas.width = width\r\n    canvas.height = this.height\r\n\r\n    Object.assign(canvas.style, {\r\n      position: \"fixed\",\r\n      bottom: `${window.innerHeight / 20 + 10}px`,\r\n      left: \"50%\",\r\n      transform: \"translateX(-50%)\",\r\n      backgroundColor: \"#000000\",\r\n      border: \"1px solid rgba(255, 255, 255, 0.2)\",\r\n      zIndex: \"1000\",\r\n      pointerEvents: \"none\",\r\n    })\r\n\r\n    this.canvas = canvas\r\n    this.context = canvas.getContext(\"2d\")!\r\n    document.body.appendChild(canvas)\r\n  }\r\n\r\n  /**\r\n   * Optional method to update external comparison target.\r\n   */\r\n  public setTarget(position: number): void {\r\n    this.target = position\r\n  }\r\n\r\n  /**\r\n   * Removes the canvas from DOM and resets.\r\n   */\r\n  public clear(): void {\r\n    this.canvas.remove()\r\n    this.history = []\r\n  }\r\n}\r\n","import { StringData } from \"../..\"\r\nimport { StringContext } from \"../../core/StringContext\"\r\nimport { StringModule } from \"../../core/StringModule\"\r\n\r\n/**\r\n * FPS Tracker Module.\r\n * Displays how many times `onFrame()` is called per second.\r\n * Useful for debugging rendering performance or vsync issues.\r\n */\r\nexport class StringFPSTracker extends StringModule {\r\n  private displayElement!: HTMLDivElement\r\n  private intervalId!: number\r\n  private frameCount = 0\r\n\r\n  constructor(context: StringContext) {\r\n    super(context)\r\n    this._type = 2\r\n  }\r\n\r\n  /**\r\n   * Initializes the visual FPS counter and update interval.\r\n   */\r\n  onInit(): void {\r\n    this.createDisplayElement()\r\n\r\n    this.intervalId = window.setInterval(() => {\r\n      this.displayElement.textContent = `FPS: ${this.frameCount}`\r\n      this.frameCount = 0\r\n    }, 1000)\r\n  }\r\n\r\n  /**\r\n   * Increments the frame counter each frame.\r\n   */\r\n  onFrame(_data: StringData): void {\r\n    this.frameCount++\r\n  }\r\n\r\n  /**\r\n   * Cleans up DOM and interval.\r\n   */\r\n  destroy(): void {\r\n    clearInterval(this.intervalId)\r\n    this.displayElement.remove()\r\n  }\r\n\r\n  /**\r\n   * Creates and styles the floating FPS display.\r\n   */\r\n  private createDisplayElement(): void {\r\n    const el = document.createElement(\"div\")\r\n\r\n    Object.assign(el.style, {\r\n      position: \"fixed\",\r\n      bottom: \"10px\",\r\n      right: \"10px\",\r\n      backgroundColor: \"#000\",\r\n      color: \"#fff\",\r\n      padding: \"4px 8px\",\r\n      fontSize: \"12px\",\r\n      fontFamily: \"monospace\",\r\n      border: \"1px solid rgba(255,255,255,0.2)\",\r\n      zIndex: \"1000\",\r\n      pointerEvents: \"none\",\r\n    })\r\n\r\n    el.textContent = \"FPS: 0\"\r\n    document.body.appendChild(el)\r\n\r\n    this.displayElement = el\r\n  }\r\n}\r\n","import { StringData } from \"../..\"\r\nimport { StringContext } from \"../../core/StringContext\"\r\nimport { StringModule } from \"../../core/StringModule\"\r\n\r\n/**\r\n * Visual tracker that plots lerped scroll velocity (v) in real time.\r\n * Useful for analyzing smooth scroll interpolation behavior.\r\n */\r\nexport class StringLerpTracker extends StringModule {\r\n  private canvas!: HTMLCanvasElement\r\n  private context!: CanvasRenderingContext2D\r\n  private history: number[] = []\r\n\r\n  private maxPoints = 0\r\n  private canvasHeight = 0\r\n  private currentValue = 0\r\n  private targetValue = 0\r\n\r\n  constructor(context: StringContext) {\r\n    super(context)\r\n    this._type = 2\r\n  }\r\n\r\n  /**\r\n   * Called on start — sets up canvas overlay.\r\n   */\r\n  onInit(): void {\r\n    this.initCanvas()\r\n    this.maxPoints = this.canvas.width\r\n  }\r\n\r\n  /**\r\n   * Called on scroll — reads smoothed scroll velocity (v).\r\n   */\r\n  onScroll(data: StringData): void {\r\n    const v = Math.abs(data.scroll.displacement)\r\n    this.currentValue = v\r\n    this.history.push(v)\r\n\r\n    if (this.history.length > this.maxPoints) {\r\n      this.history.shift()\r\n    }\r\n\r\n    this.draw()\r\n  }\r\n\r\n  /**\r\n   * Draws the current graph line based on v-history.\r\n   */\r\n  private draw(): void {\r\n    const ctx = this.context\r\n    const w = this.canvas.width\r\n    const h = this.canvas.height\r\n\r\n    ctx.clearRect(0, 0, w, h)\r\n\r\n    ctx.strokeStyle = \"#007bff\"\r\n    ctx.lineWidth = 2\r\n    ctx.beginPath()\r\n\r\n    this.history.forEach((val, i) => {\r\n      const x = i\r\n      const y = h - val / 2\r\n      i === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y)\r\n    })\r\n\r\n    ctx.stroke()\r\n  }\r\n\r\n  /**\r\n   * Creates the canvas overlay and applies style.\r\n   */\r\n  private initCanvas(): void {\r\n    this.canvas = document.createElement(\"canvas\")\r\n    this.canvasHeight = window.innerHeight / 15 - 20\r\n    this.canvas.width = window.innerWidth * 0.5\r\n    this.canvas.height = this.canvasHeight\r\n\r\n    Object.assign(this.canvas.style, {\r\n      position: \"fixed\",\r\n      bottom: \"10px\",\r\n      left: \"50%\",\r\n      transform: \"translateX(-50%)\",\r\n      backgroundColor: \"#000\",\r\n      border: \"1px solid rgba(255,255,255,0.2)\",\r\n      zIndex: \"1000\",\r\n      pointerEvents: \"none\",\r\n    })\r\n\r\n    this.context = this.canvas.getContext(\"2d\")!\r\n    document.body.appendChild(this.canvas)\r\n  }\r\n\r\n  /**\r\n   * Optional external target value for debugging.\r\n   */\r\n  public setTarget(position: number): void {\r\n    this.targetValue = position\r\n  }\r\n\r\n  /**\r\n   * Removes canvas from DOM and clears history.\r\n   */\r\n  public clear(): void {\r\n    this.canvas.remove()\r\n    this.history = []\r\n  }\r\n}\r\n","import { StringData } from \"../..\"\r\nimport { StringContext } from \"../../core/StringContext\"\r\nimport { StringModule } from \"../../core/StringModule\"\r\n\r\n/**\r\n * Tracker module that shows current scroll position and direction.\r\n * Displays a fixed label in the corner of the screen for debugging.\r\n */\r\nexport class StringPositionTracker extends StringModule {\r\n  private displayElement!: HTMLDivElement\r\n\r\n  constructor(context: StringContext) {\r\n    super(context)\r\n    this._type = 2\r\n  }\r\n\r\n  /**\r\n   * Called on start — creates the DOM element for position display.\r\n   */\r\n  onInit(): void {\r\n    this.createDisplayElement()\r\n  }\r\n\r\n  /**\r\n   * Called on scroll — updates scroll position and direction symbol.\r\n   */\r\n  onScroll(data: StringData): void {\r\n    const current = data.scroll.current\r\n    const target = data.scroll.target\r\n\r\n    const direction = current < target ? \"↓\" : current > target ? \"↑\" : \"-\"\r\n\r\n    this.displayElement.setAttribute(\"data-dir\", direction)\r\n    this.displayElement.setAttribute(\"data-val\", `${Math.round(current)}`)\r\n  }\r\n\r\n  /**\r\n   * Removes display element from DOM.\r\n   */\r\n  destroy(): void {\r\n    this.displayElement.remove()\r\n  }\r\n\r\n  /**\r\n   * Creates and styles the floating position indicator.\r\n   */\r\n  private createDisplayElement(): void {\r\n    const el = document.createElement(\"div\")\r\n\r\n    Object.assign(el.style, {\r\n      position: \"fixed\",\r\n      bottom: \"10px\",\r\n      left: \"10px\",\r\n      backgroundColor: \"#000\",\r\n      color: \"#fff\",\r\n      border: \"1px solid rgba(255,255,255,0.2)\",\r\n      padding: \"5px 8px\",\r\n      fontSize: \"12px\",\r\n      fontFamily: \"monospace\",\r\n      zIndex: \"1000\",\r\n      pointerEvents: \"none\",\r\n    })\r\n\r\n    el.setAttribute(\"data-dir\", \"-\")\r\n    el.setAttribute(\"data-val\", \"0\")\r\n    document.body.appendChild(el)\r\n\r\n    // Inject dynamic CSS if needed\r\n    const style = document.createElement(\"style\")\r\n    style.innerHTML = `\r\n      div[data-dir][data-val]::before {\r\n        content: attr(data-dir) ' Top: ' attr(data-val) 'px';\r\n      }\r\n    `\r\n    document.head.appendChild(style)\r\n\r\n    this.displayElement = el\r\n  }\r\n}\r\n","/**\r\n * Creates a debounced version of a function that delays invoking the function\r\n * until after `delay` milliseconds have passed since the last time the\r\n * debounced function was invoked.\r\n *\r\n * @template T The type of the function to debounce.\r\n * @param func The function to debounce.\r\n * @param delay The number of milliseconds to delay.\r\n * @returns The new debounced function.\r\n */\r\nexport function Debounce<T extends (...args: any[]) => any>(func: T, delay: number): (...args: Parameters<T>) => void {\r\n  let timeoutId: ReturnType<typeof setTimeout> | null = null;\r\n\r\n  // Return a new function that will be called instead of the original\r\n  return function(this: ThisParameterType<T>, ...args: Parameters<T>) {\r\n    // Capture the 'this' context and arguments for the original function\r\n    const context = this;\r\n\r\n    // If there is already a scheduled call, cancel it\r\n    if (timeoutId) {\r\n      clearTimeout(timeoutId);\r\n    }\r\n\r\n    // Schedule a new call to the original function after 'delay' ms\r\n    timeoutId = setTimeout(() => {\r\n      func.apply(context, args); // Call the original function with the correct 'this' and arguments\r\n      timeoutId = null; // Clear the timer ID after execution (optional but good practice)\r\n    }, delay);\r\n  };\r\n}","/**\r\n * Utility class that provides a customizable requestAnimationFrame loop.\r\n * Allows running a callback function on every frame or at a specific FPS rate.\r\n * Automatically pauses on `document.hidden` and resumes on visibility change.\r\n */\r\nexport class StringFPS {\r\n  /** Target frames per second (FPS). */\r\n  private fps: number = 0;\r\n\r\n  /** Whether the animation loop is currently active. */\r\n  private isAnimationStarted: boolean = false;\r\n\r\n  /** Time interval between frames in milliseconds, based on FPS. */\r\n  private fpsInterval: number = 0;\r\n\r\n  /** Timestamp of the previous frame (used for timing calculations). */\r\n  private then: number = 0;\r\n\r\n  /** The requestAnimationFrame ID (used to cancel the loop). */\r\n  private requestAnimationId: number = 0;\r\n\r\n  /** Bound function for visibilitychange event handler. */\r\n  private onVisibilityChangeBind: any;\r\n\r\n  /** Callback executed on each frame. */\r\n  private onFrameCallback: (time: number) => void = (time: number) => {};\r\n\r\n  /** Internal animation loop function. */\r\n  private animate: () => void = () => {};\r\n\r\n  constructor() {\r\n    this.onVisibilityChangeBind = this.onVisibilityChange.bind(this);\r\n  }\r\n\r\n  /**\r\n   * Handles visibility change events.\r\n   * Stops the loop when the document is hidden and resumes it when visible.\r\n   */\r\n  private onVisibilityChange() {\r\n    if (document.hidden) {\r\n      this.stop();\r\n      this.isAnimationStarted = false;\r\n    } else {\r\n      this.start(this.fps);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Starts the animation loop at a given FPS rate.\r\n   * If `fps` is 0, runs the callback as fast as possible (uncapped).\r\n   * \r\n   * @param fps Target frames per second (0 = uncapped).\r\n   */\r\n  public start(fps: number) {\r\n    this.fps = fps;\r\n    if (this.isAnimationStarted) return;\r\n\r\n    this.fpsInterval = 1000 / fps;\r\n    this.then = performance.now();\r\n    this.isAnimationStarted = true;\r\n\r\n    if (fps === 0) {\r\n      this.animate = () => {\r\n        const now = performance.now();\r\n        this.requestAnimationId = requestAnimationFrame(() => this.animate());\r\n        this.onFrameCallback(now);\r\n      };\r\n    } else {\r\n      this.animate = () => {\r\n        const now = performance.now();\r\n        const elapsed = now - this.then;\r\n        if (elapsed > this.fpsInterval) {\r\n          this.then = now - (elapsed % this.fpsInterval);\r\n          this.onFrameCallback(now);\r\n        }\r\n        this.requestAnimationId = requestAnimationFrame(() => this.animate());\r\n      };\r\n    }\r\n\r\n    this.animate();\r\n    // document.addEventListener(\"visibilitychange\", this.onVisibilityChangeBind);\r\n  }\r\n\r\n  /**\r\n   * Stops the animation loop and removes the animation frame.\r\n   */\r\n  public stop() {\r\n    if (!this.isAnimationStarted) return;\r\n    cancelAnimationFrame(this.requestAnimationId);\r\n    this.requestAnimationId = 0;\r\n    this.isAnimationStarted = false;\r\n  }\r\n\r\n  /**\r\n   * Assigns a callback function to be called on each frame.\r\n   * \r\n   * @param callback The function to execute per frame.\r\n   */\r\n  public setOnFrame(callback: (time: number) => void) {\r\n    this.onFrameCallback = callback;\r\n  }\r\n\r\n  /**\r\n   * Stops the loop and removes event listeners.\r\n   * Should be called when the loop is no longer needed.\r\n   */\r\n  public destructor() {\r\n    this.stop();\r\n    // document.removeEventListener(\"visibilitychange\", this.onVisibilityChangeBind);\r\n  }\r\n}\r\n","import { StringObject } from \"../../objects/StringObject\";\r\nimport { StringModule } from \"../../core/StringModule\";\r\nimport { StringContext } from \"../../core/StringContext\";\r\n\r\nexport class StringVideoAutoplay extends StringModule {\r\n  constructor(context: StringContext) {\r\n    super(context);\r\n    this.htmlKey = \"autoplay\";\r\n\r\n    this.attributesToMap = [\r\n      ...this.attributesToMap,\r\n      {\r\n        key: \"src\",\r\n        type: \"string\",\r\n        fallback: \"\",\r\n      },\r\n    ];\r\n  }\r\n\r\n  onObjectConnected(object: StringObject) {\r\n    object.setProperty(\"onEnterEvent\", this.onEnterObject.bind(this));\r\n    object.events.on(\r\n      \"enter\",\r\n      object.getProperty<(object: StringObject) => void>(\"onEnterEvent\")\r\n    );\r\n    object.setProperty(\"onLeaveEvent\", this.onLeaveObject.bind(this));\r\n    object.events.on(\r\n      \"leave\",\r\n      object.getProperty<(object: StringObject) => void>(\"onLeaveEvent\")\r\n    );\r\n\r\n    const videoElement = object.htmlElement as HTMLVideoElement;\r\n    const started =\r\n      this.tools.domAttribute.process({\r\n        element: videoElement,\r\n        key: \"string-started\",\r\n        fallback: null,\r\n      }) !== null;\r\n\r\n    if (videoElement.tagName.toLowerCase() === \"video\" && !started) {\r\n      videoElement.setAttribute(\"string-started\", \"\");\r\n      videoElement.muted = true;\r\n      videoElement.setAttribute(\"muted\", \"muted\");\r\n      videoElement.setAttribute(\"playsinline\", \"\");\r\n      videoElement.setAttribute(\"loop\", \"\");\r\n      videoElement.setAttribute(\"autoplay\", \"\");\r\n      videoElement.src = object.getProperty(\"src\");\r\n      videoElement.load();\r\n      videoElement.addEventListener(\"canplay\", () => {});\r\n    }\r\n  }\r\n\r\n  private onEnterObject(object: StringObject) {\r\n    const videoElement = object.htmlElement as HTMLVideoElement;\r\n    this.tryPlay(videoElement);\r\n  }\r\n  private onLeaveObject(object: StringObject) {\r\n    const videoElement = object.htmlElement as HTMLVideoElement;\r\n    videoElement.pause();\r\n  }\r\n\r\n  private tryPlay(element: HTMLVideoElement) {\r\n    element\r\n      .play()\r\n      .catch((err) =>\r\n        console.warn(\"[StringVideoAutoplay] Autoplay failed:\", err)\r\n      );\r\n  }\r\n}\r\n"],"mappings":"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","names":["index_exports","__export","StringAnchor","StringCursor","StringData","StringDelayLerpTracker","StringFPSTracker","StringGlide","StringLazy","StringLerp","StringLerpTracker","StringLoading","StringMagnetic","StringModule","StringObject","StringParallax","StringPositionTracker","StringProgress","StringResponsive","StringScrollbar","StringSplit","StringTune","StringVideoAutoplay","__toCommonJS","CursorController","smoothing","context","e","targetX","targetY","smoothedX","smoothedY","stepX","stepY","distance","lerp","x","y","EventManager","eventName","callback","id","fullEvent","payload","set","value","visible","ModuleManager","data","module","type","m","e","added","removed","StringObject","id","element","EventManager","key","value","module","ObjectManager","data","modules","events","el","idAttr","object","StringObject","keysAttr","attributes","m","q","item","id","obj","element","attr","start","end","inviewTop","inviewBottom","progressCallback","entries","e","inviewCallback","progressObserver","inviewObserver","mutations","mutation","node","child","copyFrom","ScrollController","context","scrollDirection","e","StringScrollDefault","ScrollController","context","delta","scrollTop","plusDelta","StringScrollDisable","ScrollController","context","CLASS_NAMES","StringScrollSmooth","ScrollController","context","newDirection","absVelocity","scrollDirection","atTop","atBottom","ScrollManager","context","StringScrollSmooth","StringScrollDefault","StringScrollDisable","mode","newMode","engine","e","events","CursorState","RenderState","ScrollState","TimeState","ViewportState","StringData","ScrollState","ViewportState","CursorState","RenderState","TimeState","StringModule","context","element","object","boundingRect","top","height","globalId","attributes","key","type","fallback","transform","resolvedFallback","raw","parsed","windowSize","value","id","index","applyFn","data","event","added","removed","BoundingClientRectTool","element","DOMAttributeTool","element","key","fallback","RecordAttributeTool","record","name","fallback","TransformNullifyTool","element","rect","values","a","b","c","d","e","f","det","RelativePositionTool","transformTool","TransformNullifyTool","element","container","containerRect","elRect","LerpTool","from","to","progress","UnitParserTool","value","element","viewportHeight","baseRem","isNegative","result","AdaptiveLerpTool","value","inMin","inMax","outMin","outMax","t","OriginParserTool","value","raw","options","s","index","ColorParserTool","value","str","hex","ch","r","g","b","a","rgbMatch","v","hslMatch","h","l","s","hue2rgb","p","q","t","ValidationTool","value","rules","messages","rule","code","raw","message","EasingFunctionTool","easing","def","match","x1","y1","x2","y2","t","cx","bx","ax","cy","by","ay","sampleCurveX","sampleCurveY","sampleCurveDerivativeX","solveCurveX","x","epsilon","t0","t1","t2","d2","i","MagneticPullTool","distance","radius","strength","proximity","LerpColorTool","from","to","progress","LerpVector2Tool","from","to","progress","TransformScaleParserTool","value","str","matrixValues","matrixNumbers","scaleValue","scaleNumbers","scaleXValue","scaleNumber","scale3dValue","matrix3dValues","error","CharIndexerTool","processedWords","lines","options","totalChars","processedChars","globalCharIndex","totalLineCharsMap","line","lineIndex","totalCharsInLine","sum","word","currentLineCharIndex","previousLineIndex","pWord","wordText","parentLineIndex","wordLength","totalCharsInCurrentLine","char","wordCharIndex","calculatedValues","optDef","value","option","primaryIndex","localIndex","parentLength","index","min","max","effectiveMin","effectiveMax","LayoutLineSplitterTool","text","targetElement","words","word","tempSpan","compStyles","layoutLines","currentLineWords","currentLineWidth","spaceWidth","containerWidth","wordWidth","potentialWidth","w","str","SplitDomBuilderTool","lines","words","chars","options","rootElement","wordCounter","charCounter","needsLineSpans","needsWordSpans","needsCharSpans","line","lineIndex","lineContainer","wordsInThisLine","pWord","indexInLine","currentWordChars","wordSpan","pChar","charSpan","span","calculatedValues","calcValue","variableName","type","align","WordIndexerTool","lines","options","processedWords","globalWordIndex","totalWords","sum","line","lineIndex","wordsInLine","lineWordCount","word","wordIndexInLine","calculatedValues","optDef","value","option","primaryIndex","localIndex","parentLength","index","min","max","effectiveMin","effectiveMax","SplitOptionsParserTool","attributeValue","options","part","trimmedPart","match","prefix","optionType","fullOptionKey","params","p","parsedParam","result","param","randomMatch","DefaultToolsContainer","DOMAttributeTool","RecordAttributeTool","TransformNullifyTool","BoundingClientRectTool","RelativePositionTool","UnitParserTool","LerpTool","AdaptiveLerpTool","OriginParserTool","ColorParserTool","ValidationTool","EasingFunctionTool","MagneticPullTool","LerpColorTool","LerpVector2Tool","TransformScaleParserTool","LayoutLineSplitterTool","WordIndexerTool","CharIndexerTool","SplitDomBuilderTool","SplitOptionsParserTool","StringCursor","StringModule","context","value","globalId","object","element","attributes","data","isOver","isDisabled","lerpFactor","rect","cursorX","cursorY","elementX","elementY","px","py","dx","dy","lerpedX","lerpedY","updatedX","updatedY","alignment","offsetX","offsetY","mouseX","mouseY","halfWidth","halfHeight","targetX","targetY","newMouseX","newMouseY","stepX","stepY","smoothedX","smoothedY","cursorClass","x","y","el","mousePos","size","StringMagnetic","StringModule","context","globalId","object","element","attributes","e","rect","centerX","centerY","dx","dy","distance","radius","strength","factor","data","magneticX","magneticY","lerp","targetMagneticX","targetMagneticY","lerpX","lerpY","el","StringLazy","StringModule","context","img","object","src","el","url","resolve","reject","xhr","blob","StringLoading","StringModule","context","StringInview","StringModule","visitor","object","StringResponsiveQueryDevice","config","enable","min","max","query","StringResponsive","StringModule","context","isMobileMedia","isTabletMedia","isLaptopMedia","isDesktopMedia","element","showElement","StringAnchor","StringModule","context","tuple","xRaw","yRaw","x","y","object","anchor","el","ACCELERATION_STEP","MIN_DISPLACEMENT","MAX_DISPLACEMENT","MIN_VELOCITY","MAX_VELOCITY","StringGlide","StringModule","context","object","glide","glideValue","transformCompute","i","isDirectionUp","isConditionMet","data","el","StringLerp","StringModule","context","object","data","velocity","value","StringProgress","StringModule","context","globalId","object","element","attributes","data","startPosition","differencePosition","key","progress","progressStr","el","windowSize","start","size","offsetStart","offsetEnd","startElement","startViewport","endElement","endViewport","endPosition","StringParallax","StringProgress","context","object","progress","factor","start","end","screenSize","translation","transform","el","globalId","element","attributes","bias","data","isDesktop","StringScrollbarHorizontal","data","scrollbar","thumb","contentWidth","visibleWidth","thumbSize","e","deltaY","newScrollPosition","StringScrollbarVertical","data","scrollbar","thumb","contentSize","visibleSize","thumbSize","contentHeight","visibleHeight","e","deltaY","newScrollPosition","maxScroll","clamped","StringScrollbar","StringModule","context","data","style","StringScrollbarHorizontal","StringScrollbarVertical","StringSplit","StringModule","context","element","object","isAlreadySplit","originalHtml","attributeValue","options","newHtml","error","revertError","textToSplit","layoutReferenceElement","textForLayout","totalChars","layoutLines","processedWords","processedChars","spanElement","textContent","StringDelayLerpTracker","StringModule","context","data","d","ctx","w","h","val","i","x","y","canvas","width","position","StringFPSTracker","StringModule","context","_data","el","StringLerpTracker","StringModule","context","data","v","ctx","w","h","val","i","x","y","position","StringPositionTracker","StringModule","context","data","current","target","direction","el","style","Debounce","func","delay","timeoutId","args","context","StringFPS","time","fps","now","elapsed","callback","StringVideoAutoplay","StringModule","context","object","videoElement","started","element","err","StringTune","_StringTune","StringFPS","Debounce","DefaultToolsContainer","StringData","EventManager","ModuleManager","ObjectManager","CursorController","ScrollManager","time","value","container","speed","mode","type","objectClass","settings","effectiveSettings","module","eventName","callback","id","fps","observerContainerMutation","mutationsList","observer","mutation","config","StringInview","htmlFontSize","fontSizeNumber","element","connectTargetId","e","scroll","width","height","newScrollHeight","newContainerTopPosition","rect","transformScale","isDesktop","widthChanged","heightChanged","scrollHeightChanged","shouldRebuild"]}