@fiddle-digital/string-tune 1.1.5 → 1.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"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/models/scroll/ScrollHTMLClass.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/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/models/text/SplitElementClass.ts","../src/utils/text/BuildDOMTree.ts","../src/utils/text/BuildTokens.ts","../src/utils/text/LayoutMeasurer.ts","../src/utils/text/SplitMeasuredTokens.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","../src/models/slider/SequenceState.ts","../src/modules/slider/StringSequence.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\nimport { ScrollMarkRule } from \"./models/scroll/ScrollTriggerRule\";\r\nimport { StringSequence } from \"./modules/slider/StringSequence\";\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.transformedCurrent =\r\n this.data.scroll.current * this.data.viewport.transformScale;\r\n this.data.scroll.delta = 0;\r\n this.data.scroll.lerped = 0;\r\n this.scrollManager.updatePosition();\r\n this.moduleManager.onScroll();\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;\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 public emit(eventName: string, data: any) {\r\n this.eventManager.emit(eventName, data);\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 * Adds a scroll trigger rule that activates when the user scrolls past a defined offset\r\n * in a specific direction. This can be used to toggle CSS classes or execute callbacks\r\n * when elements come into view or go out of view.\r\n *\r\n * @param rule - The scroll trigger configuration object.\r\n * - `id`: A unique identifier for this rule.\r\n * - `offset`: The vertical scroll offset (in pixels) where the rule should activate.\r\n * - `direction`: Defines the scroll direction required to activate the rule.\r\n * Can be `\"forward\"`, `\"backward\"`, or `\"any\"`.\r\n * - `onEnter`: (Optional) A function that will be called when the scroll position enters the trigger zone\r\n * in the specified direction.\r\n * - `onLeave`: (Optional) A function that will be called when the scroll position leaves the trigger zone\r\n * or scrolls in the opposite direction.\r\n * - `toggleClass`: (Optional) An object defining a class toggle behavior.\r\n * It contains a target element and a class name to be added when the trigger is active\r\n * and removed when it's not.\r\n */\r\n public addScrollMark(rule: ScrollMarkRule) {\r\n this.scrollManager.addScrollMark(rule);\r\n }\r\n\r\n /**\r\n * Removes a scroll trigger by its unique identifier.\r\n *\r\n * @param id - The unique identifier of the scroll trigger to be removed.\r\n */\r\n public removeScrollMark(id: string) {\r\n this.scrollManager.removeScrollMark(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 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 const target = e.target as HTMLElement;\r\n const isModal = target.closest(\r\n \"[string-isolation],[data-string-isolation]\"\r\n );\r\n if (isModal != null) return;\r\n\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.objectManager.checkInview();\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 if (this.context.data.scroll.container.scrollTop > 0) {\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 }\r\n\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 StringSequence,\r\n type ScrollMarkRule as ScrollTriggerRule,\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 * Removes the current object by iterating through all associated modules\r\n * and invoking their `removeObject` method with the object's ID.\r\n *\r\n * This method ensures that the object is properly removed from all\r\n * modules it is associated with.\r\n */\r\n public remove(): void {\r\n this.modules.forEach((module) => {\r\n module.removeObject(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 let idAttr = `string-${this.globalId++}`;\r\n let key = \"string-id\";\r\n\r\n if (el.getAttribute(\"string-id\")) {\r\n idAttr = el.getAttribute(\"string-id\")!;\r\n key = \"string-id\";\r\n }\r\n if (el.getAttribute(\"data-string-id\")) {\r\n idAttr = el.getAttribute(\"data-string-id\")!;\r\n key = \"data-string-id\";\r\n }\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(key, 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 m.addObject(object.id, 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 obj.remove();\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 /**\r\n * Retrieves all attributes of a given HTML element and returns them as a record.\r\n *\r\n * @param el - The HTML element from which to extract attributes.\r\n * @returns A record where the keys are attribute names and the values are attribute values.\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 /**\r\n * Initializes IntersectionObservers for a given object and its associated HTML element.\r\n *\r\n * This method sets up observer:\r\n * - A \"progress\" observer to track when the object enters or leaves the viewport.\r\n *\r\n * The observers are configured with custom root margins and thresholds based on the object's properties.\r\n * Existing observers, if any, are disconnected before creating new ones.\r\n *\r\n * @param obj - The `StringObject` instance containing properties and methods for interaction.\r\n * @param el - The `HTMLElement` to observe for intersection changes.\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 obj.getProperty<IntersectionObserver>(\"observer-progress\")?.disconnect();\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 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,\r\n });\r\n progressObserver.observe(el);\r\n obj.setProperty(\"observer-progress\", progressObserver);\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 =\r\n el.getAttribute(\"string-id\") ?? el.getAttribute(\"data-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 public checkInview() {\r\n this.objects.forEach((object) => {\r\n const scrollPos = this.data.scroll.transformedCurrent;\r\n const inviewStart = object.getProperty<number>(\"inview-start-position\");\r\n const inviewEnd = object.getProperty<number>(\"inview-end-position\");\r\n const wasInView = object.getProperty<boolean>(\"is-inview\") ?? false;\r\n const isNowInView = scrollPos >= inviewStart && scrollPos <= inviewEnd;\r\n if (isNowInView !== wasInView) {\r\n object.setProperty(\"is-inview\", isNowInView);\r\n this.events.emit(`object:inview:${object.id}`, isNowInView);\r\n isNowInView ? object.show() : object.hide();\r\n }\r\n });\r\n }\r\n}\r\n","import { ScrollMarkRule } from \"../../models/scroll/ScrollTriggerRule\";\r\nimport { 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 * Current scroll direction.\r\n * - `true` — scrolling down\r\n * - `false` — scrolling up\r\n * - `null` — unknown (initial state)\r\n */\r\n protected isBottomScrollDirection: boolean | null = null;\r\n\r\n protected isLastBottomScrollDirection: boolean = true;\r\n\r\n protected scrollTriggerRules: Array<ScrollMarkRule> = [];\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.triggerScrollRules();\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 };\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 this.triggerScrollRules();\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 private triggerScrollRules() {\r\n this.scrollTriggerRules.forEach((rule) => {\r\n const shouldTrigger =\r\n (rule.direction === \"any\" ||\r\n (this.isLastBottomScrollDirection && rule.direction === \"forward\")) &&\r\n this.context.data.scroll.current >= rule.offset;\r\n if (shouldTrigger) {\r\n rule.onEnter?.();\r\n if (rule.toggleClass) {\r\n rule.toggleClass.target.classList.add(rule.toggleClass.className);\r\n }\r\n } else {\r\n rule.onLeave?.();\r\n if (rule.toggleClass) {\r\n rule.toggleClass.target.classList.remove(rule.toggleClass.className);\r\n }\r\n }\r\n });\r\n }\r\n\r\n public addScrollMark(rule: ScrollMarkRule) {\r\n this.scrollTriggerRules.push(rule);\r\n }\r\n\r\n public removeScrollMark(id: string) {\r\n this.scrollTriggerRules = this.scrollTriggerRules.filter(\r\n (rule) => rule.id !== id\r\n );\r\n }\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","/**\n * CSS class names applied to `<html>` element based on scroll direction.\n */\nexport const SCROLL_CLASS_NAMES = {\n SCROLL_FORWARD: \"-scroll-forward\",\n SCROLL_BACKWARD: \"-scroll-backward\",\n SCROLLING_FORWARD: \"-scrolling-forward\",\n SCROLLING_BACKWARD: \"-scrolling-backward\",\n} as const;\n","import { SCROLL_CLASS_NAMES } from \"../../models/scroll/ScrollHTMLClass\";\r\nimport { StringContext } from \"../StringContext\";\r\nimport { ScrollController } from \"./ScrollController\";\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\n public 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\n private 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\n private 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\n private 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\n private previousCurrent: number = 0;\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\n private readonly velocityThreshold = 0.1;\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 this.isLastBottomScrollDirection = newDirection;\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(\r\n SCROLL_CLASS_NAMES.SCROLLING_FORWARD,\r\n newDirection\r\n );\r\n document.documentElement.classList.toggle(\r\n SCROLL_CLASS_NAMES.SCROLLING_BACKWARD,\r\n !newDirection\r\n );\r\n document.documentElement.classList.toggle(\r\n SCROLL_CLASS_NAMES.SCROLL_FORWARD,\r\n newDirection\r\n );\r\n document.documentElement.classList.toggle(\r\n SCROLL_CLASS_NAMES.SCROLL_BACKWARD,\r\n !newDirection\r\n );\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(\r\n SCROLL_CLASS_NAMES.SCROLLING_BACKWARD,\r\n SCROLL_CLASS_NAMES.SCROLLING_FORWARD\r\n );\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 =\r\n this.context.data.scroll.elementContainer.scrollTop;\r\n this.context.data.scroll.target =\r\n this.context.data.scroll.elementContainer.scrollTop;\r\n this.context.data.scroll.transformedCurrent =\r\n this.context.data.scroll.current *\r\n this.context.data.viewport.transformScale;\r\n return;\r\n }\r\n\r\n if (this.context.data.scroll.delta !== 0) {\r\n this.scrollForce =\r\n this.context.data.scroll.delta *\r\n 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(\r\n this.context.data.scroll.current + this.context.data.scroll.lerped\r\n );\r\n } else {\r\n this.context.data.scroll.current = Math.floor(\r\n this.context.data.scroll.current + this.context.data.scroll.lerped\r\n );\r\n }\r\n\r\n this.context.data.scroll.transformedCurrent =\r\n this.context.data.scroll.current *\r\n 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 =\r\n this.context.data.scroll.target ===\r\n 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 { ScrollMarkRule } from \"../../models/scroll/ScrollTriggerRule\";\r\nimport { 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 public addScrollMark(rule: ScrollMarkRule) {\r\n this.modes.forEach((engine) => {\r\n engine.addScrollMark(rule);\r\n });\r\n }\r\n public removeScrollMark(id: string) {\r\n this.modes.forEach((engine) => {\r\n engine.removeScrollMark(id);\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 * 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 * 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 that associates string keys with `StringObject` instances.\r\n * This map is used to manage and track `StringObject` instances on a page.\r\n */\r\n protected objectMapOnPage: Map<string, StringObject> = new Map();\r\n\r\n /**\r\n * A protected array that holds the collection of `StringObject` instances\r\n * currently present on the page.\r\n */\r\n protected objectsOnPage: StringObject[] = [];\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 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 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 {\r\n key: \"self-disable\",\r\n type: \"boolean\",\r\n fallback: this.settings[\"self-disable\"],\r\n },\r\n { key: \"abs\", type: \"boolean\", fallback: this.settings[\"abs\"] },\r\n { key: \"key\", type: \"string\", fallback: this.settings[\"key\"] },\r\n {\r\n key: \"offset-top\",\r\n type: \"dimension\",\r\n fallback: this.settings[\"offset-top\"],\r\n },\r\n {\r\n key: \"offset-bottom\",\r\n type: \"dimension\",\r\n fallback: this.settings[\"offset-bottom\"],\r\n },\r\n {\r\n key: \"inview-top\",\r\n type: \"dimension\",\r\n fallback: this.settings[\"inview-top\"],\r\n },\r\n {\r\n key: \"inview-bottom\",\r\n type: \"dimension\",\r\n fallback: this.settings[\"inview-bottom\"],\r\n },\r\n {\r\n key: \"start\",\r\n type: \"number\",\r\n fallback: (\r\n element: HTMLElement,\r\n object: StringObject,\r\n boundingRect: DOMRect\r\n ) => {\r\n const top = boundingRect.top;\r\n return (\r\n Math.floor(top) +\r\n this.data.scroll.container.scrollTop *\r\n this.data.viewport.transformScale\r\n );\r\n },\r\n },\r\n {\r\n key: \"end\",\r\n type: \"number\",\r\n fallback: (\r\n element: HTMLElement,\r\n object: StringObject,\r\n boundingRect: DOMRect\r\n ) => {\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\",\r\n type: \"number\",\r\n fallback: (\r\n element: HTMLElement,\r\n object: StringObject,\r\n boundingRect: DOMRect\r\n ) => {\r\n return boundingRect.height;\r\n },\r\n },\r\n {\r\n key: \"half-width\",\r\n type: \"number\",\r\n fallback: (\r\n element: HTMLElement,\r\n object: StringObject,\r\n boundingRect: DOMRect\r\n ) => {\r\n return boundingRect.width / 2;\r\n },\r\n },\r\n {\r\n key: \"half-height\",\r\n type: \"number\",\r\n fallback: (\r\n element: HTMLElement,\r\n object: StringObject,\r\n boundingRect: DOMRect\r\n ) => {\r\n return boundingRect.height / 2;\r\n },\r\n },\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 ];\r\n }\r\n\r\n /**\r\n * Initializes a `StringObject` by mapping attributes from an HTML element\r\n * and applying transformations as needed.\r\n *\r\n * @param globalId - A unique identifier for the object being initialized.\r\n * @param object - The `StringObject` instance to be initialized.\r\n * @param element - The HTML element from which attributes are extracted.\r\n * @param attributes - A record of additional attributes to be used during initialization.\r\n *\r\n * The method performs the following steps:\r\n * 1. Retrieves the bounding rectangle of the provided HTML element.\r\n * 2. Iterates over a predefined list of attributes to map.\r\n * 3. Resolves fallback values for attributes, either from the provided attributes,\r\n * settings, or a fallback function.\r\n * 4. Processes and parses the raw attribute values based on their expected type.\r\n * 5. Applies optional transformations to the parsed values.\r\n * 6. Sets the processed attributes as properties on the `StringObject` instance.\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\"\r\n ? fallback(element, object, boundingRect)\r\n : 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 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 let startBias = 0;\r\n let endBias = 0;\r\n\r\n if (\r\n (startElement === \"top\" && startViewport === \"top\") ||\r\n (startElement === \"left\" && startViewport === \"left\")\r\n ) {\r\n startBias = -windowSize + 1;\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 startBias = -windowSize - size + 1;\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 startBias = -size + 1;\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 endBias = -size + 1;\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 endBias = -windowSize - size + 1;\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 endBias = -windowSize + 1;\r\n endPosition = start - windowSize + size + offsetEnd;\r\n }\r\n\r\n object.setProperty<number>(\"start-bias\", startBias);\r\n object.setProperty<number>(\"end-bias\", endBias);\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 const inviewTop = object.getProperty<number>(\"inview-top\") ?? 0;\r\n const inviewBottom = object.getProperty<number>(\"inview-bottom\") ?? 0;\r\n object.setProperty<number>(\r\n \"inview-start-position\",\r\n startPosition - this.data.scroll.topPosition + startBias + inviewTop\r\n );\r\n object.setProperty<number>(\r\n \"inview-end-position\",\r\n endPosition + endBias + inviewBottom\r\n );\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 (\r\n context.element != null &&\r\n context.viewportHeight != null &&\r\n context.baseRem != null\r\n ) {\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 * Adds a `StringObject` to the internal collections if it does not already exist.\r\n *\r\n * @param id - The unique identifier for the `StringObject`.\r\n * @param object - The `StringObject` to be added.\r\n *\r\n * @remarks\r\n * This method ensures that the object is added to both `objectMapOnPage` and\r\n * `objectsOnPage` only if the `id` is not already present in `objectMapOnPage`.\r\n */\r\n addObject(id: string, object: StringObject): void {\r\n if (!this.objectMapOnPage.has(id)) {\r\n this.objectMapOnPage.set(id, object);\r\n this.objectsOnPage.push(object);\r\n }\r\n }\r\n\r\n /**\r\n * Removes an object from the page by its unique identifier.\r\n *\r\n * This method performs the following steps:\r\n * 1. Retrieves the object associated with the given `id` from `objectMapOnPage`.\r\n * 2. If the object is not found, the method exits early.\r\n * 3. Deletes the object from `objectMapOnPage`.\r\n * 4. Finds the index of the object in the `objectsOnPage` array.\r\n * 5. If the object exists in the array, it is removed using `splice`.\r\n *\r\n * @param id - The unique identifier of the object to be removed.\r\n */\r\n removeObject(id: string): void {\r\n const object = this.objectMapOnPage.get(id);\r\n if (!object) return;\r\n\r\n this.objectMapOnPage.delete(id);\r\n\r\n const index = this.objectsOnPage.indexOf(object);\r\n if (index !== -1) {\r\n this.objectsOnPage.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(\r\n object: StringObject,\r\n applyFn: (el: HTMLElement) => void\r\n ) {\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 { 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 { 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 optionsParser: SplitOptionsParserTool;\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 optionsParser = new SplitOptionsParserTool();\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\n * Represents a module responsible for handling loading-related functionality.\r\n * Extends the `StringModule` class and provides additional behavior for managing\r\n * loading states and timeouts.\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\n/**\r\n * The `StringAnchor` class extends the `StringModule` class and is responsible for\r\n * managing anchor-related functionality within the string module system.\r\n *\r\n * This class maps an `anchor` attribute to a tuple containing x and y coordinates,\r\n * processes these coordinates using the `originParser` tool, and applies the resulting\r\n * values to the connected object's element as a CSS `transform-origin` style.\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\n/**\r\n * The `StringGlide` class is a module that handles the glide effect for string objects\r\n * based on scroll events. It calculates displacement, acceleration, and velocity\r\n * to create a smooth scrolling effect for objects.\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\n/**\r\n * The `StringProgress` class extends the `StringModule` class and is responsible for\r\n * managing progress-based behavior for elements during scroll events. It maps specific\r\n * attributes, initializes objects, and updates their progress based on scroll data.\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: \"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 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","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\n/**\r\n * The `StringParallax` class extends the `StringProgress` class to provide\r\n * functionality for handling parallax effects on scrollable elements.\r\n * It maps specific attributes related to parallax and calculates the\r\n * necessary transformations based on scroll progress and viewport size.\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 = Math.abs(object.getProperty<number>(\"parallax\") ?? 0.2);\r\n object.setProperty(\r\n \"parallax-sign\",\r\n Math.sign(object.getProperty<number>(\"parallax\"))\r\n );\r\n object.setProperty<number>(\"parallax\", factor);\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 const sign = object.getProperty<number>(\"parallax-sign\") ?? 1;\r\n\r\n const screenSize = this.data.viewport.windowHeight;\r\n const translation =\r\n sign * factor * (screenSize * start + progress * 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","export const SPLIT_ELEMENT_CLASS = {\n BEFORE_ELEMENT: \"-before-element\",\n AFTER_ELEMENT: \"-after-element\",\n} as const;\n","import { CalculatedValue } from \"../../models/text/CalculatedValue\";\nimport { LayoutLine } from \"./SplitMeasuredTokens\";\nimport { ISplitOptions } from \"../../models/text/ISplitOptions\";\nimport { SPLIT_ELEMENT_CLASS } from \"../../models/text/SplitElementClass\";\n\n/**\n * Builds a DOM tree representation of the given layout lines based on the provided options.\n *\n * @param layoutLines - An array of `LayoutLine` objects, each representing a line of text\n * with associated words and characters.\n * @param options - An `ISplitOptions` object that specifies how the DOM tree should be constructed,\n * including options for line, word, and character-level styling and structure.\n *\n * @returns A `DocumentFragment` containing the constructed DOM tree.\n *\n * The function processes the layout lines and creates a hierarchical DOM structure:\n * - If line-level options are enabled, each line is wrapped in a `<span>` element with the class `-s-line`.\n * - If word-level options are enabled, each word is wrapped in a `<span>` element with the class `-s-word`.\n * - If character-level options are enabled, each character is wrapped in a `<span>` element with the class `-s-char`.\n *\n * The function also applies styles and attributes to the created elements based on the provided options\n * and the calculated values in the layout lines, words, and characters.\n *\n * Special handling is applied for tokens of type `element`, where the original DOM node is cloned\n * and appended directly to the container.\n *\n * Spaces between words are preserved using non-breaking space (`\\u00a0`) text nodes.\n */\nexport function BuildDOMTree(\n layoutLines: LayoutLine[],\n options: ISplitOptions\n): DocumentFragment {\n const fragment = document.createDocumentFragment();\n let localCharIndex = 0;\n const hasLine =\n hasOption(options, \"line\") ||\n hasOption(options, \"charLine\") ||\n hasOption(options, \"wordLine\");\n\n layoutLines.forEach((line) => {\n let container: HTMLElement | DocumentFragment = fragment;\n if (hasLine) {\n container = document.createElement(\"span\");\n container.classList.add(\"-s-line\");\n if (line.isBeforeElement) {\n container.classList.add(SPLIT_ELEMENT_CLASS.BEFORE_ELEMENT);\n }\n if (line.isAfterElement) {\n container.classList.add(SPLIT_ELEMENT_CLASS.AFTER_ELEMENT);\n }\n container.style.setProperty(\"--line-index\", String(line.lineIndex));\n container.style.setProperty(\"--word-total\", String(line.words.length));\n applyStyles(container, (line as any).calculatedValues, options);\n }\n\n line.words.forEach((word, wi) => {\n const isLast = wi === line.words.length - 1;\n\n if (word.chars.length === 1 && word.chars[0].token.type === \"element\") {\n const original = word.chars[0].token.node.cloneNode(\n true\n ) as HTMLElement;\n container.appendChild(original);\n if (!isLast) container.appendChild(document.createTextNode(\"\\u00a0\"));\n return;\n }\n\n const hasWord =\n hasOption(options, \"word\") ||\n hasOption(options, \"charWord\") ||\n hasOption(options, \"wordLine\");\n const wordEl = hasWord\n ? document.createElement(\"span\")\n : (container as HTMLElement);\n\n if (hasWord) {\n wordEl.classList.add(\"-s-word\");\n if (word.isBeforeElement) {\n wordEl.classList.add(SPLIT_ELEMENT_CLASS.BEFORE_ELEMENT);\n }\n if (word.isAfterElement) {\n wordEl.classList.add(SPLIT_ELEMENT_CLASS.AFTER_ELEMENT);\n }\n wordEl.style.setProperty(\"--word-index\", String(word.wordIndexGlobal));\n wordEl.style.setProperty(\"--char-total\", String(word.chars.length));\n applyStyles(wordEl, (word as any).calculatedValues, options);\n }\n\n const hasChar =\n hasOption(options, \"char\") ||\n hasOption(options, \"charLine\") ||\n hasOption(options, \"charWord\");\n\n if (hasChar) {\n word.chars.forEach((char) => {\n if (char.char === \" \" || char.char === \"\\t\") return;\n const charNode = document.createElement(\"span\");\n const charEl = charNode as HTMLElement;\n charEl.classList.add(\"-s-char\");\n if (char.isBeforeElement) {\n charEl.classList.add(SPLIT_ELEMENT_CLASS.BEFORE_ELEMENT);\n }\n if (char.isAfterElement) {\n charEl.classList.add(SPLIT_ELEMENT_CLASS.AFTER_ELEMENT);\n }\n charEl.textContent = char.char;\n charEl.style.setProperty(\"--char-index\", String(localCharIndex++));\n applyStyles(charEl, (char as any).calculatedValues, options);\n wordEl.appendChild(charNode);\n });\n } else {\n const charNode = document.createTextNode(\n word.chars.map((c) => c.char).join(\"\")\n );\n wordEl.appendChild(charNode);\n }\n\n if (hasWord) {\n container.appendChild(wordEl);\n }\n if (!isLast) {\n wordEl.appendChild(document.createTextNode(\"\\u00a0\"));\n } else {\n container.appendChild(document.createElement(\"br\"));\n }\n });\n\n if (hasLine) fragment.appendChild(container as HTMLElement);\n });\n\n return fragment;\n}\n\n/**\n * Applies calculated styles to a given HTML element based on the provided values and options.\n *\n * @param el - The HTML element to which the styles will be applied.\n * @param calculatedValues - An array of calculated values containing style information, or `undefined` if no styles are to be applied.\n * @param options - The options object that determines which styles are enabled and how they should be aligned.\n *\n * @remarks\n * This function iterates over the `calculatedValues` array and applies styles to the element\n * only if the corresponding option is enabled. The style property name is generated dynamically\n * using the `generateVariableName` function.\n *\n * @example\n * ```typescript\n * const element = document.createElement('div');\n * const calculatedValues = [\n * { type: 'color', align: 'left', value: '#ff0000' },\n * { type: 'margin', align: 'top', value: '10px' }\n * ];\n * const options = { enableColor: true, enableMargin: true };\n * applyStyles(element, calculatedValues, options);\n * ```\n */\nfunction applyStyles(\n el: HTMLElement,\n calculatedValues: CalculatedValue[] | undefined,\n options: ISplitOptions\n) {\n if (!calculatedValues) return;\n for (const val of calculatedValues) {\n if (!isOptionEnabled(val.type, val.align, options)) continue;\n const varName = generateVariableName(val.type, val.align);\n el.style.setProperty(varName, String(val.value));\n }\n}\n\n/**\n * Determines whether a specific option is enabled based on the provided type, alignment, and options.\n *\n * @param type - The type of the option to check within the options object.\n * @param align - The alignment string to match against the option's alignment.\n * If the alignment starts with \"random\", it checks for options\n * whose alignment also starts with \"random\".\n * @param options - An object containing various option groups, where each group\n * is an array of items with an `align` property.\n * @returns `true` if the specified option is enabled, otherwise `false`.\n */\nfunction isOptionEnabled(\n type: string,\n align: string,\n options: ISplitOptions\n): boolean {\n const group = options[type as keyof ISplitOptions] ?? [];\n return (\n Array.isArray(group) &&\n group.some((item) =>\n align.startsWith(\"random\")\n ? item.align.startsWith(\"random\")\n : item.align === align\n )\n );\n}\n\n/**\n * Generates a CSS variable name based on the provided type and alignment.\n *\n * The function normalizes the `align` parameter by checking if it starts with \"random\".\n * If it does, the alignment is normalized to \"random\"; otherwise, the original alignment is used.\n * The resulting variable name is constructed in the format `--<type>-<normalizedAlign>`.\n *\n * @param type - The type of the variable, typically representing a category or context.\n * @param align - The alignment or variation, which may start with \"random\" or be a specific value.\n * @returns A string representing the generated CSS variable name.\n */\nfunction generateVariableName(type: string, align: string): string {\n const norm = align.startsWith(\"random\") ? \"random\" : align;\n return `--${type}-${norm}`;\n}\n\n/**\n * Checks if a specific key in the given options object is an array and contains at least one element.\n *\n * @param options - The options object implementing the `ISplitOptions` interface.\n * @param key - The key to check within the options object.\n * @returns `true` if the value associated with the key is an array with at least one element, otherwise `false`.\n */\nfunction hasOption(options: ISplitOptions, key: keyof ISplitOptions): boolean {\n return Array.isArray(options[key]) && options[key]!.length > 0;\n}\n","export type Token =\n | {\n type: \"text\";\n id: string;\n node: Text;\n content: string;\n meta?: Record<string, any>;\n }\n | {\n type: \"space\";\n id: string;\n node: Text;\n content: string;\n meta?: Record<string, any>;\n }\n | {\n type: \"element\";\n id: string;\n node: HTMLElement;\n tagName: string;\n meta?: Record<string, any>;\n }\n | {\n type: \"other\";\n id: string;\n node: Node;\n meta?: Record<string, any>;\n };\n\nlet tokenCounter = 0;\n\n/**\n * Builds an array of tokens from a given list of child nodes.\n *\n * This function processes each node in the provided `NodeListOf<ChildNode>` and generates\n * a corresponding token object based on the node type. The tokens can represent elements,\n * text nodes, whitespace, or other types of nodes.\n *\n * @param nodes - A collection of child nodes to be processed into tokens.\n * @returns An array of tokens, where each token represents a node with additional metadata.\n *\n * Token Types:\n * - `element`: Represents an HTML element node, including its tag name.\n * - `text`: Represents a text node with non-whitespace content.\n * - `space`: Represents a text node with only whitespace content.\n * - `other`: Represents any other type of node.\n *\n * Each token includes:\n * - `type`: The type of the token (`element`, `text`, `space`, or `other`).\n * - `id`: A unique identifier for the token.\n * - `node`: The original DOM node.\n * - Additional properties depending on the token type:\n * - `tagName` for `element` tokens.\n * - `content` for `text` and `space` tokens.\n */\nexport function BuildTokens(nodes: NodeListOf<ChildNode>): Token[] {\n tokenCounter = 0;\n const tokens: Token[] = [];\n\n nodes.forEach((node) => {\n if (node.nodeType === Node.ELEMENT_NODE) {\n const el = node as HTMLElement;\n\n tokens.push({\n type: \"element\",\n id: `el_${tokenCounter++}`,\n node: el,\n tagName: el.tagName.toLowerCase(),\n });\n } else if (node.nodeType === Node.TEXT_NODE) {\n const text = node.nodeValue ?? \"\";\n const id = `text_${tokenCounter++}`;\n\n if (text.trim()) {\n tokens.push({ type: \"text\", id, node: node as Text, content: text });\n } else {\n tokens.push({ type: \"space\", id, node: node as Text, content: text });\n }\n } else {\n tokens.push({ type: \"other\", id: `node_${tokenCounter++}`, node });\n }\n });\n\n return tokens;\n}\n","import { Token } from \"./BuildTokens\";\n\nexport type MeasuredToken = {\n token: Token;\n rect: DOMRect;\n};\n\n/**\n * Measures the layout of tokens within a given container element.\n * This function calculates the bounding rectangles for each token\n * by rendering them temporarily in a hidden wrapper element and\n * measuring their dimensions.\n *\n * @param tokens - An array of tokens to be measured. Each token can be of type \"text\", \"element\", or \"other\".\n * - \"text\": Represents a text token with content to be measured.\n * - \"element\": Represents an HTML element token to be measured.\n * - \"other\": Tokens of this type are ignored.\n * @param container - The container HTMLElement within which the tokens are measured.\n * The width of this container is used to constrain the layout.\n * @returns An array of measured tokens, where each measured token contains:\n * - `token`: The original token with additional information for \"text\" tokens.\n * - `rect`: The DOMRect representing the bounding rectangle of the token.\n */\nexport function LayoutMeasurer(\n tokens: Token[],\n container: HTMLElement\n): MeasuredToken[] {\n const wrapper = document.createElement(\"div\");\n const computed = window.getComputedStyle(container);\n wrapper.style.position = \"absolute\";\n wrapper.style.visibility = \"hidden\";\n wrapper.style.pointerEvents = \"none\";\n wrapper.style.width = container.clientWidth + \"px\";\n wrapper.style.padding = computed.padding;\n wrapper.style.font = computed.font;\n wrapper.style.letterSpacing = computed.letterSpacing;\n wrapper.style.lineHeight = computed.lineHeight;\n wrapper.style.fontVariant = computed.fontVariant;\n wrapper.style.fontStretch = computed.fontStretch;\n\n container.appendChild(wrapper);\n\n const measured: MeasuredToken[] = [];\n\n let isAfterElement = false;\n\n var span;\n var rect;\n tokens.forEach((token, idx) => {\n let node: Node;\n\n switch (token.type) {\n case \"text\":\n let words = token.content\n .trim()\n .split(/\\s+/)\n .filter((word) => word.length > 0);\n\n words.forEach((word, wordInd) => {\n node = document.createTextNode(word);\n\n span = document.createElement(\"span\");\n span.style.display = \"inline-block\";\n span.appendChild(node);\n span.appendChild(document.createTextNode(\"\\u00a0\"));\n wrapper.appendChild(span);\n rect = span.getBoundingClientRect();\n let measuredText: MeasuredToken = {\n token: {\n type: \"text\",\n id: \"\",\n node: node as Text,\n content: word,\n },\n rect,\n };\n if (isAfterElement) {\n isAfterElement = false;\n measuredText.token.meta = {\n ...(measuredText.token.meta || {}),\n isAfterElement: true,\n };\n }\n measured.push(measuredText);\n });\n\n break;\n case \"element\":\n node = token.node.cloneNode(true);\n span = document.createElement(\"span\");\n span.style.display = \"inline-block\";\n span.appendChild(node);\n wrapper.appendChild(span);\n rect = span.getBoundingClientRect();\n measured.push({ token, rect });\n\n const prev = measured[measured.length - 2];\n if (prev?.token.type === \"text\") {\n prev.token.meta = {\n ...(prev.token.meta || {}),\n isBeforeElement: true,\n };\n }\n isAfterElement = true;\n break;\n case \"other\":\n return;\n }\n });\n\n container.removeChild(wrapper);\n return measured;\n}\n","import { MeasuredToken } from \"./LayoutMeasurer\";\nimport { Token } from \"./BuildTokens\";\n\nexport type ProcessedChar = {\n char: string;\n rect: DOMRect;\n token: Token;\n charIndexGlobal: number;\n charIndexInLine: number;\n charIndexInWord: number;\n isBeforeElement?: boolean;\n isAfterElement?: boolean;\n};\n\nexport type ProcessedWord = {\n chars: ProcessedChar[];\n rect: DOMRect;\n wordIndexGlobal: number;\n wordIndexInLine: number;\n isBeforeElement?: boolean;\n isAfterElement?: boolean;\n};\n\nexport type LayoutLine = {\n words: ProcessedWord[];\n rect: DOMRect;\n lineIndex: number;\n isBeforeElement?: boolean;\n isAfterElement?: boolean;\n};\n\nconst LINE_TOLERANCE = 1;\n\nexport function SplitMeasuredTokens(measured: MeasuredToken[]): LayoutLine[] {\n const lines: LayoutLine[] = [];\n let currentLine: LayoutLine | null = null;\n let y = 0;\n\n let charIndexGlobal = 0;\n let wordIndexGlobal = 0;\n\n measured.forEach((mt) => {\n const token = mt.token;\n const isBefore = token.meta?.isBeforeElement ?? false;\n const isAfter = token.meta?.isAfterElement ?? false;\n\n if (token.type === \"text\") {\n const segments = token.content.match(/(\\s+|\\S+)/g);\n if (!segments) return;\n\n let offsetX = mt.rect.left;\n const contentLength = token.content.length;\n const avgCharWidth =\n contentLength > 0 ? mt.rect.width / contentLength : 0;\n\n segments.forEach((segment) => {\n if (/^\\s+$/.test(segment)) {\n offsetX += avgCharWidth * segment.length;\n return;\n }\n\n const chars: ProcessedChar[] = [];\n segment.split(\"\").forEach((char, i) => {\n const rect = new DOMRect(\n offsetX,\n mt.rect.top,\n avgCharWidth,\n mt.rect.height\n );\n chars.push({\n char,\n rect,\n token,\n charIndexInWord: i,\n charIndexInLine: 0,\n charIndexGlobal: charIndexGlobal++,\n });\n offsetX += avgCharWidth;\n });\n\n if (chars.length > 0) {\n const lastChar = chars[chars.length - 1];\n if (isBefore) lastChar.isBeforeElement = true;\n if (isAfter) lastChar.isAfterElement = true;\n }\n\n const isNewLine =\n !currentLine || Math.abs(mt.rect.top - y) > LINE_TOLERANCE;\n if (isNewLine) {\n y = mt.rect.top;\n currentLine = { words: [], rect: mt.rect, lineIndex: lines.length };\n lines.push(currentLine);\n }\n\n if (!currentLine) return;\n\n const wordIndexInLine = currentLine.words.length;\n const charsBefore = currentLine.words.reduce(\n (acc, w) => acc + w.chars.length,\n 0\n );\n chars.forEach((c, i) => (c.charIndexInLine = charsBefore + i));\n\n const processedWord: ProcessedWord = {\n chars,\n rect: mt.rect,\n wordIndexGlobal: wordIndexGlobal++,\n wordIndexInLine,\n isBeforeElement: isBefore,\n isAfterElement: isAfter,\n };\n\n currentLine.words.push(processedWord);\n currentLine.rect = mergeRects(currentLine.words.map((w) => w.rect));\n if (isBefore) currentLine.isBeforeElement = true;\n if (isAfter) currentLine.isAfterElement = true;\n });\n } else if (token.type === \"element\") {\n const rect = mt.rect;\n const isNewLine = !currentLine || Math.abs(rect.top - y) > LINE_TOLERANCE;\n\n if (isNewLine) {\n y = rect.top;\n currentLine = { words: [], rect, lineIndex: lines.length };\n lines.push(currentLine);\n }\n\n if (!currentLine) return;\n\n const wordIndexInLine = currentLine.words.length;\n const charsBefore = currentLine.words.reduce(\n (acc, w) => acc + w.chars.length,\n 0\n );\n\n const chars: ProcessedChar[] = [\n {\n char: \"[E]\",\n rect,\n token,\n charIndexInWord: 0,\n charIndexInLine: charsBefore,\n charIndexGlobal: charIndexGlobal++,\n },\n ];\n\n const processedWord: ProcessedWord = {\n chars,\n rect,\n wordIndexGlobal: wordIndexGlobal++,\n wordIndexInLine,\n isBeforeElement: false,\n isAfterElement: false,\n };\n\n currentLine.words.push(processedWord);\n currentLine.rect = mergeRects(currentLine.words.map((w) => w.rect));\n }\n });\n\n return lines;\n}\n\nfunction mergeRects(rects: DOMRect[]): DOMRect {\n const left = Math.min(...rects.map((r) => r.left));\n const top = Math.min(...rects.map((r) => r.top));\n const right = Math.max(...rects.map((r) => r.right));\n const bottom = Math.max(...rects.map((r) => r.bottom));\n return new DOMRect(left, top, right - left, bottom - top);\n}\n","import { StringContext } from \"../../core/StringContext\";\r\nimport { StringModule } from \"../../core/StringModule\";\r\nimport { CalculatedValue } from \"../../models/text/CalculatedValue\";\r\nimport { ISplitOptionItem } from \"../../models/text/ISplitOptionItem\";\r\nimport { ISplitOptions } from \"../../models/text/ISplitOptions\";\r\nimport { StringObject } from \"../../objects/StringObject\";\r\nimport { BuildDOMTree } from \"../../utils/text/BuildDOMTree\";\r\nimport { BuildTokens } from \"../../utils/text/BuildTokens\";\r\nimport { LayoutMeasurer } from \"../../utils/text/LayoutMeasurer\";\r\nimport {\r\n LayoutLine,\r\n ProcessedChar,\r\n ProcessedWord,\r\n SplitMeasuredTokens,\r\n} from \"../../utils/text/SplitMeasuredTokens\";\r\n\r\n/**\r\n * StringSplit module: splits text into lines, words, chars,\r\n * computes alignment/random values, and applies CSS vars.\r\n */\r\nexport class StringSplit extends StringModule {\r\n constructor(context: StringContext) {\r\n super(context);\r\n this.htmlKey = \"split\";\r\n }\r\n\r\n onResize(): void {\r\n this.objectsOnPage.forEach((object) => {\r\n this.onObjectConnected(object);\r\n });\r\n }\r\n\r\n onObjectConnected(object: StringObject): void {\r\n const element = object.htmlElement;\r\n if (!element) return;\r\n\r\n const isAlreadySplit = element.classList.contains(\"-splitted\");\r\n let originalHtml = element.getAttribute(\"string-split-original\");\r\n\r\n if (!isAlreadySplit || originalHtml === null) {\r\n originalHtml = this.escapeAttribute(element.innerHTML);\r\n element.setAttribute(\"string-split-original\", originalHtml);\r\n element.classList.add(\"-splitted\");\r\n }\r\n\r\n object.htmlElement.innerHTML = originalHtml;\r\n const attr =\r\n element.getAttribute(\"string-split\") ??\r\n element.getAttribute(\"data-string-split\") ??\r\n \"\";\r\n const options: ISplitOptions = this.tools.optionsParser.process({\r\n attributeValue: attr,\r\n });\r\n const { fragment, result } = this.split(element, options);\r\n object.setProperty(\"nodes\", fragment.childNodes);\r\n element.innerHTML = \"\";\r\n element.appendChild(result);\r\n }\r\n\r\n public split(element: HTMLElement, options: ISplitOptions) {\r\n const frag = document.createDocumentFragment();\r\n element.childNodes.forEach((ch) => frag.appendChild(ch.cloneNode(true)));\r\n const tokens = BuildTokens(frag.childNodes as NodeListOf<ChildNode>);\r\n const measured = LayoutMeasurer(tokens, element);\r\n const layoutLines: LayoutLine[] = SplitMeasuredTokens(measured);\r\n this.applyCalculatedValues(layoutLines, options);\r\n const dom = BuildDOMTree(layoutLines, options);\r\n return {\r\n fragment: frag,\r\n result: dom,\r\n };\r\n }\r\n\r\n /**\r\n * Computes a numeric value based on the provided split option, index, and total count.\r\n *\r\n * @param opt - The split option item containing alignment and optional random range.\r\n * @param index - The current index in the sequence.\r\n * @param total - The total number of items in the sequence.\r\n * @returns A computed numeric value based on the alignment strategy:\r\n * - \"random\": A random value within the specified range or default range.\r\n * - \"start\": The current index.\r\n * - \"end\": The reverse index from the end of the sequence.\r\n * - \"center\": The distance from the center index.\r\n * - Default: The current index.\r\n */\r\n private computeValue(\r\n opt: ISplitOptionItem,\r\n index: number,\r\n total: number\r\n ): number {\r\n if (opt.align.startsWith(\"random\")) {\r\n const min = opt.random?.min ?? 0;\r\n const max = opt.random?.max ?? total - 1;\r\n return Math.floor(Math.random() * (max - min + 1)) + min;\r\n }\r\n switch (opt.align) {\r\n case \"start\":\r\n return index;\r\n case \"end\":\r\n return total - index - 1;\r\n case \"center\": {\r\n const centerIdx = Math.floor((total - 1) / 2);\r\n return Math.abs(index - centerIdx);\r\n }\r\n default:\r\n return index;\r\n }\r\n }\r\n\r\n /**\r\n * Applies calculated values to the provided layout lines and their components (words and characters)\r\n * based on the given options. This method computes and assigns various calculated values\r\n * (e.g., alignment and value) to lines, words, and characters, depending on the specified options.\r\n *\r\n * @param lines - An array of `LayoutLine` objects representing the lines of text to process.\r\n * @param options - An `ISplitOptions` object specifying the calculation options for lines, words, and characters.\r\n *\r\n * The `options` parameter can include the following properties:\r\n * - `line`: An array of options for calculating values at the line level.\r\n * - `word`: An array of options for calculating values at the word level.\r\n * - `wordLine`: An array of options for calculating values at the word level relative to the line.\r\n * - `char`: An array of options for calculating values at the character level.\r\n * - `charWord`: An array of options for calculating values at the character level relative to the word.\r\n * - `charLine`: An array of options for calculating values at the character level relative to the line.\r\n *\r\n * Each calculated value is assigned to the corresponding `calculatedValues` property of the line, word, or character.\r\n * The method ensures that all specified options are processed and the calculated values are appended accordingly.\r\n */\r\n private applyCalculatedValues(\r\n lines: LayoutLine[],\r\n options: ISplitOptions\r\n ): void {\r\n const countChars = (ln: LayoutLine) =>\r\n ln.words.reduce((acc, w: ProcessedWord) => acc + w.chars.length, 0);\r\n\r\n const totalWords = lines.reduce((acc, l) => acc + l.words.length, 0);\r\n const totalCharsGlobal = lines.reduce(\r\n (acc, l) => acc + l.words.reduce((acc2, w) => acc2 + w.chars.length, 0),\r\n 0\r\n );\r\n\r\n lines.forEach((line, li) => {\r\n if (options.line) {\r\n (line as any).calculatedValues = options.line.map(\r\n (opt) =>\r\n ({\r\n type: \"line\",\r\n align: opt.align,\r\n value: this.computeValue(opt, li, lines.length),\r\n } as CalculatedValue)\r\n );\r\n }\r\n\r\n line.words.forEach((word: ProcessedWord, wi) => {\r\n if (options.word) {\r\n (word as any).calculatedValues = options.word.map(\r\n (opt) =>\r\n ({\r\n type: \"word\",\r\n align: opt.align,\r\n value: this.computeValue(opt, word.wordIndexGlobal, totalWords),\r\n } as CalculatedValue)\r\n );\r\n }\r\n\r\n if (options.wordLine) {\r\n (word as any).calculatedValues ??= [];\r\n (word as any).calculatedValues.push(\r\n ...options.wordLine.map(\r\n (opt) =>\r\n ({\r\n type: \"wordLine\",\r\n align: opt.align,\r\n value: this.computeValue(\r\n opt,\r\n word.wordIndexInLine,\r\n line.words.length\r\n ),\r\n } as CalculatedValue)\r\n )\r\n );\r\n }\r\n\r\n const totalCharsInLine = countChars(line);\r\n\r\n word.chars.forEach((char: ProcessedChar) => {\r\n const cvs: CalculatedValue[] = [];\r\n\r\n if (options.char) {\r\n cvs.push(\r\n ...options.char.map(\r\n (opt) =>\r\n ({\r\n type: \"char\",\r\n align: opt.align,\r\n value: this.computeValue(\r\n opt,\r\n char.charIndexGlobal,\r\n totalCharsGlobal\r\n ),\r\n } as CalculatedValue)\r\n )\r\n );\r\n }\r\n\r\n if (options.charWord) {\r\n cvs.push(\r\n ...options.charWord.map(\r\n (opt) =>\r\n ({\r\n type: \"charWord\",\r\n align: opt.align,\r\n value: this.computeValue(\r\n opt,\r\n char.charIndexInWord,\r\n word.chars.length\r\n ),\r\n } as CalculatedValue)\r\n )\r\n );\r\n }\r\n\r\n if (options.charLine) {\r\n cvs.push(\r\n ...options.charLine.map(\r\n (opt) =>\r\n ({\r\n type: \"charLine\",\r\n align: opt.align,\r\n value: this.computeValue(\r\n opt,\r\n char.charIndexInLine,\r\n totalCharsInLine\r\n ),\r\n } as CalculatedValue)\r\n )\r\n );\r\n }\r\n\r\n (char as any).calculatedValues = cvs;\r\n });\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Escapes the `src` attribute in a given string by removing the quotes around the URL.\r\n *\r\n * This method searches for occurrences of `src=\"URL\"` where `URL` is an HTTP or HTTPS link,\r\n * and replaces it with `src=URL` (removing the quotes around the URL).\r\n *\r\n * @param str - The input string containing the `src` attributes to be escaped.\r\n * @returns The modified string with escaped `src` attributes.\r\n */\r\n private escapeAttribute(str: string): string {\r\n return str.replace(/src=\"(https?:\\/\\/[^\"\\s]+)\"/g, \"src=$1\");\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","export enum SequenceState {\n ACTIVE = \"-active\",\n HIDE = \"-hide\",\n DISABLE = \"-disable\",\n}\n","import { StringContext } from \"../../core/StringContext\";\nimport { StringData } from \"../../core/StringData\";\nimport { StringModule } from \"../../core/StringModule\";\nimport { StringToolsContainer } from \"../../core/StringToolsContainer\";\nimport { SequenceState } from \"../../models/slider/SequenceState\";\nimport { StringObject } from \"../../objects/StringObject\";\n\n/**\n * Module that updates the `--lerp` CSS variable on elements\n * based on current scroll velocity.\n */\nexport class StringSequence extends StringModule {\n constructor(context: StringContext) {\n super(context);\n this.htmlKey = \"sequence\";\n\n this.attributesToMap = [\n ...this.attributesToMap,\n { key: \"sequence\", type: \"string\", fallback: \"string[0]\" },\n ];\n }\n\n private activeStepForSlides: Map<string, number> = new Map();\n private hideStepForSlides: Map<string, number> = new Map();\n onInit(): void {\n super.onInit();\n this.events.on<{ slider: string; step: number }>(\n \"sequence\",\n ({ slider, step }) => {\n this.objectsOnPage.forEach((object) => {\n const sequence = object.getProperty<string>(\"sequence\");\n if (\n sequence == `${slider}[${this.hideStepForSlides.get(slider)}]` &&\n sequence != `${slider}[${step}]`\n ) {\n this.setSequenceState(object, SequenceState.DISABLE);\n }\n if (\n sequence == `${slider}[${this.activeStepForSlides.get(slider)}]`\n ) {\n this.setSequenceState(object, SequenceState.HIDE);\n }\n if (sequence == `${slider}[${step}]`) {\n this.setSequenceState(object, SequenceState.ACTIVE);\n }\n });\n let activeIndex = this.activeStepForSlides.get(slider);\n if (activeIndex != undefined) {\n this.hideStepForSlides.set(slider, activeIndex);\n }\n this.activeStepForSlides.set(slider, step);\n }\n );\n }\n\n onObjectConnected(object: StringObject): void {\n super.onObjectConnected(object);\n this.setSequenceState(object, SequenceState.DISABLE);\n }\n\n private setSequenceState(object: StringObject, state: SequenceState) {\n requestAnimationFrame(() => {\n object.htmlElement.classList.remove(...Object.values(SequenceState));\n object.htmlElement.classList.add(state);\n });\n }\n}\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","StringSequence","StringSplit","StringTune","StringVideoAutoplay","__toCommonJS","CursorController","smoothing","context","targetX","targetY","smoothedX","smoothedY","stepX","stepY","distance","lerp","t","x","y","EventManager","eventName","callback","id","fullEvent","payload","set","value","visible","ModuleManager","data","module","type","m","added","removed","StringObject","id","element","EventManager","key","value","module","ObjectManager","data","modules","events","el","idAttr","key","object","StringObject","keysAttr","attributes","m","q","item","id","obj","element","attr","start","end","progressCallback","entries","e","progressObserver","mutations","mutation","node","child","copyFrom","scrollPos","inviewStart","inviewEnd","wasInView","isNowInView","ScrollController","context","scrollDirection","rule","id","StringScrollDefault","ScrollController","context","delta","e","scrollTop","plusDelta","StringScrollDisable","ScrollController","context","e","SCROLL_CLASS_NAMES","StringScrollSmooth","ScrollController","context","newDirection","SCROLL_CLASS_NAMES","absVelocity","e","scrollDirection","atTop","atBottom","ScrollManager","context","StringScrollSmooth","StringScrollDefault","StringScrollDisable","mode","newMode","engine","events","rule","id","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","start","size","offsetStart","offsetEnd","startElement","startViewport","endElement","endViewport","startPosition","endPosition","startBias","endBias","inviewTop","inviewBottom","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","s","l","hue2rgb","q","t","p","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","s","scaleValue","scaleNumbers","scaleXValue","scaleNumber","scale3dValue","matrix3dValues","error","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","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","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","StringParallax","StringProgress","context","object","progress","factor","start","end","sign","screenSize","translation","transform","el","globalId","element","attributes","bias","data","isDesktop","StringScrollbarHorizontal","data","scrollbar","thumb","contentWidth","visibleWidth","thumbSize","deltaY","newScrollPosition","StringScrollbarVertical","data","scrollbar","thumb","contentSize","visibleSize","thumbSize","contentHeight","visibleHeight","deltaY","newScrollPosition","maxScroll","clamped","StringScrollbar","StringModule","context","data","style","StringScrollbarHorizontal","StringScrollbarVertical","e","SPLIT_ELEMENT_CLASS","BuildDOMTree","layoutLines","options","fragment","localCharIndex","hasLine","hasOption","line","container","SPLIT_ELEMENT_CLASS","applyStyles","word","wi","isLast","original","hasWord","wordEl","char","charNode","charEl","c","el","calculatedValues","val","isOptionEnabled","varName","generateVariableName","type","align","group","item","norm","key","tokenCounter","BuildTokens","nodes","tokens","node","el","text","id","LayoutMeasurer","tokens","container","wrapper","computed","measured","isAfterElement","span","rect","token","idx","node","word","wordInd","measuredText","prev","LINE_TOLERANCE","SplitMeasuredTokens","measured","lines","currentLine","y","charIndexGlobal","wordIndexGlobal","mt","token","isBefore","isAfter","segments","offsetX","contentLength","avgCharWidth","segment","chars","char","i","rect","lastChar","wordIndexInLine","charsBefore","acc","w","c","processedWord","mergeRects","rects","left","r","top","right","bottom","StringSplit","StringModule","context","object","element","isAlreadySplit","originalHtml","attr","options","fragment","result","frag","ch","tokens","BuildTokens","measured","LayoutMeasurer","layoutLines","SplitMeasuredTokens","dom","BuildDOMTree","opt","index","total","min","max","centerIdx","lines","countChars","ln","acc","w","totalWords","l","totalCharsGlobal","acc2","line","li","word","wi","totalCharsInLine","char","cvs","str","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","SequenceState","StringSequence","StringModule","context","slider","step","object","sequence","activeIndex","state","SequenceState","StringTune","_StringTune","StringFPS","Debounce","DefaultToolsContainer","StringData","EventManager","ModuleManager","ObjectManager","CursorController","ScrollManager","time","value","container","speed","mode","type","objectClass","settings","effectiveSettings","module","eventName","callback","id","data","rule","fps","observerContainerMutation","mutationsList","observer","mutation","config","StringInview","htmlFontSize","fontSizeNumber","element","connectTargetId","scroll","width","height","newScrollHeight","newContainerTopPosition","rect","transformScale","isDesktop","widthChanged","heightChanged","scrollHeightChanged","shouldRebuild"]}
1
+ {"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/models/scroll/ScrollHTMLClass.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/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/models/text/SplitElementClass.ts","../src/utils/text/BuildDOMTree.ts","../src/utils/text/BuildTokens.ts","../src/utils/text/LayoutMeasurer.ts","../src/utils/text/SplitMeasuredTokens.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","../src/models/slider/SequenceState.ts","../src/modules/slider/StringSequence.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\nimport { ScrollMarkRule } from \"./models/scroll/ScrollTriggerRule\";\r\nimport { StringSequence } from \"./modules/slider/StringSequence\";\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.transformedCurrent =\r\n this.data.scroll.current * this.data.viewport.transformScale;\r\n this.data.scroll.delta = 0;\r\n this.data.scroll.lerped = 0;\r\n this.scrollManager.updatePosition();\r\n this.moduleManager.onScroll();\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;\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 public emit(eventName: string, data: any) {\r\n this.eventManager.emit(eventName, data);\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 * Adds a scroll trigger rule that activates when the user scrolls past a defined offset\r\n * in a specific direction. This can be used to toggle CSS classes or execute callbacks\r\n * when elements come into view or go out of view.\r\n *\r\n * @param rule - The scroll trigger configuration object.\r\n * - `id`: A unique identifier for this rule.\r\n * - `offset`: The vertical scroll offset (in pixels) where the rule should activate.\r\n * - `direction`: Defines the scroll direction required to activate the rule.\r\n * Can be `\"forward\"`, `\"backward\"`, or `\"any\"`.\r\n * - `onEnter`: (Optional) A function that will be called when the scroll position enters the trigger zone\r\n * in the specified direction.\r\n * - `onLeave`: (Optional) A function that will be called when the scroll position leaves the trigger zone\r\n * or scrolls in the opposite direction.\r\n * - `toggleClass`: (Optional) An object defining a class toggle behavior.\r\n * It contains a target element and a class name to be added when the trigger is active\r\n * and removed when it's not.\r\n */\r\n public addScrollMark(rule: ScrollMarkRule) {\r\n this.scrollManager.addScrollMark(rule);\r\n }\r\n\r\n /**\r\n * Removes a scroll trigger by its unique identifier.\r\n *\r\n * @param id - The unique identifier of the scroll trigger to be removed.\r\n */\r\n public removeScrollMark(id: string) {\r\n this.scrollManager.removeScrollMark(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 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 const target = e.target as HTMLElement;\r\n const isModal = target.closest(\r\n \"[string-isolation],[data-string-isolation]\"\r\n );\r\n if (isModal != null) return;\r\n\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.objectManager.checkInview();\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 if (this.context.data.scroll.container.scrollTop > 0) {\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 }\r\n\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 StringSequence,\r\n type ScrollMarkRule as ScrollTriggerRule,\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 * Removes the current object by iterating through all associated modules\r\n * and invoking their `removeObject` method with the object's ID.\r\n *\r\n * This method ensures that the object is properly removed from all\r\n * modules it is associated with.\r\n */\r\n public remove(): void {\r\n this.modules.forEach((module) => {\r\n module.removeObject(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 let idAttr = `string-${this.globalId++}`;\r\n let key = \"string-id\";\r\n\r\n if (el.getAttribute(\"string-id\")) {\r\n idAttr = el.getAttribute(\"string-id\")!;\r\n key = \"string-id\";\r\n }\r\n if (el.getAttribute(\"data-string-id\")) {\r\n idAttr = el.getAttribute(\"data-string-id\")!;\r\n key = \"data-string-id\";\r\n }\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(key, 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 m.addObject(object.id, 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 obj.remove();\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 /**\r\n * Retrieves all attributes of a given HTML element and returns them as a record.\r\n *\r\n * @param el - The HTML element from which to extract attributes.\r\n * @returns A record where the keys are attribute names and the values are attribute values.\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 /**\r\n * Initializes IntersectionObservers for a given object and its associated HTML element.\r\n *\r\n * This method sets up observer:\r\n * - A \"progress\" observer to track when the object enters or leaves the viewport.\r\n *\r\n * The observers are configured with custom root margins and thresholds based on the object's properties.\r\n * Existing observers, if any, are disconnected before creating new ones.\r\n *\r\n * @param obj - The `StringObject` instance containing properties and methods for interaction.\r\n * @param el - The `HTMLElement` to observe for intersection changes.\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 obj.getProperty<IntersectionObserver>(\"observer-progress\")?.disconnect();\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 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,\r\n });\r\n progressObserver.observe(el);\r\n obj.setProperty(\"observer-progress\", progressObserver);\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 =\r\n el.getAttribute(\"string-id\") ?? el.getAttribute(\"data-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 public checkInview() {\r\n this.objects.forEach((object) => {\r\n const scrollPos = this.data.scroll.transformedCurrent;\r\n const inviewStart = object.getProperty<number>(\"inview-start-position\");\r\n const inviewEnd = object.getProperty<number>(\"inview-end-position\");\r\n const wasInView = object.getProperty<boolean>(\"is-inview\") ?? false;\r\n const isNowInView = scrollPos >= inviewStart && scrollPos <= inviewEnd;\r\n if (isNowInView !== wasInView) {\r\n object.setProperty(\"is-inview\", isNowInView);\r\n this.events.emit(`object:inview:${object.id}`, isNowInView);\r\n isNowInView ? object.show() : object.hide();\r\n }\r\n });\r\n }\r\n}\r\n","import { ScrollMarkRule } from \"../../models/scroll/ScrollTriggerRule\";\r\nimport { 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 * Current scroll direction.\r\n * - `true` — scrolling down\r\n * - `false` — scrolling up\r\n * - `null` — unknown (initial state)\r\n */\r\n protected isBottomScrollDirection: boolean | null = null;\r\n\r\n protected isLastBottomScrollDirection: boolean = true;\r\n\r\n protected scrollTriggerRules: Array<ScrollMarkRule> = [];\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.triggerScrollRules();\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 };\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 this.triggerScrollRules();\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 private triggerScrollRules() {\r\n this.scrollTriggerRules.forEach((rule) => {\r\n const shouldTrigger =\r\n (rule.direction === \"any\" ||\r\n (this.isLastBottomScrollDirection && rule.direction === \"forward\")) &&\r\n this.context.data.scroll.current >= rule.offset;\r\n if (shouldTrigger) {\r\n rule.onEnter?.();\r\n if (rule.toggleClass) {\r\n rule.toggleClass.target.classList.add(rule.toggleClass.className);\r\n }\r\n } else {\r\n rule.onLeave?.();\r\n if (rule.toggleClass) {\r\n rule.toggleClass.target.classList.remove(rule.toggleClass.className);\r\n }\r\n }\r\n });\r\n }\r\n\r\n public addScrollMark(rule: ScrollMarkRule) {\r\n this.scrollTriggerRules.push(rule);\r\n }\r\n\r\n public removeScrollMark(id: string) {\r\n this.scrollTriggerRules = this.scrollTriggerRules.filter(\r\n (rule) => rule.id !== id\r\n );\r\n }\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","/**\n * CSS class names applied to `<html>` element based on scroll direction.\n */\nexport const SCROLL_CLASS_NAMES = {\n SCROLL_FORWARD: \"-scroll-forward\",\n SCROLL_BACKWARD: \"-scroll-backward\",\n SCROLLING_FORWARD: \"-scrolling-forward\",\n SCROLLING_BACKWARD: \"-scrolling-backward\",\n} as const;\n","import { SCROLL_CLASS_NAMES } from \"../../models/scroll/ScrollHTMLClass\";\r\nimport { StringContext } from \"../StringContext\";\r\nimport { ScrollController } from \"./ScrollController\";\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\n public 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\n private 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\n private 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\n private 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\n private previousCurrent: number = 0;\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\n private readonly velocityThreshold = 0.1;\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 this.isLastBottomScrollDirection = newDirection;\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(\r\n SCROLL_CLASS_NAMES.SCROLLING_FORWARD,\r\n newDirection\r\n );\r\n document.documentElement.classList.toggle(\r\n SCROLL_CLASS_NAMES.SCROLLING_BACKWARD,\r\n !newDirection\r\n );\r\n document.documentElement.classList.toggle(\r\n SCROLL_CLASS_NAMES.SCROLL_FORWARD,\r\n newDirection\r\n );\r\n document.documentElement.classList.toggle(\r\n SCROLL_CLASS_NAMES.SCROLL_BACKWARD,\r\n !newDirection\r\n );\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(\r\n SCROLL_CLASS_NAMES.SCROLLING_BACKWARD,\r\n SCROLL_CLASS_NAMES.SCROLLING_FORWARD\r\n );\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 =\r\n this.context.data.scroll.elementContainer.scrollTop;\r\n this.context.data.scroll.target =\r\n this.context.data.scroll.elementContainer.scrollTop;\r\n this.context.data.scroll.transformedCurrent =\r\n this.context.data.scroll.current *\r\n this.context.data.viewport.transformScale;\r\n return;\r\n }\r\n\r\n if (this.context.data.scroll.delta !== 0) {\r\n this.scrollForce =\r\n this.context.data.scroll.delta *\r\n 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(\r\n this.context.data.scroll.current + this.context.data.scroll.lerped\r\n );\r\n } else {\r\n this.context.data.scroll.current = Math.floor(\r\n this.context.data.scroll.current + this.context.data.scroll.lerped\r\n );\r\n }\r\n\r\n this.context.data.scroll.transformedCurrent =\r\n this.context.data.scroll.current *\r\n 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 =\r\n this.context.data.scroll.target ===\r\n 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 { ScrollMarkRule } from \"../../models/scroll/ScrollTriggerRule\";\r\nimport { 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 public addScrollMark(rule: ScrollMarkRule) {\r\n this.modes.forEach((engine) => {\r\n engine.addScrollMark(rule);\r\n });\r\n }\r\n public removeScrollMark(id: string) {\r\n this.modes.forEach((engine) => {\r\n engine.removeScrollMark(id);\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 * 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 * 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 that associates string keys with `StringObject` instances.\r\n * This map is used to manage and track `StringObject` instances on a page.\r\n */\r\n protected objectMapOnPage: Map<string, StringObject> = new Map();\r\n\r\n /**\r\n * A protected array that holds the collection of `StringObject` instances\r\n * currently present on the page.\r\n */\r\n protected objectsOnPage: StringObject[] = [];\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 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 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 {\r\n key: \"self-disable\",\r\n type: \"boolean\",\r\n fallback: this.settings[\"self-disable\"],\r\n },\r\n { key: \"abs\", type: \"boolean\", fallback: this.settings[\"abs\"] },\r\n { key: \"key\", type: \"string\", fallback: this.settings[\"key\"] },\r\n {\r\n key: \"offset-top\",\r\n type: \"dimension\",\r\n fallback: this.settings[\"offset-top\"],\r\n },\r\n {\r\n key: \"offset-bottom\",\r\n type: \"dimension\",\r\n fallback: this.settings[\"offset-bottom\"],\r\n },\r\n {\r\n key: \"inview-top\",\r\n type: \"dimension\",\r\n fallback: this.settings[\"inview-top\"],\r\n },\r\n {\r\n key: \"inview-bottom\",\r\n type: \"dimension\",\r\n fallback: this.settings[\"inview-bottom\"],\r\n },\r\n {\r\n key: \"start\",\r\n type: \"number\",\r\n fallback: (\r\n element: HTMLElement,\r\n object: StringObject,\r\n boundingRect: DOMRect\r\n ) => {\r\n const top = boundingRect.top;\r\n return (\r\n Math.floor(top) +\r\n this.data.scroll.container.scrollTop *\r\n this.data.viewport.transformScale\r\n );\r\n },\r\n },\r\n {\r\n key: \"end\",\r\n type: \"number\",\r\n fallback: (\r\n element: HTMLElement,\r\n object: StringObject,\r\n boundingRect: DOMRect\r\n ) => {\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\",\r\n type: \"number\",\r\n fallback: (\r\n element: HTMLElement,\r\n object: StringObject,\r\n boundingRect: DOMRect\r\n ) => {\r\n return boundingRect.height;\r\n },\r\n },\r\n {\r\n key: \"half-width\",\r\n type: \"number\",\r\n fallback: (\r\n element: HTMLElement,\r\n object: StringObject,\r\n boundingRect: DOMRect\r\n ) => {\r\n return boundingRect.width / 2;\r\n },\r\n },\r\n {\r\n key: \"half-height\",\r\n type: \"number\",\r\n fallback: (\r\n element: HTMLElement,\r\n object: StringObject,\r\n boundingRect: DOMRect\r\n ) => {\r\n return boundingRect.height / 2;\r\n },\r\n },\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 ];\r\n }\r\n\r\n /**\r\n * Initializes a `StringObject` by mapping attributes from an HTML element\r\n * and applying transformations as needed.\r\n *\r\n * @param globalId - A unique identifier for the object being initialized.\r\n * @param object - The `StringObject` instance to be initialized.\r\n * @param element - The HTML element from which attributes are extracted.\r\n * @param attributes - A record of additional attributes to be used during initialization.\r\n *\r\n * The method performs the following steps:\r\n * 1. Retrieves the bounding rectangle of the provided HTML element.\r\n * 2. Iterates over a predefined list of attributes to map.\r\n * 3. Resolves fallback values for attributes, either from the provided attributes,\r\n * settings, or a fallback function.\r\n * 4. Processes and parses the raw attribute values based on their expected type.\r\n * 5. Applies optional transformations to the parsed values.\r\n * 6. Sets the processed attributes as properties on the `StringObject` instance.\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\"\r\n ? fallback(element, object, boundingRect)\r\n : 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 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 let startBias = 0;\r\n let endBias = 0;\r\n\r\n if (\r\n (startElement === \"top\" && startViewport === \"top\") ||\r\n (startElement === \"left\" && startViewport === \"left\")\r\n ) {\r\n startBias = -windowSize + 1;\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 startBias = -windowSize - size + 1;\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 startBias = -size + 1;\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 endBias = -size + 1;\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 endBias = -windowSize - size + 1;\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 endBias = -windowSize + 1;\r\n endPosition = start - windowSize + size + offsetEnd;\r\n }\r\n\r\n object.setProperty<number>(\"start-bias\", startBias);\r\n object.setProperty<number>(\"end-bias\", endBias);\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 const inviewTop = object.getProperty<number>(\"inview-top\") ?? 0;\r\n const inviewBottom = object.getProperty<number>(\"inview-bottom\") ?? 0;\r\n object.setProperty<number>(\r\n \"inview-start-position\",\r\n startPosition - this.data.scroll.topPosition + startBias + inviewTop\r\n );\r\n object.setProperty<number>(\r\n \"inview-end-position\",\r\n endPosition + endBias + inviewBottom\r\n );\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 (\r\n context.element != null &&\r\n context.viewportHeight != null &&\r\n context.baseRem != null\r\n ) {\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 * Adds a `StringObject` to the internal collections if it does not already exist.\r\n *\r\n * @param id - The unique identifier for the `StringObject`.\r\n * @param object - The `StringObject` to be added.\r\n *\r\n * @remarks\r\n * This method ensures that the object is added to both `objectMapOnPage` and\r\n * `objectsOnPage` only if the `id` is not already present in `objectMapOnPage`.\r\n */\r\n addObject(id: string, object: StringObject): void {\r\n if (!this.objectMapOnPage.has(id)) {\r\n this.objectMapOnPage.set(id, object);\r\n this.objectsOnPage.push(object);\r\n }\r\n }\r\n\r\n /**\r\n * Removes an object from the page by its unique identifier.\r\n *\r\n * This method performs the following steps:\r\n * 1. Retrieves the object associated with the given `id` from `objectMapOnPage`.\r\n * 2. If the object is not found, the method exits early.\r\n * 3. Deletes the object from `objectMapOnPage`.\r\n * 4. Finds the index of the object in the `objectsOnPage` array.\r\n * 5. If the object exists in the array, it is removed using `splice`.\r\n *\r\n * @param id - The unique identifier of the object to be removed.\r\n */\r\n removeObject(id: string): void {\r\n const object = this.objectMapOnPage.get(id);\r\n if (!object) return;\r\n\r\n this.objectMapOnPage.delete(id);\r\n\r\n const index = this.objectsOnPage.indexOf(object);\r\n if (index !== -1) {\r\n this.objectsOnPage.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(\r\n object: StringObject,\r\n applyFn: (el: HTMLElement) => void\r\n ) {\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 { 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 { 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 optionsParser: SplitOptionsParserTool;\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 optionsParser = new SplitOptionsParserTool();\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\n * Represents a module responsible for handling loading-related functionality.\r\n * Extends the `StringModule` class and provides additional behavior for managing\r\n * loading states and timeouts.\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\n/**\r\n * The `StringAnchor` class extends the `StringModule` class and is responsible for\r\n * managing anchor-related functionality within the string module system.\r\n *\r\n * This class maps an `anchor` attribute to a tuple containing x and y coordinates,\r\n * processes these coordinates using the `originParser` tool, and applies the resulting\r\n * values to the connected object's element as a CSS `transform-origin` style.\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\n/**\r\n * The `StringGlide` class is a module that handles the glide effect for string objects\r\n * based on scroll events. It calculates displacement, acceleration, and velocity\r\n * to create a smooth scrolling effect for objects.\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\n/**\r\n * The `StringProgress` class extends the `StringModule` class and is responsible for\r\n * managing progress-based behavior for elements during scroll events. It maps specific\r\n * attributes, initializes objects, and updates their progress based on scroll data.\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: \"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 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","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\n/**\r\n * The `StringParallax` class extends the `StringProgress` class to provide\r\n * functionality for handling parallax effects on scrollable elements.\r\n * It maps specific attributes related to parallax and calculates the\r\n * necessary transformations based on scroll progress and viewport size.\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 = Math.abs(object.getProperty<number>(\"parallax\") ?? 0.2);\r\n object.setProperty(\r\n \"parallax-sign\",\r\n Math.sign(object.getProperty<number>(\"parallax\"))\r\n );\r\n object.setProperty<number>(\"parallax\", factor);\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 const sign = object.getProperty<number>(\"parallax-sign\") ?? 1;\r\n\r\n const screenSize = this.data.viewport.windowHeight;\r\n const translation =\r\n sign * factor * (screenSize * start + progress * 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","export const SPLIT_ELEMENT_CLASS = {\n BEFORE_ELEMENT: \"-before-element\",\n AFTER_ELEMENT: \"-after-element\",\n} as const;\n","import { CalculatedValue } from \"../../models/text/CalculatedValue\";\nimport { LayoutLine } from \"./SplitMeasuredTokens\";\nimport { ISplitOptions } from \"../../models/text/ISplitOptions\";\nimport { SPLIT_ELEMENT_CLASS } from \"../../models/text/SplitElementClass\";\n\n/**\n * Builds a DOM tree representation of the given layout lines based on the provided options.\n *\n * @param layoutLines - An array of `LayoutLine` objects, each representing a line of text\n * with associated words and characters.\n * @param options - An `ISplitOptions` object that specifies how the DOM tree should be constructed,\n * including options for line, word, and character-level styling and structure.\n *\n * @returns A `DocumentFragment` containing the constructed DOM tree.\n *\n * The function processes the layout lines and creates a hierarchical DOM structure:\n * - If line-level options are enabled, each line is wrapped in a `<span>` element with the class `-s-line`.\n * - If word-level options are enabled, each word is wrapped in a `<span>` element with the class `-s-word`.\n * - If character-level options are enabled, each character is wrapped in a `<span>` element with the class `-s-char`.\n *\n * The function also applies styles and attributes to the created elements based on the provided options\n * and the calculated values in the layout lines, words, and characters.\n *\n * Special handling is applied for tokens of type `element`, where the original DOM node is cloned\n * and appended directly to the container.\n *\n * Spaces between words are preserved using non-breaking space (`\\u00a0`) text nodes.\n */\nexport function BuildDOMTree(\n layoutLines: LayoutLine[],\n options: ISplitOptions\n): DocumentFragment {\n const fragment = document.createDocumentFragment();\n let localCharIndex = 0;\n const hasLine =\n hasOption(options, \"line\") ||\n hasOption(options, \"charLine\") ||\n hasOption(options, \"wordLine\");\n\n layoutLines.forEach((line) => {\n let container: HTMLElement | DocumentFragment = fragment;\n if (hasLine) {\n container = document.createElement(\"span\");\n container.classList.add(\"-s-line\");\n if (line.isBeforeElement) {\n container.classList.add(SPLIT_ELEMENT_CLASS.BEFORE_ELEMENT);\n }\n if (line.isAfterElement) {\n container.classList.add(SPLIT_ELEMENT_CLASS.AFTER_ELEMENT);\n }\n container.style.setProperty(\"--line-index\", String(line.lineIndex));\n container.style.setProperty(\"--word-total\", String(line.words.length));\n applyStyles(container, (line as any).calculatedValues, options);\n }\n\n line.words.forEach((word, wi) => {\n const isLast = wi === line.words.length - 1;\n\n if (word.chars.length === 1 && word.chars[0].token.type === \"element\") {\n const original = word.chars[0].token.node.cloneNode(\n true\n ) as HTMLElement;\n container.appendChild(original);\n if (!isLast) container.appendChild(document.createTextNode(\"\\u00a0\"));\n return;\n }\n\n const hasWord =\n hasOption(options, \"word\") ||\n hasOption(options, \"charWord\") ||\n hasOption(options, \"wordLine\");\n const wordEl = hasWord\n ? document.createElement(\"span\")\n : (container as HTMLElement);\n\n if (hasWord) {\n wordEl.classList.add(\"-s-word\");\n if (word.isBeforeElement) {\n wordEl.classList.add(SPLIT_ELEMENT_CLASS.BEFORE_ELEMENT);\n }\n if (word.isAfterElement) {\n wordEl.classList.add(SPLIT_ELEMENT_CLASS.AFTER_ELEMENT);\n }\n wordEl.style.setProperty(\"--word-index\", String(word.wordIndexGlobal));\n wordEl.style.setProperty(\"--char-total\", String(word.chars.length));\n applyStyles(wordEl, (word as any).calculatedValues, options);\n }\n\n const hasChar =\n hasOption(options, \"char\") ||\n hasOption(options, \"charLine\") ||\n hasOption(options, \"charWord\");\n\n if (hasChar) {\n word.chars.forEach((char) => {\n if (char.char === \" \" || char.char === \"\\t\") return;\n const charNode = document.createElement(\"span\");\n const charEl = charNode as HTMLElement;\n charEl.classList.add(\"-s-char\");\n if (char.isBeforeElement) {\n charEl.classList.add(SPLIT_ELEMENT_CLASS.BEFORE_ELEMENT);\n }\n if (char.isAfterElement) {\n charEl.classList.add(SPLIT_ELEMENT_CLASS.AFTER_ELEMENT);\n }\n charEl.textContent = char.char;\n charEl.style.setProperty(\"--char-index\", String(localCharIndex++));\n applyStyles(charEl, (char as any).calculatedValues, options);\n wordEl.appendChild(charNode);\n });\n } else {\n const charNode = document.createTextNode(\n word.chars.map((c) => c.char).join(\"\")\n );\n wordEl.appendChild(charNode);\n }\n\n if (hasWord) {\n container.appendChild(wordEl);\n }\n if (!isLast) {\n wordEl.appendChild(document.createTextNode(\"\\u00a0\"));\n } else {\n container.appendChild(document.createElement(\"br\"));\n }\n });\n\n if (hasLine) fragment.appendChild(container as HTMLElement);\n });\n\n return fragment;\n}\n\n/**\n * Applies calculated styles to a given HTML element based on the provided values and options.\n *\n * @param el - The HTML element to which the styles will be applied.\n * @param calculatedValues - An array of calculated values containing style information, or `undefined` if no styles are to be applied.\n * @param options - The options object that determines which styles are enabled and how they should be aligned.\n *\n * @remarks\n * This function iterates over the `calculatedValues` array and applies styles to the element\n * only if the corresponding option is enabled. The style property name is generated dynamically\n * using the `generateVariableName` function.\n *\n * @example\n * ```typescript\n * const element = document.createElement('div');\n * const calculatedValues = [\n * { type: 'color', align: 'left', value: '#ff0000' },\n * { type: 'margin', align: 'top', value: '10px' }\n * ];\n * const options = { enableColor: true, enableMargin: true };\n * applyStyles(element, calculatedValues, options);\n * ```\n */\nfunction applyStyles(\n el: HTMLElement,\n calculatedValues: CalculatedValue[] | undefined,\n options: ISplitOptions\n) {\n if (!calculatedValues) return;\n for (const val of calculatedValues) {\n if (!isOptionEnabled(val.type, val.align, options)) continue;\n const varName = generateVariableName(val.type, val.align);\n el.style.setProperty(varName, String(val.value));\n }\n}\n\n/**\n * Determines whether a specific option is enabled based on the provided type, alignment, and options.\n *\n * @param type - The type of the option to check within the options object.\n * @param align - The alignment string to match against the option's alignment.\n * If the alignment starts with \"random\", it checks for options\n * whose alignment also starts with \"random\".\n * @param options - An object containing various option groups, where each group\n * is an array of items with an `align` property.\n * @returns `true` if the specified option is enabled, otherwise `false`.\n */\nfunction isOptionEnabled(\n type: string,\n align: string,\n options: ISplitOptions\n): boolean {\n const group = options[type as keyof ISplitOptions] ?? [];\n return (\n Array.isArray(group) &&\n group.some((item) =>\n align.startsWith(\"random\")\n ? item.align.startsWith(\"random\")\n : item.align === align\n )\n );\n}\n\n/**\n * Generates a CSS variable name based on the provided type and alignment.\n *\n * The function normalizes the `align` parameter by checking if it starts with \"random\".\n * If it does, the alignment is normalized to \"random\"; otherwise, the original alignment is used.\n * The resulting variable name is constructed in the format `--<type>-<normalizedAlign>`.\n *\n * @param type - The type of the variable, typically representing a category or context.\n * @param align - The alignment or variation, which may start with \"random\" or be a specific value.\n * @returns A string representing the generated CSS variable name.\n */\nfunction generateVariableName(type: string, align: string): string {\n const norm = align.startsWith(\"random\") ? \"random\" : align;\n return `--${type}-${norm}`;\n}\n\n/**\n * Checks if a specific key in the given options object is an array and contains at least one element.\n *\n * @param options - The options object implementing the `ISplitOptions` interface.\n * @param key - The key to check within the options object.\n * @returns `true` if the value associated with the key is an array with at least one element, otherwise `false`.\n */\nfunction hasOption(options: ISplitOptions, key: keyof ISplitOptions): boolean {\n return Array.isArray(options[key]) && options[key]!.length > 0;\n}\n","export type Token =\n | {\n type: \"text\";\n id: string;\n node: Text;\n content: string;\n meta?: Record<string, any>;\n }\n | {\n type: \"space\";\n id: string;\n node: Text;\n content: string;\n meta?: Record<string, any>;\n }\n | {\n type: \"element\";\n id: string;\n node: HTMLElement;\n tagName: string;\n meta?: Record<string, any>;\n }\n | {\n type: \"other\";\n id: string;\n node: Node;\n meta?: Record<string, any>;\n };\n\nlet tokenCounter = 0;\n\n/**\n * Builds an array of tokens from a given list of child nodes.\n *\n * This function processes each node in the provided `NodeListOf<ChildNode>` and generates\n * a corresponding token object based on the node type. The tokens can represent elements,\n * text nodes, whitespace, or other types of nodes.\n *\n * @param nodes - A collection of child nodes to be processed into tokens.\n * @returns An array of tokens, where each token represents a node with additional metadata.\n *\n * Token Types:\n * - `element`: Represents an HTML element node, including its tag name.\n * - `text`: Represents a text node with non-whitespace content.\n * - `space`: Represents a text node with only whitespace content.\n * - `other`: Represents any other type of node.\n *\n * Each token includes:\n * - `type`: The type of the token (`element`, `text`, `space`, or `other`).\n * - `id`: A unique identifier for the token.\n * - `node`: The original DOM node.\n * - Additional properties depending on the token type:\n * - `tagName` for `element` tokens.\n * - `content` for `text` and `space` tokens.\n */\nexport function BuildTokens(nodes: NodeListOf<ChildNode>): Token[] {\n tokenCounter = 0;\n const tokens: Token[] = [];\n\n nodes.forEach((node) => {\n if (node.nodeType === Node.ELEMENT_NODE) {\n const el = node as HTMLElement;\n\n tokens.push({\n type: \"element\",\n id: `el_${tokenCounter++}`,\n node: el,\n tagName: el.tagName.toLowerCase(),\n });\n } else if (node.nodeType === Node.TEXT_NODE) {\n const text = node.nodeValue ?? \"\";\n const id = `text_${tokenCounter++}`;\n\n if (text.trim()) {\n tokens.push({ type: \"text\", id, node: node as Text, content: text });\n } else {\n tokens.push({ type: \"space\", id, node: node as Text, content: text });\n }\n } else {\n tokens.push({ type: \"other\", id: `node_${tokenCounter++}`, node });\n }\n });\n\n return tokens;\n}\n","import { Token } from \"./BuildTokens\";\n\nexport type MeasuredToken = {\n token: Token;\n rect: DOMRect;\n};\n\n/**\n * Measures the layout of tokens within a given container element.\n * This function calculates the bounding rectangles for each token\n * by rendering them temporarily in a hidden wrapper element and\n * measuring their dimensions.\n *\n * @param tokens - An array of tokens to be measured. Each token can be of type \"text\", \"element\", or \"other\".\n * - \"text\": Represents a text token with content to be measured.\n * - \"element\": Represents an HTML element token to be measured.\n * - \"other\": Tokens of this type are ignored.\n * @param container - The container HTMLElement within which the tokens are measured.\n * The width of this container is used to constrain the layout.\n * @returns An array of measured tokens, where each measured token contains:\n * - `token`: The original token with additional information for \"text\" tokens.\n * - `rect`: The DOMRect representing the bounding rectangle of the token.\n */\nexport function LayoutMeasurer(\n tokens: Token[],\n container: HTMLElement\n): MeasuredToken[] {\n const wrapper = document.createElement(\"div\");\n const computed = window.getComputedStyle(container);\n wrapper.style.position = \"absolute\";\n wrapper.style.visibility = \"hidden\";\n wrapper.style.pointerEvents = \"none\";\n wrapper.style.width = container.clientWidth + \"px\";\n wrapper.style.padding = computed.padding;\n wrapper.style.font = computed.font;\n wrapper.style.letterSpacing = computed.letterSpacing;\n wrapper.style.lineHeight = computed.lineHeight;\n wrapper.style.fontVariant = computed.fontVariant;\n wrapper.style.fontStretch = computed.fontStretch;\n\n container.appendChild(wrapper);\n\n const measured: MeasuredToken[] = [];\n\n let isAfterElement = false;\n\n var span;\n var rect;\n tokens.forEach((token, idx) => {\n let node: Node;\n\n switch (token.type) {\n case \"text\":\n let words = token.content\n .trim()\n .split(/\\s+/)\n .filter((word) => word.length > 0);\n\n words.forEach((word, wordInd) => {\n node = document.createTextNode(word);\n\n span = document.createElement(\"span\");\n span.style.display = \"inline-block\";\n span.appendChild(node);\n span.appendChild(document.createTextNode(\"\\u00a0\"));\n wrapper.appendChild(span);\n rect = span.getBoundingClientRect();\n let measuredText: MeasuredToken = {\n token: {\n type: \"text\",\n id: \"\",\n node: node as Text,\n content: word,\n },\n rect,\n };\n if (isAfterElement) {\n isAfterElement = false;\n measuredText.token.meta = {\n ...(measuredText.token.meta || {}),\n isAfterElement: true,\n };\n }\n measured.push(measuredText);\n });\n\n break;\n case \"element\":\n node = token.node.cloneNode(true);\n span = document.createElement(\"span\");\n span.style.display = \"inline-block\";\n span.appendChild(node);\n wrapper.appendChild(span);\n rect = span.getBoundingClientRect();\n measured.push({ token, rect });\n\n const prev = measured[measured.length - 2];\n if (prev?.token.type === \"text\") {\n prev.token.meta = {\n ...(prev.token.meta || {}),\n isBeforeElement: true,\n };\n }\n isAfterElement = true;\n break;\n case \"other\":\n return;\n }\n });\n\n container.removeChild(wrapper);\n return measured;\n}\n","import { MeasuredToken } from \"./LayoutMeasurer\";\nimport { Token } from \"./BuildTokens\";\n\nexport type ProcessedChar = {\n char: string;\n rect: DOMRect;\n token: Token;\n charIndexGlobal: number;\n charIndexInLine: number;\n charIndexInWord: number;\n isBeforeElement?: boolean;\n isAfterElement?: boolean;\n};\n\nexport type ProcessedWord = {\n chars: ProcessedChar[];\n rect: DOMRect;\n wordIndexGlobal: number;\n wordIndexInLine: number;\n isBeforeElement?: boolean;\n isAfterElement?: boolean;\n};\n\nexport type LayoutLine = {\n words: ProcessedWord[];\n rect: DOMRect;\n lineIndex: number;\n isBeforeElement?: boolean;\n isAfterElement?: boolean;\n};\n\nconst LINE_TOLERANCE = 1;\n\nexport function SplitMeasuredTokens(measured: MeasuredToken[]): LayoutLine[] {\n const lines: LayoutLine[] = [];\n let currentLine: LayoutLine | null = null;\n let y = 0;\n\n let charIndexGlobal = 0;\n let wordIndexGlobal = 0;\n\n measured.forEach((mt) => {\n const token = mt.token;\n const isBefore = token.meta?.isBeforeElement ?? false;\n const isAfter = token.meta?.isAfterElement ?? false;\n\n if (token.type === \"text\") {\n const segments = token.content.match(/(\\s+|\\S+)/g);\n if (!segments) return;\n\n let offsetX = mt.rect.left;\n const contentLength = token.content.length;\n const avgCharWidth =\n contentLength > 0 ? mt.rect.width / contentLength : 0;\n\n segments.forEach((segment) => {\n if (/^\\s+$/.test(segment)) {\n offsetX += avgCharWidth * segment.length;\n return;\n }\n\n const chars: ProcessedChar[] = [];\n segment.split(\"\").forEach((char, i) => {\n const rect = new DOMRect(\n offsetX,\n mt.rect.top,\n avgCharWidth,\n mt.rect.height\n );\n chars.push({\n char,\n rect,\n token,\n charIndexInWord: i,\n charIndexInLine: 0,\n charIndexGlobal: charIndexGlobal++,\n });\n offsetX += avgCharWidth;\n });\n\n if (chars.length > 0) {\n const lastChar = chars[chars.length - 1];\n if (isBefore) lastChar.isBeforeElement = true;\n if (isAfter) lastChar.isAfterElement = true;\n }\n\n const isNewLine =\n !currentLine || Math.abs(mt.rect.top - y) > LINE_TOLERANCE;\n if (isNewLine) {\n y = mt.rect.top;\n currentLine = { words: [], rect: mt.rect, lineIndex: lines.length };\n lines.push(currentLine);\n }\n\n if (!currentLine) return;\n\n const wordIndexInLine = currentLine.words.length;\n const charsBefore = currentLine.words.reduce(\n (acc, w) => acc + w.chars.length,\n 0\n );\n chars.forEach((c, i) => (c.charIndexInLine = charsBefore + i));\n\n const processedWord: ProcessedWord = {\n chars,\n rect: mt.rect,\n wordIndexGlobal: wordIndexGlobal++,\n wordIndexInLine,\n isBeforeElement: isBefore,\n isAfterElement: isAfter,\n };\n\n currentLine.words.push(processedWord);\n currentLine.rect = mergeRects(currentLine.words.map((w) => w.rect));\n if (isBefore) currentLine.isBeforeElement = true;\n if (isAfter) currentLine.isAfterElement = true;\n });\n } else if (token.type === \"element\") {\n const rect = mt.rect;\n const isNewLine = !currentLine || Math.abs(rect.top - y) > LINE_TOLERANCE;\n\n if (isNewLine) {\n y = rect.top;\n currentLine = { words: [], rect, lineIndex: lines.length };\n lines.push(currentLine);\n }\n\n if (!currentLine) return;\n\n const wordIndexInLine = currentLine.words.length;\n const charsBefore = currentLine.words.reduce(\n (acc, w) => acc + w.chars.length,\n 0\n );\n\n const chars: ProcessedChar[] = [\n {\n char: \"[E]\",\n rect,\n token,\n charIndexInWord: 0,\n charIndexInLine: charsBefore,\n charIndexGlobal: charIndexGlobal++,\n },\n ];\n\n const processedWord: ProcessedWord = {\n chars,\n rect,\n wordIndexGlobal: wordIndexGlobal++,\n wordIndexInLine,\n isBeforeElement: false,\n isAfterElement: false,\n };\n\n currentLine.words.push(processedWord);\n currentLine.rect = mergeRects(currentLine.words.map((w) => w.rect));\n }\n });\n\n return lines;\n}\n\nfunction mergeRects(rects: DOMRect[]): DOMRect {\n const left = Math.min(...rects.map((r) => r.left));\n const top = Math.min(...rects.map((r) => r.top));\n const right = Math.max(...rects.map((r) => r.right));\n const bottom = Math.max(...rects.map((r) => r.bottom));\n return new DOMRect(left, top, right - left, bottom - top);\n}\n","import { StringContext } from \"../../core/StringContext\";\r\nimport { StringModule } from \"../../core/StringModule\";\r\nimport { CalculatedValue } from \"../../models/text/CalculatedValue\";\r\nimport { ISplitOptionItem } from \"../../models/text/ISplitOptionItem\";\r\nimport { ISplitOptions } from \"../../models/text/ISplitOptions\";\r\nimport { StringObject } from \"../../objects/StringObject\";\r\nimport { BuildDOMTree } from \"../../utils/text/BuildDOMTree\";\r\nimport { BuildTokens } from \"../../utils/text/BuildTokens\";\r\nimport { LayoutMeasurer } from \"../../utils/text/LayoutMeasurer\";\r\nimport {\r\n LayoutLine,\r\n ProcessedChar,\r\n ProcessedWord,\r\n SplitMeasuredTokens,\r\n} from \"../../utils/text/SplitMeasuredTokens\";\r\n\r\n/**\r\n * StringSplit module: splits text into lines, words, chars,\r\n * computes alignment/random values, and applies CSS vars.\r\n */\r\nexport class StringSplit extends StringModule {\r\n constructor(context: StringContext) {\r\n super(context);\r\n this.htmlKey = \"split\";\r\n }\r\n\r\n onResize(): void {\r\n this.objectsOnPage.forEach((object) => {\r\n this.onObjectConnected(object);\r\n });\r\n }\r\n\r\n onObjectConnected(object: StringObject): void {\r\n const element = object.htmlElement;\r\n if (!element) return;\r\n\r\n const isAlreadySplit = element.classList.contains(\"-splitted\");\r\n let originalHtml = element.getAttribute(\"string-split-original\");\r\n\r\n if (!isAlreadySplit || originalHtml === null) {\r\n originalHtml = this.escapeAttribute(element.innerHTML);\r\n element.setAttribute(\"string-split-original\", originalHtml);\r\n element.classList.add(\"-splitted\");\r\n }\r\n\r\n object.htmlElement.innerHTML = originalHtml;\r\n const attr =\r\n element.getAttribute(\"string-split\") ??\r\n element.getAttribute(\"data-string-split\") ??\r\n \"\";\r\n const options: ISplitOptions = this.tools.optionsParser.process({\r\n attributeValue: attr,\r\n });\r\n const { fragment, result } = this.split(element, options);\r\n object.setProperty(\"nodes\", fragment.childNodes);\r\n element.innerHTML = \"\";\r\n element.appendChild(result);\r\n }\r\n\r\n public split(element: HTMLElement, options: ISplitOptions) {\r\n const frag = document.createDocumentFragment();\r\n element.childNodes.forEach((ch) => frag.appendChild(ch.cloneNode(true)));\r\n const tokens = BuildTokens(frag.childNodes as NodeListOf<ChildNode>);\r\n const measured = LayoutMeasurer(tokens, element);\r\n const layoutLines: LayoutLine[] = SplitMeasuredTokens(measured);\r\n this.applyCalculatedValues(layoutLines, options);\r\n const dom = BuildDOMTree(layoutLines, options);\r\n return {\r\n fragment: frag,\r\n result: dom,\r\n };\r\n }\r\n\r\n /**\r\n * Computes a numeric value based on the provided split option, index, and total count.\r\n *\r\n * @param opt - The split option item containing alignment and optional random range.\r\n * @param index - The current index in the sequence.\r\n * @param total - The total number of items in the sequence.\r\n * @returns A computed numeric value based on the alignment strategy:\r\n * - \"random\": A random value within the specified range or default range.\r\n * - \"start\": The current index.\r\n * - \"end\": The reverse index from the end of the sequence.\r\n * - \"center\": The distance from the center index.\r\n * - Default: The current index.\r\n */\r\n private computeValue(\r\n opt: ISplitOptionItem,\r\n index: number,\r\n total: number\r\n ): number {\r\n if (opt.align.startsWith(\"random\")) {\r\n const min = opt.random?.min ?? 0;\r\n const max = opt.random?.max ?? total - 1;\r\n return Math.floor(Math.random() * (max - min + 1)) + min;\r\n }\r\n switch (opt.align) {\r\n case \"start\":\r\n return index;\r\n case \"end\":\r\n return total - index - 1;\r\n case \"center\": {\r\n const centerIdx = Math.floor((total - 1) / 2);\r\n return Math.abs(index - centerIdx);\r\n }\r\n default:\r\n return index;\r\n }\r\n }\r\n\r\n /**\r\n * Applies calculated values to the provided layout lines and their components (words and characters)\r\n * based on the given options. This method computes and assigns various calculated values\r\n * (e.g., alignment and value) to lines, words, and characters, depending on the specified options.\r\n *\r\n * @param lines - An array of `LayoutLine` objects representing the lines of text to process.\r\n * @param options - An `ISplitOptions` object specifying the calculation options for lines, words, and characters.\r\n *\r\n * The `options` parameter can include the following properties:\r\n * - `line`: An array of options for calculating values at the line level.\r\n * - `word`: An array of options for calculating values at the word level.\r\n * - `wordLine`: An array of options for calculating values at the word level relative to the line.\r\n * - `char`: An array of options for calculating values at the character level.\r\n * - `charWord`: An array of options for calculating values at the character level relative to the word.\r\n * - `charLine`: An array of options for calculating values at the character level relative to the line.\r\n *\r\n * Each calculated value is assigned to the corresponding `calculatedValues` property of the line, word, or character.\r\n * The method ensures that all specified options are processed and the calculated values are appended accordingly.\r\n */\r\n private applyCalculatedValues(\r\n lines: LayoutLine[],\r\n options: ISplitOptions\r\n ): void {\r\n const countChars = (ln: LayoutLine) =>\r\n ln.words.reduce((acc, w: ProcessedWord) => acc + w.chars.length, 0);\r\n\r\n const totalWords = lines.reduce((acc, l) => acc + l.words.length, 0);\r\n const totalCharsGlobal = lines.reduce(\r\n (acc, l) => acc + l.words.reduce((acc2, w) => acc2 + w.chars.length, 0),\r\n 0\r\n );\r\n\r\n lines.forEach((line, li) => {\r\n if (options.line) {\r\n (line as any).calculatedValues = options.line.map(\r\n (opt) =>\r\n ({\r\n type: \"line\",\r\n align: opt.align,\r\n value: this.computeValue(opt, li, lines.length),\r\n } as CalculatedValue)\r\n );\r\n }\r\n\r\n line.words.forEach((word: ProcessedWord, wi) => {\r\n if (options.word) {\r\n (word as any).calculatedValues = options.word.map(\r\n (opt) =>\r\n ({\r\n type: \"word\",\r\n align: opt.align,\r\n value: this.computeValue(opt, word.wordIndexGlobal, totalWords),\r\n } as CalculatedValue)\r\n );\r\n }\r\n\r\n if (options.wordLine) {\r\n (word as any).calculatedValues ??= [];\r\n (word as any).calculatedValues.push(\r\n ...options.wordLine.map(\r\n (opt) =>\r\n ({\r\n type: \"wordLine\",\r\n align: opt.align,\r\n value: this.computeValue(\r\n opt,\r\n word.wordIndexInLine,\r\n line.words.length\r\n ),\r\n } as CalculatedValue)\r\n )\r\n );\r\n }\r\n\r\n const totalCharsInLine = countChars(line);\r\n\r\n word.chars.forEach((char: ProcessedChar) => {\r\n const cvs: CalculatedValue[] = [];\r\n\r\n if (options.char) {\r\n cvs.push(\r\n ...options.char.map(\r\n (opt) =>\r\n ({\r\n type: \"char\",\r\n align: opt.align,\r\n value: this.computeValue(\r\n opt,\r\n char.charIndexGlobal,\r\n totalCharsGlobal\r\n ),\r\n } as CalculatedValue)\r\n )\r\n );\r\n }\r\n\r\n if (options.charWord) {\r\n cvs.push(\r\n ...options.charWord.map(\r\n (opt) =>\r\n ({\r\n type: \"charWord\",\r\n align: opt.align,\r\n value: this.computeValue(\r\n opt,\r\n char.charIndexInWord,\r\n word.chars.length\r\n ),\r\n } as CalculatedValue)\r\n )\r\n );\r\n }\r\n\r\n if (options.charLine) {\r\n cvs.push(\r\n ...options.charLine.map(\r\n (opt) =>\r\n ({\r\n type: \"charLine\",\r\n align: opt.align,\r\n value: this.computeValue(\r\n opt,\r\n char.charIndexInLine,\r\n totalCharsInLine\r\n ),\r\n } as CalculatedValue)\r\n )\r\n );\r\n }\r\n\r\n (char as any).calculatedValues = cvs;\r\n });\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Escapes the `src` attribute in a given string by removing the quotes around the URL.\r\n *\r\n * This method searches for occurrences of `src=\"URL\"` where `URL` is an HTTP or HTTPS link,\r\n * and replaces it with `src=URL` (removing the quotes around the URL).\r\n *\r\n * @param str - The input string containing the `src` attributes to be escaped.\r\n * @returns The modified string with escaped `src` attributes.\r\n */\r\n private escapeAttribute(str: string): string {\r\n return str.replace(/src=\"(https?:\\/\\/[^\"\\s]+)\"/g, \"src=$1\");\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","export enum SequenceState {\r\n ACTIVE = \"-active\",\r\n HIDE = \"-hide\",\r\n DISABLE = \"-disable\",\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 { SequenceState } from \"../../models/slider/SequenceState\";\r\nimport { StringObject } from \"../../objects/StringObject\";\r\n\r\n/**\r\n * Module that manages sequence states for elements based on slider step events.\r\n * Updates element classes (ACTIVE, HIDE, DISABLE) according to the current sequence position.\r\n */\r\nexport class StringSequence extends StringModule {\r\n /**\r\n * Stores the current active step index for each slider.\r\n */\r\n private activeStepForSlides: Map<string, number> = new Map();\r\n\r\n /**\r\n * Stores the last active step index for each slider to hide the previous element.\r\n */\r\n private hideStepForSlides: Map<string, number> = new Map();\r\n /**\r\n * @param context StringContext instance for dependency injection.\r\n */\r\n\r\n constructor(context: StringContext) {\r\n super(context);\r\n this.htmlKey = \"sequence\";\r\n\r\n this.attributesToMap = [\r\n ...this.attributesToMap,\r\n { key: \"sequence\", type: \"string\", fallback: \"string[0]\" },\r\n ];\r\n }\r\n\r\n /**\r\n * Subscribes to slider step events and updates element states:\r\n * - Sets ACTIVE for the current element.\r\n * - Sets HIDE for the previously active element.\r\n * - Sets DISABLE for all others.\r\n */\r\n onInit(): void {\r\n super.onInit();\r\n this.events.on<{ slider: string; step: number }>(\r\n \"sequence\",\r\n ({ slider, step }) => {\r\n this.objectsOnPage.forEach((object) => {\r\n const sequence = object.getProperty<string>(\"sequence\");\r\n if (\r\n sequence == `${slider}[${this.hideStepForSlides.get(slider)}]` &&\r\n sequence != `${slider}[${step}]`\r\n ) {\r\n this.setSequenceState(object, SequenceState.DISABLE);\r\n }\r\n if (\r\n sequence == `${slider}[${this.activeStepForSlides.get(slider)}]`\r\n ) {\r\n this.setSequenceState(object, SequenceState.HIDE);\r\n }\r\n if (sequence == `${slider}[${step}]`) {\r\n this.setSequenceState(object, SequenceState.ACTIVE);\r\n }\r\n });\r\n let activeIndex = this.activeStepForSlides.get(slider);\r\n if (activeIndex != undefined) {\r\n this.hideStepForSlides.set(slider, activeIndex);\r\n }\r\n this.activeStepForSlides.set(slider, step);\r\n }\r\n );\r\n }\r\n\r\n /**\r\n * Sets initial state DISABLE for a newly connected element.\r\n * @param object The connected StringObject.\r\n */\r\n onObjectConnected(object: StringObject): void {\r\n super.onObjectConnected(object);\r\n this.setSequenceState(object, SequenceState.DISABLE);\r\n }\r\n\r\n /**\r\n * Updates the element's class according to the given SequenceState.\r\n * Removes all possible sequence state classes before applying the new one.\r\n * @param object The target StringObject.\r\n * @param state The state to set (ACTIVE, HIDE, DISABLE).\r\n */\r\n private setSequenceState(object: StringObject, state: SequenceState) {\r\n requestAnimationFrame(() => {\r\n object.htmlElement.classList.remove(...Object.values(SequenceState));\r\n object.htmlElement.classList.add(state);\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","StringSequence","StringSplit","StringTune","StringVideoAutoplay","__toCommonJS","CursorController","smoothing","context","targetX","targetY","smoothedX","smoothedY","stepX","stepY","distance","lerp","t","x","y","EventManager","eventName","callback","id","fullEvent","payload","set","value","visible","ModuleManager","data","module","type","m","added","removed","StringObject","id","element","EventManager","key","value","module","ObjectManager","data","modules","events","el","idAttr","key","object","StringObject","keysAttr","attributes","m","q","item","id","obj","element","attr","start","end","progressCallback","entries","e","progressObserver","mutations","mutation","node","child","copyFrom","scrollPos","inviewStart","inviewEnd","wasInView","isNowInView","ScrollController","context","scrollDirection","rule","id","StringScrollDefault","ScrollController","context","delta","e","scrollTop","plusDelta","StringScrollDisable","ScrollController","context","e","SCROLL_CLASS_NAMES","StringScrollSmooth","ScrollController","context","newDirection","SCROLL_CLASS_NAMES","absVelocity","e","scrollDirection","atTop","atBottom","ScrollManager","context","StringScrollSmooth","StringScrollDefault","StringScrollDisable","mode","newMode","engine","events","rule","id","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","start","size","offsetStart","offsetEnd","startElement","startViewport","endElement","endViewport","startPosition","endPosition","startBias","endBias","inviewTop","inviewBottom","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","s","l","hue2rgb","q","t","p","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","s","scaleValue","scaleNumbers","scaleXValue","scaleNumber","scale3dValue","matrix3dValues","error","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","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","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","StringParallax","StringProgress","context","object","progress","factor","start","end","sign","screenSize","translation","transform","el","globalId","element","attributes","bias","data","isDesktop","StringScrollbarHorizontal","data","scrollbar","thumb","contentWidth","visibleWidth","thumbSize","deltaY","newScrollPosition","StringScrollbarVertical","data","scrollbar","thumb","contentSize","visibleSize","thumbSize","contentHeight","visibleHeight","deltaY","newScrollPosition","maxScroll","clamped","StringScrollbar","StringModule","context","data","style","StringScrollbarHorizontal","StringScrollbarVertical","e","SPLIT_ELEMENT_CLASS","BuildDOMTree","layoutLines","options","fragment","localCharIndex","hasLine","hasOption","line","container","SPLIT_ELEMENT_CLASS","applyStyles","word","wi","isLast","original","hasWord","wordEl","char","charNode","charEl","c","el","calculatedValues","val","isOptionEnabled","varName","generateVariableName","type","align","group","item","norm","key","tokenCounter","BuildTokens","nodes","tokens","node","el","text","id","LayoutMeasurer","tokens","container","wrapper","computed","measured","isAfterElement","span","rect","token","idx","node","word","wordInd","measuredText","prev","LINE_TOLERANCE","SplitMeasuredTokens","measured","lines","currentLine","y","charIndexGlobal","wordIndexGlobal","mt","token","isBefore","isAfter","segments","offsetX","contentLength","avgCharWidth","segment","chars","char","i","rect","lastChar","wordIndexInLine","charsBefore","acc","w","c","processedWord","mergeRects","rects","left","r","top","right","bottom","StringSplit","StringModule","context","object","element","isAlreadySplit","originalHtml","attr","options","fragment","result","frag","ch","tokens","BuildTokens","measured","LayoutMeasurer","layoutLines","SplitMeasuredTokens","dom","BuildDOMTree","opt","index","total","min","max","centerIdx","lines","countChars","ln","acc","w","totalWords","l","totalCharsGlobal","acc2","line","li","word","wi","totalCharsInLine","char","cvs","str","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","SequenceState","StringSequence","StringModule","context","slider","step","object","sequence","activeIndex","state","SequenceState","StringTune","_StringTune","StringFPS","Debounce","DefaultToolsContainer","StringData","EventManager","ModuleManager","ObjectManager","CursorController","ScrollManager","time","value","container","speed","mode","type","objectClass","settings","effectiveSettings","module","eventName","callback","id","data","rule","fps","observerContainerMutation","mutationsList","observer","mutation","config","StringInview","htmlFontSize","fontSizeNumber","element","connectTargetId","scroll","width","height","newScrollHeight","newContainerTopPosition","rect","transformScale","isDesktop","widthChanged","heightChanged","scrollHeightChanged","shouldRebuild"]}